採用vue.js開發搜索界面則SEO不友好,須要解決SEO的問題。javascript
seo是網站爲了提升自已的網站排名,得到更多的流量,對網站的結構及內容進行調整優化,以便搜索引擎
(百度,google等)更好抓取到更優質的網站的內容。html
採用什麼技術有利於SEO?要解答這個問題須要理解服務端渲染和客戶端渲染。
什麼是服務端渲染?
咱們用傳統的servlet開發來舉例:瀏覽器請求servlet,servlet在服務端生成html響應給瀏覽器,瀏覽器展現html
的內容,這個過程就是服務端渲染,以下圖:前端
服務端渲染的特色:vue
1 )在服務端生成html網頁的dom元素。
2)客戶端(瀏覽器)只負責顯示dom元素內容。java
當初隨着web2.0的到來,AJAX技術興起,出現了客戶端渲染:客戶端(瀏覽器) 使用AJAX向服務端發起http請
求,獲取到了想要的數據,客戶端拿着數據開始渲染html網頁,生成Dom元素,並最終將網頁內容展現給用戶,
以下圖:react
客戶端渲染的特色:
1)在服務端只是給客戶端響應的了數據,而不是html網頁
2)客戶端(瀏覽器)負責獲取服務端的數據生成Dom元素。webpack
客戶端渲染:
1) 缺點
不利於網站進行SEO,由於網站大量使用javascript技術,不利於spider抓取網頁。
2) 優勢
客戶端負責渲染,用戶體驗性好,服務端只提供數據不用關心用戶界面的內容,有利於提升服務端的開發效率。
3)適用場景
對SEO沒有要求的系統,好比後臺管理類的系統,如電商後臺管理,用戶管理等。git
服務端渲染:
1) 優勢
有利於SEO,網站經過href的url將spider直接引到服務端,服務端提供優質的網頁內容給spider。
2) 缺點
服務端完成一部分客戶端的工做,一般完成一個需求須要修改客戶端和服務端的代碼,開發效率低,不利於系統的
穩定性。程序員
3 )適用場景
對SEO有要求的系統,好比:門戶首頁、商品詳情頁面等github
移動互聯網的興起促進了web先後端分離開發模式的發展,服務端只專一業務,前端只專一用戶體驗,前端大量運
用的前端渲染技術,好比流行的vue.js、react框架都實現了功能強大的前端渲染。
可是,對於有SEO需求的網頁若是使用前端渲染技術去開發就不利於SEO了,有沒有一種即便用vue.js、react的前
端技術也實現服務端渲染的技術呢?其實,對於服務端渲染的需求,vue.js、react這樣流行的前端框架提供了服務
端渲染的解決方案。
從上圖能夠看到:
react框架提供next.js實現服務端渲染。
vue.js框架提供Nuxt.js實現服務端渲染。
下圖展現了從客戶端請求到Nuxt.js進行服務端渲染的總體的工做流程:
一、用戶打開瀏覽器,輸入網址請求到Node.js
二、部署在Node.js的應用Nuxt.js接收瀏覽器請求,並請求服務端獲取數據
三、Nuxt.js獲取到數據後進行服務端渲染
四、Nuxt.js將html網頁響應給瀏覽器
Nuxt.js使用了哪些技術?
Nuxt.js使用Vue.js+webpack+Babel三大技術框架/組件
Babel 是一個js的轉碼器,負責將ES6的代碼轉成瀏覽器識別的ES5代碼。
Webpack是一個前端工程打包工具。
Vue.js是一個優秀的前端框架。
nuxt.js有標準的目錄結構,官方提供了模板工程,能夠模板工程快速建立nuxt項目。
模板工程地址:https://github.com/nuxt-community/starter-template/archive/master.zip
本項目提供基於 Nuxt.js的封裝工程,基於此封裝工程開發搜索前端,見「資料」--》xc-ui-pc-portal.zip,解壓
xc-ui-pc-portal.zip到本項目前端工程目錄下。
本前端工程屬於門戶的一部分,將承載一部分考慮SEO的非靜態化頁面。
本工程基於Nuxt.js模板工程構建,Nuxt.js使用1.3版本,並加入了從此開發中所使用的依賴包,直接解壓本工程即
可以使用。
‐ 資源目錄
資源目錄 assets 用於組織未編譯的靜態資源如 LESS、SASS 或 JavaScript。
‐ 組件目錄
組件目錄 components 用於組織應用的 Vue.js 組件。Nuxt.js 不會擴展加強該目錄下 Vue.js 組件,即這些組件不
會像頁面組件那樣有 asyncData 方法的特性。
‐ 佈局目錄
佈局目錄 layouts 用於組織應用的佈局組件。
該目錄名爲Nuxt.js保留的,不可更改。
‐ 中間件目錄
middleware 目錄用於存放應用的中間件。
‐ 頁面目錄
頁面目錄 pages 用於組織應用的路由及視圖。Nuxt.js 框架讀取該目錄下全部的 .vue 文件並自動生成對應的路由配
置。
該目錄名爲Nuxt.js保留的,不可更改。
‐ 插件目錄
插件目錄 plugins 用於組織那些須要在 根vue.js應用 實例化以前須要運行的 Javascript 插件。
‐ 靜態文件目錄
靜態文件目錄 static 用於存放應用的靜態文件,此類文件不會被 Nuxt.js 調用 Webpack 進行構建編譯處理。 服務
器啓動的時候,該目錄下的文件會映射至應用的根路徑 / 下。
舉個例子: /static/logo.png 映射至 /logo.png
該目錄名爲Nuxt.js保留的,不可更改。
‐ Store 目錄
store 目錄用於組織應用的 Vuex 狀態樹 文件。 Nuxt.js 框架集成了 Vuex 狀態樹 的相關功能配置,在 store 目
錄下建立一個 index.js 文件可激活這些配置。
該目錄名爲Nuxt.js保留的,不可更改。
‐ nuxt.config.js 文件
nuxt.config.js 文件用於組織Nuxt.js 應用的個性化配置,以便覆蓋默認配置。
該文件名爲Nuxt.js保留的,不可更改。
‐ package.json 文件
package.json 文件用於描述應用的依賴關係和對外暴露的腳本接口。
該文件名爲Nuxt.js保留的,不可更改。
nuxt.js 提供了目錄的別名,方便在程序中引用:
Nuxt.js 依據 pages 目錄結構自動生成 vue-router 模塊的路由配置。
Nuxt.js根據pages的目錄結構及頁面名稱定義規範來生成路由,下邊是一個基礎路由的例子:
假設 pages 的目錄結構以下:
pages/
‐‐| user/
‐‐‐‐‐| index.vue
‐‐‐‐‐| one.vue
那麼,Nuxt.js 自動生成的路由配置以下:
router: {
routes: [
{
name: 'user',
path: '/user',
component: 'pages/user/index.vue'
},
{
name: 'user‐one',
path: '/user/one',
component: 'pages/user/one.vue'
}
]
}
index.vue 代碼以下:
<template> <div> 用戶管理首頁 </div> </template> <script> export default{ layout:"test" } </script> <style> </style>
one.vue代碼以下:
<template> <div> one頁面 </div> </template> <script> export default{ layout:"test" } </script> <style> </style>
你能夠經過 vue-router 的子路由建立 Nuxt.js 應用的嵌套路由。
建立內嵌子路由,你須要添加一個 Vue 文件,同時添加一個與該文件同名的目錄用來存放子視圖組件。
別忘了在父級 Vue 文件內增長 <nuxt -child/> 用於顯示子視圖內容。
假設文件結構如:
pages/
‐‐| user/
‐‐‐‐‐| _id.vue
‐‐‐‐‐| index.vue
‐‐| user.vue
Nuxt.js 自動生成的路由配置以下:
router: {
routes: [
{
path: '/user',
component: 'pages/user.vue',
children: [
{
path: '',
component: 'pages/user/index.vue',
name: 'user'
},
{
path: ':id',
component: 'pages/user/_id.vue',
name: 'user‐id'
}
]
}
]
}
將user.vue文件建立到與user目錄的父目錄下,即和user目錄保持平級。
<template> <div> 用戶管理導航,<nuxt‐link :to="'/user/101'">修改</nuxt‐link> <nuxt‐child/> </div> </template> <script> export default{ layout:"test" } </script> <style> </style>
_id.vue頁面實現了向頁面傳入id參數,頁面內容以下:
<template> <div> 修改用戶信息{{id}} </div> </template> <script> export default{ layout:"test", data(){ return { id:'' } }, mounted(){ this.id = this.$route.params.id; console.log(this.id) } } </script> <style> </style>
測試:http://localhost:10000/user
點擊修改:
Nuxt.js 擴展了 Vue.js,增長了一個叫 asyncData 的方法, asyncData 方法會在組件(限於頁面組件)每次加載
以前被調用。它能夠在服務端或路由更新以前被調用。 在這個方法被調用的時候,第一個參數被設定爲當前頁面的
上下文對象,你能夠利用 asyncData 方法來獲取數據,Nuxt.js 會將 asyncData 返回的數據融合組件 data 方法
返回的數據一併返回給當前組件。
注意:因爲 asyncData 方法是在組件 初始化 前被調用的,因此在方法內是沒有辦法經過 this 來引用組件的實例
對象。
例子:
在上邊例子中的user/_id.vue中添加,頁面代碼以下:
<template> <div> 修改用戶信息{{id}},名稱:{{name}} </div> </template> <script> export default{ layout:'test', //根據id查詢用戶信息 asyncData(){ console.log("async方法") return { name:'黑馬程序員' } }, data(){ return { id:'' } }, mounted(){ this.id = this.$route.params.id; } } </script> <style> </style>
此方法在服務端被執行,觀察服務端控制檯打印輸出 「async方法」。
此方法返回data模型數據,在服務端被渲染,最後響應給前端,刷新此頁面查看頁面源代碼能夠看到name模型數
據已在頁面源代碼中顯示。
使用async 和 await配合promise也能夠實現同步調用,nuxt.js中使用async/await實現同步調用效果。
一、先測試異步調用,增長a、b兩個方法,並在mounted中調用。
methods:{
a(){
return new Promise(function(resolve,reject){
setTimeout(function () {
resolve(1)
},2000)
})
},
b(){
return new Promise(function(resolve,reject){
setTimeout(function () {
resolve(2)
},1000)
})
}
},
mounted(){
this.a().then(res=>{
alert(res)
console.log(res)
})
this.b().then(res=>{
alert(res)
console.log(res)
})
}
觀察客戶端,並無按照方法執行的順序輸出,使用Promise實現了異步調用。
2 、使用async/await完成同步調用
async asyncData({ store, route }) {
console.log("async方法")
var a = await new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("1")
resolve(1)
},2000)
});
var a = await new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("2")
resolve(2)
},1000)
});
return {
name:'黑馬程序員'
}
},
觀察服務端控制檯發現是按照a、b方法的調用順序輸出一、2,實現了使用async/await完成同步調用。