Zašto `serve` je prikazivao ružan sajt dok je `publishSite` bio savršen
Објављено 22 April 2026
Znate li o tom trenutku kad vaš lokalni sajt izgleda kao ništa, ali kada se objavi na mreži sve je u redu? To je mi se desilo sa mojim Gradle JBake pluginom. Zadatak`serve`prikazivao kvadratni dugmad, temni tekst na crnoj pozadini, i bizarno odsutan CSS. Ipak`publishSite`je generisao isti sajt, onaj, bez greške. Krivac nije bio ni CSS, ni preglednik, ni keš. Bio je jedna linija Kotlin koda — i loša navika sa argumentima komandne linije.
- tik
-
[]
Сцена: четири скриншота, два рендера
Било je nakon краха система. Снимio сам четири слике екрана да упоређим локални рендер (./gradlew serve`na`localhost:8820) sa inline renderovanjem (`publishSite`na GitHub Pages). Dva screenshots po stranici : gore i dole.
Lokalni render
Vrh stranice— Дугмићи Project i Template суmali, pravougaoni, u standardnim bojama (plava i zelena). Kartica Start Writing imajednobojno crno pozadina, bez okvira.
podnožje— Podnaslov "Последњи чланци и ресурси" јепочти нијечитљив, previše tamno na crnom pozadini. Datumi ispod slika bloga ("17 October 2013", itd.) suodsutne.
Izrenderivano na mreži
Врх странице— Isto dugma suвелики, овјарски, неоново зелен, јучест, tekst u velikim slovima. Karta imazaobljeni beli okvir s senkom.
Futer— Podnaslov jedobro čitavo. Datumi suвидљиви. Kartice artikala imajuzaobljeni kutovii naslovi suuvlaceno.
Први рефлекс: тема. Користим систем теме динамичке (светла, тама, high-contrast) базиран на`localStorage`. Možda je lokalni store pokretao temu high-contrast? Ne. Već sam napisaohttps://cheroliv.com/blog/2025/0098_preloading_css_variable_post.html[ceo članak o učitanju tema unapred], Znam kako to radi. I pak, čak i u high-contrast modu, CSS struktura (ovaoblasta dugmeta, senke) trebalo da bude tamo. Nije bila.
Drugi refleks: keš pretraživača. Ne, testirao sam na čistim profilima. Razlika je ostala.
Трећи рефлекс :`serve`nije služio iste fajlove kao`publishSite`.
Dijagnostika : serve nije ukazivalo na pravilan folder
Moj Gradle plugin`bakery`ima dva glavna zadatka:
-
bake: generira statički sajt u`build/bake/` -
serve: Pokreni lokalni web server -
publishSite: dira`build/bake/`ka GitHub Pages
Divergencija je mogla da dođe samo iz`serve`. Si publishSite`Objavljivao je ispravan sadržaj, jer je`build/bake/`Bilo je dobro. Ako`serve`prikazivao je nešto drugo, zato što nije služio`build/bake/.
Pogledajmo kod. U`SiteManager.kt`, zadatak`serve`je definisana kao ovo:
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`je ulazna tačka CLI JBake 2.7.0. Ideja: proći-b`за изворни директоријум и`-s`за одредешњи folder, pokreni server мод. Осим што…
Главна причина: JBake CLI ne radi tako
JBake 2.7.0 ocekujepozicioni argumentiza izvor i destinaciju, zatim opcione flagove. Potpis je:
jbake <source> <destination> [options]
Али у мојем коду јех писао:
args = listOf("-b", "/path/to/site", "-s", "/path/to/build/bake")
JBake je tumačio da je:
-
-b→ parsiraj flag "bake" (boolean), ispotrošeno -
/path/to/site→ postaje pozicioni argument 1 (izvor) -
-s→ parsiraj flag "serve" (bool), server pokrenutодмах -
/path/to/build/bake→ postaće siromasni argument, zanemaren ili pogrešno tumačen
Резултат: JBake узимао`/path/to/site`kao izvor,није узимало у обзир одредиштеобесбечена (build/bake), i koristilo je svoj podrazumevani repertoar (često`./output`или времену копију). Датотека`css/styles.css`build-a je bio prepisan ili ignorisan, a bio je staro podrazumevano CSS (bez custom promenjivih, bez zaobljenja, bez senki) koje je bilo servisano.
U poredbi,bake et publishSite`koristezvanični Gradle JBake plugin(`jbake-gradle-plugin) koji piše uređeno u`build/bake/`kroz Gradle API. Ne prolaze kroz CLI.
Решение : позициони аргументи, не флагови
Korekcija je trivijalna — jednom kada znaš. Dovoljno je proslediti izvor i destinaciju kao pozicionalni argumenti, pa`-s`на крају
args = listOf(
file(site.bake.srcPath).absolutePath,
layout.buildDirectory.get()
.asFile.resolve(site.bake.destDirPath)
.absolutePath,
"-s"
)
To je sve. Tri linije promenjene, greška rešena.
После локалног објављивања плагина (publishToMavenLocal), un `./gradlew serve`pokreni JBake sa ispravnom sintaksom:
jbake /home/user/project/site /home/user/project/build/bake -s
И ови пут, Jetty сервер интегрован у JBake добро служи садржају`build/bake/`— идентично што је објављено онлайн.
@startuml
!define RECTANGLE class
package "PRE (bug)" {
RECTANGLE JBakeCLI1 {
+ args = ["-b", "сајт", "-s", "graditi/peci"]
}
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 "POSLE (fix)" {
RECTANGLE JBakeCLI2 {
+ args = ["сајт", "graditi/peci", "-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
Brza provera sa curl
Da biste se uverili da server ispravno služi dobrog sadržaja, jednostavno`curl`potvrđuje da`index.html`sadrži`data-bs-theme="light"`i da`build/bake/css/styles.css`teži tacno 31 402 bajta — identičan datoteci generisanoj od`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
Локални рендер је садапиксељ-идентичанна разгредовани приказ.
Zašto je ovaj bug bio lukav?
Видиш зато је било тешко да се ухвати?
-
Nema explicitne greške: JBake nije pao. "Funkcionisao" je, jednostavno sa pogrešnim direktorijumom.
-
Build je radio :
./gradlew bake`исправно генерисао фајлове у`build/bake/. -
Распоред је радио:`publishSite`Postavljao je dobar sadržaj na internetu.
-
Samo
serveje bio pokvaren: zadatak razvoja, onaj koji stalno koristimo za iteriranje -
Navika od
-key value: kao programer, smo uslovljeni godinama rada u Unix CLI (-o output`,-i input). JBake CLI je izuzetak — izvor i destinacija su pozicionirani.
Zaključak
Ako održavate Gradle plugin koji omotava JBake (ili bilo koji CLI alat),pročitajte dokumentaciju argumenataćak i ako mislite da ih poznajete. Jedna implicitna hipoteza (-s = "set destination")` може вам коштати сате визуелног дебаговања.
Ово, поправка је била дословно да се промени:
args = listOf("-b", src, "-s", dest) // ❌ BUG
en :
args = listOf(src, dest, "-s") // ✅ FIX
Tri pomerena token, i moj lokalni sajt ponovo postaje leпокao kao sajt u produkciji.
Lekcija: kad se renderovanje razlikuje između lokalnog i produkcijskog okruženja bez očiglednog razloga, prvo sumnjajte na pipeline — ne na CSS, ne na pretraživač, a još manje na framework. Često je korak ispravno prije renderovanja koji vara.