vue.js服务器端渲染的两种方式之 Nuxt.js 使用
vue.js服务器端渲染的两种方式:
- vue-server-renderer
- Nuxt.js
1. vue-server-renderer
vue-server-renderer插件,使用 Node.js server 的服务器端单页面应用程序渲染。将 Vue 服务器端渲染 (SSR) 与其他后端设置进行混合使用。
用法:安装 ==> 渲染一个 Vue 实例 ==> 与服务器集成
从头搭建一个服务端渲染的应用是相当复杂的。在工作中推荐使用 Nuxt.js 来完成服务端渲染。关于 vue-server-renderer 的使用方法在这里就不做详细的说明,感兴趣的话可以查看官方文档。
2. Nuxt.js
2016 年 10 月 25 日,zeit.co 背后的团队对外发布了 Next.js,一个 React 的服务端渲染应用框架。几小时后,与 Next.js 异曲同工,一个基于 Vue.js 的服务端渲染应用框架应运而生,我们称之为:Nuxt.js。
2.1 介绍
- Nuxt 是一个基于 Vue 生态的更高层的通用应用框架,为开发服务端渲染的 Vue 应用提供了极其便利的开发体验。
- Nuxt.js 主要关注的是应用的 UI渲染。
- Nuxt.js 预设了利用 Vue.js 开发服务端渲染的应用所需要的各种配置。
- 使用 nuxt generate 命令,可以为基于 Vue.js 的应用生成对应的静态代码,存放在根目录下的dist目录里。
- Nuxt.js 使用 Webpack 和 vue-loader 、 babel-loader 来处理代码的自动化构建工作(如打包、代码分层、压缩等等)。
2.2 特性
- 基于 Vue.js
- 自动代码分层
- 服务端渲染
- 强大的路由功能,支持异步数据
- 静态文件服务
- ES2015+ 语法支持
- 打包和压缩 JS 和 CSS
- HTML 头部标签管理
- 本地开发支持热加载
- 集成 ESLint
- 支持各种样式预处理器: SASS、LESS、 Stylus 等等
- 支持 HTTP/2 推送
2.3 安装
通过脚手架工具 create-nuxt-app 可以快速创建一个 nuxt 项目
终端中输入以下命令,在当前目录创建 nuxt 项目npx create-nuxt-app ./
创建时需要进行一些选择
$ npx create-nuxt-app ./
create-nuxt-app v2.15.0
✨ Generating Nuxt.js project in ./
? Project name nuxtJs //项目名称
? Project description My astounding Nuxt.js project //项目描述
? Author name 11111 //作者姓名
? Choose programming language JavaScript //选择开发的语言 javascript or typescript
? Choose the package manager Yarn //选择包管理的工具 npm or yarn
? Choose UI framework Element //选择一个UI框架
? Choose custom server framework Express //选择一种服务端框架
? Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection) //检查代码是否规范
? Choose test framework None //选择一个测试框架
? Choose rendering mode Universal (SSR) //选择一种渲染模式 SSR or SPA
? Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection)
Warning: name can no longer contain capital letters
创建成功后,会输出下面的信息
???? Successfully created project nuxtJs
To get started:
yarn dev
To build & start for production:
yarn build
yarn start
终端输入 yarn dev,启动项目,浏览器打开 http://localhost:3000/,页面出现以下内容,则项目创建成功。
2.4 目录结构
nuxt中默认设置的别名:
别名 | 目录 |
---|---|
~ 或 @ | srcDir |
~~ 或 @@ | rootDir |
默认情况下,srcDir 和 rootDir 相同。
2.5 引入资源文件
在vuecli中,我们可以在入口文件中引入一些静态资源文件,比如scss文件等,在nuxt中,文件的引入需要在nuxt.config.js 配置文件中设置。修改配置文件后,需要重新启动服务。
比如:在assets目录下新建了 /css/style.scss 文件,在 nuxt.config.js配置文件中添加如下内容:
重启服务后,发现报错了
ERROR Failed to compile with 1 errors friendly-errors 19:20:30
This relative module was not found: friendly-errors 19:20:30 friendly-errors 19:20:30
* ../assets/css/style.scss in ./.nuxt/App.js friendly-errors 19:20:30
ℹ Waiting for file changes
如果我们要想在项目中解析sass文件的话,需要手动安装sass-loaderyarn add node-sass sass-loader -D
安装完,不需要做别的配置,重新启动服务,就可以了。
2.6 路由
nuxtJs中并不需要手动配置路由,它可以依据 pages 目录结构自动生成 vue-router 模块的路由配置。
<template>
<nuxt-link to="/">首页</nuxt-link>
<!-- <nuxt-link> 相当于 <router-link> -->
<nuxt-link to="/user">用户</nuxt-link>
<nuxt/>
<!-- <nuxt/> 相当于 <router-view /> -->
</template>
2.6.1 基础路由
假设 pages 的目录结构如下:
pages/
--| user/
-----| index.vue
-----| one.vue
--| index.vue
那么,Nuxt.js 自动生成的路由配置如下:
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'user',
path: '/user',
component: 'pages/user/index.vue'
},
{
name: 'user-one',
path: '/user/one',
component: 'pages/user/one.vue'
}
]
}
2.6.2 动态路由
在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录。
通过$route.params.id
获取路由参数。
假设 pages 的目录结构如下:
pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue
--| index.vue
那么,Nuxt.js 自动生成的路由配置如下:
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'users-id',
path: '/users/:id?',
component: 'pages/users/_id.vue'
},
{
name: 'slug',
path: '/:slug',
component: 'pages/_slug/index.vue'
},
{
name: 'slug-comments',
path: '/:slug/comments',
component: 'pages/_slug/comments.vue'
}
]
}
2.6.3 嵌套路由
- 创建内嵌子路由,你需要添加一个 Vue 文件,同时添加一个与该文件同名的目录用来存放子视图组件。
- 在父组件(.vue文件) 内增加 用于显示子视图内容。
假设 pages 的目录结构如下:
pages/
--| users/
-----| _id.vue
-----| index.vue
--| users.vue
那么,Nuxt.js 自动生成的路由配置如下:
router: {
routes: [
{
path: '/users',
component: 'pages/users.vue',
children: [
{
path: '',
component: 'pages/users/index.vue',
name: 'users'
},
{
path: ':id',
component: 'pages/users/_id.vue',
name: 'users-id'
}
]
}
]
}
2.7 请求数据
- Nuxt.js 扩展了 Vue.js,增加了一个叫
asyncData
的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据。 - Nuxt.js 会将 asyncData 返回的数据融合组件 data 方法返回的数据一并返回给当前组件。
- 由于asyncData方法是在组件初始化前被调用的,所以在方法内是没有办法通过 this 来引用组件的实例对象。
例如在组件中请求数据,可以这么写:
<template>
<div>
{{result}}
</div>
</template>
<script>
import axios from "axios"
export default {
async asyncData() {
let rs = await axios.get("/data/list.json")
return {
result: rs.data
}
}
}
</script>
2.8 vuex
- 在store目录下创建的 index.js 文件,nuxtJs 会自动将该文件引入到项目里。
- 如果有多个模块,就新建多个js文件,每个文件对应一个模块,不需要再做额外的关联。
- 在组件中操作vuex中的数据时,和在vueJs中使用方法一样。
- 与在vueJs中使用vuex不同的是,在index.js 文件中,state、mutation等方法需要以函数的形式导出。
nuxtJs中使用vuex:
export const state = () => ({
counter: 100
})
export const mutations = {
increment (state) {
state.counter++
}
}
vueJs中使用vuex:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
counter: 100
},
mutations: {
increment (state) {
state.counter++
}
},
})
在组件中操作vuex数据:
<template>
<div>
{{$store.state.counter}}
<button @click="$store.commit('increment')">increment</button>
</div>
</template>
2.9 视图
页面模板,默认使用 layouts目录下的 default.vue 组件,这个组件将用于所有未指定布局的页面。
如果需要自定义页面模板,可以在 layouts 目录下创建一个自定义布局,在页面中设置 layout 属性,指定这个页面模板。
例如,在layouts 目录下新建了 dialog.vue 文件:
<template>
<div>
<nuxt />
</div>
</template>
然后,我们必须告诉页面(即pages目录下的组件)使用这个自定义布局:
<template>
<div> </div>
</template>
<script>
export default {
layout:"dialog"
}
</script>
在工作中如果已经使用vuecli开发完成了一个项目,不建议再使用Nuxt.js 来做服务器端渲染,因为迁移的成本是很高的。可以使用php或者java在服务器端生成静态页面,再输出到浏览器。