細說Vue組件的服務器端渲染的過程
聲明:需要讀者對 NodeJs、Vue 服務器端渲染有一定的了解
現(xiàn)在,前后端分離與客戶端渲染已經(jīng)成為前端開發(fā)的主流模式,絕大部分的前端應用都適合用這種方式來開發(fā),又特別是 React、Vue 等組件技術的發(fā)展,更是使這種方式深入人心。
但有一些應用,客戶端渲染就會遇到一些問題了:
- 需要做 SEO(搜索引擎優(yōu)化),但客戶端渲染的
html中幾乎沒有可用的信息 - 需要首屏快速加載,但客戶端渲染一般是長時間的加載動畫或者白屏
如果能把客戶端渲染的組件化技術(React、Vue 等)與傳統(tǒng)的后端渲染的方式有效的結合起來,兩者兼具,那就太完美了。
所以,這次就來聊聊 Vue 組件的服務器端渲染。
根據(jù)社區(qū)現(xiàn)有的一些方案,結合自己的實踐,針對團隊技術力量的不同,說說不同應用場景選擇方案時的優(yōu)先級。
1. NodeJs 渲染中間層
一般前后端的工作流是 后端 -> 前端。
傳統(tǒng)的后端渲染模式是后端負責包括 url、接口、模板渲染等,前端與后端耦合在一起,當然這種方式正在慢慢的退出歷史舞臺。
主流的客戶端渲染則是后端只提供接口(如有需要,可以提供必要的 url),前端與后端只通過接口交流數(shù)據(jù),路由與渲染都在前端完成。
而 NodeJs 渲染中間層的工作流則是 后端 -> NodeJs -> 前端(NodeJs 渲染中間層由前端開發(fā)人員掌握)。

這種模式下,后端只提供接口,傳統(tǒng)的服務器端路由(url)、模板渲染則都有 NodeJs 層接管。這樣,前端開發(fā)人員可以自由的決定哪些組件需要在服務器端渲染,哪些組件可以放在客戶端渲染,前后端完全解耦,但又保留了服務器端渲染的功能。
這種方案最成熟的是nuxt.js。
如果有需要,大家可以自己去 nuxt.js 官方文檔 看看具體的使用方法和詳細的功能。
應該說,這種方式是目前最完美的一種方案,但也有一些隱患:
- 增加了一個 NodeJs 中間層,應用性能會有所降低
- 增加了架構的復雜度、不穩(wěn)定性,也降低了應用的安全性
- 對于高并發(fā)應用,NodeJs 層會很容易形成瓶頸
- 對開發(fā)人員要求高了很多
所以,這種方式適合對并發(fā)量、安全性、穩(wěn)定性等要求不高,但又需要做 SEO 或首屏快速加載的頁面。
當然,如果你能夠自己改造相關的工具,就另當別論了。
2. 保留后端模板渲染
當不能使用 NodeJs 中間層時,而又要達到 SEO 與首屏快速響應的目的時,在傳統(tǒng)的后端模板渲染的基礎上,就需要對前端的頁面加以適當?shù)母脑臁?/p>
2.1 首屏快速響應
首屏快速響應就意味著首屏渲染所需的數(shù)據(jù)是跟 HTML 文件一起到達瀏覽器的,這些數(shù)據(jù)當前是由后端模板引擎嵌入到 HTML 頁面中的。
以 Java 的 freemarker 模板引擎為例:
(html 中以 script 的方式獲取模板的數(shù)據(jù),這樣就算是在本地調(diào)試、開發(fā),也不會報錯)。
<script>
window.globalData = {
stringValue: '${stringValueTplName}',
intValue: parseInt('${intValueTplName}', 10),
};
</script>
如果是復雜的 Json 數(shù)據(jù)或者其他復雜的模板數(shù)據(jù)(比如列表數(shù)據(jù)),則可以像下面這樣接收:
<script type="text/tpl" id="tpl-script-json">
window.tmpData = {
jsonValue: ${jsonValueTplName},
};
</script>
<script>
try {
eval(document.getElementById('tpl-script-json').innerText);
} catch (e) {
window.tmpData = { jsonValue: {} };
}
window.globalData = {
jsonValue: window.tmpData.jsonValue,
};
</script>
這樣,你就可以在組件里使用 window.globalData 的數(shù)據(jù)了,而不用另外用接口獲取數(shù)據(jù),達到加快首屏渲染的目的,而且本地開發(fā)、調(diào)試也不會報錯。
如果你使用了本地數(shù)據(jù) Mock 功能,也可以很容易的與這種方式結合在一起,只要稍加改造:
- 在代碼中定義本地和服務器兩個環(huán)境,本地環(huán)境使用 Mock 數(shù)據(jù),服務器環(huán)境使用
window.globalData - 可以使用see-ajax, see-fetch 來簡化這種方式的開發(fā)
此外,還有一些措施來進一步加快首屏渲染:
- 盡量減少首屏加載的腳本文件大小,其他腳本可以按需加載
- 如果需要,可以將 CSS、JS 內(nèi)容注入到 HTML 中,這樣就只會發(fā)起一個請求,也可以加快加載速度
2.2 SEO 優(yōu)化
在上面加載首屏渲染的基礎上,對于 SEO 優(yōu)化也可以做相應的改造。
其實,在客戶端渲染已慢慢成為主流開發(fā)模式的同時,搜索引擎也在跟進這種變化。
截至目前,Google 和 Bing 可以很好對同步 JavaScript 應用程序進行索引,也就是說,即使是客戶端渲染,但只要是同步數(shù)據(jù)渲染(非 Ajax 獲取數(shù)據(jù),比如模板數(shù)據(jù)),搜索引擎也能抓取到相應的 HTML 片段。
(國內(nèi)的百度搜索與360搜索等暫時還沒有跟進動態(tài))
但為了兼容所有的搜索引擎,可以像下面改造:
先由后端模板引擎渲染一些 HTML 片段,僅給搜索引擎抓取,不作為給用戶展示的頁面
然后再由客戶端渲染同步或異步的數(shù)據(jù)給用戶展示真正的頁面
<div>
<!-- 這里放置由后端模板引擎渲染的專給搜索引擎抓取的片段,用戶不可見 -->
</div>
<script>
// 接收同步數(shù)據(jù)
window.globalData = {
stringValue: '${stringValueTplName}',
intValue: parseInt('${intValueTplName}', 10),
};
</script>
3. 導出靜態(tài) html
如果頁面沒有動態(tài)數(shù)據(jù),那就好辦了,直接把組件導出為靜態(tài) html,然后由客戶端激活。
具體過程可以參考 官方文檔。
這種方案比較好的是 nuxt.js generate 靜態(tài) HTML 文件。
目錄結構:
- pages/ # 頁面結構目錄 - index.vue - second.vue - ... - nuxt.config.js # 配置文件 - package.json - dist # 導出靜態(tài) HTML 文件的默認目錄
導出靜態(tài) HTML 文件
npx nuxt generate
如果一個項目里有多個 pages,可以這樣構建:
目錄結構:
- nuxt.config.js # 配置文件 - package.json - src/ - home/ # home 頁面 - pages/ # 頁面結構目錄 - index.vue - second.vue - ... - dist # 導出靜態(tài) HTML 文件的默認目錄 - about/ # about 頁面 - pages/ # 頁面結構目錄 - index.vue - second.vue - ... - dist # 導出靜態(tài) HTML 文件的默認目錄
導出靜態(tài) HTML 文件
npx nuxt generate src/home -c ../../nuxt.config.js # home 頁面 npx nuxt generate src/about -c ../../nuxt.config.js # about 頁面
除了上面提到的這些方式外,當然還有其他的方式,比如:
使用 Chrome Headless 模式獲取組件的靜態(tài) HTML,參考 react-snap, puppeteer
官方 vue-server-renderer 導出靜態(tài) HTML
4. 總結
因為模式的改變,服務器端渲染與傳統(tǒng)的后端模板渲染工作方式有很大的不同,所以在開發(fā)時需要與后端開發(fā)人員做好溝通,避免認知上的不同導致協(xié)作不協(xié)調(diào)。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Vue-admin-template?報Uncaught?(in?promise)?error問題及解決
這篇文章主要介紹了Vue-admin-template?報Uncaught?(in?promise)?error問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07
Vue關于element穿梭框進行的修改成table表格穿梭框方式
這篇文章主要介紹了Vue關于element穿梭框進行的修改成table表格穿梭框方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04
基于Ant-design-vue的Modal彈窗 封裝 命令式與Hooks用法
這篇文章主要給大家介紹了基于Ant-design-vue的Modal彈窗封裝命令式與Hooks用法,文中有詳細的代碼示例,具有一定的參考價值,感興趣的同學可以借鑒閱讀2023-06-06
el-table表格點擊該行任意位置時也勾選上其前面的復選框
本文主要介紹了在el-table組件中實現(xiàn)雙擊表格某一行任意位置自動勾選復選框的功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-02-02
解決@vue/cli安裝成功后,運行vue -V報:不是內(nèi)部或外部命令的問題
這篇文章主要介紹了解決@vue/cli安裝成功后,運行vue -V報:不是內(nèi)部或外部命令的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10
Vue-Router實現(xiàn)頁面正在加載特效方法示例
這篇文章主要給大家介紹了利用Vue-Router實現(xiàn)頁面正在加載特效方法示例,文中給出了詳細的示例代碼,相信對大家具有一定的參考價值,有需要的朋友們下面來一起看看吧。2017-02-02

