vue-cli3构建的项目使用prerender-spa-plugin做预渲染
需求描述:
某项目需要做SEO优化,进行对SEO友好处理,不仅仅是添加TDK
技术方案
- 前端使用node+koa2进行服务端渲染,也就是SSR,因为我们使用的是vue,也可以采用nuxt
- 前端使用prerender-spa-plugin做预渲染,只针对需要进行SEO的页面进行预渲染,比如新闻、资讯等页面
技术利好对比
- 如果采用ssr,服务端渲染,可能对已经开发好的项目,改动比较大,虽然也能做,但是比较麻烦,重构成本较高,不建议使用
- 采用预渲染,改动较小,开发成本低,但是不能预渲染动态页面,比如某条资讯或者某条新闻等页面不能进行预渲染,可能不能满足需求
最后,进过以上比对,采用了方案二,因为我们虽然不能动态渲染新闻资讯页面,但是我们可以提前将新闻和资讯列表等请求出来放在页面 超出隐藏,可能比较投机取巧,但是以满足业务为主。所以决定了方案,就开始执行了,当然就遇到了一些问题。
开发时遇到的问题
- 本地通过serve命令模拟一个服务启动项目,能预渲染,但是放到线上后,就出现了预渲染失败
- nginx文件放在服务器端,在配置预渲染页面时极其不方便
预渲染webpack配置代码 vue.config.js:
if (env === 'production' || env === 'development') {
config.plugins.push(
new PrerenderSPAPlugin({
// 生成文件的路径,也可以与webpakc打包的一致。
// 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。
staticDir: path.join(__dirname, 'dist'),
// 对应自己的路由文件,比如a有参数,就需要写成 /a/param1。
routes: ['/', '/unlogin', '/news', '/newsmore'],
minify: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
decodeEntities: true,
keepClosingSlash: true,
sortAttributes: true
},
renderer: new Renderer({
headless: true,
renderAfterTime: 5000, // Wait 5 seconds.
// 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。
renderAfterDocumentEvent: 'render-event'
})
})
)
}
在main.js里面需写上:
new Vue({
el: '#app',
router,
store,
render: h => h(App),
mounted() {
// render-event 需与webpack配置的事件名称同名
document.dispatchEvent(new Event('render-event'))
}
})
然后在本地build一次,dist目录里面会创建好你预渲染的页面
然后在通过serve -s dist
命令 启动项目打开 localhost:5000
(安装serve npm install serve -g
)
打开浏览器控制台,查看document资源,可以看到preview已经把整个页面渲染出来了
说明已经成功了!
至此,前端配置已经完成了!
那么问题来了,为什么放到服务器上就GG了呢?
放上去的效果是可以打开页面,但首次不是预渲染页面,刷新一下当前页面,页面就丢失了。实在的 困惑了我很久,也用过很多方式,比如修改打包配置文件啊等等,到最后都不行,所以只能采取强制措施了,修改nginx 叫你不听话!!!
这也是问题1,2的关键所在,咱们需要配置nginx。怎么配置的呢? 直接上代码:
location / {
if ($uri = /unlogin) {
rewrite .* /unlogin/index.html break; // 重定向
}
if ($uri = /news) {
rewrite .* /news/index.html break;
}
if ($uri = /newsmore) {
rewrite .* /newsmore/index.html break;
}
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html; #目录不存在则执行index.html
}
就这样哈,不解释了,一口干了!(看得懂的非常好,看不懂的copy) 好了,以上的一系列已经解决了我的问题了。不知道能不能解决你的问题呢。 最后说几个没去调研的注意事项吧,帮助有问题的同学找到问题(不要抠字眼啊!!!)
注意事项:
- vue项目路由需要history模式
- webpack配置的预渲染的输出目录 staticDir outputDir indexPath
- nginx 放在前端配置,每次通过jenkins部署的时候 通过命令将nginx文件 copy进去就ok了
- 下载不了prerender-spa-plugin是因为 默认使用的是chormeium,你可以在jenkins的服务器上安装一个cnpm,通过cnpm来下载,记住第一次使用cnpm install的时候 需要修改jenkins构建配置清除上一次下载的包,因为npm install 会生成package-lock.json文件,会默认下载里面的东西,导致下载不了,以后就可以不用清除了,因为cnpm install不会生成版本锁,prerender-spa-plugin每次都重新下载的话,还是比较浪费时间的。
完事了!谢谢!