探究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

相關文章
相關標籤/搜索