关于的vue框架的一个弊端就是不利于seo优化,不利于百度收录,基于这个问题vue官方也是出台了nuxt服务端渲染,上周公司让我用服务端对项目进行重构,事情来得比较突然,没办法只能硬着头皮边踩坑边实现了。
现在我就把这一周来拆的坑肯大家说一遍,减少大家的踩坑时间,提高开发效率!
万事开头难,先从文档开始说起!https://zh.nuxtjs.org/
1、流程图
下图阐述了 Nuxt.js 应用一个完整的服务器请求到渲染(或用户通过
切换路由渲染页面)的流程:
2、既然是服务端渲染就会有:“服务端”和“客户端”,如果对于一个前端来说这一说可能会有点蒙,接下来举个例子说明一下你绝对明白,不明白我吃屎!!开玩笑的!
例子开始:拿cookie来说事!
cookie:他妈的,我真倒霉,躺着都中枪!!
npm install js-cookie --save
使用方法:
详细使用方法参考:https://www.jianshu.com/p/6e1bacd35f59
因此存cookie需要这样
if (process.server){//判断是否为服务端
if (req.headers.cookie) {
const parsed = cookieparser.parse(req.headers.cookie)
console.log(parsed)
}
}
分清了吧!还没分清你说,去吃屎!
nuxt.js(中文官方文档)是vue.js的一个通用型应用框架,有了之前搭建vue项目的过程之后,搭建一个nuxt项目就会十分简单。
1.打开命令提示符,进入到相关文件夹下;
2.使用如下命令一步搭建项目
vue init nuxt-community/starter-template testPro --testPro为项目名称
3.需要进一步输入以下信息
Project name (testPro) test-pro --输入项目名称,回车
Project description (Nuxt.js project) --项目描述,直接回车即可
Author syf --输入作者姓名,回车即可
4.进入到testPro
cd testPro
5.安装依赖
npm install
6.启动项目
npm run dev
7.具体过程如下
8.访问http://localhost:3000,得到如下图所示,说明nuxt项目搭建成功
Nuxt.js 是一个基于 Vue 的通用应用框架。 通过对客户端/服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI渲染。Nuxt.js 预设了利用 Vue 开发服务端渲染的应用所需要的各种配置。
Nuxt.js是使用 Webpack 和 Node.js 进行封装的基于Vue的SSR框架,使用它,你可以不需要自己搭建一套 SSR 程序,而是通过其约定好的文件结构和API就可以实现一个首屏渲染的 Web 应用。
按照上面步骤生成nuxt应用,目录结构如下
.nuxt : Nuxt自动生成,临时的用于编辑的文件,build
assets:Webpack 编译的各类资源,// 用于组织未编译的静态资源入LESS、SASS 或 JavaScript
components:各组件,用于你自己管理公共组件或非公共组件 ,比如滚动组件,日历组件,分页组件
layouts:宿主布局页面模板组件,用于你可以把不同的页面指定使用不同的布局,不可更改。
middleware:中间件,首屏渲染和路由跳转前均执行对应中间件,可以返回promise或直接next(很实用!)
pages:各页面组件,用于生成对应路由,支持嵌套,支持动态路由,存放写的页面,我们主要的工作区域
plugins:插件,SPA中用的各类第三方组件和一些node模块,JavaScript插件放的地方
static :/ 用于存放静态资源文件,比如图片
store:内置了vuex,可以直接返回数据模块或返回一个自建vuex根对象,具体要翻文档,用于组织应用的Vuex 状态管理
.editorconfig: // 开发工具格式配置
.eslintrc.js: // ESLint的配置文件,用于检查代码格式
.gitignore: // 配置git不上传的文件
nuxt.config.json: // 用于组织Nuxt.js应用的个性化配置,已覆盖默认配置
package-lock.json: // npm自动生成,用于帮助package的统一性设置的,yarn也有相同的操作
package.json: // npm包管理配置文件
nuxt.config.js对程序的扩展管理可大概分为以下类:
build:主要对应 Webpack 中的各配置项,可以对默认的 Webpack 配置进行扩展,如这里代码
cache:主要对应内置的组件缓存模块lru-cache的配置对象,有默认值,可选关闭
css:对应我们在SPA随处引用样式文件的require语句
dev:用于自定义配置环境变量,对应之前webpack.config.js相关文件中的变量语句
env:同上息息相关
generate:对generate命令执行时的行为做一些定制
head:对应vue-meta插件的全局配置,vue-meta用于VUE/SSR程序的文档元信息的管理
loading:用于定制化Nuxt.js内置的进度条组件
performance:用于配置Node.js服务器性能上的配置
plugins:用于管理和应用对应plugins文件夹中的插件
rootdir:用于设置 Nuxt.js 应用的根目录(这俩api有很大合并的意义)
srcdir:用于设置 Nuxt.js 应用的源码目录(这俩api有很大合并的意义)
router:用于对vue-router的扩展和定制,其中还包括了中间件的配置,但并不完美(后面说)
transition:用于定制Nuxt.js内置的页面切换过渡效果的默认属性值
watchers:用于定制Nuxt.js内置的文件监听模块chokidar和 -Webpack 的相关配置项
好了,大致介绍也就到这了,,现在我把我的一些收获分享给大家!!!优雅的说一句(大佬勿喷)!
1.下载element模块
npm install element-ui -S
2.在plugins文件夹下,添加element.js文件,内容如下所示
import Vue from 'vue'
import ElementUI from 'element-ui'
Vue.use(ElementUI)
3.在nuxt.config.js中添加配置
plugins: [
{ src: '~plugins/ElementUI',ssr: true}
],
css: [
'element-ui/lib/theme-chalk/index.css'
],
//plugins 属性配置
//src: String (文件的路径)
//ssr: Boolean (默认为 true) 如果值为 false,该文件只会在客户端被打包引入。
4.大致的引入第三方插件就是这样了!!!学会了吗!!!
服务端和客户端同构的问题就是:
当用户点击的时候我们就用客户端渲染,当页面只是刷新的时候就是用服务端渲染,简单的说就是使用户操作的就用客户端渲染,不是用户操作的就使用服务端渲染,这样既减轻了服务器的压力,又能达到我们服务端渲染的要求,提高项目性能!
这个问题本来就是nuxt直接就支持的问题,nuxt会直接自己判断是客户端操作还是服务端操作,就是用nuxt-link直接跳转路由,然后在async asyncData里面请求数据就行了。
下面看我的代码:
//请求数据的
async asyncData({ params, $axios, query }) {
let name = encodeURI(query.content);
let [company] = await Promise.all([
$axios({
method: "get",
url:
"https://===================================="
}).then(res => {
if(process.server){
return { company: res.data.data.rows };
}
})
]);
return {
company: company
};
},
就因为这样导致我跳转路由时回来会找不到数据,就因为这个问题我还百度了一下,网上找了一个文章说用a链接进行跳转路由,虽然目的达到了,但是导致我的代码变成了全部是服务端渲染!
window.location.href = "路径";
主要还是因为上面的一个判断
if(process.server){
return { company: res.data.data.rows };
}
就是因为这个导致所有的请求数据都是服务端执行,好像是判断的process.server具体是什么也忘了,反正就是拦截了客户端
第一种:返回 Promise
export default {
asyncData ({ params }) {
return axios.get(`https://****************`)
.then((res) => {
return { title: res.data.title }
})
}
}
export default {
async asyncData ({ params }) {
let { data } = await axios.get(`https://my-api/posts/${params.id}`)
return { title: data.title }
}
}
export default {
asyncData ({ params }, callback) {
axios.get(`https://my-api/posts/${params.id}`)
.then((res) => {
callback(null, { title: res.data.title })
})
}
}
async asyncData({ params, $axios }) {
let [news, hotData, addCompany] = await Promise.all([
$axios({
method: "get",
url: "https://************************",
headers: { page: 1, size: 3 }
}).then(res => {
return { news: res.data.data };
}),
$axios({
method: "get",
url: "https://**************************"
}).then(res => {
return { hotData: res.data };
}),
$axios({
method: "get",
url: "https://*******************************"
}).then(res => {
return { addCompany: res.data.data.rows };
})
]);
return {
news: news,
hotData: hotData,
addCompany: addCompany
};
},
详情请参考官网链接:https://zh.nuxtjs.org/guide/async-data
context
上下文对象先说在async asyncData里面的用法
async asyncData ({ context }) { //context就是上下文对象
// 请检查您是否在服务器端
// 使用 req 和 res
if (process.server) {
return { host: req.headers.host }
}
return {}
}
要是在生命周期里面使用的话就直接打印this.nuxt就是了
methods:{
console.log(this.nuxt)
}
context 变量的可用属性一览:
属性字段 | 类型 | 可用 | 描述 |
---|---|---|---|
app |
Vue 根实例 | 客户端 & 服务端 | 包含所有插件的 Vue 根实例。例如:在使用 axios 的时候,你想获取 $axios 可以直接通过 context.app.$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 } ,参考 示例 |
详情见官网:https://zh.nuxtjs.org/api/context
用法就不多说了 ,直接在对象里添加就行了