服務端與客戶端同構——Vue.js 應用框架 Nuxt.js
前言
為了體驗紛紛SPA,為了SEO大家妥協了。最近早讀君遇到跟昨天一個網友跟我分享的情況都很類似,在產品開發前期用了React/Vue框架開發產品,待後續提了要SEO就疼了。今日早讀文章由眾成翻譯@凈化翻譯分享。
正文從這開始~
通用(也稱同構)的JavaScript已經成為JavaScript社區很常用的一個術語。通用的JavaScript用來形容可以在客戶端執行,也可在服務端執行的Javascript 代碼。
很多現代的JavaScript框架,比如Vue.js, 旨在構建單頁應用(SPA)。單頁應用的優勢在於,改善用戶體驗,讓網頁速度更快,像APP一樣流暢,即使更新。雖然單頁應用優點很多,但是由於依賴多導致首屏渲染慢,無法做seo優化也是讓人頭疼的問題。
服務端渲染是指,提前將頁面在伺服器端渲染好,當瀏覽器請求伺服器時,直接返回渲染好的html頁面返回。
構建服務端渲染的JavaScript程序多少有些無趣,在開始編碼之前,需要大量的基礎配置。因此,解決vue.js服務端渲染問題的Nuxt.js產生了。
Nuxt.js 概要
簡而言之,Nuxt.js是幫助Vue.js輕鬆完成服務端渲染工作的框架。Nuxt.js預設了服務端渲染所需要的各種配置,如非同步數據,中間件,路由。它好比是 Angular Universal 之於 Angular, Next.js 之於 React。
如Nuxt.js文檔所說,通過對客戶端/服務端基礎架構的抽象,Nuxt.js 讓開發者專註於頁面的UI渲染。
靜態文件生成器
Nuxt.js的一個重要功能是,通過 generate 命令,生成靜態站點。類似於流行的靜態生成工具Jekyll。
Nuxt.js 內部依賴
除了Vue.js 2.0之外,Nuxt.js集成了如下模塊: Vue-Router, Vue-Meta 和 Vuex (僅在使用 Vuex 狀態樹配置項 時引入)。 這樣的好處在於,不需要手工配置依賴,不需要同時在客戶端和服務端配置相同的庫。 Nuxt.js在包含如上依賴的情況下,總大小仍然保持在 28kb min+gzip (如果使用了 Vuex 特性的話為 31kb)。
另外,Nuxt.js 使用 Webpack 和 vue-loader 、 babel-loader 來處理代碼的自動化構建工作(如打包、代碼分層、壓縮等等)。
工作原理
當你訪問一個基於Nuxt.js構建的頁面時,發生了的事情如下:
當用戶訪問應用程序, 如果store中定義了 nuxtServerInit action,Nuxt.js將調用它更新store。
接下來,將載入即將訪問頁面所依賴的任何中間件。Nuxt首先從nuxt.config.js這個文件中,載入全局依賴的中間件,之後檢測每個相應頁面對應的布局文件 ,最後,檢測布局文件下子組件依賴的中間件。以上是中間件的載入順序。
如果要訪問的路由是一個動態路由, 且有一個相應的 validate() 方法路由的validate 方法,講進行路由校驗。
之後, Nuxt.js 調用 asyncData() 和 fetch() 方法,在渲染頁面之前載入非同步數據。asyncData() 方法用於非同步獲取數據,並將fetch回來的數據,在服務端渲染到頁面。 用fetch() 方法取回的將數據在渲染頁面之前填入store。
最後一步, 將所有數據渲染到頁面。
下圖闡述了 Nuxt.js 應用一個完整的伺服器請求到渲染的流程,摘自官網:
使用 Nuxt.js 創建一個靜態網站
下面讓我們動手創建一個基於Nuxt.js簡單的靜態博客。我們的發送的請求,返回 mock 的JSON數據。
完成下面例子,你需要了解基礎的 vue.js 知識。如果你是個新手,你可以通過Jack Franklin的getting started guide了解 Vue.js 2.0。同時,我將使用ES6語法,你可以參考https://www.sitepoint.com/tag/es6/ 重溫ES6語法。
我們的 Demo 最終效果如下:
GIF/303K
基礎配置
開始使用 Nuxt.js 最簡單的方式是使用 Nuxt.js 團隊自己開發的腳手架。我們可以使用 vue-cli 快速創建我們的項目 (ssr-blog):
`vue init nuxt/starter ssr-blog`
提示: 如果你沒有安裝過vue-cli,請先通過npm install -g vue-cli 命令安裝vue-cli。
之後,我們將安裝項目的依賴:
cd ssr-blog
npm install
現在我們啟動程序:
`npm run dev`
如果正確啟動, 你能訪問 http://localhost:3000 ,展示的頁面是 Nuxt.js 模板的初始頁面。你也可以通過查看頁面源代碼,驗證頁面所展示的一切內容,都是服務端渲染好的。
// ./nuxt.config.js
module.exports={
/*
* Headers of the page
*/
head:{
titleTemplate: %s | Awesome JS SSR Blog ,
// ...
link:[
// ...
{
rel: stylesheet ,
href: https://cdnjs.cloudflare.com/ajax/libs/bulma/0.4.2/css/bulma.min.css
}
]
},
// ...
}
在如上配置文件下,我們使用 titleTemplate 欄位 title 變數指定文章題目,在渲染之前用title變數值替換掉%s這個佔位,填充到titleTemplate 。
同時,我也使用了 CSS 框架, Bulma, 預設一些樣式。通過 link 配置項。
提示: Nuxt.js使用 vue-meta 更新我們的 html headers 信息。所以,我們可以看看 meta 具體的配置項,優化頁面 html 信息。
現在,我們可以通過幾個步驟,完成博客的頁面和功能。
使用 Layouts
首先,我們將為我們所有的頁面定義一個通用的基本布局。我們通過修改 layouts/default.vue 文件,更新 main Nuxt.js layout:
Awesome JS SSR Blog!
Home
About
在我們通用的布局裡,我們僅僅對頁面添加導航欄,我們通過 component進一步完成具體頁面模塊的定製。你可以查看components-nuxt-link 進一步了解。
在創建布局時component非常重要,它決定具體頁面展示的元素。
當然,component也可以做更多事情,比如定義通用組件和錯誤頁面,但是我們的博客很簡單,不需要這些功能。強烈建議閱讀 Nuxt.js documentation on views ,你可以通過這篇文章了解更多 Nuxt.js 特性。
簡單的頁面和路由
Nuxt.js 頁面是以 單文件組件 形式組織目錄結構。 Nuxt.js 自動找到目錄下每個 .vue 文件,並添加到頁面中。
創建博客主頁
我們可以通過修改 index.vue 文件修改主頁, 通過 Nuxt.js 創建的文件如下:
Welcome to the JavaScript SSR Blog.
Hope you find something you like.
exportdefault{
head:{
title: Home
}
}
如前所述,在渲染之前,題目將自動填充至文件。
我們現在可以刷新頁面,看看主頁的變化。
創建 About 頁面
Nuxt.js 還有一個優秀的特性,監聽文件夾下文件的更改,所以,在文件更改時,不需要重啟應用更新。
來,我們添加一個簡單的 about.vue 頁面:
Aboutthiswebsite.
Curabitur accumsan turpis pharetraaugue tinciduntblandit.Quisque condimentum maximus mi,sit amet commodo arcu rutrum id.Proin pretium urna vel cursus venenatis.Suspendisse potenti.Etiam mattis sem rhoncus lacus dapibus facilisis.Donec at dignissim dui.Ut et neque nisl.
What we hope to achieve:
In fermentum leo eu lectus mollis,quis dictum mi aliquet.
Morbi eu nulla lobortis,lobortis estin,fringilla felis.
Aliquam nec felisinsapien venenatis viverra fermentum nec lectus.
Ut non enim metus.
exportdefault{
head:{
title: About
}
}
現在我們訪問 http://localhost:3000/about 看看about頁面,無需重啟,非常方便。
在主頁展示文章列表
我們的首頁在沒有內容的時候展示如上, 所以下一步,我們要在 index.vue 上添加博客列表這個組件。
首先,我們需要把 JSON 格式的文章保存在服務根目錄下。文件可以從 這裡下載,或者你可以複製下面的 JSON 到根目錄文件夾 posts.json 下:
[
{
"id":4,
"title":"Building universal JS apps with Nuxt.js",
"summary":"Get introduced to Nuxt.js, and build great SSR Apps with Vue.js.",
"content":"
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
",
"author":"Jane Doe",
"published":"08:00 - 07/06/2017"
},
{
"id":3,
"title":"Great SSR Use cases",
"summary":"See simple and rich server rendered JavaScript apps.",
"content":"
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
",
"author":"Jane Doe",
"published":"17:00 - 06/06/2017"
},
{
"id":2,
"title":"SSR in Vue.js",
"summary":"Learn about SSR in Vue.js, and where Nuxt.js can make it all faster.",
"content":"
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
",
"author":"Jane Doe",
"published":"13:00 - 06/06/2017"
},
{
"id":1,
"title":"Introduction to SSR",
"summary":"Learn about SSR in JavaScript and how it can be super cool.",
"content":"
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
",
"author":"John Doe",
"published":"11:00 - 06/06/2017"
}
]
提示: 理想情況下,我們應該從通過 API 獲取文章數據。例如,Contentful是就是一個提供cms後台服務的網站。
components 存放在 components 文件夾下,我們可以創建如下組件:
Recent Posts.
{{post.title}}
{{post.summary}}
by{{post.author}}
\{{post.published}}
class="card-footer-item">
Read More
importpostsfrom ~/posts.json
exportdefault{
name: posts ,
data(){
return{posts}
}
}
我們引入 JSON 文件充當非同步數據,通過 v-for 指令循環列表,取出我們需要的屬性填充進組件模板展示。
提示: ~ 符號是 / 的別名。你可以查看 這篇文檔 了解更具體的用法。
下面,我們添加 component 到主頁:
importPostsfrom ~components/Posts.vue
exportdefault{
components:{
Posts
},
// ...
}
添加動態路由
現在,我們為文章頁配置動態路由,我們以 /post/1 為例:
為此,我們添加 post 文件夾到 pages 目錄下,如下:
pages
└── post
└── _id
└── index.vue
我們的程序生成相應的動態路由:
router:{
routes:[
// ...
{
name: post-id ,
path: /post/:id ,
component: pages/post/_id/index.vue
}
]
}
更新單一發布文件:
{{post.title}}
by{{post.author}}at{{post.published}}
// import posts saved JSON data
importpostsfrom ~/posts.json
exportdefault{
validate({params}){
return/^d+$/.test(params.id)
},
asyncData({params},callback){
letpost=posts.find(post=>post.id===parseInt(params.id))
if(post){
callback(null,{post})
}else{
callback({statusCode:404,message: Post not found })
}
},
head(){
return{
title:this.post.title,
meta:[
{
hid: description ,
name: description ,
content:this.post.summary
}
]
}
}
}
Nuxt.js通過添加通用方法,簡化開發流程。看看我們應該如何在單文件應用中使用它。
路由校驗可以通過路由校驗方法 validate 校驗路由。如果我們的驗證路由參數驗證數字,如果驗證失敗,將自動跳轉到404頁面。如果它返回「false」,Nuxt。js將自動載入404錯誤頁面。想看更多,請查看這篇文檔。
asyncData 方法用於 fetch 數據,並在服務端渲染頁面,返回給瀏覽器。它可以通過多種方式返回數據。我們可以通過多種方式返回數據。在本文中的例子里,我們使用回調函數返回頁面。我們使用一個回調函數來返回相同的帖子「id」屬性「id」參數的路線。你可以看到不同的方式使用這個函數(這裡)(https://nuxtjs.org/guide/async-data)。
正如我們之前看到的,我們使用head 的方法來設置頁面 header 。這時,我們改變頁面你的 title ,添加頁面信息到具體頁面。
現在我們可以再次訪問我們的博客看到所有路線和頁面正常工作,並查看頁面源代碼生成的HTML。我們有一個伺服器端JavaScript應用程序呈現功能。
生成靜態文件
接下來,我們要生成程序的 HTML 靜態文件。
我們使用回調函數,返回以後包含動態路由的列表:
// ./nuxt.config.js
module.exports={
// ...
generate:{
routes(callback){
constposts=require( ./posts.json )
letroutes=posts.map(post=>`/post/${post.id}`)
callback(null,routes)
}
}
}
如果你想查看全部關於 generate 的配置, 可以參照 這篇文檔 。
運行如下命令,生成全部頁面:
`npm run generate`
Nuxt 將所有生成的頁面放到 dist 文件夾下。
使用 Firebase Hosting 部署
最後一步,我們推薦使用 Firebase Hosting 對項目進行部署,這樣,網友在幾秒內就能訪問到我們的網站。
如果你沒使用過 Firebase,首先安裝 Firebase CLI:
`npm install -g firebase-tools`
接下來,我們初始化網站,指定 dist 文件夾為公共目錄,當提示:
`firebase init`
我們可以通過如下命令部署:
`firebase deploy`
這樣,我們就可以訪問 .firebaseapp.com 查看我們的網頁了。查看官方 Demo 請訪問https://nuxt-ssr-blog.firebaseapp.com/ 。
結論
通過本文,我們學習了如何利用 Nuxt.js 搭配 Vue.js 構建服務端渲染的 JavaScript 應用程序。我們還學習了如何使用其 generate 命令來生成我們頁面的靜態文件,並且,我們可以利用 Firebase Hosting 這樣的靜態託管工具部署。
Nuxt.js 框架非常優秀,它已經成為了 Vue.js 官方推薦的 SSR 框架 。我期待 Nuxt.js 用於更多的 SSR 項目,使用更多 Nuxt.js 的特性。
nuxt.js官網:https://nuxtjs.org/
關於本文
譯者:@凈化
譯文:http://www.zcfy.cc/article/4036
作者:@Olayinka Omole
原文:https://www.sitepoint.com/nuxt-js-universal-vue-js
點擊展開全文
※高階函數:利用Filter、Map和Reduce來編寫更易維護的代碼
※騰訊 Web UI 解決方案 QMUI Web——探索與沉澱
※組件庫設計實戰-複雜組件設計
※指尖上行 移動前端開發進階之路
※重新認識JS的this、作用域、閉包、對象
TAG:前端早讀課 |