Nuxt.js 服务端渲染方案
- 了解 Nuxt.js 的作用
- 掌握 Nuxt.js 中的路由
- 掌握 layouts、pages 以及 components 的区别
- 能够在 Nuxt.js 项目中使用第三方 ui 库或者插件
- 掌握 Nuxt.js 中异步获取数据的方式
- 掌握 SEO 的优化
一、什么是 SEO
SEO 是英文 Search Engine Optimization 的缩写,中文意思“搜索引擎优化”。SEO 是指在了解搜索引擎自然排名机制的基础上,对网站进行内部及外部的调整优化,改进网站在搜索引擎中的关键词自然排名,从而获得更多流量,最终达成品牌建设或者产品销售的目的。
二、什么是 Nuxt.js
- SPA(single page web application)单页 Web 应用,Web 不再是一张张页面,而是一个整体的应用,一个由路由系统、数据系统、页面(组件)系统 等等,组成的应用程序。
- Vue 就是 SPA 中的佼佼者。
- SPA 应用广泛用于对 SEO 要求不高的场景中
- SEO:搜索引擎优化(增加收录、提高权重)
- SSR:服务器端渲染
将前端拆分 2 部分:客户端和服务端 - 服务器端渲染,就是让前端服务端的代码先执行,就可以提前获得后端提供的数据
- nuxt.js 就是基于 vue.js 的 SSR 技术。
三、为什么选择它
- Nuxt.js 是一个基于 Vue.js 的通用应用框架。主要关注的是应用的 UI 渲染。
- Nuxt.js 预设了利用 Vue.js 开发服务端渲染的应用所需要的各种配置。
- 与传统的 Vue SPA 相比,使用 SSR 将带来巨大的 SEO 提升、更好的用户体验和更多的机会。
- 支持服务器端渲染部署
- 支持静态站点部署
四、如何使用
安装
为了快速入门,Nuxt.js 团队创建了脚手架工具 create-nuxt-app
npx create-nuxt-app <项目名>
# 或
yarn create nuxt-app <项目名>
它会让你进行一些选择:
在集成的服务器端框架之间进行选择
None (Nuxt 默认服务器)
Express
Koa
Hapi
Feathers
Micro
Fastify
Adonis (WIP)
选择您喜欢的 UI 框架
None (无)
Bootstrap
Vuetify
Bulma
Tailwind
Element UI
Ant Design Vue
Buefy
iView
Tachyons
选择您喜欢的测试框架
None (无)
Jest
AVA
选择你想要的 Nuxt 模式 (Universal or SPA)
添加 axios module 以轻松地将 HTTP 请求发送到您的应用程序中。
添加 EsLint 以在保存时代码规范和错误检查您的代码。
添加 Prettier 以在保存时格式化/美化您的代码。
当运行完时,它将安装所有依赖项,因此下一步是启动项目:
cd <project-name>
npm run dev
::: warning
注意:Nuxt.js 会监听 pages 目录中的文件更改,并自动生成相应路由,因此在添加新页面时无需重新启动应用程序,也无需配置路由。
:::
目录结构
└─nuxt-template
├─.nuxt // Nuxt自动生成,临时的用于编译的文件,build
├─assets // 用于组织未编译的静态资源如LESS、SASS或JavaScript
├─components // 用于自己编写的Vue组件
├─layouts // 布局目录,用于组织应用的布局组件
├─middleware // 用于存放应用的中间件
├─node_modules // 依赖文件包
├─pages // 用于组织应用的路由及视图,Nuxt.js根据该目录结构自动生成对应的路由配置
├─plugins // 用于组织那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件
├─static // 用于存放应用的静态文件,此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。 服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下
└─store // 用于组织应用的Vuex 状态管理
├─nuxt.config.js // 用于组织Nuxt.js 应用的个性化配置,以便覆盖默认配置
├─package.json // npm 包管理配置文件
├─README.md
页面和路由
Nuxt.js 依据 pages 目录结构自动生成 vue-router 模块的路由配置。
例如如下目录
└─pages
├─index.vue
└─admin
├─index.vue
├─user.vue
自动生成如下路面
router: {
routes: [
{
name: "index",
path: "/",
component: "pages/index.vue",
},
{
name: "admin",
path: "/admin",
component: "pages/admin/index.vue",
},
{
name: "admin-user",
path: "/admin/user",
component: "pages/admin/user.vue",
},
];
}
页面跳转
参数传递、动态路由及使用参考 vue-router
<nuxt-link to="/admin"></nuxt-link>
this.$router.push("/admin");
layouts & pages & components
-
layouts: 布局文件的目录,里面的 vue 文件用于所使用页面的布局模板,页面不指定则使用默认模板。
default.vue
模板代码<template> <div class="blog-wrap"> <Nuxt /> </div> </template>
blog.vue
模板<template> <div class="default-wrap"> <Header /> <div class="default-box"> <Nuxt /> </div> </div> </template> <style lang="scss"> .default-box { padding: 20px; margin: 20px; } </style>
-
pages: 页面文件,可使用 vue 的所有生命周期函数。也可以使用 nuxt 的专有生命周期函数。
使用layout
指定当前页面所使用的布局模板<template> <div class="article-wrap"> {{ title }} </div> </template> <script> export default { name: "", components: {}, layout: "blog", data() { return { title: "这里是使用了模板的页面", }; }, }; </script> <style lang="scss"> .article-wrap { } </style>
-
components: 存放组件的文件夹,参考 vue 的组件使用方式。
Nuxt 新特性,在此文件夹下的组件将会自动注册,可以不需要引入直接在页面使用。
plugins
Nuxt.js 允许您在运行 Vue.js 应用程序之前执行 js 插件。这在您需要使用自己的库或第三方模块时特别有用。
:::warning
需要注意的是,在任何 Vue 组件的生命周期内, 只有 beforeCreate 和 created 这两个方法会在 客户端和服务端被调用。其他生命周期函数仅在客户端被调用。
:::
假如我们想使用 vant UI,我们需要在程序运行前配置好这个插件。
- 首先下载插件
npm i vant -S
- 增加文件
plugins/vant.js
import Vue from "vue";
import Vant from "vant";
import "vant/lib/index.css";
Vue.use(Vant);
- 然后, 在
nuxt.config.js
内配置 plugins 如下
module.exports = {
plugins: ["~/plugins/vant"],
};
- 最后按照文档在页面中直接使用
<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>
<van-button type="default">默认按钮</van-button>
<van-button type="warning">警告按钮</van-button>
<van-button type="danger">危险按钮</van-button>
获取异步数据 asyncData
你可能想要在服务器端获取并渲染数据。Nuxt.js 添加了 asyncData 方法使得你能够在渲染组件之前异步获取数据。
asyncData
方法会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,你可以利用 asyncData
方法来获取数据并返回给当前组件。
:::warning
注意:由于 asyncData 方法是在组件 初始化 前被调用的,所以在方法内是没有办法通过 this 来引用组件的实例对象。
:::
- 使用自定义请求 axios
import axios from "axios";
export default {
async asyncData({ params }) {
let { data } = await axios.post(`https://uni.wangcong.wang/uni/article`, {
action: "getArticle",
type: "dayRead",
pagingDto: {
pageNo: 1,
pageSize: 100,
},
});
return { list: data.rows };
},
};
- 使用内置的
@nuxtjs/axios
// nuxt.config.js
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy',
],
axios: {
proxy: true,
},
// 使用
export default {
async asyncData({ $axios }) {
let { data } = await $axios.$post(`https://uni.wangcong.wang/uni/article`, {
action: "getArticle",
type: "dayRead",
pagingDto: {
pageNo: 1,
pageSize: 100,
},
});
return { list: data.rows };
},
};
fetch 方法
fetch 方法用于在渲染页面前填充应用的状态树(store)数据, 与 asyncData 方法类似,不同的是它不会设置组件的数据。
如果页面组件设置了 fetch 方法,它会在组件每次加载前被调用(在服务端或切换至目标路由之前)。
<template>
<h1>Stars: {{ $store.state.stars }}</h1>
</template>
<script>
export default {
fetch({ store, params }) {
return axios.get('http://my-api/stars').then(res => {
store.commit('setStars', res.data)
})
}
}
</script>
其他方法参考官方 api 文档,不做阐述
SEO 配置
SEO 的基础配置包含网页的标题(title)、关键字(keywords)、描述(description),Nuxt 中可全局配置或者单独每个页面配置
- nuxt.config.js 中配置全局
head
head: {
title: '网站标题',
meta: [
{ charset: 'utf-8' },
{ hid: 'keywords', name: 'keywords', content: '关键字1,关键字2' },
{ hid: 'description', name: 'description', content: '这里是网页的描述' }
]
}
-
在每个页面中也可以配置
head
这里可以结合 异步数据获取方法asyncData
提前设置网页需要的 seo 基础信息export default { async asyncData({ params }) { let { data } = await axios.post(`https://uni.wangcong.wang/uni/article`, { action: "articleDetaile", _id: params.id, }); return { info: data.rows && data.rows.length ? data.rows[0] : null }; }, head() { return { title: this.info.title, meta: [ { charset: "utf-8" }, { hid: "keywords", name: "keywords", content: "页面A关键字1,页面A关键字2", }, { hid: "description", name: "description", content: "这里是页面A的描述", }, ], }; }, };
五、部署
部署方式
Nuxt.js 提供了两种发布部署应用的方式:服务端渲染应用部署 和 静态应用部署。
- 服务器部署
nuxt build
后nuxt start
- 静态站点部署
nuxt generate
- 你可以将这些命令添加至 package.json:
"scripts": { "dev": "nuxt", "build": "nuxt build", "start": "nuxt start", "generate": "nuxt generate" }
- 本地打包,执行
npm run build
打包,上传如下文件到服务器对应目录 - .nuxt
- nuxt.config.js
- static
- package.json
package.json
说明,dev
中是本地启动端口,start
是服务器启动端口
{ "scripts": { "dev": "nuxt --port 3006", "build": "nuxt build", "start": "nuxt start --port 3006", "generate": "nuxt generate" } }
- 静态应用部署
Nuxt.js 可依据路由配置将应用静态化,使得我们可以将应用部署至任何一个静态站点主机服务商。
npm run generate
这个命令会创建一个 dist 文件夹,所有静态化后的资源文件均在其中。
:::warning
注意:使用 nuxt generate 静态化应用的时候, 传给 asyncData() 和 fetch() 方法的上下文对象 不会包含 req 和 res 两个属性
:::可参考以下文献
- 服务器部署