Mga Artikulo
Gumamit ng purong front-end upang lumikha ng isang "dynamic + article" na multi-lingual na blog
Ginawa ko ang aking website sa isang "dynamic + article" na multi-lingual na blog: ang nilalaman ay pinamamahalaan gamit ang Markdown, ang pagsasalin ay nakumpleto kapag nagpo-post, ang mga static na pahina ay nabuo habang ginagawa, at ang browser ay may pananagutan sa pagbabasa at pagpapalit ng mga wika. Pinaghiwa-hiwalay ng artikulong ito ang modelo ng nilalaman, mga nakabahaging pipeline, mga trade-off sa pagitan ng on-demand na pag-load at SEO, at kung ano ang eksaktong nai-save ng purong front-end.
· 10 minutong basa
Umaasa ako na ang aking website ay magagamit upang isulat ang isang talata ng mga kaisipan, o upang isulat nang malinaw ang isang kumpletong teknikal na isyu. Ilagay ang "dynamics" sa maikli at "artikulo" sa mahaba. Ang dalawa ay maaaring maiugnay sa isa't isa, at kapag ang bisita ay lumipat ng wika, ang nilalaman ay dapat ding ilipat nang magkasama.
Ang pangangailangang ito ay tila napakakaraniwan, ngunit kung magdaragdag ka ng database, backend, at content API mula sa simula, at pagkatapos ay hahawakan ang bersyon ng bawat wika, ito ay malapit nang maging isa pang produkto na nangangailangan ng pangmatagalang pagpapanatili.
Pinili kong paliitin muna ang mga kinakailangan sa kung ano talaga ang magagamit ko: **Isang may-akda, ilagay ang nilalaman sa Git, at muling itayo ang website pagkatapos mai-publish. Ang mambabasa ay nangangailangan lamang ng mga static na file at isang browser. ** Ito ang kasalukuyang istraktura ng "dynamic + article" ng stephen.taipei.
Ang purong front-end ay tumutukoy sa reading end#
Gawin muna nating malinaw ang mga hangganan. Gumagamit ang proyektong ito ng React, Vite at Tailwind. Kinakailangan pa rin ang Node.js para sa pagpoproseso ng nilalaman, conversion ng imahe at paggawa ng script; tatawagan din ng pagsasalin ang mga panlabas na serbisyo sa yugto ng pag-publish. Pagkatapos ng pag-deploy, ang mga static na file ay ibinibigay ng Nginx.
Kaya ang ibig kong sabihin sa purong front-end ay kapag binuksan ng mga mambabasa ang website, hindi nila kailangan ng espesyal na back-end ng Blog para maghanap ng impormasyon, mga pahina ng pangkat o magsalin nang real time. Mayroon itong proseso ng pagbuo at isang host, ngunit walang patuloy na application API o database para sa pagbabasa ng mga artikulo.
Kung ang gawain ay tapos na nang maaga, ang pagtatapos ng pagbabasa ay magiging mas madali.
Ang mga balita at artikulo ay nagbabahagi ng parehong pinagmulan, bawat isa ay may sariling modelo#
Ang nilalaman ay puro sa content/, at ang orihinal na teksto ay Markdown lahat. Ang dalawang nilalaman ay hindi na-shoehorn sa parehong format:
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
Ang dinamika ay mga maikling card. Ginagamit ng pangalan ng file ang minuto ng oras ng Taipei bilang ID. Maaari itong markahan ng mga ideya, pag-aaral, online, pagdaraya o pagbabasa. Maaari itong maitatag sa pamamagitan lamang ng pagsulat ng isang talata nang hindi kinakailangang mag-isip ng pamagat sa bawat oras. May lalabas na paalala kung lumampas ito sa 500 salita, at dapat itong gawing artikulo kung lumampas ito sa 1,000 salita.
Ang mga artikulo ay may nakapirming slug, pamagat, abstract, petsa, at maaari ding magkaroon ng cover at oras ng pag-update. Hindi babaguhin ang URL pagkatapos itong isapubliko upang maiwasang maging di-wasto ang orihinal na nakabahaging link.
Ang dalawa ay magkakaugnay gamit ang article:. Para sa mga update, maaari mong isulat muna ang tanong at pagkatapos ay i-link sa kumpletong artikulo; ililista ng pahina ng artikulo ang mga update na nagre-refer dito sa kabaligtaran. Ang maikling nilalaman ay nagpapanatili sa kasalukuyang panimulang punto, at ang mahabang nilalaman ay responsable para sa pagtatapos ng derivation. Hindi na kailangang mag-post ng parehong buong teksto sa magkabilang panig.
Hayaang harangan ng mga panuntunan ng content ang mga error bago bumuo#
Kung ang Markdown ay itinapon lamang sa larawan, maraming problema ang hindi makikita hanggang matapos itong maging live: mga maling petsa, hindi konektadong mga artikulo, mga larawang walang alts, o ang parehong paksa na isinulat na may tatlong katulad na mga tag.
Inilalagay ko ang mga panuntunang ito sa pipeline ng nakabahaging content. loadContent Basahin ang file, suriin ang mga field gamit ang Zod, at pagkatapos ay iproseso ang Markdown, mga larawan, wika at mga relasyon sa nilalaman. Parehong ginagamit ng CLI inspection at Vite construction ang pipeline na ito upang bawasan ang agwat sa pagitan ng "sabi ng lokal na makina ay gumagana ito, ngunit hindi gumagana ang opisyal na kapaligiran."
Ang tag ay tumatanggap lamang ng tags.yaml nakarehistrong susi; ang mga artikulong may dynamic na isinangguni at iba pang dinamika ay dapat na umiiral; Ang lokal na preview ay maaaring magbasa ng mga draft, at ang opisyal na build ay magbubukod ng mga draft. Ang mga patakarang ito ay hindi batay sa pag-alala sa kanila kapag nagpo-post, ngunit talagang hinaharangan nila ang mga inspeksyon.
May malinaw ding hangganan sa output ng Markdown: hindi direktang inilalabas ang raw HTML, nililinis ang nabuong HTML, at hina-highlight ang mga code block habang nagbu-build. Kino-convert sa WebP na may pinakamataas na lapad na 1600px ang mga content image na tinutukoy gamit ang lokal na relative path, at inaalis ang EXIF metadata, kasama ang GPS data. Iisang naprosesong larawan ang ginagamit ng mga artikulo, card, at preview kapag ibinabahagi. Hindi dumaraan sa lokal na conversion na ito ang mga remote image at larawang tinutukoy gamit ang absolute path mula sa root.
Ang halaga ng multi-lingual system ay babayaran kapag nai-publish ang artikulo.#
Ang website ay kasalukuyang sumusuporta sa 22 wika. Ang orihinal na Tradisyunal na Chinese na teksto ay isinulat nang isang beses, at ang mga pamagat, abstract, teksto at paglalarawan ng larawan ng iba pang 21 wika ay naka-imbak sa locales.yaml sa tabi nito.
Narito ang isang desisyon na mahalaga sa akin: **Ang mga mambabasa ay hindi kailangang maghintay para sa pagsasalin. ** content:localize Bumuo ng mga pagsasalin kapag nagpo-post. Ang opisyal na build ay nagbabasa lamang ng mga umiiral na file at hindi na muling tumatawag sa serbisyo ng pagsasalin sa tuwing ito ay na-deploy.
Gamitin ang source digest upang ihambing ang orihinal na teksto at ang isinalin na teksto. Kung ang orihinal na teksto ay binago, ang lumang pagsasalin ay hindi na maituturing na pinakabagong bersyon; kung ang isang pamilya ng wika ay nawawala o ang pagsasalin ay hindi napapanahon, content:check ay mabibigo. Pinoprotektahan ng proseso ng pagsasalin ang code, inline na code, at mga target ng link mula sa pagsasalin ng mga teknikal na identifier o URL.
Hindi ito nangangahulugan na ang awtomatikong pagsasalin ay may kalidad ng pag-edit ng tao. Tinutugunan nito ang pagkakumpleto at na-update na pagkakapare-pareho, at nangangailangan pa rin ng pag-proofread ang propesyonal na wika at tono. Ang orihinal na teksto na hindi nabago ay mananatili sa kasalukuyang pagsasalin, at ang manu-manong binagong teksto ay hindi mapapatungan ng muling pagpapatakbo.
Basahin ang abstract sa listahan, i-click upang i-load ang artikulo#
Pagkatapos madagdagan ang nilalaman, kung ilo-load ng homepage ang buong teksto ng bawat artikulo at bawat pamilya ng wika, ang dalisay na front-end ay magiging napakabagal.
Hinahati ng Vite plugin ang content sa tatlong entry point: virtual:content/latest para sa homepage, virtual:content/index para sa mga content page, at hiwalay na virtual:content/article/<slug> para sa bawat artikulo. Ipinapakita sa homepage ang tatlong pinakabagong maikling post at tatlong article card. Nasa datos pa rin ng maiikling post ang buong teksto at mga salin; pinuputol lang ang ipinapakita sa card. Buod at kaugnay na datos lang ang laman ng mga card para sa mahahabang artikulo, habang hiwalay na nilo-load ang buong katawan ng bawat artikulo sa pamamagitan ng dynamic import.
Ang Suspense ng React ay may pananagutan sa paghihintay para sa teksto, at ang panlabas na hangganan ng error ay responsable para sa pagpapakita ng mensahe ng pagkabigo sa paglo-load. Kapag nabigo ang kahilingan sa text, mananatili ang pamagat, abstract, at page navigation.
Mayroon ding mga trade-off dito: sa kasalukuyan, mayroong isang tipak ng teksto bawat artikulo, na naglalaman ng mga pagsasalin ng bawat pamilya ng wika, at hindi pa ito nahahati sa isang tipak bawat pamilya ng wika. Ang dinamikong buong teksto at mga pagsasalin ay ipinasok sa index ng nilalaman. Habang patuloy na tumataas ang dami ng nilalaman, ang laki ng index at ang bilang ng mga pag-download ng multilingguwal na teksto ay ang mga susunod na hakbang na susukatin.
Dapat mayroong front-end switching at pasukan para sa static na pagbabasa.#
SPA lang ang ginagawa namin, at kapag ibinahagi namin, madalas sa homepage lang namin makikita ang pamagat at larawan. Ito ay hindi sapat para sa artikulo.
Samakatuwid, kapag nagse-set up, ang bawat dynamic, artikulo at tag na URL ay may sarili nitong HTML shell, na naglalaman ng pamagat, paglalarawan, canonical, Open Graph at JSON-LD, at ang nababasang orihinal na text ay inilalagay sa noscript. Makukuha mo ang nilalaman at eksklusibong pabalat ng artikulong ito nang hindi gumagamit ng JavaScript.
Ang parehong piraso ng nilalaman ay maglalabas din ng feed.xml, sitemap-content.xml, ang Markdown na bersyon ng artikulo, at ang index ng artikulo para sa llms.txt. Ang mga ito ay mga binuong produkto, hindi isa pang hanay ng nilalaman na nangangailangan ng manu-manong pag-synchronize.
Gayunpaman, dapat ding linawin ang mga hangganan ng multilinggwal na SEO: **Sa kasalukuyan, ang mga update at artikulo ay nagbabahagi ng parehong URL sa bawat wika, at ang wika ay inililipat ng front end; Pinapanatili ng mga static na content page, feed, at Markdown na bersyon ang orihinal na text. ** Ang homepage ay mayroon ding pre-rendering para sa wika at light at dark mode. Hindi ito nangangahulugan na ang bawat artikulo ay mayroon ding 22 independiyenteng nai-index na mga pahina ng wika.
Kung kailangan mong payagan ang bawat pamilya ng wika na maisama ng mga search engine sa hinaharap, kakailanganin mong magdagdag ng pagruruta ng pamilya ng wika, kaukulang mga static na pahina at hreflang. Iyon ay isa pang kinakailangan na hindi pa natutupad ng hanay na ito.
Ang pag-post ay isa ring proseso ng paghahatid#
Ang aking proseso sa pag-publish ay: isulat ang orihinal na teksto, buuin ang pagsasalin, suriin ang nilalaman, isumite sa Git, at pagkatapos ay pagsamahin ito sa main. Ang mga kasalukuyang GitHub Actions ay muling bubuo sa website at i-deploy ito.
npm run content:localize
npm run content:check
npm run test:content
npm run build
Kung may mga wikang hindi pa kumpleto ang salin, inaayos ko muna ang mga iyon. Nananatili sa lokal na preview ang mga artikulong draft pa. Tinitiyak din ng production output na walang draft page at sinusuri ang mahahalagang pampublikong output, gaya ng feed, sitemap, homepage, at JavaScript bundle, para sa mga palatandaan ng draft. Gaya ng code, may diff at kasaysayan ng bersyon ang content at maaari itong ibalik kasama nito.
Ang pamamaraang ito ay nagsasakripisyo ng mga real-time na update: kung babaguhin mo ang isang piraso ng text, kailangan mong maghintay para sa isang deployment. Ngunit para sa aking teknikal na website, handa akong ipagpalit ang paghihintay na ito kapalit ng isang mas kaunting backend, isang mas kaunting dependency sa panahon ng pagpapatupad, at isang talaan ng pagbabago na mas madaling subaybayan.
Kailan angkop na gawin ito?#
Kung ikaw ay isang may-akda, ang dalas ng pag-post ay maaaring muling itayo, ang nilalaman ay pangunahing teksto, at ikaw ay sanay sa Git, ang arkitektura na ito ay napaka-angkop. Ang mga maiikling update ay nagpapababa sa threshold sa pagsusulat, pinapanatili ng artikulo ang kumpletong derivation, at pinapayagan ng maraming wika ang parehong nilalaman na mabasa ng mas maraming tao.
Kung ang mga kinakailangan ay naging real-time na pakikipagtulungan sa pagitan ng maraming tao, pamamahala ng pahintulot, komento ng mambabasa, pag-login o subscription, kung gayon ang CMS at backend ay kailangang muling suriin. Ang purong front-end ay hindi awtomatikong mawawala ang mga pangangailangang ito, ngunit hindi ko pa ito inilalagay sa saklaw ng blog na ito sa ngayon.
Ang mga prinsipyo ng disenyo sa pagkakataong ito ay napakalapit sa isinulat ko sa Pattern ng disenyo ng arkitektura para sa maraming layout at theme: hiwalay muna nang malinaw ang mga responsibilidad, at pagkatapos ay hayaang mapanatili ang pagkakapare-pareho ng mga nakabahaging panuntunan.
Para sa website na ito, ang pangunahing punto ay upang payagan akong magpatuloy sa pagsusulat at malaman kung ano talaga ang nilalaman na inihahatid sa tuwing mag-publish ako.