Panduan Pasukan Lucee MY

Templat CFML tidak dikompil atau cache basi

Perubahan templat CFML tidak berkuat kuasa atau kelas CFC lama masih digunakan? Fahami beza kompil templat .cfm dan cache .cfc serta cara flush tanpa restart.

Templat CFML tidak dikompil atau cache basi
0
Kandungan

Templat CFML tidak dikompil atau cache basi

Penulis: Thalhah · Tarikh: 7 Oktober 2026

Apabila anda menyunting fail .cfm dan perubahan itu tidak muncul, atau menambah kaedah baharu pada komponen .cfc tetapi enjin masih memanggil kelas lama, puncanya hampir selalu sama: Lucee mengkompil kod anda kepada kelas Java dan menyimpannya dalam cache, dan cara cache itu dibuang berbeza antara templat dan komponen. Artikel ini menunjukkan bukti yang dijalankan dalam enjin Lucee 7.1, bukan teori, dan cara membaikinya tanpa meneka.

Dua laluan yang berbeza: templat dan komponen

CFML sebenarnya tidak ditafsir baris demi baris seperti skrip lama. Lucee mengkompil setiap fail kepada kelas Java dan menyimpannya dalam cache kod terkompil, yang dalam dokumentasi dipanggil "page pool". Perbezaan penting terletak pada bila Lucee menyemak semula fail sumber untuk perubahan.

Fail .cfm ialah templat. Ia disemak mengikut tetapan "Inspect templates (CFM/CFC)" dalam Lucee Admin. Dalam mod lalai "Once", Lucee menyemak setiap templat sekali bagi setiap permintaan. Hasilnya, apabila anda menyunting .cfm lalu memuat semula halaman, versi baharu dikompil dan digunakan serta-merta. Inilah sebabnya semasa membangun, suntingan .cfm hampir selalu terus berkuat kuasa tanpa sebarang langkah tambahan.

Komponen .cfc pula dikompil menjadi kelas Java yang dimuatkan ke dalam JVM. Kelas yang sudah dimuatkan tidak ditukar hanya kerana fail sumbernya berubah. Lucee memang boleh mengkompil fail .cfc yang berubah menjadi kelas baharu untuk tika yang dicipta kemudian, tetapi tika yang sudah wujud dalam memori kekal terikat kepada kelas lama. Beza ini adalah punca hampir semua kekeliruan tentang cache basi.

Mengapa suntingan .cfm terus berkuat kuasa

Mekanismenya mudah. Setiap kali permintaan tiba untuk fail .cfm, Lucee membandingkan cap masa fail pada cakera dengan versi yang ada dalam page pool. Jika fail berubah, Lucee mengkompil semula dan menggunakan kelas baharu untuk permintaan itu. Tiada tindakan manual diperlukan.

Ini boleh dibuktikan dalam beberapa saat. Tulis satu templat yang memaparkan rentetan, minta ia melalui HTTP, sunting rentetan itu, lalu minta sekali lagi. Keluaran kedua berubah serta-merta, seperti yang kami jalankan dalam rig Lucee 7.1 di bawah.

Komponen .cfc dikompil dan di-cache

Komponen berkelakuan berbeza kerana ia menjadi objek hidup dalam memori, bukan sekadar teks yang dipaparkan. Apabila anda menulis new View(), Lucee mengkompil View.cfc menjadi kelas, mencipta satu tika daripada kelas itu, dan memulangkan rujukan kepadanya. Baca panduan fungsi dan komponen CFC untuk asas menulis dan memetakan komponen. Tika itu memegang senarai kaedah yang wujud pada masa ia dicipta.

Jika anda kemudian menambah kaedah baharu pada fail View.cfc, perkara berikut berlaku pada permintaan seterusnya. Tika yang baru dicipta dengan new akan mendapat kelas baharu dan melihat kaedah baharu itu. Tetapi tika yang sudah wujud sebelum suntingan itu, contohnya yang disimpan dalam skop application, masih memegang kelas lama dan tidak mengenali kaedah baharu. Kod di bawah menunjukkan perbezaan ini dengan jelas.

component {
    public string function kaedahSatu() {
        return "CFC kaedah satu";
    }
}
// Tika disimpan dalam skop application pada permintaan pertama sahaja
if (!structKeyExists(application, "cacheDemo")) {
    application.cacheDemo = new uji.CacheDemo();
}
objLama = application.cacheDemo;
writeOutput("kaedahSatu (objLama): " & objLama.kaedahSatu());

Bukti dalam enjin: templat lawan CFC

Kami menjalankan ujian ini dalam Lucee 7.1.2.54 supaya anda tidak perlu mempercayai dakwaan kosong. Untuk templat, satu fail .cfm ditulis dengan rentetan "TEMPLAT VERSI 1", diminta melalui curl, disunting kepada "TEMPLAT VERSI 2", lalu diminta semula. Keluaran pertama memaparkan VERSI 1 dan keluaran kedua memaparkan VERSI 2, tanpa sebarang langkah lain.

Untuk komponen, kami menulis komponen dengan satu kaedah kaedahSatu(), menyimpannya dalam skop application, kemudian menambah kaedah kedua kaedahDua() pada fail .cfc yang sama tanpa memulakan semula aplikasi. Hasilnya menunjukkan dua perkara yang berbeza sekali gus. Tika baharu yang dicipta dengan new selepas suntingan memanggil kaedahDua() dengan jayanya dan memulangkan "CFC kaedah dua". Tetapi tika yang disimpan dalam skop application masih membalas Component [uji.CacheDemo] has no function with name [kaedahDua]. Kelas lama kekal hidup di dalam tika itu walaupun fail sumber sudah berubah.

Objek dalam skop application mengekalkan kelas lama

Ini perangkap yang paling kerap menggigit pembangun CFML. Corak application.view = new View() sangat biasa kerana ia menjimatkan masa: anda mencipta komponen sekali sahaja semasa aplikasi dimulakan dan menggunakannya semula pada setiap permintaan. Tetapi corak yang sama ini yang menyebabkan perubahan tidak kelihatan.

Sebaik sahaja tika View disimpan dalam skop application, ia kekal sebagai objek kelas lama sehingga aplikasi dimulakan semula dan tika baharu dicipta. Untuk memahami mengapa skop ini bertahan merentas permintaan, baca panduan skop CFML. Menyunting fail .cfc, memanggil semula halaman, malah mencipta tika baharu di tempat lain, tidak mengubah tika yang sudah tersimpan itu. Peraturan mudahnya: jika anda menyimpan tika komponen dalam skop application, sebarang perubahan pada komponen itu memerlukan mulakan semula aplikasi, atau reka bentuk yang tidak menyimpan tika lama.

Kenapa reinit kadang-kadang tidak cukup

Pembaca mungkin berfikir penyelesaiannya ialah menyentuh Application.cfc atau memanggil reinit untuk menjana semula skop application. Itu benar untuk sebahagian kes, tetapi bukan semua, dan kami ada bukti daripada projek ini sendiri. Dalam projek laman ini, kami menambah kaedah baharu loginUrl() pada satu komponen yang sudah disimpan dalam skop application. Menyentuh Application.cfc dan memaksa reinit tidak menjadikan loginUrl() dikenali. Kaedah itu terus membalas ralat sehinggalah runtime dimulakan semula sepenuhnya.

Puncanya ialah kelas yang sudah dimuatkan ke dalam JVM dan cache kod terkompil di peringkat enjin, bukan sekadar skop application. Reinit membina semula skop application, tetapi kelas lama mungkin masih dipegang oleh page pool atau oleh rujukan lain, jadi tika baharu pun boleh mengambil kelas lama. Apabila ini berlaku, langkah yang berkesan ialah flush cache kod terkompil, atau mulakan semula enjin.

this.compileExtensions dan sambungan yang dikompil

Application.cfc membenarkan anda mengawal sambungan fail yang Lucee anggap sebagai kod CFML melalui this.compileExtensions. Secara lalai Lucee mengkompil sambungan cfm, cfml dan cfc. Jika projek anda menggunakan sambungan lain, atau anda mahu mengehadkan kompil kepada sambungan tertentu sahaja, tetapkan nilai ini secara eksplisit.

component {
    this.name = "kedai";
    this.compileExtensions = "cfm,cfc";
}

Ini berguna apabila direktori projek bercampur fail CFML dengan fail teks lain. Menyempitkan senarai mengelakkan Lucee membuang masa cuba mengkompil fail yang bukan kod. Ingat bahawa sambungan di luar senarai ini tidak akan dihantar melalui pengkompil, jadi fail itu dihidangkan sebagai statik atau tidak dihidangkan langsung bergantung pada konfigurasi pelayan web di hadapannya. Ini satu daripada banyak tetapan yang boleh anda kawal dalam Application.cfc.

Tetapan cache dalam Lucee Admin

Pentadbir Lucee menyediakan tetapan "Inspect templates (CFM/CFC)" di bawah bahagian Performance atau Caching, dengan tiga nilai yang menentukan seberapa kerap Lucee menyemak perubahan fail. Nilai "Never" bermaksud Lucee tidak pernah menyemak perubahan, paling pantas tetapi memerlukan anda flush cache secara manual selepas setiap deploy. Nilai "Once" menyemak setiap templat sekali bagi setiap permintaan, keseimbangan yang baik untuk kebanyakan laman. Nilai "Always" menyemak setiap templat pada setiap permintaan, sesuai untuk pembangunan tetapi paling perlahan dan patut dielakkan dalam produksi.

Bahagian yang sama juga memaparkan bilangan item dalam Template Cache dan Query Cache, dengan butang untuk membuang isi cache tersebut. Untuk gambaran menyeluruh strategi caching dalam Lucee, baca panduan caching dan prestasi. Flush Template Cache memaksa Lucee menyemak semula fail yang berubah, manakala Query Cache mengosongkan hasil query yang di-cache. Selepas flush, jangan terkejut jika beberapa templat muncul semula dalam cache: templat yang dipanggil untuk memproses permintaan flush itu sendiri akan masuk semula ke dalam cache.

inspectTemplates(), pagePoolClear() dan flush manual

Dua fungsi ini wujud sebagai fungsi global dalam Lucee dan boleh dipanggil terus daripada kod. inspectTemplates() menandakan semua kod CFML dalam cache kod terkompil untuk disemak sekali bagi perubahan, iaitu cara programatik untuk memaksa Lucee mengesan fail yang berubah tanpa membuka pentadbir. pagePoolClear() mengosongkan page pool, memaksa Lucee mengkompil semula templat pada permintaan seterusnya.

inspectTemplates();
pagePoolClear();

Kedua-duanya kami jalankan dalam rig dan kedua-duanya memulangkan nilai benar. Satu perkara yang perlu dinyatakan dengan jujur: clearTemplateCache() tidak wujud sebagai fungsi global dalam versi enjin ini, walaupun namanya kedengaran seperti yang anda cari. Gunakan inspectTemplates() dan pagePoolClear() sebaliknya, atau butang flush dalam pentadbir.

Gejala, punca dan tindakan

Jadual berikut mengumpulkan gejala yang paling biasa dengan punca dan tindakan yang sepadan.

GejalaPuncaTindakan
Perubahan tidak berkuat kuasa selepas suntingCache templat basi atau "Inspect templates" ditetapkan kepada NeverTetapkan "Inspect templates" kepada Once, atau panggil inspectTemplates()
Halaman kosong dengan status 200Templat dikompil tetapi versi dalam page pool kosong atau basiFlush Template Cache, kemudian muat semula halaman
Ralat 500 selepas menyunting failRalat kompil dalam fail yang baru disunting, bukan cache basiBaca mesej ralat, baiki sintaks, kemudian flush cache
Kelas CFC lama masih digunakanTika disimpan dalam skop application memegang kelas lamaMulakan semula aplikasi atau jangan simpan tika lama dalam application

Pola yang paling mudah diingati ialah: ralat 500 selepas sunting biasanya pepijat dalam kod anda, manakala perubahan yang tidak muncul tanpa ralat biasanya masalah cache basi. Bezakan kedua-duanya sebelum membaiki sesuatu yang tidak rosak.

Soalan Lazim

Kenapa perubahan .cfm saya tidak berkuat kuasa?

Kemungkinan besar tetapan "Inspect templates" dalam Lucee Admin ditetapkan kepada Never, jadi Lucee tidak menyemak perubahan fail. Tetapkan kepada Once atau panggil inspectTemplates() untuk memaksa semakan.

Kenapa kelas CFC lama masih digunakan selepas saya sunting fail .cfc?

Tika komponen yang sudah wujud dalam memori, contohnya yang disimpan dalam skop application, terikat kepada kelas lama. Fail .cfc yang disunting hanya memberi kesan kepada tika yang dicipta selepas itu, bukan tika yang sudah wujud.

Apa bezanya inspectTemplates() dengan pagePoolClear()?

inspectTemplates() menandakan kod dalam cache untuk disemak sekali bagi perubahan, manakala pagePoolClear() mengosongkan page pool sepenuhnya supaya templat dikompil semula pada permintaan seterusnya.

Apakah tetapan "Inspect templates" yang sesuai untuk produksi?

Guna Never untuk prestasi terbaik jika templat jarang berubah dan anda flush cache selepas setiap deploy, atau Once untuk keseimbangan yang selamat. Elakkan Always dalam produksi kerana ia menambah beban pada setiap permintaan.

Bagaimana cara memaksa perubahan dikenali tanpa memulakan semula pelayan?

Panggil inspectTemplates() untuk menyemak perubahan, pagePoolClear() untuk mengosongkan page pool, atau gunakan butang flush Template Cache dalam Lucee Admin. Untuk tika yang tersimpan dalam skop application, anda masih perlu mencipta tika baharu.

Sumber

0 komen

0 komen

Log masuk untuk menjawab atau memberi komen.

Log masuk