χρόνος ανάγνωσης : 10 minutes

Ξέρεις αυτό το στιγμίο όταν η τοπική σου ιστοσελίδα φαίνεται τίποτα, αλλά μόλις αναπτυχθεί online, όλα είναι τέλεια; Αυτό μου συνέβη με το Gradle JBake plugin μου. Η εργασία`serve`Εμφανιζε τετράγωνα κουμπιά, σκοτεινό κείμενο πάνω σε μαύρο φόντο, και ένα CSS ασυνήθιστα λείπον. Μεντοι`publishSite`έφερε τον ίδιο ιστότοπο, αυτό, άριστο. Ο ένοχος δεν ήταν το CSS, ούτε ο περιηγητής, ούτε το cache. Ηταν μια γραμμή κώδικα Kotlin — και μια κακή συνήθεια με τα ορίσματα της γραμμής εντολών.

Η σκηνή : τέσσερα screenshots, δύο render

Ήταν μετά από μια σύπτωση του συστήματος. Έχα πάρει τέσσερις λήψεις οθόνης για να συγκρίνω την τοπική απόδοση (./gradlew serve`επί`localhost:8820) με την αποδόση ενσαφής (`publishSite`σε το GitHub Pages). Δύο στιγμιότυπα ανά σελίδα : η κορυφή και το κάτω.

τοπική απόδοση

Κορυφή σελίδας— Τα κουμπιά Project και Template είναιμικρά, ορθογώνια, στα πρότυπα χρώματα (μπλε και πράσινο). Η κάρτα Start Writing έχει έναομογενο μαύρο φόντο, χωρίς πλαίσιο.

Rendu local - haut de page

το υποπλοίο— Ο υποτίτλος "Τελευταία άρθρα και πόροι" είναιπεριτυχώς αναγνώσιμο, πολύ σκούρο σε μαύρο φόντο. Οι ημερομηνίες κάτω από τις εικόνες του blog ("17 October 2013", κλπ.) είναιαπουσιάζουσες.

Rendu local - bas de page

Απεικόνιση σε διαδίκτυο

Κορυφή της σελίδας— Οι ίδιοί κουμπίες είναιμεγάλα, σβάτες, φλaσαρικό πράσινο νéon, κείμενο κεφαλαίων. Η κάρτα έχει έναλευκό στρογγυλό πλαίσιο με σκιά.

Rendu en ligne - haut de page

κάτω μέρος της σελίδας— Ο υπότίτλος είναιευανάγνωστο. Οι ημερομηνίες είναιορατοί. Οι κάρτες των άρθρων έχουνστρογγυλεμένες γωνίεςκαι οι τίτλοι είναιέντονα.

Rendu en ligne - bas de page

Πρώτο αντανακλαστικό: το θέμα. Χρησιμοποιώ ένα δυναμικό σύστημα θέματος (φωτεινό, σκοτεινό, high-contrast) βασισμένο σε`localStorage`. Ίσως το local store ενεργοποίησε ένα θέμα high-contrast? Όχι. είχα ήδη γράψειhttps://cheroliv.com/blog/2025/0098_preloading_css_variable_post.html[ένα ολόκληρο άρθρο για την προφόρτωση των θεμάτων], ξέρω πώς λειτουργεί. Και ας πούμε, ακόμα και σε κατάσταση high-contrast, η δομή CSS (κοντουράκια οβάλια, σκιές) έπρεπε να υπάρχει. Δεν υπήρχε.

Δεύτερο αντανακλαστικό: ο cache του περιηγητή. Όχι, έκανα τη δοκιμή με καθαρούς προφίλ. Η διαφορά συνέμενε.

Τρίτο αντανακλαστικό:`serve`δεν παρείχε τα ίδια αρχεία όπως`publishSite`.

Η διάγνωση: serve δεν demonstr*…​ Actually correct: "Η διάγνωση: serve δεν δείχνουσε στο σωστό φάκελο". We need to ensure no typo.

Let’s output exactly that.

</think>

Η διάγνωση: serve δεν δείχνουσε στο σωστό φάκελο

Το πρόσθετο μου Gradle`bakery`έχει δύο κύριεςεργασίες:

  • bake: δημιουργεί το στατικό ιστότοπο στο`build/bake/`

  • `serve`εκκινεί έναν τοπικό διακομιστής web

  • publishSite: ωθεί`build/bake/`προς το GitHub Pages

η διαróżα δενμποριζούσε να προέρχεται μόνο από`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`είναι το σημείο εισόδου της CLI JBake 2.7.0. Η ιδέα : περάστε-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→ parse το flag "bake" (βολéen), καταναλωμένο

  2. /path/to/site→ γίνεται το πρώτο όρισμα θέσης (πηγή)

  3. -s→ αναλύει το flag "serve" (βολεάν), εξυπηρετητή ξεκίνησεαμέσως

  4. /path/to/build/bake→ γίνεται ένα ορφανό επιχείρημα, αγνοούμενο ή λανθασμένα ερμηνευόμενο

Αποτέλεσμα: Το JBake έπαιρνε`/path/to/site`ως πηγή,Δεν había λάβει υπόψη τον προορισμόπαρεχόμενη (build/bake), και χρησιμοποίησε το προεπιλεγμένο του φάκελο (συχνά`./output`ή mia? No.`css/styles.css`Η κατασκευή (build) ήταν επικάλυπτο ή αγνοημένο, και ήταν ένα παλιό προεπιλεγμένο CSS (χωρίς τις προσαρμοσμένες μεταβλητές, χωρίς τις στρογγυλοποιήσεις, χωρίς τις σκιές) που παρείχετο.

Σε σύγκριση,bake et publishSite`χρησιμοποιούν τοπρόσθετο Gradle JBake επίσημο(`jbake-gradle-plugin) ο οποίος γράφει καθαρά σε`build/bake/`μέσω της Gradle API. Δεν περνούν από τη CLI.

Η λύση : θέσινες παραμέτρους, όχι flags

Η διόρθωση είναι απλή — όταν το ξέρεις. Αρκεί να μεταδώσετε τη πηγή και τον προορισμό ως ορισματα positional, και`-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"
)

Έτσι είναι. Τρεις αλλαγμένες γραμμές, επιλυμένο σφάλμα

Μετά την τοπική δημοσίευση του plugin (publishToMavenLocal), un `./gradlew serve`Εκκίνησε το JBake με τη σωστή σύνταξη:

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

Και αυτή τη φορά, ο ενσωματωμένος διακομιστής Jetty στο JBake εξυπηρετεί καλά το περιεχόμενο του`build/bake/`— ίδιο με αυτό που δημοσιεύεται σε σύνδεση.

@startuml
!define RECTANGLE class

package "ΠΡΟ (bug)" {
  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 "ΜΕΤΑ (fix)" {
  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 byte — ίδιο με το αρχείο που δημιουργήθηκε από`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

Η τοπική απόδοση είναι τώραpixel ίδιοςστο εγκατεστημένο rendering

Γιατί αυτό το bug ήταν πρόκλητο;

Βλέπετε γιατί ήταν δύσκολο να πιαστεί;

  1. Δεν υπάρχει ρητρό σφάλμαJBake δεν έκοβε. Αυτό "λειτούργει", απλώς με ένα λάθος φάκελο.

  2. Η build funcionούσε : ./gradlew bake`εδimiourgούσε σωστά τα αρχεία σε`build/bake/.

  3. Η ανάπτυξη λειτούργιζε(Empty output)`publishSite`έβαινε το σωστό περιεχόμενο διαδικτυακά.

  4. Μόνο serve ήταν σπασμένο: η εργασία ανάπτυξης, αυτή που τη χρησιμοποιούμε συνεχώς για να επαναλάβουμε.

  5. Η συνήθεια του -key value: ως προγραμματιστής, ειμαστε προπονημένοι από χρόνια CLI Unix (-o output`, -i input). JBake CLI είναι μια εξαίρεση — η πηγή και ο προορισμός είναι ορισμένες με βάση τη θέση.

Συμπέρασμα

Αν διαχειρίζεστε ένα plugin Gradle που κάνει wrap το JBake (οποιοδήποτε εργαλείο CLI)Διαβάστε την τεκμηρίωση των ορισμάτωνΑκόμα κι αν πιστεύετε ότι τα γνωρίζετε. Μια υπόθεση εμμεσής (-s = "set destination") μπορεί να σας κοστίσει ώρες οπτικού debugging.

Εδώ, η διόρθωση ήταν πραγματικά να αλλάξει :

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

en :

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

Τρία μετακινημένα tokens, και ο τοπικός μου ιστότοπος γίνεται επίσης όμορφος όσο και ο ιστότοπος παραγωγής.

Μάθημα: Συχνά είναι το βήμα ακριβώς πριν την αποδόση που δεν παίζει καθαρά.

Σχετικά άρθρα