읽기 시간 : 10 minutes

로컬에서 사이트가 아무 것도 아닌 것처럼 보였지만, 온라인에 배포된 후에는 모든 것이 깔끔해졌을 때를 아시나요? 이건 내 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단색 검은 배경, 틀 없이.

Rendu local - haut de page

바닥글— 부제목 *최신 글과 자료*는거의 읽을 수 없는, 검은 배경에 너무 어둡습니다. 블로그 이미지 아래의 날짜('17 October 2013', 등등)은결석한.

Rendu local - bas de page

온라인 렌더링

페이지 상단— 같은 버튼들은큰, 양의, 화려한 네온 초록, 대문자 텍스트. 카드에는흰색 둥근 프레임에 그림자.

Rendu en ligne - haut de page

하단— 부제목은가독성이 좋습니다. 날짜는보이는. 기사 카드에는둥근 모서리그리고 제목들은굵게.

Rendu en ligne - bas de page

첫 번째 반사: 테마. 나는 (밝은, 어두운, 높은 대비) 기반의 동적 테마 시스템을 사용`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`다음과 같이 정의됩니다:

SiteManager.kt — La tâche serve (version buggy)
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는 이것을 이렇게 해석했습니다 :

  1. -b→ "bake" 플래그(부울)를 파싱, 소비됨

  2. /path/to/site→ 위치 기반 인수 1이 됩니다 (출처)

  3. -s→ 'serve' 플래그(불리언)를 파싱, 서버 시작됨즉시

  4. /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`마지막으로:

SiteManager.kt — La tâche serve (version corrigée)
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

로컬 렌더링은 이제픽셀-동일배포된 렌더링에서

왜 이 버그는 교활했는가?

왜 잡기 어려웠는지 보이시죠?

  1. 명시적 오류 없음: JBake는 크래시되지 않았습니다. 그것은 단지 잘못된 폴더와 함께 '작동’하고 있었습니다.

  2. 빌드가 작동하고 있었습니다:`./gradlew bake`파일을 올바르게 생성하고 있었습니다`build/bake/`.

  3. 배포가 작동하고 있었다(Empty)`publishSite`좋은 콘텐츠를 온라인에 게시하고 있었습니다.

  4. serve`만 고장 났습니다: 개발 작업, 그것을 반복하기 위해 계속 사용하는 것.

  5. -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가 아니고, 브라우저가 아니고, 더더욱 프레임워크가 아닙니다. 종종 렌더링 직전의 단계가 속이는 경우가 많습니다.

관련 기사