zoukankan      html  css  js  c++  java
  • Vue项目预渲染机制引入实践

    周末想顺便把已经做好静态页面的webApp项目做一下SEO优化,由于不想写蹩脚的SSR代码,所以准备采用预渲染,本来想着网上有这么多预渲染的文章,随便找个来跟着做不就完了嘛,结果年轻的我付出了整个周末..... 这篇文章就记录一下最后是怎么配置的 T.T

    声明:

    1. 以下配置只保留有必要的
    2. 生成目录这里使用base代替,请自行修改
    3. vue-cli模板使用webpack,其他模板类推
    4. webApp - 在线预览
    5. Github - 配置了预渲染的demo

    1. 简介与使用场景

    我们知道SPA有很多优点,不过一个缺点就是对(不是Google的)愚蠢的搜索引擎的SEO不友好,为了照顾这些引擎,目前主要有两个方案:服务端渲染(Server Side Rendering)、预渲染(Prerending)。

    如果你只需要改善少数页面(例如 //about/contact 等)的 SEO,那么你可能需要预渲染。无需使用 web 服务器实时动态编译 HTML (服务端渲染, SSR),而是使用预渲染方式,在构建时(build time)简单地生成针对特定路由的静态 HTML 文件。它主要使用 prerender-spa-plugin 插件,其与SSR一样都可以加快页面的加载速度,并且侵入性更小,在已上线的项目稍加改动也可以轻松引入预渲染机制,而SSR方案则需要将整个项目结构推翻;

    访问预渲染出来的页面在访问时与SSR一样快,并且它将服务端编译HTML的时机提前到了构建时,因此也降低了服务端的压力,如果你的服务器跟我的一样买的 1M1G1核 的小水管服务器 ( 穷 ),那么预渲染可能更适合你。不过SSR和预渲染的使用场景还是有较明显的区别的。预渲染的使用场景更多是简单的静态页面。服务端渲染适用于复杂、较大型、与服务端交互频繁的功能型网站,比如电商网站。

    2. 安装配置

    首先来看看相关技术栈:vue^2.5.2、vue-router^3.0.1、vue-cli^2.9.6、webpack^3.6.0、prerender-spa-plugin^3.3.0

    2.1 安装

    安装跟其他库一样

    # Yarn
    $ yarn add prerender-spa-plugin -D
    # or NPM
    $ npm install prerender-spa-plugin --save-dev

    2.2 前端配置

    首先看看文件结构,用的是vue-cli2的webpack模板生成的文件结构

    │  .babelrc
    │  index.html
    │  package.json
    │  README.md
    ├─build
    │      build.js
    │      check-versions.js
    │      utils.js
    │      vue-loader.conf.js
    │      webpack.base.conf.js
    │      webpack.dev.conf.js
    │      webpack.prod.conf.js
    ├─config
    │      dev.env.js
    │      index.js
    │      prod.env.js
    ├─src
    │  │  App.vue
    │  │  main.js
    │  │ 
    │  ├─assets
    │  ├─components
    │  ├─router
    │  │      index.js
    │  ├─styles
    │  ├─utils
    │  └─views
    │          BigData.vue
    │          CompanyHonor.vue

    然后是router/index.js的配置,预渲染要求是histroy模式,有的文章说不需要history模式,这是错的,否则生成的页面都是同一个html。另外注意加上base否则如果你希望跳转到二级页面的localhost/base/home时候,在页面中点击<router-link to="/home">home</router-link>的时候会跳转localhost/home

    // src/router/index.js

    import Vue from 'vue'
    import Router from 'vue-router'
     
     
    Vue.use(Router)
     
     
    export default new Router({
      mode: 'history',
      base: '/base/',
      routes: [...]
    })
     
     

    然后是config,这里注意assetsPublicPath不是./,

    // config/index.js

    const path = require("path")
     
     
    module.exports = {
      build: {
        index: path.resolve(__dirname, "../base/index.html"),
        assetsRoot: path.resolve(__dirname, ".."),
        assetsSubDirectory: "base/static",
        assetsPublicPath: "/",
      }
    }

    然后是插件的配置,是放在prod中的,因为只有build的时候会用

    // build/webpack.prod.conf.js

    const path = require('path')
    const config = require('../config')
    const PrerenderSPAPlugin = require('prerender-spa-plugin')
    const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
     
     
    const webpackConfig = merge(baseWebpackConfig, {
      new PrerenderSPAPlugin({
       staticDir: config.build.assetsRoot,
       outputDir: path.join(config.build.assetsRoot, 'base'),
       indexPath: config.build.index,
     
       // 对应路由文件的path
       routes: [
         '/',
         '/BigData',
         '/CompanyHonor'
       ],
     
       renderer: new Renderer({
         headless: false,            // 无桌面系统去掉
         renderAfterDocumentEvent: 'render-event'
       })
      })
    })

    注意了,如果你的项目是部署在linux/centOS之类没有桌面的系统,需要把headless: false去掉,如果centOS报没有找到lib的错,请参考 issue-200 的解决办法。

    另外注意上面一个renderAfterDocumentEvent: 'render-event'了么,这个意思是在render-event事件触发之后执行prerender,这个事件我们在main.js中mounted钩子触发

    // src/main.js

    import Vue from 'vue'
    import App from './App'
     
     
    new Vue({
      el: '#app',
      render: h => h(App),
      mounted() {
        document.dispatchEvent(new Event('render-event'))
      }
    })

    还有个配置要注意下在 build/utils.js 中的 ExtractTextPlugin.extract 的 publicPath ,否则一些vue中引用的资源会找不到

    // build/utils.js

    ExtractTextPlugin.extract({
      use: loaders,
      fallback: 'vue-style-loader',
      // publicPath: '../../'
    })

    这时候执行npm run build就可以生成刚刚配置在PrerenderSPAPlugin插件中routes中的页面html了,这过程中会一闪而过的短暂打开chromium浏览器,不用管。

    最后生成的目录树:

    │  index.html
    ├─BigData
    │      index.html
    ├─CompanyHonor
    │      index.html
    └─static
        ├─css
        ├─fonts
        ├─img
        └─js

    最后如果希望进一步优化生成出来页面的SEO,可以配合 vue-meta-info 这个网上有很多文章,就不赘述了

    2.3 nginx配置

    顺便贴一下nginx配置

    server {
            listen 80;
            server_name localhost;
            root /nginx-1.14.0/html;
    
            error_page 500 502 503 504 /50x.html;
            
            location ~ ^/base/ {
              try_files $uri $uri/ /base/index.html;
            }
            location = /50x.html {
                root html;
            }
    }

     转载:SHERlocked93

  • 相关阅读:
    异常处理(五)
    抽象与接口(七)
    MYSQL创建数据库时候直接指定编码和排序规则
    C#基本语法(一)
    C#中字符串处理(三)
    Ajax实例化(五)
    C#函数(二)
    MemberCache学习摘要
    ORACLE 根据日期范围自动日期table
    动态执行SQL语句,并输出参数
  • 原文地址:https://www.cnblogs.com/AlbertP/p/10785083.html
Copyright © 2011-2022 走看看