Nuxt入门到打包部署 Vue-SSR项

Vue

2020年12月24日 11:45:391422

什么是服务端渲染

前端渲染流程:

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

优点

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

缺点

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

如何选择

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

静态化:把vue文件变成html文件

什么是Nuxt.js

Vue服务端渲染官网

Nuxt.js官网

Nuxt.js 是一个基于 Vue.js 的通用应用框架。

第一个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'
    }
  ]
}

页面跳转

  1. 不要写成a标签,因为是重新获取一个新的页面,并不是SPA
  2. <nuxt-link to="/users"></nuxt-link>
  3. this.$router.push(’/users’)
  4. 不能写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)
  }
}

嵌套路由

  1. 添加一个Vue文件,作为父组件
  2. 添加一个与父组件同名的文件夹来存放子视图组件
  3. 在父文件中,添加组件,用于展示匹配到的子视图
    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

  1. 去layouts文件夹下面新建一个新的layout组件,例如test.vue,并在这个组件中添加组件,这样,所有和test相关的页面都会有公共的layout
  2. 给需要用到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使用

  1. 下载npm i element-ui -S

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

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

在nuxt.config.js中添加配置

css: [ /* 配置全局样式 */
    '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函数中发送*/
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:3302/in_test')
    .then(res => {
      console.log(res);
      callback(null, {list: res.data})
    })
}

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

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

可以用json-server模拟假数据

  1. 下载json-server工具:npm i json-server -g
  2. 可能会报错,用管理员身份运行powershell执行就解决了。
    json-server --watch --port 3302 db.json
{
  "in_test": [
    {
      "id": 1,
      "title": "黄金兄弟",
      "rating": 5.3,
      "genres": ["动作", "犯罪"],
      "img": "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2535191502.jpg"
    }],
}

SEO优化

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,这四个文件夹放到服务器目录文件下

npm install
npm start

Nginx配置

server {
    listen  80;
    server_name  你的域名 你的域名;
    location ~ / {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Nginx-Proxy true;
        proxy_cache_bypass $http_upgrade;
        proxy_pass http://nodenuxt;  #反向代理
    } 
}
upstream nodenuxt {
    server 127.0.0.1:3000; #nuxt项目 监听端口
    keepalive 64;
}

pm2开启进程守护

pm2 start npm --name “bigstu” – run start

最后这个域名就能正常访问啦:你的域名

pm2 stop 1 // 先停止

pm2 restart 1 // 再重启

赞 15
收藏
分享

本作品系 转载,作者:Jack おう

原文链接:https://blog.csdn.net/weixin_45345105/article/details/109391918

文本版权:文本版权归作者所有

转载需著名并注明出处(禁止商业使用)

评论和回复

0/500
    没有更多啦~
    怎么一条数据都没有呢?
简介
Node.js 服务器将基于 Vue 的组件渲染成 HTML 并传输到客户端,而不是纯 javascript。与传统的 Vue SPA 相比,使用 SSR 将带来巨大的 SEO 提升、更好的用户体验和更多的机会。-- nuxtjs.cn
目录
推荐阅读

D&D By x先生 With