vue hash模式改成history,同时实现spa预渲染问题
作者:奇怪的守护神
这篇文章主要介绍了vue hash模式改成history,同时实现spa预渲染问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
1.前言
由于公司需要把首页进行seo排名,但是首页已经完成好,并且还是hash模式,要做成seo排名,不能有hash模式的#,同时要能读取到渲染好的页面.所以,针对这2点困难,最终想到的解决方案是:
- 先hash需要转换为history,保证是无#的美观模式;
- 需要做到提前渲染好,可以采取vue的SSR,spa预渲染或nuxt.js.
2.选取渲染方式
首先,hash转换为history已经是板上钉钉的事情,这时候就开始找快捷简单改动少的渲染方式,分别有vue的SSR,spa和nuxt.js.
- vue项目提供了ssr的方案.不过ssr方案需要在node上调用
renderToString
来渲染。如果不介意在系统结构中增加一层node
的话,就可以使用ssr的方式,这种方式会改变前后端交互的方式。ssr文档.改动中等 - spa预渲染,即使用prerender-spa-plugin插件预渲染.由于页面较少,且预渲染相对于SSH比较简单,于是选择预渲染页面,预渲染可以极大的提高网页访问速度。而且配合一些meat插件,基本可以满足SEO需求。改动在三者中最小
- Nuxt就是基于Vue的一个应用框架,采用服务端渲染,让你的SPA应用(Vue)也可以拥有SEO.官方文档,但是由于需要重新改变底层框架,改动在三者中最大.
综上所述,选择第二个方式,spa预渲染,改动小,同时也能达到seo的要求
3.hash转为history
1.模式修改 (目录:src/router/index.js)
// mode:'hash', mode: 'history', base: '/',
2.相对路径调整
- 2.1 目录:build/webpack.prod.conf.js
//history为"/",hash:'./' //publicPath:'./', publicPath:'/',
- 2.2目录:config/index.js
// histroy模式:"/" ,hash模式:"./" //assetsPublicPath: './', assetsPublicPath: '/',
2.3 修改原因:
- ./ 是指用户所在的当前目录(相对路径);
- / 是指根目录(绝对路径,项目根目录),也就是项目根目录;
对于hash模式,根路径是固定的,就是项目的根目录,但是history模式下,以/
开头的嵌套路径会被当作根路径,所以使用“./”引入文件,就会找不到文件了,因为文件本身就是在项目根目录下的,并不在嵌套路径这个目录下。
总结,无论hash模式还是history模式,可以直接使用“/”从项目根目录引入静态文件。
3.服务端修改
nginx配置:参考官网教程
location / { proxy_pass http://127.0.0.1:80; root /usr/local/tomcat/tomcat_xhcf/webapps/ROOT; #表明路径 index index.html index.htm; try_files $uri $uri/ /index.html; #交给index.html处理 }
原因:这样修改,避免了刷新404的问题,因为如果URL匹配不到任何静态资源,就跳转到默认的index.html进行处理。
4.SPA预渲染
1.安装prerender-spa-plugin
npm i -s prerender-spa-plugin
或者 (淘宝镜像)
cnpm i --save prerender-spa-plugin
2.配置
- 2.1目录:build/webpack.prod.conf.js
- 在plugins列表里,加入下面代码:
// 在vue-cli生成的文件的基础上,只有下面这个才是我们要配置的 new PrerenderSPAPlugin({ // 生成文件的路径,也可以与webpakc打包的一致。 // 下面这句话非常重要!!! // 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。 staticDir: path.join(__dirname, '../dist'), // 对应自己的路由文件,比如index有参数,就需要写成 /index/param1。这里很重要,需要把自己想要生成静态文件的路由全部写进去。 routes: [ '/', '/about', ], // 这个很重要,如果没有配置这段,也不会进行预编译 renderer: new Renderer({ inject: { foo: 'bar' }, headless: false, // 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。 renderAfterDocumentEvent: 'render-event', //时间 renderAfterTime:5000 }) })
- 2.2目录:src/main.js (mounted是新增代码,对应build/webpack.prod.conf.js里加的)
/* 记得要通过 router 配置参数注入路由,从而让整个应用都有路由功能*/ const app =new Vue({ el: '#app', router, components: { App }, template: '<App/>', /* 这句非常重要,否则预渲染将不会启动 */ mounted () { document.dispatchEvent(new Event('render-event')) } }).$mount('#app')
最终npm run build ,生成代码,目录如下即成功
dist │ ├── about │ └── index.html │ ├── index.html └── static
5.全程操作概览
- 修改完以上全部配置;
- 项目里npm run build生成文件,放入对应服务器目录;
- nginx重启配置:
nginx -t #测试配置是否正确 nginx -s reload #重启nginx配置
大功告成!
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。