摘要:回到純靜態(tài)頁面開發(fā)階段,讓頁面不需要后端渲染也能跑起來。改造開始本文著重介紹如何將靜態(tài)頁面改造成后端渲染需要的模板。總結(jié)在后端渲染的項目里使用多頁應(yīng)用架構(gòu)是絕對可行的,可不要給老頑固們嚇唬得又回到傳統(tǒng)前端架構(gòu)了。
本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。前言
原文地址:https://segmentfault.com/a/1190000008203380
如果您對本系列文章感興趣,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang
近年來前端領(lǐng)域發(fā)展迅猛,前后端分離早已成為業(yè)界共識,各類管控系統(tǒng)(to B)上個SPA什么的也不值一提,但唯獨(dú)偏展示類的項目,為了SEO,始終還是需要依賴于服務(wù)器端渲染html。
我過往也曾嘗試為SPA彌補(bǔ)SEO,但現(xiàn)在看來,效果雖然達(dá)到了,但工作量也大大地增加(因為后端用的PHP,不能做到前后同構(gòu))。
雖然無法改變依賴服務(wù)器端渲染這一現(xiàn)實(shí),但我們可以去勇敢地?fù)肀们岸说膱源?aka webpack),把服務(wù)器端模板層給啃下來!
前導(dǎo)知識webpack的基本使用
利用webpack生成HTML文件,及,構(gòu)建模板布局系統(tǒng)
你所在項目后端模板引擎(如我目前使用的Slim框架,模板引擎僅為原生PHP)
兩個階段整個前端項目,以本文主題的視角來看,可以分為兩個階段:
純靜態(tài)頁面開發(fā)階段在這個階段里,一切開發(fā)都跟靜態(tài)網(wǎng)站無二致,按UI稿切好頁面搞好交互,要用到ajax請求API的也盡管寫,跟后端的協(xié)作點(diǎn)僅在于API文檔。
傳統(tǒng)前端的工作也就到這里為止了,但對我們來說,目前的成果并不是我們最終的交付;因此,注意了,在這個階段我們是可以“偷懶”的,比如說,一些明顯應(yīng)該由服務(wù)器端循環(huán)生成的部分(商品列表、文章列表等),我們寫一遍就OK了。
動態(tài)頁面改造階段這就是所謂的“套頁面”,傳統(tǒng)來說是由后端來做的,實(shí)際上后端也是苦不堪言,畢竟模板不是自己寫的,有時還是需要改造一番,而這正是我們前端要大力爭取的活。
在這個階段里,我們的主要工作是按照后端模板引擎的規(guī)則來撰寫模板變量占位符,當(dāng)然這里面也不會少了循環(huán)輸出和邏輯判斷,另外也可能需要用到后端定義的一些函數(shù),視項目需求而定。
在兩個階段里來回往返這兩個階段不一定是完全獨(dú)立的,有需要的話也是可以做到來回往返的。
那什么時候才叫做“有需要”呢?舉個例子,當(dāng)你把原先的靜態(tài)頁面都改造成需要后端渲染的頁面模板后,卻發(fā)現(xiàn)后端此時并未準(zhǔn)備好相應(yīng)的模板變量,而你此時又需要對頁面的UI部分進(jìn)行修改,那么你就很被動了,因為改好的這些頁面模板根本跑不起來了。有兩種解決方案:
參考API mock的思路,來個模板變量 mock,這就相當(dāng)于一直留在動態(tài)頁面改造階段了。
回到純靜態(tài)頁面開發(fā)階段,讓頁面不需要后端渲染也能跑起來。具體怎么做呢?
區(qū)分開兩個階段,使用不同的webpack配置。
在我們構(gòu)建生成頁面的前端模板(注意分清與后端模板的區(qū)別),判斷(判斷依據(jù)看這里)本次執(zhí)行webpack打包是在哪個“階段”,繼而選擇是生成靜態(tài)(且完整)的element,還是帶有模板變量占位符的element。這樣一來,我們就可以隨時選擇在不同的階段(或稱環(huán)境)里進(jìn)行開發(fā)了。
改造開始本文著重介紹如何將靜態(tài)頁面改造成后端渲染需要的模板。
配合后端模板命名規(guī)則生成相應(yīng)模板文件不同項目因應(yīng)本身所使用的后端框架或是其它需求,對模板放置的目錄結(jié)構(gòu)也會有所不一樣,那么,如何構(gòu)建后端所需要的目錄結(jié)構(gòu)呢?
在靜態(tài)網(wǎng)頁階段,我習(xí)慣把html/css/js都按照所屬頁面歸到各自的目錄中(公用的css/js也當(dāng)然是放到公用目錄中),看HtmlWebpackPlugin配置:
pageArr.forEach((page) => { const htmlPlugin = new HtmlWebpackPlugin({ filename: `${page}/index.html`, // page變量形如"product/index"、"product/detail" template: path.resolve(dirVars.pagesDir, `./${page}/html.js`), chunks: [page, "commons/commons"], hash: true, xhtml: true, }); pluginsConfig.push(htmlPlugin); });
而在改造階段,則放到后端指定位置:
pageArr.forEach((page) => { const htmlPlugin = new HtmlWebpackPlugin({ filename: `../../view/frontend/${page}.php`, // 通過控制相對路徑來確定模板的根目錄 template: path.resolve(dirVars.pagesDir, `./${page}/html.js`), chunks: [page, "commons/commons"], hash: true, xhtml: true, }); pluginsConfig.push(htmlPlugin); });
此時我模板目錄結(jié)構(gòu)是這樣的:
│ ├─alert │ index.php │ ├─article │ detail.php │ index.php │ ├─index │ index.php │ ├─product │ detail.php │ index.php │ └─user edit-password.php modify-info.php
這里需要注意的是,我的前端項目目錄實(shí)際上是作為后端目錄里的一個子目錄來存放的,這樣才能依靠相對路徑來確定模板文件存放的根目錄位置。
處理站內(nèi)鏈接對于站內(nèi)鏈接,我建議在前端模板里使用一個函數(shù)來適配兩個階段:
{ /* 拼接系統(tǒng)內(nèi)部的URL */ constructInsideUrl(url, request, urlTail) { urlTail = urlTail || ""; let finalUrl = config.PAGE_ROOT_PATH + url; if (!config.IS_PRODUCTION_MODE) { finalUrl += "/index.html" + urlTail; return finalUrl; } return ` "${url}"), $isStaticize)?>`; }, };
在前端模板里這么用:
"> ">
這樣做,就能分別在靜態(tài)頁面階段和后端渲染階段生成相應(yīng)的超鏈接。再者,在后端渲染階段,我們生成出來的也不一定是一個完整的url,可以像我上述代碼一樣,生成調(diào)用后端函數(shù)的模板代碼,從而靈活滿足后端的一些需求(比如說,我的項目有靜態(tài)化的需求,那么,靜態(tài)化后的站內(nèi)鏈接跟動態(tài)渲染的又會有所不同了)。
處理模板變量這一塊其實(shí)我要說的不多,無非就是按照后端模板引擎的規(guī)則,輸出變量、循環(huán)輸出變量、判斷條件輸出變量、調(diào)用后端(模板引擎)函數(shù)調(diào)整輸出變量。
關(guān)鍵是,我們需要拿到一份模板變量文檔,跟API文檔類似,它實(shí)際上也是一份前后端的數(shù)據(jù)協(xié)議。有了這份文檔,我們才能在后端未完工的情況下,進(jìn)入動態(tài)頁面改造階段,并根據(jù)其中內(nèi)容實(shí)現(xiàn)模板變量 mock。
爭討模板布局渲染權(quán)關(guān)于利用模板布局系統(tǒng)對多個頁面共有的部分實(shí)現(xiàn)復(fù)用,在之前的文章里已經(jīng)提及了,我設(shè)計該系統(tǒng)的思路恰恰是來自于后端模板渲染。那么,在前后端均可以實(shí)現(xiàn)模板布局系統(tǒng)的前提下,我們應(yīng)如何抉擇呢?我的答案是,前端一定要吃下來!
從前端的角度來看:
我們在純靜態(tài)頁面開發(fā)階段的產(chǎn)物就已經(jīng)是一個個完整的頁面了,再要拆開并不現(xiàn)實(shí)。
由于在webpack的輔助下這套模板布局系統(tǒng)功能相當(dāng)強(qiáng)大,因此并沒有給整個項目添加額外的成本。
從后端的角度來看:
服務(wù)器拼接多個HTML代碼段本身也是有成本(比如磁盤IO成本)的,倒不如渲染一個完整的頁面。
在公共組件的分治管理上不會有很大變化,只不過以前是一個一個組件渲染好后再拼在一起,而現(xiàn)在是把各個組件的數(shù)據(jù)整合在一起來統(tǒng)一渲染罷了。
總結(jié)在后端渲染的項目里使用webpack多頁應(yīng)用架構(gòu)是絕對可行的,可不要給老頑固們嚇唬得又回到傳統(tǒng)前端架構(gòu)了。
示例代碼諸位看本系列文章,搭配我在Github上的腳手架項目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed)。
附系列文章目錄(同步更新)webpack多頁應(yīng)用架構(gòu)系列(一):一步一步解決架構(gòu)痛點(diǎn)
webpack多頁應(yīng)用架構(gòu)系列(二):webpack配置常用部分有哪些?
webpack多頁應(yīng)用架構(gòu)系列(三):怎么打包公共代碼才能避免重復(fù)?
webpack多頁應(yīng)用架構(gòu)系列(四):老式j(luò)Query插件還不能丟,怎么兼容?
webpack多頁應(yīng)用架構(gòu)系列(五):聽說webpack連less/css也能打包?
webpack多頁應(yīng)用架構(gòu)系列(六):聽說webpack連圖片和字體也能打包?
webpack多頁應(yīng)用架構(gòu)系列(七):開發(fā)環(huán)境、生產(chǎn)環(huán)境傻傻分不清楚?
webpack多頁應(yīng)用架構(gòu)系列(八):教練我要寫ES6!webpack怎么整合Babel?
webpack多頁應(yīng)用架構(gòu)系列(九):總有刁民想害朕!ESLint為你阻擊垃圾代碼
webpack多頁應(yīng)用架構(gòu)系列(十):如何打造一個自定義的bootstrap
webpack多頁應(yīng)用架構(gòu)系列(十一):預(yù)打包Dll,實(shí)現(xiàn)webpack音速編譯
webpack多頁應(yīng)用架構(gòu)系列(十二):利用webpack生成HTML普通網(wǎng)頁&頁面模板
webpack多頁應(yīng)用架構(gòu)系列(十三):構(gòu)建一個簡單的模板布局系統(tǒng)
webpack多頁應(yīng)用架構(gòu)系列(十四):No復(fù)制粘貼!多項目共用基礎(chǔ)設(shè)施
webpack多頁應(yīng)用架構(gòu)系列(十五):論前端如何在后端渲染開發(fā)模式下夾縫生存
webpack多頁應(yīng)用架構(gòu)系列(十六):善用瀏覽器緩存,該去則去,該留則留
本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。
原文地址:https://segmentfault.com/a/1190000008203380
如果您對本系列文章感興趣,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/30543.html
摘要:回到純靜態(tài)頁面開發(fā)階段,讓頁面不需要后端渲染也能跑起來。改造開始本文著重介紹如何將靜態(tài)頁面改造成后端渲染需要的模板。總結(jié)在后端渲染的項目里使用多頁應(yīng)用架構(gòu)是絕對可行的,可不要給老頑固們嚇唬得又回到傳統(tǒng)前端架構(gòu)了。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/119000000820338...
摘要:本文首發(fā)于的技術(shù)博客實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址如果您對本系列文章感興趣,歡迎關(guān)注訂閱這里這系列文章講什么本系列文章主要介紹如何用這一當(dāng)前流行的構(gòu)建工具來設(shè)計一個多頁應(yīng)用的架構(gòu)。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190000006843916如果您對本系列文章...
摘要:在上一篇文章多頁應(yīng)用架構(gòu)系列二配置常用部分有哪些中,我介紹了如何配置多頁應(yīng)用的入口,然而,如果僅僅如此操作,帶來的后果就是,打包生成出來的每一個入口文件都會完整包含所有代碼。的初始化常用參數(shù)有哪些,給這個包含公共代碼的命個名唯一標(biāo)識。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190...
摘要:本文首發(fā)于的技術(shù)博客實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。如果你使用了,或類似的,那么,通過編譯前后的代碼相差就很大了,這會造成兩個問題以為例把你的代碼轉(zhuǎn)成什么樣你自己是無法控制的,這往往導(dǎo)致無法通過的審查。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190000007030775如果您...
摘要:徹底分離源文件目錄和生成文件目錄使用生成出來的頁面可以很安心地跟打包好的其它資源放到一起,相對于另起一個目錄專門存放頁面文件來說,整個文件目錄結(jié)構(gòu)更加合理如何利用生成頁面生成頁面主要是通過來實(shí)現(xiàn)的,下面來介紹如何實(shí)現(xiàn)。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/119000000712...
閱讀 3627·2023-04-26 02:32
閱讀 3904·2021-11-23 10:05
閱讀 2291·2021-10-08 10:04
閱讀 2711·2021-09-22 16:06
閱讀 3612·2021-09-22 15:27
閱讀 764·2019-08-30 15:54
閱讀 1698·2019-08-30 13:50
閱讀 2704·2019-08-29 13:56