왜 `serve`가 못생긴 사이트를 표시했는지, `publishSite`는 완벽했을까?
게시: 22 April 2026
로컬에서 사이트가 아무 것도 아닌 것처럼 보였지만, 온라인에 배포된 후에는 모든 것이 깔끔해졌을 때를 아시나요? 이건 내 Gradle JBake 플러그인과 함께 일어났던 일입니다. 작업`serve`네모난 버튼을 표시하고, 검은 배경에 어두운 텍스트를 보여 주었으며, CSS가 이상하게도 빠져 있었습니다. однако`publishSite`같은 사이트를 생성했고, 그것이 완벽했다. 원인은 CSS도, 브라우저도, 캐시도 아니었다. 그것은 Kotlin 코드 한 줄이었고, 명령줄 인수와 관련된 나쁜 습관 때문이었다.
- 틱
-
[]
장면: 네 개의 스크린샷, 두 개의 렌더링
시스템 충돌 뒤에 있었다. 나는 로컬 렌더링을 비교하기 위해 스크린샷 네 개를 찍어두었다 (./gradlew serve`위에`localhost:8820) 온라인 렌더링과 함께 (`publishSite`GitHub Pages에서). 페이지당 두 개의 스크린샷 : 위와 아래.
로컬 렌더링
페이지 상단— 버튼 Project 및 Template*는작은, 직사각형, aux couleurs standards (bleu et vert). La carte *Start Writing a un단색 검은 배경, 틀 없이.
바닥글— 부제목 *최신 글과 자료*는거의 읽을 수 없는, 검은 배경에 너무 어둡습니다. 블로그 이미지 아래의 날짜('17 October 2013', 등등)은결석한.
온라인 렌더링
페이지 상단— 같은 버튼들은큰, 양의, 화려한 네온 초록, 대문자 텍스트. 카드에는흰색 둥근 프레임에 그림자.
하단— 부제목은가독성이 좋습니다. 날짜는보이는. 기사 카드에는둥근 모서리그리고 제목들은굵게.
첫 번째 반사: 테마. 나는 (밝은, 어두운, 높은 대비) 기반의 동적 테마 시스템을 사용`localStorage`. 아마도 로컬 스토어가 고대비 테마를 트리거했을 수도 있지? 아니. 나는 이미 썼어.https://cheroliv.com/blog/2025/0098_preloading_css_variable_post.html[주제 사전 로드에 관한 전체 기사], 나는 어떻게 작동하는지 알아. 그리고 심지어 high-contrast 모드에서도 CSS 구조(타원형 버튼, 그림자)가 있어야 했어. 그런데 그게 없었어.
두 번째 반응: 브라우저 캐시. 아니요, 깨끗한 프로필로 테스트를 했었습니다. diff가 지속되었습니다.
세 번째 반사 :`serve`같은 파일을 제공하지 않았습니다`publishSite`.
진단 : `serve`가 올바른 폴더를 가리키고 있지 않았습니다.
내 그레이들 플러그인`bakery`두 가지 주요 작업이 있습니다:
-
bake: 안에 정적 사이트를 생성합니다`build/bake/` -
serve: 로컬 웹 서버를 시작합니다 -
publishSite: 밀다`build/bake/`GitHub Pages쪽으로
차이는 오직 …에서만 나올 수 있었다.serve. Si publishSite`그는 올바른 콘텐츠를 게시하고 있었고, 그것이`build/bake/`좋았어요. 만약`serve`다른 것을 표시하고 있었는데, 그건 그것이役에 서지 못했습니다.`build/bake/.
코드를 봅시다. 안에서`SiteManager.kt`, 작업`serve`다음과 같이 정의됩니다:
tasks.register("serve", JavaExec::class.java) { task ->
task.apply {
mainClass.set("org.jbake.launcher.Main")
classpath = jbakeRuntime
environment("GEM_PATH", jbakeRuntime.asPath)
jvmArgs(/* ... */)
args = listOf(
"-b", file(site.bake.srcPath).absolutePath,
"-s", layout.buildDirectory.get()
.asFile.resolve(site.bake.destDirPath)
.absolutePath
)
}
}
org.jbake.launcher.Main`JBake 2.7.0 CLI의 진입점입니다. 아이디어: 전달하다-b`소스 폴더와`-s`대상 폴더에 대해, 서버 모드를 시작합니다. 단, …
근본 원인: JBake CLI는 이렇게 작동하지 않습니다
JBake 2.7.0은(는) 기다리고 있는위치 인수소스와 목적지, 그리고 옵션 플래그. 서명은:
jbake <source> <destination> [options]
그러나 내 코드에서 쓰고 있었는데:
args = listOf("-b", "/path/to/site", "-s", "/path/to/build/bake")
JBake는 이것을 이렇게 해석했습니다 :
-
-b→ "bake" 플래그(부울)를 파싱, 소비됨 -
/path/to/site→ 위치 기반 인수 1이 됩니다 (출처) -
-s→ 'serve' 플래그(불리언)를 파싱, 서버 시작됨즉시 -
/path/to/build/bake→ 버려진 주장이 되어 무시되거나 잘못 해석됩니다.
결과 : JBake 가져갔다`/path/to/site`소스로서,목적지를 고려하지 않았습니다.제공된 (build/bake), 그리고는 기본 디렉터리를 사용하고 있었습니다 (자주`./output`또는 임시 복사본) 파일`css/styles.css`빌드는 덮어쓰여지거나 무시되었고, 그래서 기본 제공되는 오래된 CSS(커스텀 변수도 없고, 둥근 모서리도 없고, 그림자도 없이)가 제공되었습니다.
비교하면,bake et publishSite`그들이 그것을공식 Gradle JBake 플러그인(`jbake-gradle-plugin) 깔끔하게 쓰는 안에`build/bake/`Gradle API를 통해. 그들은 CLI를 통과하지 않습니다.
해결책: 위치 인자, 플래그가 아닌
수정은 간단합니다 — 한번 알면 됩니다. 소스와 대상을 위치 인수로 전달하기만 하면 됩니다, 그다음`-s`마지막으로:
args = listOf(
file(site.bake.srcPath).absolutePath,
layout.buildDirectory.get()
.asFile.resolve(site.bake.destDirPath)
.absolutePath,
"-s"
)
그게 다예요. 세 줄이 변경되었고 버그가 해결되었습니다.
로컬에서 플러그인을 게시한 후 (publishToMavenLocal), un `./gradlew serve`JBake를 올바른 구문으로 실행합니다 :
jbake /home/user/project/site /home/user/project/build/bake -s
그리고 이번엔, JBake에 내장된 Jetty 서버가 콘텐츠를 잘 제공합니다`build/bake/`— 온라인에 게시된 내용과 동일합니다.
@startuml
!define RECTANGLE class
package "이전 (버그)" {
RECTANGLE JBakeCLI1 {
+ args = ["-b", "사이트", "-s", "빌드/베이크"]
}
RECTANGLE Source1 {
+ site/
}
RECTANGLE Dest1 {
+ ??? (dossier temporaire)
}
RECTANGLE Jetty1 {
+ sert mauvais fichiers
}
JBakeCLI1 --> Source1 : lit
JBakeCLI1 -[#red]x Dest1 : destination ignorée
Jetty1 --> Dest1 : sert
}
package "후 (수정)" {
RECTANGLE JBakeCLI2 {
+ args = ["사이트", "빌드/베이크", "-s"]
}
RECTANGLE Source2 {
+ site/
}
RECTANGLE Dest2 {
+ build/bake/
}
RECTANGLE Jetty2 {
+ sert les bons fichiers
}
JBakeCLI2 --> Source2 : lit
JBakeCLI2 --> Dest2 : écrit dans
Jetty2 --> Dest2 : sert OK
}
@enduml
cURL을 사용한 빠른 검증
서버가 올바른 콘텐츠를 제공하고 있는지 확인하기 위해, 간단한`curl`확인한다`index.html`포함한다`data-bs-theme="light"`그리고`build/bake/css/styles.css`정확히 31 402 바이트입니다 — 생성된 파일과 동일한`bake`.
$ ./gradlew serve
# Dans un autre terminal :
$ curl -s http://localhost:8820/ | grep data-bs-theme
<html ... data-bs-theme="light" ...>
$ curl -I http://localhost:8820/css/styles.css
HTTP/1.1 200 OK
Content-Length: 31402
Content-Type: text/css
로컬 렌더링은 이제픽셀-동일배포된 렌더링에서
왜 이 버그는 교활했는가?
왜 잡기 어려웠는지 보이시죠?
-
명시적 오류 없음: JBake는 크래시되지 않았습니다. 그것은 단지 잘못된 폴더와 함께 '작동’하고 있었습니다.
-
빌드가 작동하고 있었습니다:`./gradlew bake`파일을 올바르게 생성하고 있었습니다`build/bake/`.
-
배포가 작동하고 있었다(Empty)`publishSite`좋은 콘텐츠를 온라인에 게시하고 있었습니다.
-
serve`만 고장 났습니다: 개발 작업, 그것을 반복하기 위해 계속 사용하는 것.
-
-key value`의 습관: 개발자로서, 우리는 수년간의 Unix CLI에 익숙해져 있다`-o output`,
-i input). JBake CLI는 예외입니다 — 소스와 목적은 위치 기반.
결론
JBake를 래핑하는 Gradle 플러그인(또는 기타 CLI 도구 포함)을 유지 관리하는 경우,인수 문서를 읽으세요당신이 그들을 알고 있다고 생각하더라도. 암묵적인 가설 (-s= "set destination") 시각적 디버깅에 몇 시간을 소비하게 만들 수 있습니다.
여기서 수정은 말 그대로 변경하는 것이었습니다 :
args = listOf("-b", src, "-s", dest) // ❌ BUG
en :
args = listOf(src, dest, "-s") // ✅ FIX
세 개의 토큰이 이동된 후, 내 로컬 사이트는 다시 프로덕션 사이트만큼 아름답게 되었다.
수업: 로컬과 프로덕션 간 렌더링이 명백한 이유 없이 다를 때, 먼저 *pipeline*을 의심하세요 — CSS가 아니고, 브라우저가 아니고, 더더욱 프레임워크가 아닙니다. 종종 렌더링 직전의 단계가 속이는 경우가 많습니다.
관련 기사
31 May 2026
14 May 2026