Artikel
Gunakan front-end murni untuk membuat blog multibahasa "dinamis + artikel".
Saya membuat situs web saya menjadi blog multi-bahasa "dinamis + artikel": konten dikelola dengan Markdown, terjemahan selesai saat posting, halaman statis dibuat selama konstruksi, dan browser bertanggung jawab untuk membaca dan mengganti bahasa. Artikel ini menguraikan model konten, saluran bersama, trade-off antara pemuatan on-demand dan SEO, dan apa sebenarnya yang disimpan oleh front-end murni.
· 8 menit baca
Saya berharap website saya dapat digunakan untuk menuliskan satu paragraf pemikiran, atau untuk menuliskan suatu permasalahan teknis secara lengkap dengan jelas. Cantumkan "dinamika" di bagian pendek dan "artikel" di bagian panjang. Keduanya dapat dihubungkan satu sama lain, dan ketika pengunjung berganti bahasa, kontennya juga harus tertukar secara bersamaan.
Persyaratan ini tampaknya sangat biasa, tetapi jika Anda menambahkan database, backend, dan API konten dari awal, lalu menangani versi setiap bahasa, itu akan segera menjadi produk lain yang memerlukan pemeliharaan jangka panjang.
Saya memilih untuk mempersempit persyaratan terlebih dahulu menjadi apa yang benar-benar dapat saya gunakan: **Satu penulis, masukkan konten ke Git, dan bangun kembali situs web setelah dipublikasikan. Pembaca hanya membutuhkan file statis dan browser. ** Ini adalah struktur "dinamis + artikel" saat ini di stephen.taipei.
Front-end murni mengacu pada bagian membaca#
Mari kita perjelas batasannya terlebih dahulu. Proyek ini menggunakan React, Vite dan Tailwind. Node.js masih diperlukan untuk pemrosesan konten, konversi gambar, dan pembuatan skrip; terjemahan juga akan menghubungi layanan eksternal selama tahap penerbitan. Setelah penerapan, file statis disediakan oleh Nginx.
Jadi yang saya maksud dengan front-end murni adalah ketika pembaca membuka website, mereka tidak memerlukan back-end Blog khusus untuk mencari informasi, mengelompokkan halaman, atau menerjemahkan secara real time. Ia memiliki proses pembangunan dan host, tetapi tidak ada API aplikasi atau database yang persisten untuk membaca artikel.
Jika pekerjaan dilakukan terlebih dahulu, maka pembacaan akhir akan jauh lebih mudah.
Berita dan artikel berbagi sumber yang sama, masing-masing memiliki modelnya sendiri#
Kontennya terkonsentrasi di content/, dan teks aslinya semuanya Penurunan harga. Kedua konten tersebut tidak dimasukkan ke dalam format yang sama:
content/
tags.yaml
tags.locales.yaml
notes/2026/20261004-0944.md
notes/2026/20261004-0944.locales.yaml
articles/frontend-only-multilingual-blog/
index.md
locales.yaml
cover.webp
Dinamika adalah kartu pendek. Nama file menggunakan menit waktu Taipei sebagai ID. Bisa ditandai dengan ide, pembelajaran, online, menyontek atau membaca. Hal ini dapat dilakukan hanya dengan menulis satu paragraf tanpa harus memikirkan judul setiap saat. Pengingat akan muncul jika melebihi 500 kata, dan harus diubah menjadi artikel jika melebihi 1.000 kata.
Artikel memiliki slug, judul, abstrak, tanggal yang tetap, dan juga dapat memiliki sampul dan waktu pembaruan. URL tidak akan diubah setelah dipublikasikan untuk mencegah tautan asli yang dibagikan menjadi tidak valid.
Keduanya dihubungkan menggunakan article:. Untuk pembaruan, Anda dapat menuliskan pertanyaannya terlebih dahulu lalu menautkan ke artikel lengkapnya; halaman artikel akan mencantumkan pembaruan yang merujuknya secara terbalik. Konten pendek mempertahankan titik awal saat ini, dan konten panjang bertanggung jawab untuk menyelesaikan derivasi. Tidak perlu memposting teks lengkap yang sama di kedua sisi.
Biarkan aturan konten memblokir kesalahan sebelum membuat#
Jika Markdown hanya dimasukkan ke dalam gambaran, banyak masalah yang tidak akan terlihat sampai setelah ditayangkan: tanggal yang salah, artikel yang tidak berhubungan, gambar tanpa alts, atau topik yang sama ditulis dengan tiga tag serupa.
Saya memasukkan aturan ini ke dalam saluran konten bersama. loadContent Baca file, periksa kolom dengan Zod, lalu proses Penurunan harga, gambar, bahasa, dan hubungan konten. Inspeksi CLI dan konstruksi Vite menggunakan jalur pipa ini untuk mengurangi kesenjangan antara "mesin lokal mengatakan berfungsi, tetapi lingkungan resmi tidak".
Tag hanya menerima tags.yaml kunci terdaftar; artikel yang diacu secara dinamis dan dinamika lainnya harus ada; pratinjau lokal dapat membaca draf, dan versi resmi akan mengecualikan draf. Aturan ini tidak didasarkan pada mengingatnya saat memposting, tetapi aturan tersebut benar-benar menghalangi inspeksi.
Markdown juga memiliki batas keluaran yang jelas: raw HTML tidak langsung dikeluarkan, HTML yang dihasilkan dibersihkan, dan blok kode diberi sorotan saat build. Gambar konten yang dirujuk melalui jalur relatif lokal dikonversi ke WebP dengan lebar maksimum 1600px, lalu metadata EXIF, termasuk data GPS, dihapus. Artikel, kartu, dan pratinjau berbagi menggunakan gambar yang sudah diproses. Gambar jarak jauh dan gambar yang dirujuk melalui jalur absolut dari root tidak melalui proses konversi lokal ini.
Biaya sistem multibahasa akan dibayarkan saat artikel diterbitkan.#
Situs web saat ini mendukung 22 bahasa. Teks asli Tiongkok Tradisional ditulis satu kali, dan judul, abstrak, teks, dan deskripsi gambar dari 21 bahasa lainnya disimpan di locales.yaml di sebelahnya.
Inilah keputusan yang saya pedulikan: **Pembaca tidak perlu menunggu terjemahan. ** content:localize Hasilkan terjemahan saat memposting. Versi resmi hanya membaca file yang ada dan tidak memanggil layanan terjemahan lagi setiap kali disebarkan.
Gunakan intisari sumber untuk membandingkan teks asli dan teks terjemahan. Jika teks aslinya diubah, terjemahan lama tidak lagi dapat dianggap sebagai versi terbaru; jika satu rumpun bahasa hilang atau terjemahannya kedaluwarsa, content:check akan gagal. Proses penerjemahan melindungi kode, kode sebaris, dan target tautan dari penerjemahan pengidentifikasi teknis atau URL.
Ini tidak berarti terjemahan otomatis mempunyai kualitas penyuntingan manusia. Ini membahas kelengkapan dan konsistensi yang diperbarui, dan bahasa serta nada profesional masih memerlukan koreksi. Teks asli yang belum diubah akan mempertahankan terjemahan yang ada, dan teks yang dimodifikasi secara manual tidak akan ditimpa dengan menjalankannya kembali.
Baca abstrak dalam daftar, klik untuk memuat artikel#
Setelah konten ditingkatkan, jika beranda memuat teks lengkap setiap artikel dan setiap rumpun bahasa, front-end murni akan sangat lambat.
Vite plugin membagi konten menjadi tiga titik masuk: virtual:content/latest untuk beranda, virtual:content/index untuk halaman konten, dan virtual:content/article/<slug> tersendiri untuk setiap artikel. Beranda menampilkan tiga catatan terbaru dan tiga kartu artikel. Data catatan tetap memuat teks lengkap beserta terjemahannya; kartu hanya memotong bagian yang ditampilkan. Kartu artikel panjang hanya membawa ringkasan dan data terkait, sedangkan isi lengkap dimuat per artikel melalui dynamic import.
Suspense React bertanggung jawab untuk menunggu teks, dan batas kesalahan luar bertanggung jawab untuk menampilkan pesan kegagalan pemuatan. Ketika permintaan teks gagal, judul, abstrak, dan navigasi halaman tetap ada.
Ada juga trade-off di sini: saat ini, ada satu potongan teks per artikel, yang berisi terjemahan setiap rumpun bahasa, dan belum dipecah menjadi satu potongan per rumpun bahasa. Teks lengkap dan terjemahan dinamis dimasukkan ke dalam indeks konten. Ketika volume konten terus meningkat, ukuran indeks dan jumlah unduhan teks multibahasa adalah langkah selanjutnya yang harus diukur.
Harus ada peralihan front-end dan pintu masuk untuk pembacaan statis.#
Kami hanya melakukan SPA, dan ketika kami membagikannya, seringkali kami hanya melihat judul dan gambar di halaman beranda. Ini tidak cukup untuk artikel ini.
Oleh karena itu, saat menyiapkan, setiap URL dinamis, artikel, dan tag memiliki shell HTML sendiri, yang berisi judul, deskripsi, kanonik, Grafik Terbuka, dan JSON-LD, dan teks asli yang dapat dibaca ditempatkan di noscript. Anda bisa mendapatkan konten dan sampul eksklusif artikel ini tanpa menjalankan JavaScript.
Konten yang sama juga akan menghasilkan feed.xml, sitemap-content.xml, versi penurunan harga artikel, dan indeks artikel untuk llms.txt. Ini adalah produk buatan, bukan kumpulan konten lain yang memerlukan sinkronisasi manual.
Namun, batasan SEO multibahasa juga harus diperjelas: **Saat ini, pembaruan dan artikel berbagi URL yang sama dalam setiap bahasa, dan bahasanya dialihkan di bagian depan; halaman konten statis, feed, dan versi penurunan harga mempertahankan teks aslinya. ** Beranda juga memiliki pra-render untuk bahasa dan mode terang dan gelap. Hal ini tidak berarti bahwa setiap artikel juga mempunyai 22 halaman bahasa yang dapat diindeks secara independen.
Jika Anda perlu mengizinkan setiap rumpun bahasa untuk disertakan oleh mesin pencari di masa mendatang, Anda perlu menambahkan perutean rumpun bahasa, halaman statis yang sesuai, dan hreflang. Itu adalah persyaratan lain yang belum dipenuhi oleh set ini.
Posting juga merupakan proses pengiriman#
Proses penerbitan saya adalah: menulis teks asli, membuat terjemahan, memeriksa konten, mengirimkan ke Git, lalu menggabungkannya menjadi main. Tindakan GitHub yang ada akan membangun kembali situs web dan menerapkannya.
npm run content:localize
npm run content:check
npm run test:content
npm run build
Jika semua bahasa belum tersedia, saya melengkapi terjemahan yang kurang terlebih dahulu. Artikel yang masih berupa draf tetap berada di pratinjau lokal. Keluaran produksi juga memeriksa bahwa halaman draf tidak ada, lalu memindai artefak publik utama seperti feed, sitemap, beranda, dan bundle JavaScript untuk mencari penanda draf. Seperti kode, konten memiliki diff dan riwayat versi, serta dapat dikembalikan bersama-sama.
Metode ini mengorbankan pembaruan waktu nyata: jika Anda mengubah teks, Anda harus menunggu penerapan. Namun untuk situs web teknis saya, saya bersedia menukarkan penantian ini dengan imbalan satu backend yang lebih sedikit, ketergantungan periode eksekusi yang lebih sedikit, dan catatan perubahan yang lebih mudah dilacak.
Kapan waktu yang tepat untuk melakukan hal ini?#
Jika Anda seorang penulis, frekuensi posting dapat direkonstruksi, kontennya sebagian besar berupa teks, dan Anda terbiasa dengan Git, arsitektur ini sangat cocok. Pembaruan singkat menurunkan ambang batas penulisan, artikel mempertahankan derivasi lengkap, dan multi-bahasa memungkinkan konten yang sama dibaca oleh lebih banyak orang.
Jika persyaratannya berupa kolaborasi real-time antara banyak orang, manajemen izin, komentar pembaca, login atau berlangganan, maka CMS dan backend perlu dievaluasi ulang. Front-end murni tidak akan menghilangkan kebutuhan ini secara otomatis, tetapi saya belum memasukkannya ke dalam cakupan blog ini saat ini.
Prinsip desain kali ini sangat mirip dengan apa yang saya tulis di Pola desain arsitektur untuk banyak layout dan banyak tema: pertama pisahkan tanggung jawab dengan jelas, lalu biarkan aturan bersama menjaga konsistensi.
Untuk website ini, poin kuncinya adalah memungkinkan saya untuk terus menulis dan mengetahui konten apa yang sebenarnya dikirimkan setiap kali saya mempublikasikannya.