资源

vue ssr
nuxt.js 官网
Nuxt.js 官方文档-中文
nuxt 中文
本文大部分内容转载于:服务端预渲染之Nuxt(介绍篇)

概念

现在前端开发一般都是前后端分离,mvvmmvc 的开发框架,如 AngularReactVue 等,虽然写框架能够使我们快速的完成开发,但是由于前后台分离,给项目 SEO 带来很大的不便,搜索引擎在检索的时候是在网页中爬取数据,由于单页面应用读取到的页面是几乎空白的,无法爬取到任何数据信息

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset=utf-8>
  5. <meta name=viewport content="width=device-width,initial-scale=1">
  6. <title>authorization_web</title>
  7. </head>
  8. <body>
  9. <div id=app></div>
  10. </body>
  11. </html>

如上代码,单页面应用查看源代码的时候如上所示,所以搜索引擎无法爬取到任何信息,搜索引擎会认为当前页面为一个空页面。为了解决 **SEO** 问题,推出了 **SSR** 服务端预渲染,以便提高对 **SEO** 优化

什么是SSR

在认识 SSR 之前,首先对 CSRSSR 之间做个对比。

传统的web开发:(mvc)

首先看一下传统的 web开发,传统的web开发是,客户端向服务端发送请求,服务端查询数据库,拼接 HTML字符串(模板),通过一系列的数据处理之后,把整理好的HTML返回给客户端,浏览器相当于打开了一个页面。这种比如我们经常听说过的jspPHPaspx 也就是传统的 **MVC** 的开发Nuxt 介绍 - 图1> 传统的web开发,网页内容在服务端渲染完成,一次性传输到浏览器

单页应用 Single Page App:(CSR)

SPA 应用,到了 VueReact,单页面应用优秀的用户体验,逐渐成为了主流,页面整体式 javaScript 渲染出来的,称之为客户端渲染 **CSR**SPA渲染过程。由客户端访问URL发送请求到服务端,返回HTML结构(但是SPA返回的HTML结构是非常小的,只有一个基本的结构,如第一段代码所示)。客户端接收到返回结果之后,在客户端开始渲染HTML,渲染时执行对应javaScript,最后渲染template,渲染完成之后,再次向服务端发送数据请求,注意这里是数据请求,服务端返回json格式数据。客户端接收数据,然后完成最终渲染。 Nuxt 介绍 - 图2> 单页应用优秀的用户体验,使其逐渐成为主流,页面内容由JS渲染出来,这种方式称为客户端渲染。

SPA虽然给服务器减轻了压力,但是也是有缺点的:

  1. 首屏渲染时间比较长:必须等待JavaScript加载完毕,并且执行完毕,才能渲染出首屏。
  2. SEO不友好:爬虫只能拿到一个div元素,认为页面是空的,不利于SEO。

为了解决如上两个问题,出现了SSR解决方案,后端渲染出首屏的DOM结构返回,前端拿到内容带上首屏,后续的页面操作,再用单页面路由和渲染,称之为服务端渲染(SSR)。

服务端渲染 Server Side Render

SSR渲染流程是这样的,客户端发送URL请求到服务端,服务端读取对应的url的模板信息,在服务端做出html和数据的渲染,渲染完成之后返回html结构,客户端这时拿到之后首屏页面的html结构。所以用户在浏览首屏的时候速度会很快,因为客户端不需要再次发送ajax请求。但是并不是做了SSR我们的页面就不属于SPA应用了,它仍然是一个独立的spa应用。
SSR是处于CSR与SPA应用之间的一个折中的方案,在渲染首屏的时候在服务端做出了渲染,注意仅仅是首屏,其他页面还是需要在客户端渲染的,在服务端接收到请求之后并且渲染出首屏页面,会携带着剩余的路由信息预留给客户端去渲染其他路由的页面。 Nuxt 介绍 - 图3> 后端渲染出完整的首屏的dom结构返回,前端拿到的内容包括首屏及完整spa结构,应用激活后依然按照spa方式运行,这种页面渲染方式被称为服务端渲染(server side render)

nuxt 介绍

Nuxt官方网站有一句这样的话:Nuxt.js预设了使您开发Vue.js应用程序所需的所有配置。Nuxt是一个基于Vue.js的通用应用框架。通过对客户端/服务端基础框架的抽象组织,Nuxt主要关注的是应用的ui渲染。

通过上面的这些介绍可以简单的得出:

  1. Nuxt不仅仅用于服务端渲染也可以用于SPA应用的开发
  2. 利用Nuxt提供的基础项目结构、路由生成、异步数据加载,中间件、插件、布局等特性可大幅提升开发效率
  3. Nuxt可用于网站静态化,可以使用命令将整个网页打包成静态页面,使SEO更加友好

nuxt.js特性

  1. 基于 Vue
  2. 自动代码分层
  3. 服务端渲染
  4. 强大的路由功能,支持异步数据
  5. 静态文件服务
  6. ECMAScript6ECMAScript7 的语法支持
  7. 打包和压缩 JavaScriptCss
  8. HTML 头部标签管理
  9. 本地开发支持热加载
  10. 集成 ESLint
  11. 支持各种样式预编译器 SASSLESS 等等
  12. 支持 HTTP/2 推送

nuxt渲染流程

一个完整的服务器请求到渲染的流程
image.png
通过上面的流程图可以看出,Nuxt.js 通过一系列构建于 Vue.js 之上的方法进行服务端渲染,具体流程如下:

第一步:当一个客户端请求进入的时候,服务端通过调用 nuxtServerInit 方法。预先将服务器的数据保存,如已登录的用户信息等。这个方法也可以执行异步操作 Store action,并等待数据解析后返回。让我们可以将从服务端拿到的信息存储到 Store 中。

第二步:之后使用了 Middleware 中间件机制,中间件其实就是一个函数,会在每个路由执行之前去执行,在这里可以做很多事情,或者说可以理解为是路由器的拦截器的作用。读取 nuxt.config.js 中全局 middleware 字段的配置,并调用相应的中间件方法 匹配并加载与请求相对应的 layout 调用 layoutpage 的中间件方法。

第三步:然后再调用 validate 方法,对客户端携带的请求参数进行校验,或是对第一步中服务器下发的数据进行校验,如果校验失败,将抛出 404 页面。

第四步:调用 asyncDatafetch 方法。这两个方法都会在组件加载之前被调用(进入正式的渲染周期),它们的职责各有不同,asyncData 用来异步的进行组件数据的初始化工作,把请求到的数据合并到 Vue 中的 data 中。而 fetch 方法偏重于异步获取数据后修改 Vuex 中的状态。

nuxt安装

安装命令:

确保安装了npx(npx在NPM版本5.2.0默认安装了):

  1. npx create-nuxt-app <项目名>
  2. yarn create nuxt-app <project-name>

安装向导:

  1. Project name // 项目名称
  2. Programming language // 编程语言:JavaScript / TypeScript
  3. Packge manager // 包管理工具: Yarn / NPM
  4. UI framework // ui框架: None / Ant Design Vue / BalmUI / Bootstrap Vue / Buefy / Chakra UI / Element / Framevuerk / Oruga / Tachyons / Tailwind CSS / Windi CSS / Vant / View UI / Vuesax / Vuetify.js
  5. Nuxt.js modules // 选择nuxt.js模板:
  6. Axios - Promise based HTTP client
  7. Progressive Web App (PWA)
  8. Content - Git-based headless CMS
  9. Linting tools // 选择代码规范化工具:
  10. ESLint
  11. Prettier
  12. Lint staged files
  13. StyleLint
  14. Commitlint
  15. 建议全选,团队协作时利于整体代码管理
  16. Testing framework // 选择测试框架:None / Jest / AVA / WebdriverIO / Nightwatch
  17. Rendering mode // 渲染模式:Universal (SSR / SSG) 渲染所有连接页面 / Single Page App 只渲染当前页面
  18. Deployment target // 开发目标:Server (Node.js hosting) / Static (Static/Jamstack hosting)
  19. Development tools // 开发工具
  20. jsconfig.json (Recommended for VS Code if you're not using typescript)
  21. Semantic Pull Requests
  22. Dependabot (For auto-updating dependencies, GitHub only)
  23. Continuous integration // 持续集成:None / GitHub Actions (GitHub only) / Travis CI / CircleCI
  24. What is your GitHub username? wei0925
  25. Version control system: // 版本控制系统:Git / None

等待安装,安装完毕出现下方提示命令

  1. To get started: 项目运行
  2. cd nuxt-project
  3. npm run dev
  4. To build & start for production: 项目打包
  5. cd nuxt-project
  6. npm run build
  7. npm run start
  8. To test: 项目测试
  9. cd nuxt-project
  10. npm run test

目录结构介绍

  • .nuxt
    • Nuxt自动生成,临时的用于编辑的文件,build
  • assets
    • 存放未编译的静态资源文件
    • 放置需要经过 webpack 打包处理的资源文件,如 lesssassJavaScript
  • components
    • 存放 Vue.js 可以复用的组件。
    • Nuxt.js 不会扩展增强该目录下 Vue.js 组件,即这些组件不会像⻚面组件那样有 asyncData 方法的特性。
  • content
  • layouts
    • 存放布局组件
    • 该目录名为 Nuxt.js 保留的,不可更改。
    • 页面都需要有一个布局,默认为 default.vue。它规定了一个页面如何布局页面。 可以在这个目录下创建全局页面的统一布局,或是错误页布局。
    • 如果需要在布局中渲染 pages 目录中的路由页面,需要在布局文件中加上 <nuxt /> 标签。
    • 如果需要在普通页面中使用下级路由,则需要在页面中添加 <nuxt-child />
  • middleware
    • 存放中间件
    • 在加载组件之前调用。可以在页面中调用: middleware: 'middlewareName'
  • node_modules
    • 存放依赖包
  • pages
    • 存放页面
    • 一个 vue 文件即为一个页面。index.vue 为根页面
    • 我们主要的工作区域。用于nuxt自动组织应用的路由及视图。Nuxt.js 框架读取该目录下所有的 .vue 文件并自动生成对应的路由配置。
    • 若需要二级页面,则添加文件夹即可
    • 如果页面的名称类似于 id.vue (以 开头),则为动态路由页面
      • _ 后为匹配的变量(params)。
      • 若变量是必须的,则在文件夹下建立空文件 index.vue。
  • plugins
    • 存放插件。
    • 用于组织需要在 vue.js 实例化之前运行的 Javascript 插件。
    • 需要注意的是,在任何 Vue 组件的生命周期内, 只有 beforeCreate 和 created 这两个钩子方法会在 客户端和服务端均被调用。其他钩子方法仅在客户端被调用。 可以在这个目录中放置自定义插件,在根 Vue 对象实例化之前运行。例如,可以将项目中的埋点逻辑封装成一个插件,放置在这个目录中,并在 nuxt.config.js 中加载。
  • static
    • 存放静态资源文件
    • 此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。放置不需要经过 webpack 打包的静态资源。如一些 js, css 库,图片,ico,logo,导航图标。
    • 服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下。
  • store
    • vuex 状态管理。官网
    • Nuxt.js 框架集成了 Vuex 的相关功能配置,在 store 目录下创建一个 index.js 文件可激活这些配置。
  • test
    • 存放测试代码
  • .babelrc
  • .editorconfig
    • 开发工具格式配置
  • .eslintrc.js
    • eslint 的配置文件,用于检查代码格式
  • .gitignore
    • 配置 git 不上传的文件
  • .prettierrc
  • commitlint.config.js
  • jest.config.js
    • 自动化测试配置
  • jsconfig.json
  • nuxt.config.js
    • Nuxt.js 应用个性化配置,以便覆盖默认配置。官网
  • package-lock.json
    • npm 自动生成,用于帮助 package 的统一性设置的,yarn也有相同的操作
  • package.json
    • npm 包管理配置文件
  • stylelint.config.js

nuxt.config.js

  1. const pkg = require('./package')
  2. module.exports = {
  3. mode: 'universal', // 当前渲染使用模式
  4. head: { // 页面head配置信息
  5. title: pkg.name, // title
  6. meta: [ // meat
  7. { charset: 'utf-8' },
  8. { name: 'viewport', content: 'width=device-width, initial-scale=1' },
  9. { hid: 'description', name: 'description', content: pkg.description }
  10. ],
  11. link: [ // favicon,若引用css不会进行打包处理
  12. { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
  13. ]
  14. },
  15. loading: { color: '#fff' }, // 页面进度条
  16. css: [ // 全局css(会进行webpack打包处理)
  17. 'element-ui/lib/theme-chalk/index.css'
  18. ],
  19. plugins: [ // 插件
  20. '@/plugins/element-ui'
  21. ],
  22. modules: [ // 模块
  23. '@nuxtjs/axios',
  24. ],
  25. axios: {},
  26. build: { // 打包
  27. transpile: [/^element-ui/],
  28. extend(config, ctx) { // webpack自定义配置
  29. }
  30. }
  31. }

packge.json

  1. {
  2. "scripts": {
  3. "dev": "nuxt", // 开发环境
  4. "build": "nuxt build", // 打包/构建项目
  5. "start": "nuxt start", // 线上部署命令
  6. "generate": "nuxt generate", // 生成静态页面
  7. "lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
  8. "lint:style": "stylelint \"**/*.{vue,css}\" --ignore-path .gitignore",
  9. "lint": "npm run lint:js && npm run lint:style",
  10. "test": "jest" // 自动化测试
  11. },
  12. }