本文首發於 Array_Huang的技術博客——實用至上
,非經做者贊成,請勿轉載。
原文地址: http://www.javashuo.com/article/p-yelsnimv-bq.html
若是您對本系列文章感興趣,歡迎關注訂閱這裏:https://segmentfault.com/blog/array_huang
近年來前端領域發展迅猛,先後端分離早已成爲業界共識,各種管控系統(to B)上個SPA什麼的也不值一提,但惟獨偏展現類的項目,爲了SEO,始終仍是須要依賴於服務器端渲染html。javascript
我過往也曾嘗試爲SPA彌補SEO,但如今看來,效果雖然達到了,但工做量也大大地增長(由於後端用的PHP,不能作到先後同構)。php
雖然沒法改變依賴服務器端渲染這一現實,但咱們能夠去勇敢地擁抱它,用前端的堅船利炮(aka webpack),把服務器端模板層給啃下來!css
整個前端項目,以本文主題的視角來看,能夠分爲兩個階段:html
在這個階段裏,一切開發都跟靜態網站無二致,按UI稿切好頁面搞好交互,要用到ajax請求API的也儘管寫,跟後端的協做點僅在於API文檔。前端
傳統前端的工做也就到這裏爲止了,但對咱們來講,目前的成果並非咱們最終的交付;所以,注意了,在這個階段咱們是能夠「偷懶」的,好比說,一些明顯應該由服務器端循環生成的部分(商品列表、文章列表等),咱們寫一遍就OK了。java
這就是所謂的「套頁面」,傳統來講是由後端來作的,實際上後端也是苦不堪言,畢竟模板不是本身寫的,有時仍是須要改造一番,而這正是咱們前端要大力爭取的活。webpack
在這個階段裏,咱們的主要工做是按照後端模板引擎的規則來撰寫模板變量佔位符,固然這裏面也不會少了循環輸出和邏輯判斷,另外也可能須要用到後端定義的一些函數,視項目需求而定。git
這兩個階段不必定是徹底獨立的,有須要的話也是能夠作到來回往返的。github
那何時才叫作「有須要」呢?舉個例子,當你把原先的靜態頁面都改形成須要後端渲染的頁面模板後,卻發現後端此時並未準備好相應的模板變量,而你此時又須要對頁面的UI部分進行修改,那麼你就很被動了,由於改好的這些頁面模板根本跑不起來了。有兩種解決方案:web
API mock
的思路,來個模板變量 mock
,這就至關於一直留在動態頁面改造階段了。回到純靜態頁面開發階段,讓頁面不須要後端渲染也能跑起來。具體怎麼作呢?
本文着重介紹如何將靜態頁面改形成後端渲染須要的模板。
不一樣項目因應自己所使用的後端框架或是其它需求,對模板放置的目錄結構也會有所不同,那麼,如何構建後端所須要的目錄結構呢?
在靜態網頁階段,我習慣把html/css/js都按照所屬頁面歸到各自的目錄中(公用的css/js也固然是放到公用目錄中),看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); });
此時我模板目錄結構是這樣的:
│ ├─alert │ index.php │ ├─article │ detail.php │ index.php │ ├─index │ index.php │ ├─product │ detail.php │ index.php │ └─user edit-password.php modify-info.php
這裏須要注意的是,個人前端項目目錄其實是做爲後端目錄裏的一個子目錄來存放的,這樣才能依靠相對路徑來肯定模板文件存放的根目錄位置。
對於站內連接,我建議在前端模板裏使用一個函數來適配兩個階段:
{ /* 拼接系統內部的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 `<?php echo cf::constructInsideUrl(array('module' => '${url}'), $isStaticize)?>`; }, };
在前端模板裏這麼用:
<a href="<%= constructInsideUrl('index/index') %>"> <img src="<%= require('./logo.png') %>"> </a>
這樣作,就能分別在靜態頁面階段和後端渲染階段生成相應的超連接。再者,在後端渲染階段,咱們生成出來的也不必定是一個完整的url,能夠像我上述代碼同樣,生成調用後端函數的模板代碼,從而靈活知足後端的一些需求(好比說,個人項目有靜態化的需求,那麼,靜態化後的站內連接跟動態渲染的又會有所不一樣了)。
這一塊其實我要說的很少,無非就是按照後端模板引擎的規則,輸出變量、循環輸出變量、判斷條件輸出變量、調用後端(模板引擎)函數調整輸出變量。
關鍵是,咱們須要拿到一份模板變量文檔,跟API文檔相似,它實際上也是一份先後端的數據協議。有了這份文檔,咱們才能在後端未完工的狀況下,進入動態頁面改造階段,並根據其中內容實現模板變量 mock
。
關於利用模板佈局系統對多個頁面共有的部分實現複用,在以前的文章裏已經說起了,我設計該系統的思路偏偏是來自於後端模板渲染。那麼,在先後端都可以實現模板佈局系統的前提下,咱們應如何抉擇呢?個人答案是,前端必定要吃下來!
從前端的角度來看:
從後端的角度來看:
在後端渲染的項目裏使用webpack多頁應用架構是絕對可行的,可不要給老頑固們嚇唬得又回到傳統前端架構了。
諸位看本系列文章,搭配我在Github上的腳手架項目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed
)。
本文首發於 Array_Huang的技術博客——實用至上
,非經做者贊成,請勿轉載。
原文地址: http://www.javashuo.com/article/p-yelsnimv-bq.html
若是您對本系列文章感興趣,歡迎關注訂閱這裏:https://segmentfault.com/blog/array_huang