近日用Vue写了个小项目 但由于Vue的特性 导致项目的SEO并不是很好
因此用Nuxt重构了该项目 对项目进行了一次优化
由于之前并没有相关的经验 因此遇到不少的坑 特此记录一下
一、概念
什么是Nuxt
Nuxt.js是Vue.js的通用框架 常用来作服务器端渲染(Server Side Rendering 简称SSR)
Vue适合用于开发SPA单页面应用 但因其数据绑定特性 导致爬虫只能爬取页面模板 并不能爬到渲染好的数据 不利于网站排名
对于公司内部网站等不需要排名的网站 可以不用SEO
但对于那些博客或新闻网之类的网站 SEO可谓是至关重要 这直接关系到网站的流量
二、安装
关于Nuxt的安装 这里就不多赘述了 请参看我的另一篇博客:Nuxt的介绍及简单安装(vue-cli4.x)
Nuxt是开箱即用的模块化安装 安装是傻瓜式的 非常方便
三、改造
这是Vue项目的目录结构:
这是Nuxt项目的目录结构:
可以看出 Vue和Nuxt的项目目录是很相似的 因此可以很方便地对文件进行移植
关于Nuxt的目录结构的对应含义 我在此前的博客中已经有了相关的解答:Nuxt的目录结构和常用配置
那么 接下来就是愉快的移植了:
- 【】 Vue项目下的assets是静态文件 可以放入Nuxt项目下的static目录下
- 【】 Vue项目下的components是组件 直接放入Nuxt项目下的同名目录components下
- 【】 Nuxt项目下的layouts是布局文件 其中默认生成的default.vue是页面模板 相当于Vue项目下的App.vue
里面有个<nuxt />
代表了你的页面内容 相当于Vue的<router-view/>
在其上加上tabbar 在其下加上footer即可实现页面自定义页面模板
error.vue是错误页面 这些都可以自己进行定制 - 【】 Vue项目的路由配置router/index.js就不需要了 因为Nuxt会自动生成 不过需要遵循Nuxt的相应的规则:Nuxt的路由(普通路由、动态路由、参数校验)和路由动画
- 【】 Vue项目的插件放在Nuxt项目的plugins目录下 给每个插件定义一个js文件进行配置
例如过滤器 在plugins下定义一个filter.js即可:
import Vue from 'vue'
import Moment from 'moment'
Vue.filter('dateFormat',function(value,format='YYYY-MM-DD HH:mm:ss'){
return Moment(value).format(format)
})
然后在nuxt.config.js里进行配置
忘了说了:nuxt.config.js是Nuxt项目的总配置文件 插件要在里面的plugins里导入才会生效
就比如刚才的过滤器:
plugins: [
"~/plugins/filter.js",
],
(~和@是Nuxt的语法 都能表示项目的根目录)
- 【】 Vue项目下的store是Vuex的配置文件 直接放于Nuxt项目的同名store目录下 但有少许不同:
在Vue项目下的store/index.js是这样的:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name:null
},
mutations: {
setName(state,name)
{
state.name=name.name
}
},
actions: {
},
modules: {
}
})
但在Nuxt中 是这样的:
export const state = () => ({
name:null
})
export const mutations = {
setName(state,name)
{
state.name=name.name
}
}
actions和modules也是同理 用export const对外暴露出来即可
- 【】 生成的HTML文件的头信息 在nuxt.config.js的head属性里进行配置
titleTemplate是标题模板
title是页面的标题
meta是页面的描述信息
link是页面的icon等信息
head: {
titleTemplate: '%s | ' + process.env.npm_package_name,
title: process.env.npm_package_name || '',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: process.env.npm_package_description || '' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
- 【】 asyncData()
在Nuxt里有个很重要的方法:asyncData()
它能够在页面组件每次加载之前被调用 在设置组件的数据之前能异步获取或处理数据
它返回的数据会和模板一同显示在页面上 这是实现SSR的核心
另外需要注意的是 由于asyncData方法是在组件初始化前被调用的 所以在方法内没有办法通过this
来引用组件的实例对象
通过params可以获取路由的参数
asyncData(context) {
return context.$axios.get('http://localhost:8081/test/?page='+context.params.id+'&size=10')
.then(response => {
return {data:response.data}
})
},
四、配置全局默认根域名:
在nuxt.config.js配置文件中 默认会有个axios:[ ]属性在里面进行配置即可:
axios: {
baseURL:"http://localhost:8081"
},
asyncData(context,params) {
return context.$axios.get('/test/?page='+params.id+'&size=10')
.then(response => {
return {data:response.data}
})
},
五、切换Vuetify的字体
注:强烈建议在自动构建Nuxt项目的时候就选择Vuetify作为UI库 能省去好多初始配置的麻烦
由于我是在构建Nuxt项目的时候就选择了Vuetify 所以部分默认配置就不再进行了 但如果是后来安装Vuetify 那么还需要进行额外的配置
Vuetify的默认字体是mdi 若要切换icon的字体 在Vue项目里是这样的(在这里以md字体库为例):
import Vue from 'vue';
import Vuetify from 'vuetify/lib';
import 'material-design-icons-iconfont/dist/material-design-icons.css'
Vue.use(Vuetify);
export default new Vuetify({
icons: {
iconfont: 'md', // 'mdi' || 'mdiSvg' || 'md' || 'fa' || 'fa4' || 'faSvg'
}
});
而到了Nuxt项目 这一切也是在nuxt.config.js里配置(之前傻傻的在plugins目录里配置 然后一直不生效…):
在css:[ ]里导入字体的css样式文件:
css: [
'material-design-icons-iconfont/dist/material-design-icons.css'
],
简单两步即可配置成功
六、配置MavonEditor编辑器插件
在Vue项目里 mavon这类的插件我是在main.js里配置的
到了Nuxt项目 还是在nuxt.config.js里进行配置
当然 首先要安装mavon的包:npm install mavon-editor --save
然后在plugins目录下建一个mavon-editor.js文件用于导入mavon:
import Vue from 'vue'
import mavonEditor from 'mavon-editor'
Vue.use(mavonEditor)
然后在nuxt.config.js里作为插件导入:
plugins: [
"~/plugins/filter.js",
"~/plugins/mavon-editor.js"
],
再在css属性里导入样式即可:
css: [
'mavon-editor/dist/css/index.css'
]
七、异常解决
1、localStorage is not defined
在Nuxt中 可能会产生localStorage is not defined
错误 这是因为在SSR中 created生命周期在服务端执行 而node环境中没有localStorage 所以会报错 将需要使用到localStorage的代码放置于mounted生命周期中即可
2、window is not defined
或是document is not defined
由于Nuxt是分成服务端代码和客户端代码同时生成 而在node环境中运行window和document是不存在的
在Mavon编辑器内使用到了window对象 因此 会报错window is not defined
或是document is not defined
解决方法也很简单:用<client-only>
标签将<mavon-editor>包裹住即可 使其只在客户端生成
就像这样:
<client-only>
<mavon-editor class="editor"/>
</client-only>
这是官网的解答:API: The <client-only> Component
结语:
至此 Vue项目重构Nuxt就告一段落了
Nuxt的坑真的很多 相关的资料不多 很多配置问题官方文档也没有 只能自己慢慢摸索着学习 不过在完成之后还是很有成就感的
之前想直接在Nuxt上开发 然后遇到不少的坑 就选择用Vue上开发了 但在遇到网页的SEO问题之后还是第一时间想到了Nuxt
今后还是得更加熟悉Nuxt啊