Nuxt:服务端渲染

什么是服务端渲染

前端请求服务器,把html文件以资源的形式返回前端,浏览器拿到html文件解析。

服务器渲染:返回html之前,会先将一些数据填充好到特定区域后再返回给前端,在SPA场景下,服务端渲染都是针对第一次get请求,它会完整的html给浏览器,浏览器直接渲染出首屏,用不着浏览器端多一个AJAX请求去获取数据再渲染。

渲染流程

客户端第一次请求服务器,服务器返回一个空壳的html,当created方法发送数据给服务器后,服务器才返回客户端,然后再渲染数据。此时才能看到完整的页面(搜索引擎抓取不到ajax的数据)。

服务端渲染流程:客户端请求服务器,服务器先塞数据(包含js等)进html后返回。

优点

更好的 SEO,因为传统的搜索引擎只会从 HTML 中抓取数据,这会导致前端渲染的页面无法被抓取。

更快的内容到达时间(time-to-content),特别是对于缓慢的网络情况或运行缓慢的设备 。页面首屏时间大概有80%消耗在网络上,剩下的时间在后端读取数据以及浏览器渲染,显然要优化后面的20%是比较困难的,优化网络时间是效果最明显的手段。传统的Ajax请求是先请求js再由js发起数据请求,两项时间再加上浏览器渲染时间才是首屏时间。而SSR能将两个请求合并为一个。

缺点

更多的服务器端负载。

服务器端和浏览器环境差异带来的问题,例如document等对象找不到的问题。

如何选择

建议:如果注重SEO的新闻站点,非强交互的页面,建议用SSR;像后台管理页面这类强交互的应用,建议使用前端渲染。

参考网站:Nuxt.js - Vue.js 通用应用框架 | Nuxt.js 中文网

目前nuxt3支持vue3,而nuxt2支持vue2,如果要将原来的vue2能支持nuxt3需要将vue2升级为vue3。过程比较麻烦,vue2与vue3的语法差距很大,所以建议大家在考虑前端框架使用的时候考虑下网站用途及宣传模式再来对使用框架进行决断

我们就简单介绍下nuxt,首先创建个简单的nuxt项目

npm i create-nuxt-app -g
create-nuxt-app my-nuxt-demo
cd my-nuxt-demo
npm run dev

文件结构分析

└─my-nuxt-demo

  ├─.nuxt               // Nuxt自动生成,临时的用于编辑的文件,build

  ├─assets             // 用于组织未编译的静态资源如LESS、SASS或JavaScript,对于不需要通过 Webpack 处理的静态资源文件,可以放置在 static 目录中

  ├─components   // 用于自己编写的Vue组件,比如日历组件、分页组件

  ├─layouts           // 布局目录,用于组织应用的布局组件,不可更改⭐

  ├─middleware    // 用于存放中间件

  ├─node_modules

  ├─pages            // 用于组织应用的路由及视图,Nuxt.js根据该目录结构自动生成对应的路由配置,文件名不可更改⭐

  ├─plugins          // 用于组织那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。

  ├─static            // 用于存放应用的静态文件,此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。 服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下。文件夹名不可更改。⭐

  └─store             // 用于组织应用的Vuex 状态管理。文件夹名不可更改。⭐

  ├─.editorconfig  // 开发工具格式配置

  ├─.eslintrc.js      // ESLint的配置文件,用于检查代码格式

  ├─.gitignore       // 配置git忽略文件

  ├─nuxt.config.js  // 用于组织Nuxt.js 应用的个性化配置,以便覆盖默认配置。文件名不可更改。⭐

  ├─package-lock.json   // npm自动生成,用于帮助package的统一设置的,yarn也有相同的操作

  ├─package.json        // npm 包管理配置文件

  ├─README.md

nuxt的路由是自动生成的,例如再pages下创建demo.vue,浏览器输入http://localhost:3000/demo即可发文到demo.vue文件。

└─pages

    ├─index.vue

    └─user

      ├─index.vue

      ├─demo.vue

 Nuxt.js 自动生成的路由配置如下

router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue'
    },
    {
      name: 'user',
      path: '/user',
      component: 'pages/user/index.vue'
    },
    {
      name: 'demo',
      path: '/user/demo',
      component: 'pages/user/demo.vue'
    }
  ]
}

页面跳转
不要写成a标签,因为是重新获取一个新的页面,并不是SPA
<nuxt-link to="/users"></nuxt-link>
this.$router.push(’/users’)
不能写a标签,a标签相当刷新页面
动态路由
在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录(例如新建_id文件夹,里面再创建一个index.vue),建议目录形式,文件容易出错,文件名可以自定义,但vue文件必须用index不然没效果。
获取动态参数{{$route.params.id}}
路由参数校验
Nuxt.js 可以让你在动态路由对应的页面组件中配置一个validate方法用于校验动态路由参数的有效性。该函数有一个布尔类型的返回值,如果返回true则表示校验通过,如果返回false则表示校验未通过。
注意1,这个validate要写在_id文件夹下面的index.vue文件里而且不能写在methods里,和methods同级即可。返回false就会找不到页面
注意2,validate这个方法拿不到this 可以用它自带的参数obj解决(可以打印这个obj,但是要在命令行里看不是浏览器)

export default {
  // nuxt中使用validate方法进行路由参数校验,这个方法必须返回一个布尔值,为true表示校验通过,为false表示校验失败。注意validate不能写到methods属性中。
  validate(obj) {
    // console.log(obj);
    // return true
    return /^\d+$/.test(obj.params.id)
  }
}

嵌套路由
添加一个Vue文件,作为父组件
添加一个与父组件同名的文件夹来存放子视图组件
在父文件中,添加组件,用于展示匹配到的子视图
pages文件夹下创建test.vue 然后创建一个test文件夹,创建_id文件,再创建test.vue
以下是pages文件夹下的test.vue

<template>
    <div class=''>
        <nuxt-link :to="`/test/${3}`">
          <button>todemo</button>
        </nuxt-link>
        <nuxt-child></nuxt-child>
    </div>
</template>

layouts - pages - components

创建layout

去layouts文件夹下面新建一个新的layout组件,例如test.vue,并在这个组件中添加组件,这样,所有和test相关的页面都会有公共的layout

给需要用到test.vue的组件添加layout属性,并指定需要使用的layout,例如:layout: ‘test’

<script>
import Mynav from '~/components/Mynav'
export default {
  // 通过layout属性,指定当前页面使用的布局组件,相当于本组件多了一个header
  layout: 'headerlayout',
  components: {
    Mynav
  },
  data () {
    return {
      teacherList: [
        {name: 'jack1', id: 1},
        {name: 'jack2', id: 2},
        {name: 'jack3', id: 3}
      ]
    }
  }
}
</script>

名字就是路由名称。

组件nuxt表示显示的页面。因为的组件名是movie,那么它会自动找到pages目录下的moive.vue展示

点击link就会跳转到movie type文件夹的index.vue。
如果路由后还有参数就继续创建文件夹
创建特殊layout-error
layouts文件夹下面新建error.vue,error是关键字,error.vue相当于自定义的404页面。
新建一个组件
在components文件夹下面新建一个Header.vue组件
引入组件,注意路径的~符号,表示根目录
layout中也能使用组件
配置样式nuxt.config.js

// ~表示当前目录
css: [
    '~/assets/styles/index.ccs'
],

ElementUI使用

npm i element-ui -S

在plugins文件夹下面,创建ElementUI.js文件 

import Vue from 'vue'
import ElementUI from 'element-ui'
Vue.use(ElementUI)

在nuxt.config.js中添加配置 

css: [ 
    // 配置全局样式,不带~/表示node_modules下的文件
    'element-ui/lib/theme-chalk/index.css'
],

plugins: [
    // ssr: true表示这个插件只在服务端起作用
    {
        src: '~/plugins/ElementUI', ssr: true 
    }
],

build: {   
    // 防止element-ui被多次打包
    vendor: ['element-ui', 'axios']
}

注意: 在nuxt中,生命周期只有created以及beforeCreate这两个函数能够在服务端正常使用, 在nuxt中发异步请求不能在created生命周期函数中去发,因为它会在前端执行。

Nuxt.js 扩展了 Vue.js,增加了一个叫 asyncData 的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据。asyncData方法会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。所以需要注意这个函数中不能使用this 可以使用asyncData(context, callback)callback获取,注意asyncData(context, callback)是和methods平级的函数。

 asyncData(context, callback) {
     console.log(context);
     setTimeout(() => {
       // callback有两个参数,第一个是错误对象,第二个是数据对象
      callback(null, {
       movieList: [
           {title: 'test1', id: 1},
          {title: 'test11', id: 2},
         {title: 'test131', id: 3}
        ]
       })
     }, 1000);
   }

注意:常规写法如果在created钩子中写异步,是在客户端渲染的而不是在服务端

使用方法:asyncData(context, callback) {callback(null, data)}

context.route.params.xxx获取参数

callback(new Error(), data)渲染出错的页面

注意:这个方法在服务器端执行和在客户端执行的区别

 axios的使用

npm install --save axios
import axios from 'axios'

asyncData(context, callback) {
  axios.get('http://localhost:9500/study_test')
    .then(res => {
      console.log(res);
      callback(null, {list: res.data})
    })
}

为防止重复打包,在nuxt.config.js中配置

module.exports = {
  build: {
    vendor: ['axios']
  }
}

可以用json-server模拟假数据

npm i json-server -g

可能会报错,用管理员身份运行powershell执行就解决了。

json-server --watch --port 3302 db.json
{
  "study_test": [
    {
      "id": 1,
      "title": "黄金3",
      "rating": 5.3,
      "genres": ["动作", "犯罪"],
      "img": "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2535191502.jpg"
    }],
}

SEO优化,全局和局部

全局,在nuxt.config.js配置文件中修改

head: {
    title: pkg.name,
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: pkg.description }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },

局部,再指定页面加入

<template>
  <div class="movie">
    <h1>欢迎访问本网站!</h1>
  </div>
</template>
<script>
export default {
  layout: 'movie',
  head() {
    return {
      title: '电影',
      meta: [
        {name: 'keywords', content: '电影、经典电影、热映、电视剧、美剧、影评、电影院'}
      ]
    }
  }
}
</script>

这些keywords会被搜索引擎抓取到。最后打包部署

npm run build

把本地文件的.nuxt、static,package.json、nuxt.config.js,这四个文件夹放到服务器目录文件下,然后配置nginx,当然nuxt为服务端渲染,所以在服务端需要开启进程守护,我们可以使用pm2参考CentOS:安装node及pm2-CSDN博客

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值