为什么 `serve` 显示了一个丑陋的网站,而 `publishSite` 却很完美
Publié le 22 April 2026
你知道那个时刻吗?你本地的网站看起来一团糟,但一旦部署到线上后一切就变得完美?这就是我与我的 Gradle JBake 插件所经历的。任务`serve`它显示了方形按钮、黑色背景上的深色文字,以及奇怪地缺失的 CSS。然而`publishSite`它生成了完全相同的站点,而他却是完美的。罪魁祸首既不是 CSS,也不是浏览器,也不是缓存。正是一行 Kotlin 代码 — 以及在命令行参数上的不良习惯。
- �抽搐
-
[]
场景:四个截图,两个渲染
那是在系统崩溃之后。我拍了四张截图以比较本地渲染 (./gradlew serve`在`localhost:8820) 在线渲染 (`publishSite`在 GitHub Pages 上)。每页两张截图:顶部和底部。
本地渲染
页面顶部— 按钮 Project 和 Template 是小的,矩形的, 标准颜色(蓝色和绿色)。 卡片 Start Writing 有个纯黑背景,无框。
页脚— 副标题 "Derniers articles et ressources" 是几乎无法辨认, 在黑色背景上太暗。博客图片下的日期(“17 October 2013”等)是缺席.
线上渲染
页面顶部— 同样的按钮是大的,羊的,闪亮的霓虹绿, 大写文本。 地图有一个�圆角白色框架带阴影.
页脚— 副标题是易读. 日期是可见的. 文章卡片具有的圆形硬币并且标题是加粗.
第一步是主题。我使用基于 (亮色、暗色、高对比度) 的动态主题系统。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`定义如下:
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。
解决方案:位置参数,而不是选项
修正很简单 — 只要你知道。只需要把 source 和 destination 作为位置参数传递,然后`-s`最后:
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/`— 与在线发布的内容相同。
使用 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 很狡猾
你明白为什么抓起来很难吗?
-
没有显式错误JBake 没有崩溃。它 "正常运行",只是使用了错误的文件夹。
-
构建正常运行 :
./gradlew bake`正确地生成文件在`build/bake/. -
部署正在运行。:`publishSite`在线推送了优质内容
-
只有
serve坏了: 开发任务,也就是我们一直用来迭代的那个任务。 -
‑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,不是浏览器,更不是框架。通常是在渲染之前的那一步作弊。