nuxt

想要學(xué)習(xí)nuxt.js,首先要弄清楚客戶(hù)端渲染和服務(wù)端渲染這兩個(gè)概念。

一、客戶(hù)端渲染 VS 服務(wù)端渲染

1. 客戶(hù)端渲染

簡(jiǎn)單理解就是,在服務(wù)端放一個(gè)html 頁(yè)面,客戶(hù)端發(fā)起請(qǐng)求時(shí),服務(wù)端把頁(yè)面(響應(yīng)的是字符串)發(fā)送過(guò)去??蛻?hù)端從上到下依次解析,如果發(fā)現(xiàn)ajax請(qǐng)求就再發(fā)送新請(qǐng)求,拿到ajax 響應(yīng)結(jié)果以后渲染模板引擎。整個(gè)過(guò)程至少要發(fā)起兩次請(qǐng)求。如圖:

客戶(hù)端渲染.png

但是,這種渲染方式存在的弊端也日益顯露出來(lái),比如首屏渲染慢,不利于seo等問(wèn)題。想對(duì)應(yīng)的,服務(wù)端渲染恰好彌補(bǔ)了這些不足。

2. 服務(wù)端渲染:

也稱(chēng)SSR,即server side render的縮寫(xiě)。在服務(wù)端渲染出完整的首屏dom結(jié)構(gòu),直接發(fā)送到瀏覽器;前端拿到的內(nèi)容包括首屏及完整spa結(jié)構(gòu),應(yīng)用激活后依然按照spa方式運(yùn)行。整個(gè)過(guò)程只向服務(wù)端發(fā)起一次請(qǐng)求。如圖:

image.png
服務(wù)端渲染有兩大優(yōu)點(diǎn):

一是更利于SEO。因?yàn)榕老x(chóng)只會(huì)爬取源碼,不會(huì)執(zhí)行腳本。使用了MVVM框架之后,頁(yè)面的大多數(shù)DOM元素是在客戶(hù)端根據(jù)js動(dòng)態(tài)生成的,可供爬蟲(chóng)抓取分析的內(nèi)容很少。而且瀏覽器爬蟲(chóng)不會(huì)等數(shù)據(jù)加載完成之后再去抓取。服務(wù)端渲染返回的是已經(jīng)獲取了異步數(shù)據(jù)并執(zhí)行JavaScript腳本的最終HTML,爬蟲(chóng)就可以抓取完整的頁(yè)面信息。
二是更利于首屏渲染。對(duì)服務(wù)端渲染而言,首屏渲染是node發(fā)送過(guò)來(lái)的html字符串,不依賴(lài)于js文件,這樣用戶(hù)就能更快地看到頁(yè)面內(nèi)容。尤其是大型單頁(yè)應(yīng)用,資源請(qǐng)求量大,造成首屏渲染加載緩慢,使用服務(wù)端渲染就可以在很大程度上解決首頁(yè)的白屏等待問(wèn)題。
Nuxt.js作為Vue.js的通用框架,就常被用來(lái)作SSR。

二、nuxt.js

nuxt是一個(gè)專(zhuān)注于ui渲染的應(yīng)用框架,可以快速搭建項(xiàng)目,還提供了服務(wù)端渲染的功能。

1. 安裝

直接用vue-cli安裝
vue init nuxt-community/starter-template <project-name>

2. nuxt推薦的項(xiàng)目結(jié)構(gòu)

assets——資源文件
components——組件
layouts——布局,默認(rèn)default。所有頁(yè)面都會(huì)加載在布局頁(yè)面中的<nuxt />標(biāo)簽中。如果要在普通頁(yè)面中使用下級(jí)路由,則要在頁(yè)面中添加<nuxt-child />
middleware——中間件:每個(gè)頁(yè)面加載前調(diào)用,在頁(yè)面中調(diào)用的方法是middleware: 'middlewareName'。
node_modules——依賴(lài)包
nuxt.config.js——個(gè)性化配置
package.json——
pages——頁(yè)面。根頁(yè)面是index.vue,二級(jí)頁(yè)面只要添加文件夾。動(dòng)態(tài)路由頁(yè)面的名稱(chēng)格式是:_變量.vue
plugins——插件
static——靜態(tài)文件(不需要webpack打包的)。
store——狀態(tài)管理
yarn.lock

3. 生命周期

Nuxt在vue的基礎(chǔ)上對(duì)生命周期做了擴(kuò)展:

export defualt {
  middleware(){ }, // 服務(wù)端
  validate(){ },  // 服務(wù)端
  asyncData(){ },  // 服務(wù)端
  fetch(){ },  // store數(shù)據(jù)加載
  beforeCreate(){ },  // 服務(wù)端和客戶(hù)端都會(huì)執(zhí)行
  created(){ },  //  服務(wù)端和客戶(hù)端都會(huì)執(zhí)行
  beforeMount(){ }, // 
  mounted(){ } // 客戶(hù)端
}
4. asyncData(context)

如果需要服務(wù)端渲染,首次渲染時(shí)一定要使用這個(gè)方法。它可以在渲染組件前異步獲取數(shù)據(jù)。asyncData傳入context參數(shù),可以獲取一些信息,如:

export default {
  asyncData(ctx){
    ctx.app   // 根實(shí)例
    ctx.route   // 路由實(shí)例
    ctx.params   // 路由參數(shù)
    ctx.query   // 路由問(wèn)號(hào)后的參數(shù)
    ctx.error   // 錯(cuò)誤處理方法
  }
}

使用這個(gè)方法時(shí)要注意,如果由于服務(wù)器或api錯(cuò)誤導(dǎo)致無(wú)法渲染,就要做好容錯(cuò)機(jī)制,可以使用context.error方法。我們可以這樣做:

async asyncData(ctx){
  try {
    throw new Error()
  } catch {
    ctx.error( {statusCode: 500, message: '服務(wù)器開(kāi)小差了~'} ) // 這里的statusCode參數(shù)必須是http狀態(tài)碼
  }
}

此時(shí),錯(cuò)誤頁(yè)可以通過(guò)/layout/error.vue自定義。
注意:該方法在服務(wù)端執(zhí)行,返回的數(shù)據(jù)與data()返回的數(shù)據(jù)合并。該方法在組件初始化前被調(diào)用,所以不能通過(guò)this引用實(shí)例對(duì)象。

5. head()

用于更新頭部信息title/descripe等,可以通過(guò)this獲取組件數(shù)據(jù)。

6. middleware()

在特定頁(yè)面實(shí)戰(zhàn)中間件使用axios請(qǐng)求數(shù)據(jù):
(1)nuxt項(xiàng)目默認(rèn)安裝axios,所以只要安裝proxy即可

npm install @nuxtjs/proxy

(2)在nuxt.config.js中加上:

export default {
  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/proxy'
  ],
  proxy: {
    './api': {
      target: 'http://www.xxx.com',
      changeOrigin: true,
      pathRewrite: {
        '^/api': ''
      }
    }
  }
}

(3)頁(yè)面中使用

import axios from 'axios'
export default {
    data () {
        return {
          page: 0
        }
    },
    async asyncData () {
        let data = await axios.get('http://localhost:3000/api/admin/list')
        return {
          page: data.data.page
        }
  },
}

采用 import axios from 'axios' 方式引入axios時(shí),接口參數(shù)前須加baseURL。

5. 使用scss

(1)安裝sass

npm i node-sass sass-loader scss-loader --save-dev

(2)如果要全局使用某個(gè)scss文件,要借助sass-resources-loader,還需要在nuxt.config.js的build配置中調(diào)整導(dǎo)出的loader配置:

export default {
  build: {
    extend(config, { isDev, isClient }){
      const sassResourcesLoader = {
        loader: 'sass-resources-loader',
        options: {
          resources: [
            // 填寫(xiě)需要全局注入scss的文件
            'assets/styles/mixins.scss'
          ]
        }
      }
      // 修改 scss sass 引用的 loader。
      config.module.rules.forEach((rule) => {  
        if (rule.test.toString() === '/\\.vue$/') {  
          rule.options.loaders.sass.push(sassResourcesLoader)  
          rule.options.loaders.scss.push(sassResourcesLoader)  
        }  
        if (['/\\.sass$/', '/\\.scss$/'].indexOf(rule.test.toString()) !== -1) {  
          rule.use.push(sassResourcesLoader)  
        }  
      })  
    }
  }
}
6. nuxt和vue的區(qū)別

(1)路由
nuxt按照 pages 文件夾的目錄結(jié)構(gòu)自動(dòng)生成路由
vue需在 src/router/index.js 手動(dòng)配置路由
(2)入口頁(yè)面
nuxt頁(yè)面入口為 layouts/default.vue
vue頁(yè)面入口為 src/App.vue
(3)webpack配置
nuxt內(nèi)置webpack,允許根據(jù)服務(wù)端需求,在 nuxt.config.js 中的build屬性自定義構(gòu)建webpack的配置,覆蓋默認(rèn)配置。
vue關(guān)于webpack的配置存放在build文件夾下。

7. 編譯過(guò)程

(1)加載nuxt.config.js;
(2)初始化nuxt,builder,開(kāi)始執(zhí)行構(gòu)建;
(3)準(zhǔn)備模板使用的參數(shù),然后根據(jù)模板生成真正的webpack編譯的js;
(4)分別執(zhí)行客戶(hù)端編譯和服務(wù)端編譯,生成最終的js腳本;
(5)編譯成功后,就需要啟動(dòng)服務(wù),監(jiān)聽(tīng)端口,這個(gè)是在npm run start中實(shí)現(xiàn)的。

關(guān)于nuxt.js先寫(xiě)這些了,更多內(nèi)容還是要去看官網(wǎng)文檔哦~

關(guān)注微信公眾號(hào)【CC前端手記】一起學(xué)更多前端小知識(shí)吧~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容