1.前端耗时少,首屏加载速度快。因为后端拼接完了html,浏览器只需要直接渲染出来。
2.有利于SEO。因为在后端有完整的html页面,所以爬虫更容易爬取获得信息,更有利于seo。
3.无需占用客户端资源。即解析模板的工作完全交由后端来做,客户端只要解析标准的html页面即可,这样对于客户端的资源占用更少,尤其是移动端,也可以更省电。
4.后端生成静态化文件。即生成缓存片段,这样就可以减少数据库查询浪费的时间了,且对于数据变化不大的页面非常高效 。
1.不利于前后端分离,开发效率低。(无框架前)
2.占用服务器端资源。
即服务器端完成html模板的解析,如果请求较多,会对服务器造成一定的访问压力。而如果使用前端渲染,就是把这些解析的压力分摊了前端,而这里确实完全交给了一个服务器。
2016 年 10 月 25 日, zeit.co 背后的团队对外发布了 Next.js ,一个 React 的服务端渲染应用框架。几小时后,与 Next.js 异曲同工,一个基于 Vue.js 的服务端渲染应用框架应运而生,我们称之为:Nuxt.js。
Nuxt 是服务器呈现的简约应用程序的框架,通过对客户端和服务端基础架构的抽象,Nuxt.js 可以让开发者更专注于页面的UI渲染。作用就是在 node.js 上进一步封装,然后省去我们搭建服务端环境的步骤,只需要遵循这个库的一些规则就能轻松实现 SSR。
Nuxt.js 集成了以下组件/框架,用于开发完整而强大的 Web 应用:
压缩并 gzip 后,总代码大小为:57kb (如果使用了 Vuex 特性的话为 60kb)。
另外,Nuxt.js 使用 Webpack 和 vue-loader 、 babel-loader 来处理代码的自动化构建工作(如打包、代码分层、压缩等等)。
work flow:
详见 zh.nuxtjs.org/guide/insta…
├── assets //用于组织未编译的静态资源如 LESS、SASS 或 JavaScript
│ └── README.md
├── components //用于组织应用的 Vue.js 组件。Nuxt.js 不会扩展增强该目录下 Vue.js 组件,即这些组件不会像页面组件那样有 asyncData 方法的特性
├── layouts //布局目录 layouts 用于组织应用的布局组件。若无额外配置,该目录不能被重命名。
│ ├── README.md
│ └── default.vue
├── middleware //目录用于存放应用的中间件
│ └── README.md
├── nuxt.config.js //nuxt 配置文件
├── pages //放page页面,自动生产路由
│ ├── README.md
│ ├── index.vue
│
├── plugins //用于组织那些需要在 根vue.js应用 实例化之前需要运行的 插件
│ ├── README.md
│ └── axios.js
├── server
│ └── index.js //服务配置
├── static
│ ├── README.md //存放静态文件,不被编译
│ ├── favicon.ico
│ ├── icon.png
│ └── sw.js
├── store //vuex状态
│ ├── README.md
│ ├── index.js
│ └── webLogin.js
复制代码
Nuxt扩展了Vue的生命周期
export default {
middleware (ctx) {}, //服务端
validate (ctx) {}, // 服务端
asyncData (ctx) {}, //服务端
fetch (ctx) {}, // store数据加载
beforeCreate () { // 服务端和客户端都会执行},
created () { // 服务端和客户端都会执行 },
beforeMount () {},
mounted () {} // 客户端
}
复制代码
context 的可用属性一览:
属性字段 | 类型 | 可用 | 描述 |
---|---|---|---|
app | Vue 根实例 | 客户端 & 服务端 | 包含所有插件的 Vue 根实例。例如:在使用 axios 的时候,你想获取 axios 来获取 |
isClient | Boolean | 客户端 & 服务端 | 是否来自客户端渲染(废弃。请使用 process.client ) |
isServer | Boolean | 客户端 & 服务端 | 是否来自服务端渲染(废弃。请使用 process.server ) |
isStatic | Boolean | 客户端 & 服务端 | 是否来自 nuxt generate 静态化(预渲染)(废弃。请使用 process.static ) |
isDev | Boolean | 客户端 & 服务端 | 是否是开发 dev 模式,在生产环境的数据缓存中用到 |
isHMR | Boolean | 客户端 & 服务端 | 是否是通过模块热替换 webpack hot module replacement (仅在客户端以 dev 模式) |
route | Vue Router 路由 | 客户端 & 服务端 | Vue Router 路由实例 |
store | Vuex 数据 | 客户端 & 服务端 | Vuex.Store 实例。只有vuex 数据流存在相关配置时可用 |
env | Object | 客户端 & 服务端 | nuxt.config.js 中配置的环境变量,见 环境变量 api |
params | Object | 客户端 & 服务端 | route.params 的别名 |
query | Object | 客户端 & 服务端 | route.query 的别名 |
req | http.Request | 服务端 | Node.js API 的 Request 对象。如果 Nuxt 以中间件形式使用的话,这个对象就根据你所使用的框架而定。nuxt generate 不可用 |
res | http.Response | 服务端 | Node.js API 的 Response 对象。如果 Nuxt 以中间件形式使用的话,这个对象就根据你所使用的框架而定。nuxt generate 不可用 |
redirect | Function | 客户端 & 服务端 | 用这个方法重定向用户请求到另一个路由。状态码在服务端被使用,默认 302 redirect([status,] path [, query]) |
error | Function | 客户端 & 服务端 | 用这个方法展示错误页:error(params) 。params 参数应该包含 statusCode 和 message 字段 |
nuxtState | Object | 客户端 | Nuxt 状态,在使用 beforeNuxtRender 之前,用于客户端获取 Nuxt 状态,仅在 universal 模式下可用 |
beforeNuxtRender(fn) | Function | 服务端 | 使用此方法更新 NUXT 在客户端呈现的变量,fn 调用 (可以是异步) { Components, nuxtState } ,参考 示例 |
asyncData 方法会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,你可以利用 asyncData 方法来获取数据并返回给当前组件。
export default {
data () {
return { project: 'default' }
},
asyncData (context) {
return { project: 'nuxt' }
}
}
复制代码
注意:由于 asyncData 方法是在组件 初始化 前被调用的,所以在方法内是没有办法通过 this 来引用组件的实例对象。
fetch 方法用于在渲染页面前填充应用的状态树(store)数据, 与 asyncData 方法类似,不同的是它不会设置组件的数据。
如果页面组件设置了 fetch 方法,它会在组件每次加载前被调用(在服务端或切换至目标路由之前)。
fetch 方法的第一个参数是页面组件的 上下文对象 context,我们可以用 fetch 方法来获取数据填充应用的vuex状态树。为了让获取过程可以异步,你需要返回一个 Promise,Nuxt.js 会等这个 promise 完成后再渲染组件。
警告: 您无法在内部使用 this 获取组件实例,fetch 是在组件初始化之前被调用
例如 pages/index.vue:
Stars: {{ $store.state.stars }}
你也可以使用 async 或 await 的模式简化代码如下:
Stars: {{ $store.state.stars }}
复制代码
如果要在 fetch 中调用并操作 store,请使用 store.dispatch,但是要确保在内部使用 async / await 等待操作结束:
store/index.js
// ...
export const actions = {
async GET_STARS ({ commit }) {
const { data } = await axios.get('http://my-api/stars')
commit('SET_STARS', data)
}
}
复制代码
监听 query 字符串的改变 默认情况下,不会在查询字符串更改时调用 fetch 方法。如果想更改此行为,例如,在编写分页组件时,您可以设置通过页面组件的 watchQuery 属性来监听参数的变化。了解更多有关 API watchQuery page 的信息。
增加用户体验的两个插件
toast可以说是很常用的功能,一般的UI框架都会有这个功能。但如果你的站点没有使用UI框架,而alert又太丑,不妨引入该模块:
npm install @nuxtjs/toast
复制代码
然后在nuxt.config.js中引入
module.exports = {
modules: [
'@nuxtjs/toast',
['@nuxtjs/dotenv', { filename: '.env.prod' }] // 指定打包时使用的dotenv
],
toast: {// toast模块的配置
position: 'top-center',
duration: 2000
}
}
复制代码
这样,nuxt就会在全局注册$toast方法供你使用,非常方便:
this.$toast.error('服务器开小差啦~~')
this.$toast.error('请求成功~~')
复制代码
nuxt内置了页面顶部loading进度条的样式 推荐使用,提供页面跳转体验。
//打开
this.$nuxt.$loading.start()
//完成
this.$nuxt.$loading.finish()
复制代码
更多 API 详见官网 zh.nuxtjs.org/api
源码地址:github.com/nuxt/nuxt.j…
源码目录:
这个是我们项目生成的临时文件,我们项目运行时候配置的文件都是在这里,大家可以看到这里的路由文件,没错,这个就是系统自动给我们配置的路由文件,根据我们的 pages 文件夹路径生成的,大家还可以看到,由app.js ,client.js 和 server.js 这两个就是类似我们的 SSR 中配置的那个 server.js 入口文件,然后还有 middleware.js 中间件文件,其实这个时候我们大概能懂了,上边我们说的工作流程,走的就是这个 临时文件.nuxt 文件夹中的内容,但是这个文件夹是如何生成的呢,大家请往下看。
本文主要研究nuxt的运行原理,分析它从接收一条nuxt指令,到完成指令背后所发生的一系列事情,在开始本文之前,请读者务必亲自体验过nuxt.js的使用,并且具备一定的vue.js相关开发经验。
通过查看nuxt.js工程目录下的package.json文件,我们可以看到下列几条指令:
"scripts": { "dev": "nuxt", // 开启一个监听3000端口的服务器,同时提供hot-reloading功能
"build": "nuxt build", //构建整个应用,压缩合并JS和CSS文件(用于生产环境)
"start": "nuxt start", // 开启一个生产模式的服务器(必须先运行nuxt build命令)
"generate": "nuxt generate" //构建整个应用,并为每一个路由生成一个静态页面(用于静态服务器)
}
复制代码
咱们还从来没有看过我们的依赖包哈,今天就来看看,打开我们的 node_modules 文件夹下的 nuxt工程文件夹 进入到到bin目录,我们可以看到几个文件:
咱们就说一下 dev 是如何工作的,咱们先找到一个片段,发现基本是执行了以下几个步骤:
async run (cmd) {
const { argv } = cmd
await this.startDev(cmd, argv, argv.open)
},
async startDev (cmd, argv) {
let nuxt
try {
nuxt = await this._listenDev(cmd, argv)
} catch (error) {
consola.fatal(error)
return
}
try {
await this._buildDev(cmd, argv, nuxt)
} catch (error) {
await nuxt.callHook('cli:buildError', error)
consola.error(error)
}
return nuxt
},
复制代码
那什么是 nuxt() 类,它又是执行了什么样的方法呢?
上图中每一步都可以在具体的代码中自行浏览。在用户输入指令并实例化了Nuxt()类以后,实例化
同时,Nuxt()类也提供了一个close()公有方法,用于关闭其所开启的服务器。
简单来说,build()方法在判断完运行条件后,会先初始化产出目录.nuxt,然后通过不同目录下的文件结构来生成一系列的配置,写入模板文件后输出到.nuxt目录。接下来,则会根据不同的开发环境来调用不同的webpack配置,运行不同的webpack构建方案。
在nuxt/lib目录下找到render.js文件,它包含着我们即将要分析的三个方法:render(), renderRoute(), renderAndGetWindow()。
通过这张图片,我们可以知道nuxt对于处理“客户端渲染”与“服务端渲染”的逻辑其实是非常清晰的。
上传全部代码到自己到服务器上执行 编译打包:
npm run build
npm run start
复制代码
建议部署方式Docker+K8S
------------------------------------个人项目-----------------------------------
如果你发现本项目有内容上的错误,欢迎提交 issues 进行指正。
建了一个“全栈大前端”的微信交流群,欢迎纯粹技术交流爱好者加入!