溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

使用Nuxt.js怎么實現(xiàn)一個SSR前端博客

發(fā)布時間:2021-04-14 17:00:06 來源:億速云 閱讀:552 作者:Leah 欄目:web開發(fā)

這篇文章將為大家詳細講解有關(guān)使用Nuxt.js怎么實現(xiàn)一個SSR前端博客,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

目錄結(jié)構(gòu)

  •  assets: 資源文件。用于組織未編譯的靜態(tài)資源如 LESS、SASS或 JavaScript。

  • components: 組件。

  • layouts: page: 模板頁面,默認為 default.vue可以在這個目錄下創(chuàng)建全局頁面的統(tǒng)一布局,或是錯誤處理頁面頁,需要提供一個nuxt 標簽,類似于router-view

  • middleware: 中間件,放置自定義的中間件,會在加載組件之前調(diào)用??梢栽陧撁嬷姓{(diào)用: middleware: '中間件名稱'。

  • pages: 頁面,index.vue 為根頁面,Nuxt.js 框架讀取該目錄下所有的 .vue文件并自動生成對應(yīng)的路由配置,如需要動態(tài)參數(shù)id,則可以添加_id的文件,必須是下劃線加參數(shù)名。

  • plugin: 插件,用于組織那些需要在 根Vue.js應(yīng)用實例化之前需要運行的 Javascript 插件。

  • static: 靜態(tài)文件,靜態(tài)文件目錄 static用于存放應(yīng)用的靜態(tài)文件,此類文件不會被 Nuxt.js 調(diào)用 Webpack 進行構(gòu)建編譯處理。

  • store: 用于組織vuex狀態(tài)管理。具體使用請移步至 官網(wǎng)。

  • nuxt.config.js: nuxt.config.js文件用于組織Nuxt.js 應(yīng)用的個性化配置,配置head,loading,css,plugins等。

Nuxt.js生命周期

使用Nuxt.js怎么實現(xiàn)一個SSR前端博客

1. incoming Request 瀏覽器發(fā)出的請求)
2. nuxtServerInit 服務(wù)端接受請求后,要檢查當前有沒有 nuxtServerInit配置項,如果有就執(zhí)行這個函數(shù)
3. store action 用來操作vuex
4. middleware 可以做jWT等一些操作。
5. validate() 檢驗參數(shù),參數(shù)檢驗失敗,可以在layout里的error里面進行捕捉。
6. asyncData()& fetch() asyncData用來渲染組件,fetch用來渲染vuex
7. Render

Nuxt擴展以后的生命周期和方法以下:

beforeCreate: ? beforeCreate()
components: {NuxtLoading: {…}}
computed: {isOffline: ?}
context: {isStatic: false, isDev: true, isHMR: true, app: {…}, payload: undefined, …}
created: ? created()
data: ? data()
head: {title: "nuxt-meituan-ssr", meta: Array(3), link: Array(1), style: Array(0), script: Array(0)}
methods: {refreshOnlineStatus: ?, refresh: ?, errorChanged: ?, setLayout: ?, loadLayout: ?}
mounted: ? mounted()
nuxt: {…}
render: ? render(h, props)
router: VueRouter {app: Vue, apps: Array(1), options: {…}, beforeHooks: Array(2), resolveHooks: Array(0), …}
watch: {nuxt.err: "errorChanged"}

注意:

  • Vue.js生命周期的鉤子只有beforeCreate和created會在服務(wù)端和客戶端渲染。

  • 以上生命周期里都獲取不到window對象。

  • asyncData和fetch我們可以拿到數(shù)據(jù),不要嘗試掛載數(shù)據(jù)到data上,此時獲取不到this對象。

開發(fā)總結(jié)

如何修改默認啟動端口?

可以在package.json下面修改配置,如下。

"config":{
  "nuxt":{
    "host":"127.0.0.1",
    "port":"3304"
  }
}

如何添加全局的樣式?

可以在assets里添加全局Css文件,如在assets下的Css文件夾目錄下添加了一個index.css文件,然后在nuxt-config.js里配置該css文件路徑即可。 css:['~assers/css/index.css']

通過別名訪問圖片在template里是正確的,為何在Css設(shè)置背景圖卻報錯?

在css配置的是,需要將'~/'后面的'/'去除掉。

  <img src="~/static/logo.jpg"/> 
  backround-image:url('~static/logo.jpg');

如何添加路由動畫?

同樣,我們在Css文件里添加一些動畫代碼,一般樣式會在其后面添加-active和-leave-active,其實和Vue動畫形式一致。其中以page開頭的動畫,默認會作用于全部頁面,如果想給特定的頁面加動畫,可以在對應(yīng)的頁面script里引用,如 transitions: 'bounce'即可。

.page-enter-active, .page-leave-active {
  transition: opacity .3s
 }
 .page-enter, .page-leave-active {
  opacity: 0
 }
 .bounce-enter-active {
  animation: bounce-in .8s;
 }
 .bounce-leave-active {
  animation: bounce-out .5s;
 }
 @keyframes bounce-in {
  0% { transform: scale(1) }
  50% { transform: scale(1.01) }
  100% { transform: scale(1) }
 }
 @keyframes bounce-out {
  0% { transform: scale(1) }
  50% { transform: scale(1.01) }
  100% { transform: scale(1) }
 }

路由參數(shù)如何傳遞?

同Vue-router,有聲明式和編程式兩種方式,無非是標簽變成了 router.push(...)

  nuxt-link :to="{name:'article',params:{id:1234}}" >聲明式</nuxt-link>
  // 編程式
  this.$router.push({
    name:'article',
    params:{
      id:1234
    }
  })

動態(tài)路由如何進行參數(shù)檢驗?

Nuxt.js提供了一個validate的生命周期鉤子,可以在此進行參數(shù)的校驗。以文章詳情校驗id為例,我們需要判斷傳入的id是否是數(shù)字,可以像下面這樣處理。

 validate({ params }) {
  return /^\d+$/.test(params.id)
 }

如何添加404等錯誤頁面?

可以在layout下新建一個error.vue頁面,內(nèi)容如下,當訪問一個不存在的頁面的時候,或者參數(shù)檢驗失敗的時候,或者我們在middleware中間件處理拋出異常的時候,都會跳轉(zhuǎn)到該頁面。

<template>
 <div class="container">
  <h2 v-if="error.statusCode === 404">頁面不存在</h2>
  <h2 v-else>應(yīng)用發(fā)生錯誤異常</h2>
  <nuxt-link to="/">首 頁</nuxt-link>
 </div>
</template>

<script>
export default {
 props: ['error'],
 layout: 'blog' // 指定模板頁面
}
</script>

middleware中的文件拋出錯誤

export default function({ store, error, redirect }) {
  if (!store.state.user.userInfo.auth) {
      error({
       message: '沒有權(quán)限哦!',
      statusCode: 403
     })
  }
}

頂部進度條如何設(shè)置?

loading 屬性配置 可以在nuxt-config.js設(shè)置loading的顏色,使用了this. loading可能無法在created里立即使用。此種配置loading有嚴重的缺陷,無法知道真正的加載進度。也可以自定義加載組件,loading: '~components/loading.vue'。

export default {
 mounted () {
  this.$nextTick(() => {
   this.$nuxt.$loading.start()
   setTimeout(() => this.$nuxt.$loading.finish(), 500)
  })
 }
 }

異步數(shù)據(jù)如何獲?。?/strong>

Nuxt.js提供了兩個函數(shù),asyncData和fetch函數(shù)。asyncData 獲取組件的數(shù)據(jù),fetch 在渲染頁面之前獲取數(shù)據(jù)填充應(yīng)用的狀態(tài)樹(store)。

asyncData可以使用promise也可以使用async函數(shù),記住,此時返回的東西需要用一個對象進行包裹,不能掛載到data里,此時沒有this對象。

// 方式一
 asyncData({ app,params,route,query,error}) {
   return getUserlist({}).then(res => {
    let user = [];
     user = res.list
     console.log(user,'user')
     return {user}
    })
     .catch(err => {
      console.log(err)
    })
},

// 方式二
async asyncData({ app }) {
  let data = await getUserlist({});
  let user = data.list;
  return { user }
}

fetch函數(shù)同上,可以使用promise也可以使用async函數(shù),通常會commit一個mutation。

export default {
 fetch ({ store, params }) {
  return axios.get('http://my-api/stars')
  .then((res) => {
   store.commit('setStars', res.data)
  })
 }
}
</script>
// 或者使用 async 或 await 的模式簡化代碼如下:
<template>
 <h2>Stars: {{ $store.state.stars }}</h2>
</template>

<script>
export default {
 async fetch ({ store, params }) {
  let { data } = await axios.get('http://my-api/stars')
  store.commit('setStars', data)
 }
}
</script>

如何動態(tài)修改title的內(nèi)容?

如果是寫死的,可以直接修改head的配置。

 head() {
  return {
   // title: '',這里一旦聲明,在asyncdata里修改也不起作用,直接以這個為準
   meta: [
    {
     hid: 'description', // nuxt.config 替換唯一標識 hid  { hid: 'description', name: 'description', content: 'Nuxt.js project' }
     name: 'content',
     content: '文章詳情'
    }
   ]
  }
 },

如果是動態(tài)數(shù)據(jù)從數(shù)據(jù)源里獲取,然后通過asynData里的app對象,動態(tài)修改head的title。

 asyncData({ app, params }) {
  const id = params.id;
  return getArticleDetail({ id })
   .then(result => {
      app.head.title = result.title;
   })
   .catch(err => {})
 }

如何進行權(quán)限JWT驗證?

登錄成功以后,我們會在cookie和Vuex中緩存token信息,當界面刷新的時候,會走store里的nuxtServerInit 函數(shù),該函數(shù)僅在每個服務(wù)器端渲染中運,可以使用req.headers.cookie獲取瀏覽器的cookie,再次更新store里的值,接著會走到中間件,中間件進行驗證,如果有token信息則繼續(xù),沒有則跳轉(zhuǎn)到登錄頁。
1. 為什么要在nuxtServerInit更新store的值?
需要在middleware里使用,否則刷新后store里的值為空了。
2. 客戶端調(diào)用接口可以拿到token,服務(wù)器端如何拿到?
可以通過nuxtServerInit里的req拿到請求信息的cookie,然后請求接口。
3. 前后端分離,刷新的時候如何保證用戶名、token等信息依然存在?
可以像上面一樣,每次取cookie的值再次更新store,但這樣有一個問題,cookie可能會被篡改,后端代碼需要做驗證。也可以每次刷新重新通過token請求接口,更新用戶信息。

store代碼

import Vue from 'vue';
import Vuex from 'vuex';
import user from './modules/user';
import { COOKIE_KEY } from '~/assets/js/constant.js';
Vue.use(Vuex);
const store = () =>
  new Vuex.Store({
    modules: {
      user
    },
    actions: {
      async nuxtServerInit({ commit, dispatch }, { req, app }) {
        if (req.headers.cookie) {
          let parsedResult = {};
          req.headers.cookie.split(';').forEach(cookie => {
            const currentCookie = cookie.split('=');
            parsedResult[currentCookie[0].trim()] = (currentCookie[1] || '').trim();
          });
          const userInfo = {
            name: parsedResult[COOKIE_KEY.NAME],
            token: parsedResult[COOKIE_KEY.TOKEN]
          };
          commit('user/setUserInfo',userInfo);
        }
      }
    }
  });

export default store;

中間件代碼

export default function({ store, error, redirect }) {
  if (!store.state.user.userInfo.token || !store.state.user.userInfo.name) {
    //  error({
    //   message: 'You are not connected',
    //   statusCode: 403
    //  })
    redirect('/');
  }
}

nginx部署

 npm run build
選擇build以后的四個文件: .nuxt, static, nuxt.config.js, package.json上傳到服務(wù)器。
pm2 pm2 start npm --name 'package.json.name' -- run start
nginx配置

查看網(wǎng)頁源代碼可以看到:

   server{
      listen 3000;
      server_name  felix12345.club; 
      gzip on;
      gzip_buffers 32 4K;
      gzip_comp_level 6;
      gzip_min_length 100;
      gzip_types application/javascript text/css text/xml;
      gzip_disable "MSIE [1-6]\."; 
      gzip_vary on;
      proxy_buffer_size 64k;
      proxy_buffers  32 32k;
      proxy_busy_buffers_size 128k;
      location / {
        root  /data/ww/nuxt;
        proxy_pass  http://127.0.0.1:3002;
        proxy_set_header X-Real-IP $remote_addr;
      }
    }

關(guān)于使用Nuxt.js怎么實現(xiàn)一個SSR前端博客就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI