亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

Nuxt.js實戰和配置詳解

2019-11-19 11:04:40
字體:
來源:轉載
供稿:網友

前段時間剛好公司有項目使用了Nuxt.js來搭建,而剛好在公司內部做了個分享,稍微再整理一下發出來。本文比較適合初用Nuxt.js的同學,主要講下搭建過程中做的一些配置。建議初次使用Nuxt.js的同學先過一遍官方文檔,再回頭看下我這篇文章。

一、為什么要用Nuxt.js

原因其實不用多說,就是利用Nuxt.js的服務端渲染能力來解決Vue項目的SEO問題。

二、Nuxt.js和純Vue項目的簡單對比

 1. build后目標產物不同

vue: dist

nuxt: .nuxt

2. 網頁渲染流程

vue: 客戶端渲染,先下載js后,通過ajax來渲染頁面;

nuxt: 服務端渲染,可以做到服務端拼接好html后直接返回,首屏可以做到無需發起ajax請求;

3. 部署流程

vue: 只需部署dist目錄到服務器,沒有服務端,需要用nginx等做Web服務器;

nuxt: 需要部署幾乎所有文件到服務器(除node_modules,.git),自帶服務端,需要pm2管理(部署時需要reload pm2),若要求用域名,則需要nginx做代理。

4. 項目入口

vue: /src/main.js ,在main.js可以做一些全局注冊的初始化工作; nuxt: 沒有main.js入口文件,項目初始化的操作需要通過 nuxt.config.js 進行配置指定。

三、從零搭建一個Nuxt.js項目并配置 新建一個項目

直接使用腳手架進行安裝:

npx create-nuxt-app <項目名>

大概選上面這些選項。

值得一說的是,關于 Choose custom server framework (選擇服務端框架),可以根據你的業務情況選擇一個服務端框架,常見的就是Express、Koa,默認是None,即Nuxt默認服務器,我這里選了 Express 。

  • 選擇默認的Nuxt服務器,不會生成 server 文件夾,所有服務端渲染的操作都是Nuxt幫你完成,無需關心服務端的細節,開發體驗更接近Vue項目,缺點是無法做一些服務端定制化的操作。
  • 選擇其他的服務端框架,比如 Express ,會生成 server 文件夾,幫你搭建一個基本的Node服務端環境,可以在里面做一些node端的操作。比如我公司業務需要(解析protobuf)使用了 Express ,對真正的服務端api做一層轉發,在node端解析protobuf后,返回json數據給客戶端。

還有 Choose Nuxt.js modules (選擇nuxt.js的模塊),可以選 axiosPWA ,如果選了axios,則會幫你在nuxt實例下注冊 $axios ,讓你可以在.vue文件中直接 this.$axios 發起請求。

開啟eslint檢查

nuxt.config.js 的build屬性下添加:

 build: {  extend (config, ctx) {   // Run ESLint on save   if (ctx.isDev && ctx.isClient) {    config.module.rules.push({     enforce: 'pre',     test: //.(js|vue)$/,     loader: 'eslint-loader',     exclude: /(node_modules)/    })   }  } }

這樣開發時保存文件就可以檢查語法了。nuxt默認使用的規則是 @nuxtjs (底層來自eslint-config-standard ),規則配置在 /.eslintrc.js :

module.exports = { root: true, env: {  browser: true,  node: true }, parserOptions: {  parser: 'babel-eslint' }, extends: [  '@nuxtjs', // 該規則對應這個依賴: @nuxtjs/eslint-config  'plugin:nuxt/recommended' ], // add your custom rules here rules: {  'nuxt/no-cjs-in-config': 'off' }}

如果不習慣用 standard 規則的團隊可以將 @nuxtjs 改成其他的。

使用dotenv和@nuxtjs/dotenv統一管理環境變量

在node端,我們喜歡使用 dotenv 來管理項目中的環境變量,把所有環境變量都放在根目錄下的 .env 中。

安裝:

npm i dotenv

使用: 在根目錄下新建一個 .env 文件,并寫上需要管理的環境變量,比如服務端地址 APIHOST :

APIHOST=http://your_server.com/api

/server/index.js 中使用(該文件是選Express服務端框架自動生成的):

require('dotenv').config()// 通過process.env即可使用console.log(process.env.APIHOST) // http://your_server.com/api

此時我們只是讓服務端可以使用 .env 的文件而已,Nuxt客戶端并不能使用 .env ,按Nuxt.js文檔所說,可以將客戶端的環境變量放置在 nuxt.config.js 中:

module.exports = { env: {  baseUrl: process.env.BASE_URL || 'http://localhost:3000' }}

但如果node端和客戶端需要使用同一個環境變量時(后面講到API鑒權時會使用同一個SECRET變量),就需要同時在 nuxt.config.js.env 維護這個字段,比較麻煩,我們更希望環境變量只需要在一個地方維護,所以為了解決這個問題,我找到了 @nuxtjs/dotenv 這個依賴,它使得nuxt的客戶端也可以直接使用 .env ,達到了我們的預期。

安裝:

npm i @nuxtjs/dotenv

客戶端也是通過 process.env.XXX 來使用,不再舉例啦。

這樣,我們通過 dotenv@nuxtjs/dotenv 這兩個包,就可以統一管理開發環境中的變量啦。

另外, @nuxtjs/dotenv 允許打包時指定其他的env文件。比如,開發時我們使用的是 .env ,但我們打包的線上版本想用其他的環境變量,此時可以指定build時用另一份文件如 /.env.prod ,只需在 nuxt.config.js 指定:

module.exports = {  modules: [  ['@nuxtjs/dotenv', { filename: '.env.prod' }] // 指定打包時使用的dotenv ],}

@nuxtjs/toast模塊

toast可以說是很常用的功能,一般的UI框架都會有這個功能。但如果你的站點沒有使用UI框架,而alert又太丑,不妨引入該模塊:

npm install @nuxtjs/toast

然后在 nuxt.config.js 中引入

module.exports = {  modules: [  '@nuxtjs/toast',  ['@nuxtjs/dotenv', { filename: '.env.prod' }] // 指定打包時使用的dotenv ], toast: {// toast模塊的配置  position: 'top-center',   duration: 2000 }}

這樣,nuxt就會在全局注冊 $toast 方法供你使用,非常方便:

this.$toast.error('服務器開小差啦~~')this.$toast.error('請求成功~~')

API鑒權

對于某些敏感的服務,我們可能需要對API進行鑒權,防止被人輕易盜用我們node端的API,因此我們需要做一個API的鑒權機制。常見的方案有jwt,可以參考一下阮老師的介紹: 《JSON Web Token 入門教程》 。如果場景比較簡單,可以自行設計一下,這里提供一個思路:

  1. 客戶端和node端在環境變量中聲明一個秘鑰:SECRET=xxxx,注意這個是保密的;
  2. 客戶端發起請求時,將當前時間戳(timestamp)和 SECRET 通過某種算法,生成一個 signature ,請求時帶上 timestampsignature ;
  3. node接收到請求,獲得 timestampsignature ,將 timestamp 和秘鑰用同樣的算法再生成一次簽名 _signature
  4. 對比客戶端請求的 signature 和node用同樣的算法生成的 _signature ,如果一致就表示通過,否則鑒權失敗。

具體的步驟:

客戶端對axios進行一層封裝:

import axios from 'axios'import sha256 from 'crypto-js/sha256'import Base64 from 'crypto-js/enc-base64'// 加密算法,需安裝crypto-jsfunction crypto (str) { const _sign = sha256(str) return encodeURIComponent(Base64.stringify(_sign))}const SECRET = process.env.SECRETconst options = { headers: { 'X-Requested-With': 'XMLHttpRequest' }, timeout: 30000, baseURL: '/api'}// The server-side needs a full url to worksif (process.server) { options.baseURL = `http://${process.env.HOST || 'localhost'}:${process.env.PORT || 3000}/api` options.withCredentials = true}const instance = axios.create(options)// 對axios的每一個請求都做一個處理,攜帶上簽名和timestampinstance.interceptors.request.use( config => {  const timestamp = new Date().getTime()  const param = `timestamp=${timestamp}&secret=${SECRET}`  const sign = crypto(param)  config.params = Object.assign({}, config.params, { timestamp, sign })  return config })export default instance

接著,在server端寫一個鑒權的中間件, /server/middleware/verify.js

const sha256 = require('crypto-js/sha256')const Base64 = require('crypto-js/enc-base64')function crypto (str) { const _sign = sha256(str) return encodeURIComponent(Base64.stringify(_sign))}// 使用和客戶端相同的一個秘鑰const SECRET = process.env.SECRETfunction verifyMiddleware (req, res, next) { const { sign, timestamp } = req.query // 加密算法與請求時的一致 const _sign = crypto(`timestamp=${timestamp}&secret=${SECRET}`) if (_sign === sign) {  next() } else {  res.status(401).send({   message: 'invalid token'  }) }}module.exports = { verifyMiddleware }

最后,在需要鑒權的路由中引用這個中間件, /server/index.js

const { Router } = require('express')const { verifyMiddleware } = require('../middleware/verify.js')const router = Router()// 在需要鑒權的路由加上router.get('/test', verifyMiddleware, function (req, res, next) {  res.json({name: 'test'})})

靜態文件的處理

根目錄下有個 /static 文件夾,我們希望這里面的文件可以直接通過url訪問,需要在 /server/index.js 中加入一句:

const express = require('express')const app = express()app.use('/static', express.static('static'))

四、Nuxt開發相關 生命周期

Nuxt擴展了Vue的生命周期,大概如下:

export default { middleware () {}, //服務端 validate () {}, // 服務端 asyncData () {}, //服務端 fetch () {}, // store數據加載 beforeCreate () { // 服務端和客戶端都會執行}, created () { // 服務端和客戶端都會執行 }, beforeMount () {},  mounted () {} // 客戶端}

asyncData

該方法是Nuxt最大的一個賣點,服務端渲染的能力就在這里,首次渲染時務必使用該方法。 asyncData會傳進一個context參數,通過該參數可以獲得一些信息,如:

export default { asyncData (ctx) {  ctx.app // 根實例  ctx.route // 路由實例  ctx.params //路由參數  ctx.query // 路由問號后面的參數  ctx.error  // 錯誤處理方法 }}

渲染出錯和ajax請求出錯的處理

asyncData渲染出錯

使用 asyncData 鉤子時可能會由于服務器錯誤或api錯誤導致無法渲染,此時頁面還未渲染出來,需要針對這種情況做一些處理,當遇到asyncData錯誤時,跳轉到錯誤頁面,nuxt提供了 context.error 方法用于錯誤處理,在asyncData中調用該方法即可跳轉到錯誤頁面。

export default {  async asyncData (ctx) {    // 盡量使用try catch的寫法,將所有異常都捕捉到    try {      throw new Error()    } catch {      ctx.error({statusCode: 500, message: '服務器開小差了~' })    }  }}

這樣,當出現異常時會跳轉到默認的錯誤頁,錯誤頁面可以通過 /layout/error.vue 自定義。

這里會遇到一個問題, context.error 的參數必須是類似 { statusCode: 500, message: '服務器開小差了~' } , statusCode 必須是http狀態碼, 而我們服務端返回的錯誤往往有一些其他的自定義代碼,如 {resultCode: 10005, resultInfo: '服務器內部錯誤' } ,此時需要對返回的api錯誤進行轉換一下。

為了方便,我引入了 /plugins/ctx-inject.js 為context注冊一個全局的錯誤處理方法: context.$errorHandler(err) 。注入方法可以參考: 注入 $root 和 context , ctx-inject.js :

// 為context注冊全局的錯誤處理事件export default (ctx, inject) => { ctx.$errorHandler = err => {  try {   const res = err.data   if (res) {    // 由于nuxt的錯誤頁面只能識別http的狀態碼,因此statusCode統一傳500,表示服務器異常。    ctx.error({ statusCode: 500, message: res.resultInfo })   } else {    ctx.error({ statusCode: 500, message: '服務器開小差了~' })   }  } catch {   ctx.error({ statusCode: 500, message: '服務器開小差了~' })  } }}

然后在 nuxt.config.js 使用該插件:

export default { plugins: [  '~/plugins/ctx-inject.js' ]}

注入完畢,我們就可以在 asyncData 介個樣子使用了:

export default {  async asyncData (ctx) {    // 盡量使用try catch的寫法,將所有異常都捕捉到    try {      throw new Error()    } catch(err) {      ctx.$errorHandler(err)    }  }}

ajax請求出錯

對于ajax的異常,此時頁面已經渲染,出現錯誤時不必跳轉到錯誤頁,可以通過 this.$toast.error(res.message) toast出來即可。

loading方法

nuxt內置了頁面頂部loading進度條的樣式 推薦使用,提供頁面跳轉體驗。 打開: this.$nuxt.$loading.start() 完成: this.$nuxt.$loading.finish()

打包部署

一般來說,部署前可以先在本地打包,本地跑一下確認無誤后再上傳到服務器部署。命令:

// 打包npm run build// 本地跑npm start

除node_modules,.git,.env,將其他的文件都上傳到服務器,然后通過 pm2 進行管理,可以在項目根目錄建一個 pm2.json 方便維護:

{ "name": "nuxt-test", "script": "./server/index.js", "instances": 2, "cwd": "."}

然后配置生產環境的環境變量,一般是直接用 .env.prod 的配置: cp ./.env.prod ./.env 。 首次部署或有新的依賴包,需要在服務器上 npm install 一次,然后就可以用 pm2 啟動進程啦:

// 項目根目錄下運行pm2 start ./pm2.json

需要的話,可以設置開機自動啟動pm2: pm2 save && pm2 startup 。 需要注意的是,每次部署都得重啟一下進程: pm2 reload nuxt-test 。

五、最后

Nuxt.js引入了Node,同時nuxt.config.js替代了main.js的一些作用,目錄結構和vue項目都稍有不同,增加了很多的約定,對于初次接觸的同學可能會覺得非常陌生,更多的內容還是得看一遍官方的文檔。

demo源碼: fengxianqi/front_end-demos/src/nuxt-test。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品揄拍500视频| 97碰碰碰免费色视频| 成人在线精品视频| 亚洲人成在线观看| 亚洲大胆人体在线| 奇米4444一区二区三区| 欧美日韩成人黄色| 国产成人在线视频| 国产mv免费观看入口亚洲| 亚洲第一页在线| 亚洲人成伊人成综合网久久久| 久久在线免费观看视频| 日韩精品亚洲视频| 精品亚洲国产成av人片传媒| 国产精品久久久久久久久久尿| 国产日韩欧美中文在线播放| 成人乱人伦精品视频在线观看| 日韩午夜在线视频| 日本高清+成人网在线观看| 亚洲91精品在线| 欧美色另类天堂2015| 国产91色在线| 羞羞色国产精品| 欧美丝袜美女中出在线| 亚洲free嫩bbb| 亚洲激情视频在线观看| 伊人久久男人天堂| 91精品国产九九九久久久亚洲| 久久精品视频在线观看| 亚洲国产精品推荐| 欧美日韩亚洲一区二区| 国产精品久久久久久av福利软件| 亚洲精品mp4| 国产欧美精品日韩| 国产亚洲成av人片在线观看桃| 欧美激情va永久在线播放| 日韩在线免费视频观看| 97国产精品免费视频| 久久久久久一区二区三区| 91免费国产视频| 国产福利精品视频| 午夜精品久久久久久99热软件| 亚洲一区二区免费在线| 欧美一级片久久久久久久| 亚洲欧洲av一区二区| 国产成人一区二区在线| 亚洲精品日韩久久久| 日韩中文字幕免费视频| 久久五月天综合| 日韩精品999| 97在线视频观看| 国产精品一区二区三区免费视频| 精品日本美女福利在线观看| 成人xvideos免费视频| 日韩国产在线看| 亚洲精品aⅴ中文字幕乱码| 91香蕉国产在线观看| 精品亚洲aⅴ在线观看| 国产精品久久久久久久av电影| 国产精品九九久久久久久久| 伊人久久久久久久久久久| 久久精品最新地址| 亚洲最新视频在线| 91精品综合视频| www.久久久久| 亚洲色图15p| 欧美大片在线影院| 久久精品中文字幕免费mv| 国产999视频| 色婷婷成人综合| 日韩av第一页| 92看片淫黄大片欧美看国产片| 精品视频久久久久久久| 日韩电影在线观看永久视频免费网站| 精品久久久91| 26uuu国产精品视频| 成人免费高清完整版在线观看| 亚洲欧美一区二区三区久久| 欧美亚洲国产精品| 国产va免费精品高清在线观看| 日韩影视在线观看| 国产经典一区二区| 久久综合电影一区| 亚洲毛片在线免费观看| 成人午夜在线视频一区| 欧美人交a欧美精品| 欧美午夜性色大片在线观看| 亚洲成人亚洲激情| 国产在线999| 成人免费在线视频网址| 97不卡在线视频| 美女国内精品自产拍在线播放| 日韩av一区二区在线| 精品动漫一区二区三区| 色综合色综合久久综合频道88| 欧美日韩成人精品| 精品精品国产国产自在线| 久热99视频在线观看| 亚洲无av在线中文字幕| 黑人巨大精品欧美一区免费视频| 国产精品精品视频| 亚洲欧美日韩精品久久奇米色影视| 久久久久国产精品www| 欧美午夜性色大片在线观看| 在线播放日韩精品| 亚洲欧美精品伊人久久| 日韩国产高清污视频在线观看| 亚洲欧美国产一本综合首页| 欧美激情一二区| 欧美日韩一区二区精品| 亚洲欧美成人网| 91精品视频免费观看| 亚洲美女av电影| 中文字幕九色91在线| 亚洲第一免费播放区| 青青草精品毛片| 亚洲色图欧美制服丝袜另类第一页| 国产精品视频精品| 欧美性xxxx极品hd欧美风情| 亚洲第一av网站| 亚洲一区二区在线播放| 热久久视久久精品18亚洲精品| 国产精品视频免费观看www| 成人福利免费观看| 亚洲第一免费网站| 亚洲а∨天堂久久精品喷水| 米奇精品一区二区三区在线观看| 久久久久日韩精品久久久男男| 亚洲精选在线观看| 国产精品爽爽爽| 久久亚洲精品中文字幕冲田杏梨| 国产精品一区二区三区毛片淫片| 97碰在线观看| 亚洲人成亚洲人成在线观看| 日韩精品中文字幕久久臀| 91牛牛免费视频| 成人网址在线观看| 国产a∨精品一区二区三区不卡| 欧美视频二区36p| 国产视频精品va久久久久久| 欧美日韩综合视频网址| 久久91精品国产91久久久| 久久久久久香蕉网| 精品日韩中文字幕| 欧美激情性做爰免费视频| 国产精品永久免费在线| 欧美一级淫片videoshd| 一夜七次郎国产精品亚洲| 欧美高清在线观看| 亚洲国产精品一区二区久| 午夜精品久久久久久久白皮肤| 国产激情视频一区| 欧美丰满少妇xxxx| 国产一区二区三区丝袜| 中文字幕久热精品视频在线| 欧美夫妻性视频| 精品国内产的精品视频在线观看| 精品亚洲一区二区| 久久久久久久久久国产| 揄拍成人国产精品视频| 91网站在线免费观看| 狠狠久久亚洲欧美专区| 欧美成年人视频网站| 国产成人a亚洲精品|