前言
- 【音乐博客】上线啦!
- 开开心心部署到服务器,然后满怀欣喜打开首页,结果发现有点小慢,这就很不愉快啦
- 下面来解决vue首屏渲染
五个方面
1. SPA单页面应用
- 首屏打开速度很慢,因为用户首次加载需要先下载SPA框架及应用程序的代码,然后再渲染页面。
- 不利于SEO
- 根据这几个缺点,我们便又引出了接下来讨论的两个主题,SEO和SSR,先谈谈SEO。
2. SEO搜索引擎
- 搜索引擎优化。SEO是一种通过了解搜索引擎的运作规则(如何抓取网站页面,如何索引以及如何根据特定的关键字展现搜索结果排序等)来调整网站,以提高该网站在搜索引擎中某些关键词的搜索结果排名。
- Vue SSR说:
如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax 获取内容,抓取工具并不会等待异步完成后再行抓取页面内容。
- 那搜索引擎不支持ajax获取数据,那就更不用提SEO了
- 对于有些网站而言,SEO显得至关重要,例如主要以内容输出为主的Quora、stackoverflow、知乎和豆瓣等等,那如何才能正常使用SPA而又不影响SEO呢?鲁迅曰:
- 技术上的问题总有技术去解决
- 此时,SSR便闪亮登场了
3. SSR服务端渲染
- 在普通的SPA中,一般是框架及网站页面代码发送给浏览器,然后在浏览器中生成和操作DOM(这也就是为什么第一次SPA网站在同等带宽下比传统的在后端生成HTML发送到浏览器要更慢的主要原因),但其实也可以将SPA应用打包到服务器上,在服务器上渲染出HTML,发送到浏览器,这样的HTML页面还不具备交互能力,所以还需要与SPA框架配合,在浏览器上“混合”成可交互的应用程序。所以,只要能合理地运用SSR技术,不仅能一定程度上解决首屏慢的问题,还能获得更好的SEO。
- SSR的优点
- 更快的响应时间,不用等待所有的JS都下载完成,浏览器便能显示比较完整的页面了。这个个人深有体会,我的个人博客最开始仅仅使用了Vue.js,而没有做服务端渲染,加之服务器不在大陆,第一次输入地址到看到完整的页面几乎是过了4、5秒,有时候还更长。
- 更好的SSR,我们可以将SEO的关键信息直接在后台就渲染成HTML,而保证搜索引擎的爬虫都能爬取到关键数据。
- SSR的缺点
- 相对于仅仅需要提供静态文件的服务器,SSR中使用的渲染程序自然会占用更多的CPU和内存资源
- SSR常用框架
- React 的 Next
- Vue.js 的 Nuxt
- 所以要想SEO做的好,建议使用服务端SSR渲染(网页是通过服务端渲染生成后输出给客户端),可采用Nuxt(其本质是Node封装的VUE的SSR框架,所以是在服务端跑的,对首屏渲染友好)
4. 预编译prerender-spa-plugin插件
- Nuxt要用他的那套约束,也就是说你的项目要迁移到Nuxt去,解决 SEO 问题是不是只有 SSR 呢?其实预渲染也能做到
- 还有的,就是webpack的预编译,可以对首页先加载出来,然后他再慢慢去加载js文件,这样就不用等待首页加载
- 服务端渲染解决的问题,不仅只是把 HTML 页面给浏览器,更重要的是处理动态逻辑和 JS 代码后,将渲染后完整的 HTML 给浏览器,渲染的过程在服务端。
- 预渲染,是利用构建工具在 webpack 中生成静态的 HTML,直接给浏览器,渲染的过程在本地。
- 预渲染插件里面提到两种不能使用:大量路由、动态内容
- 接下来我们介绍下prerender-spa-plugin插件实现预编译
- 安装:
cnpm install prerender-spa-plugin --save
- vue-cli3.0的写法
- vue-config.js中增加
const PrerenderSPAPlugin = require('prerender-spa-plugin'); const Renderer = PrerenderSPAPlugin.PuppeteerRenderer; const path = require('path'); module.exports = { configureWebpack: config => { if (process.env.NODE_ENV !== 'production') return; return { plugins: [ new PrerenderSPAPlugin({ // 生成文件的路径,也可以与webpakc打包的一致。 // 下面这句话非常重要!!! // 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。 staticDir: path.join(__dirname,'dist'), // 对应自己的路由文件,比如a有参数,就需要写成 /a/param1。 routes: ['/', '/product','/about'], // 这个很重要,如果没有配置这段,也不会进行预编译 renderer: new Renderer({ inject: { foo: 'bar' }, headless: false, // 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。 renderAfterDocumentEvent: 'render-event' }) }), ], }; } }
- 在main.js中增加
new Vue({ router, store, render: h => h(App), mounted () { document.dispatchEvent(new Event('render-event')) } }).$mount('#app')
- router.js 中设置mode: “history”注意:官方文档上 路由模式必须为
history
。如果不设置history模式,也能运行和生成文件,每个index.html文件的内容都会是一样的。所以必须使用history
模式 - 运行npm run build,看一下生成的 dist 的目录里是不是有每个路由名称对应的文件夹。然后找个 目录里 的 index.html 用IDE打开,看文件内容里是否有该文件应该有的内容。有的话,就设置成功了
- 打包之后如下图:
突然发现原来我一直有使用Gzip压缩文件的,这就很好了
- vue-cli2.0的写法
- 修改 webpack 配置,比较简单就能完成配置
const PrerenderSPAPlugin = require('prerender-spa-plugin') const Renderer = PrerenderSPAPlugin.PuppeteerRenderermodule.exports = { plugins: [ //... new PrerenderSPAPlugin({ staticDir: path.join(__dirname, 'dist'), outputDir: path.join(__dirname, 'prerendered'), indexPath: path.join(__dirname, 'dist', 'index.html'), routes: ['/', '/about', '/some/deep/nested/route'], postProcess(renderedRoute) { renderedRoute.route = renderedRoute.originalPath renderedRoute.html = renderedRoute.html.split(/>[\s]+</gmi).join('><') if (renderedRoute.route.endsWith('.html')) { renderedRoute.outputPath = path.join(__dirname, 'dist', renderedRoute.route) } return renderedRoute }, minify: { collapseBooleanAttributes: true, collapseWhitespace: true, decodeEntities: true, keepClosingSlash: true, sortAttributes: true }, renderer: new Renderer({ inject: { foo: 'bar' }, maxConcurrentRoutes: 4 }) }) ] }
- 简直不要太爽,速度变快了很多,基本上1s就可以显示首页页面,有兴趣的小伙伴赶紧使用在项目里面吧!!!
5. 两者的区别
- 服务端SSR渲染解决的问题,不仅只是把 HTML 页面给浏览器,更重要的是处理动态逻辑和 JS 代码后,将渲染后完整的 HTML 给浏览器,渲染的过程在服务端。
- 预渲染,是利用构建工具在 webpack 中生成静态的 HTML,直接给浏览器,渲染的过程在本地。将服务端编译HTML的时机提前到了构建时,因此降低了服务端的压力
- 共性:
加载速度一样快;
入侵性小; - 不同:
服务端渲染在服务器;适用于复杂、较大型、与服务端交互频繁的网站,如电商
预渲染在客户端上;适用于简单的静态页面 - 很奇怪的一点是:打开f12,发现刷新很慢,关掉f12,刷新就很快,不明觉厉,知道的同学在评论区分享下!
最后总结
要想seo好,使用ssr服务端渲染,即服务端生成静态页面给客户端,交互的请结合Nuxt;或者不在服务端渲染,使用webpack的prerender-spa-plugin插件实现预编译,生成静态的 HTML,直接给浏览器,渲染的过程在本地。使用webpack的code splitting按需加载压缩优化首页渲染或者vue分片
参考
vue-cli3.0使用prerender-spa-plugin插件预渲染 :blog.csdn.net/lv5751394/a…
使用 prerender-spa-plugin 插件进行简单预渲染vue-cli2.0:juejin.cn/post/684490…