阅读时间 : 10 minutes

你知道那个时刻吗?你本地的网站看起来一团糟,但一旦部署到线上后一切就变得完美?这就是我与我的 Gradle JBake 插件所经历的。任务`serve`它显示了方形按钮、黑色背景上的深色文字,以及奇怪地缺失的 CSS。然而`publishSite`它生成了完全相同的站点,而他却是完美的。罪魁祸首既不是 CSS,也不是浏览器,也不是缓存。正是一行 Kotlin 代码 — 以及在命令行参数上的不良习惯。

�抽搐

[]

场景:四个截图,两个渲染

那是在系统崩溃之后。我拍了四张截图以比较本地渲染 (./gradlew serve`在`localhost:8820) 在线渲染 (`publishSite`在 GitHub Pages 上)。每页两张截图:顶部和底部。

本地渲染

页面顶部— 按钮 Project 和 Template 是小的,矩形的, 标准颜色(蓝色和绿色)。 卡片 Start Writing 有个纯黑背景,无框。

Rendu local - haut de page

页脚— 副标题 "Derniers articles et ressources" 是几乎无法辨认, 在黑色背景上太暗。博客图片下的日期(“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[一篇关于主题预加载的完整文章], 我知道它是怎么工作的。而且,即使在高对比度模式下,CSS 结构(椭圆形按钮、阴影)也应该存在。但它不存在。

第二个反射:浏览器缓存。不,我之前已经用干净的配置文件做了测试。差异仍然存在。

第三个反射:serve`没有提供与……相同的文件`publishSite.

诊断:serve 未指向正确的文件夹

我的 Gradle 插件`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。

解决方案:位置参数,而不是选项

修正很简单 — 只要你知道。只需要把 source 和 destination 作为位置参数传递,然后`-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"
)

这就完了。修改了三行代码,bug 已修复。

本地发布插件后(publishToMavenLocal), un `./gradlew serve`使用正确的语法启动 JBake :

jbake /home/user/project/site /home/user/project/build/bake -s

而这一次,JBake内嵌的Jetty服务器正确地提供了内容`build/bake/`— 与在线发布的内容相同。

serve vs publish diagram

使用 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

本地渲染现在像素相同部署的渲染

为什么这个 bug 很狡猾

你明白为什么抓起来很难吗?

  1. 没有显式错误JBake 没有崩溃。它 "正常运行",只是使用了错误的文件夹。

  2. 构建正常运行 : ./gradlew bake`正确地生成文件在`build/bake/.

  3. 部署正在运行。:`publishSite`在线推送了优质内容

  4. 只有 serve 坏了: 开发任务,也就是我们一直用来迭代的那个任务。

  5. ‑key value`的习惯: 作为开发者,我们受多年 Unix CLI 的影响 (-o output, -i input). JBake CLI 是一个例外 — 源和目标是位置参数。

结论

如果您维护一个包装 JBake(或任何 CLI 工具)的 Gradle 插件,�阅读参数的文档即使你认为你认识他们。 一个隐含的假设 (-s = "set destination")` 可能会让你在视觉调试上浪费数小时。

这里,修复 literally 就是要改变:

args = listOf("-b", src, "-s", dest)   // ❌ BUG

en :

args = listOf(src, dest, "-s")         // ✅ FIX

移动了三个标记,我的本地站点又变得和生产站点一样美丽。

课: 当渲染在本地和生产之间出现差异且没有明显原因时,首先怀疑是 pipeline 的问题 — 不是 CSS,不是浏览器,更不是框架。通常是在渲染之前的那一步作弊。

相关文章