探究SEO与VUE首屏渲染及其解决方案

前言

  • 【音乐博客】上线啦!
  • 开开心心部署到服务器,而后满怀欣喜打开首页,结果发现有点小慢,这就很不愉快啦
  • 下面来解决vue首屏渲染


五个方面

1. SPA单页面应用

  • 首屏打开速度很慢,由于用户首次加载须要先下载SPA框架及应用程序的代码,而后再渲染页面。
  • 不利于SEO
  • 根据这几个缺点,咱们便又引出了接下来讨论的两个主题,SEO和SSR,先谈谈SEO。

2. SEO搜索引擎

  • 搜索引擎优化。SEO是一种经过了解搜索引擎的运做规则(如何抓取网站页面,如何索引以及如何根据特定的关键字展示搜索结果排序等)来调整网站,以提升该网站在搜索引擎中某些关键词的搜索结果排名。
  • Vue SSR说:
若是你的应用程序初始展现 loading 菊花图,而后经过 Ajax 获取内容,抓取工具并不会等待异步完成后再行抓取页面内容。
  • 那搜索引擎不支持ajax获取数据,那就更不用提SEO了
  • 对于有些网站而言,SEO显得相当重要,例如主要之内容输出为主的Quorastackoverflow知乎豆瓣等等,那如何才能正常使用SPA而又不影响SEO呢?鲁迅曰:
  • 技术上的问题总有技术去解决
  • 此时,SSR便闪亮登场了

3. SSR服务端渲染

  • 在普通的SPA中,通常是框架及网站页面代码发送给浏览器,而后在浏览器中生成和操做DOM(这也就是为何第一次SPA网站在同等带宽下比传统的在后端生成HTML发送到浏览器要更慢的主要缘由),但其实也能够将SPA应用打包到服务器上,在服务器上渲染出HTML,发送到浏览器,这样的HTML页面还不具有交互能力,因此还须要与SPA框架配合,在浏览器上“混合”成可交互的应用程序。因此,只要能合理地运用SSR技术,不只能必定程度上解决首屏慢的问题,还能得到更好的SEO。
  • SSR的优势
  • 更快的响应时间,不用等待全部的JS都下载完成,浏览器便能显示比较完整的页面了。这个我的深有体会,个人 我的博客最开始仅仅使用了Vue.js,而没有作服务端渲染,加之服务器不在大陆,第一次输入地址到看到完整的页面几乎是过了四、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压缩文件的,这就很好了html

  • 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按需加载压缩优化首页渲染vue


原文地址

juejin.im/post/5ed10f…
webpack


参考

vue-cli3.0使用prerender-spa-plugin插件预渲染 :blog.csdn.net/lv5751394/a…git

使用 prerender-spa-plugin 插件进行简单预渲染vue-cli2.0:juejin.im/post/5e1eb1…github

相关文章
相关标签/搜索