温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

使用Nuxt.js怎么实现一个SSR前端博客

发布时间:2021-04-14 17:00:06 来源:亿速云 阅读:611 作者:Leah 栏目:web开发

这篇文章将为大家详细讲解有关使用Nuxt.js怎么实现一个SSR前端博客,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

目录结构

  •  assets: 资源文件。用于组织未编译的静态资源如 LESS、SASS或 JavaScript。

  • components: 组件。

  • layouts: page: 模板页面,默认为 default.vue可以在这个目录下创建全局页面的统一布局,或是错误处理页面页,需要提供一个nuxt 标签,类似于router-view

  • middleware: 中间件,放置自定义的中间件,会在加载组件之前调用。可以在页面中调用: middleware: '中间件名称'。

  • pages: 页面,index.vue 为根页面,Nuxt.js 框架读取该目录下所有的 .vue文件并自动生成对应的路由配置,如需要动态参数id,则可以添加_id的文件,必须是下划线加参数名。

  • plugin: 插件,用于组织那些需要在 根Vue.js应用实例化之前需要运行的 Javascript 插件。

  • static: 静态文件,静态文件目录 static用于存放应用的静态文件,此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。

  • store: 用于组织vuex状态管理。具体使用请移步至 官网。

  • nuxt.config.js: nuxt.config.js文件用于组织Nuxt.js 应用的个性化配置,配置head,loading,css,plugins等。

Nuxt.js生命周期

使用Nuxt.js怎么实现一个SSR前端博客

1. incoming Request 浏览器发出的请求)
2. nuxtServerInit 服务端接受请求后,要检查当前有没有 nuxtServerInit配置项,如果有就执行这个函数
3. store action 用来操作vuex
4. middleware 可以做jWT等一些操作。
5. validate() 检验参数,参数检验失败,可以在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会在服务端和客户端渲染。

  • 以上生命周期里都获取不到window对象。

  • asyncData和fetch我们可以拿到数据,不要尝试挂载数据到data上,此时获取不到this对象。

开发总结

如何修改默认启动端口?

可以在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设置背景图却报错?

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

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

如何添加路由动画?

同样,我们在Css文件里添加一些动画代码,一般样式会在其后面添加-active和-leave-active,其实和Vue动画形式一致。其中以page开头的动画,默认会作用于全部页面,如果想给特定的页面加动画,可以在对应的页面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) }  }

路由参数如何传递?

同Vue-router,有声明式和编程式两种方式,无非是标签变成了 router.push(...)

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

动态路由如何进行参数检验?

Nuxt.js提供了一个validate的生命周期钩子,可以在此进行参数的校验。以文章详情校验id为例,我们需要判断传入的id是否是数字,可以像下面这样处理。

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

如何添加404等错误页面?

可以在layout下新建一个error.vue页面,内容如下,当访问一个不存在的页面的时候,或者参数检验失败的时候,或者我们在middleware中间件处理抛出异常的时候,都会跳转到该页面。

<template>  <div class="container">   <h2 v-if="error.statusCode === 404">页面不存在</h2>   <h2 v-else>应用发生错误异常</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: '没有权限哦!',       statusCode: 403      })   } }

顶部进度条如何设置?

loading 属性配置 可以在nuxt-config.js设置loading的颜色,使用了this. loading可能无法在created里立即使用。此种配置loading有严重的缺陷,无法知道真正的加载进度。也可以自定义加载组件,loading: '~components/loading.vue'。

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

异步数据如何获取?

Nuxt.js提供了两个函数,asyncData和fetch函数。asyncData 获取组件的数据,fetch 在渲染页面之前获取数据填充应用的状态树(store)。

asyncData可以使用promise也可以使用async函数,记住,此时返回的东西需要用一个对象进行包裹,不能挂载到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函数同上,可以使用promise也可以使用async函数,通常会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>

如何动态修改title的内容?

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

 head() {   return {    // title: '',这里一旦声明,在asyncdata里修改也不起作用,直接以这个为准    meta: [     {      hid: 'description', // nuxt.config 替换唯一标识 hid  { hid: 'description', name: 'description', content: 'Nuxt.js project' }      name: 'content',      content: '文章详情'     }    ]   }  },

如果是动态数据从数据源里获取,然后通过asynData里的app对象,动态修改head的title。

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

如何进行权限JWT验证?

登录成功以后,我们会在cookie和Vuex中缓存token信息,当界面刷新的时候,会走store里的nuxtServerInit 函数,该函数仅在每个服务器端渲染中运,可以使用req.headers.cookie获取浏览器的cookie,再次更新store里的值,接着会走到中间件,中间件进行验证,如果有token信息则继续,没有则跳转到登录页。
1. 为什么要在nuxtServerInit更新store的值?
需要在middleware里使用,否则刷新后store里的值为空了。
2. 客户端调用接口可以拿到token,服务器端如何拿到?
可以通过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上传到服务器。
pm2 pm2 start npm --name 'package.json.name' -- run start
nginx配置

查看网页源代码可以看到:

   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;       }     }

关于使用Nuxt.js怎么实现一个SSR前端博客就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI