February 13, 2019

简单折腾一下 prerender-spa-plugin

背景

网站的首页和部分介绍页面需要预渲染,为了更好的SEO;而网站的dashboard的相关页面则保持原来的SPA处理。后续生产环境的文件构建需要放到ci统一处理。

使用工具

现在使用prerender-spa-plugin的插件用来把部分静态页面预渲染,这个插件是依赖puppeteer的工具,puppeteer工具是需要下载一个chromium的浏览器。如果没有梯子是没办法下载的,下载安装包的大小大概在70M左右。

puppeteer1.7.0版本开始就把puppeteer-core的包分离出来,如果需要单独测试的话,仅下载这个包就好了。但是prerender-spa-plugin插件是依赖puppeteer的包,所以需要设置npm的环境变量才能能够跳过下载浏览器,在安装npm install之前,需要在项目的根目录新建文件.npmrc或者往里面追加内容,内容是:

1
puppeteer_skip_chromium_download=true

使用基础例子

后面所使用的代码,均基于官方的例子进行更改

webpack 配置

在webpack的配置当中,生产环境的plugins的数组需要加入下面的实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 引入对应的插件
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer

module.exports = {
  // ...
  plugins: [
    // ...
    new PrerenderSPAPlugin({
      staticDir: path.join(__dirname, 'dist'),
      routes: [ '/', '/about', '/contact' ],

      renderer: new Renderer({
        inject: {
          foo: 'bar'
        },
        headless: false,
        // 这个事件名称需要与网站的事件名称一直,具体可以参考官方例子:
        // https://github.com/chrisvfritz/prerender-spa-plugin/tree/master/examples/vue2-webpack-router
        renderAfterDocumentEvent: 'render-event',
        // 这个是macos下chrome的调用路径
        executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
        // chromium的调用路径
        // executablePath: '/Applications/Chromium.app/Contents/MacOS/Chromium'
      })
    })  
  ]
}

vue-cli 配置

如果使用vue-cli进行配置,需要更改vue.config.js,可以通过configureWebpack的函数进行处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// vue.config.js
module.exports = {
  configureWebpack: () => {
    // 针对生产环境进行处理
    if (process.env.NODE_ENV === 'production') {
      return {
        plugins: [
            new PrerenderSPAPlugin({
              // ...
            })
        ]
      }
    }
  }
}

使用本地浏览器

在使用本地系统安装浏览器的时候,推荐使用chromium,由于部分情况chrome可能会出现问题。linux通常chrome和chromium的安装路径分别是:

1
2
/usr/bin/chromium-browser
/usr/bin/google-chrome

部分chrome版本是stable版本,所以可能是/usr/bin/google-chrome-stable;在linux可以通过which命令查看对应路径,然后把得到的路径填入executablePath字段即可。

在linux系统执行的时候,有可能会出现依赖没有装完,导致无法启动chromium,这个问题可以查看这个解决方案;也有可能会提示配置不需要沙箱环境,需要改动配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
new PrerenderSPAPlugin({
      staticDir: path.join(__dirname, 'dist'),
      routes: [ '/', '/about', '/contact' ],

      renderer: new Renderer({
        inject: {
          foo: 'bar'
        },
        headless: false,
        renderAfterDocumentEvent: 'render-event',
        // 这个是macos下chrome的调用路径
        executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
        // 配置这行
        args: ['--no-sandbox']
      })
})

ci 环境部署

如果需要在ci环境部署,浏览器的安装也是一个问题,浏览器的安装包体积也不小,这里想到的几个方案有:

  1. 不跳过安装chromium,直接在node_modules安装的时候,把浏览器安装包也下载了;然后ci的cachenode_modules加上;
  2. 跳过安装chromium,自行下载浏览器并安装浏览器,cache需要把node_modules和浏览器下载路径都缓存;
  3. 跳过安装chromium,选用一个带有chromium的docker的image,就可以避免安装chromium。

缺点:

1、2两点都能够通过不同方法安装浏览器,但是通常浏览器依赖包还是缺失,需要自行安装对应的依赖;

第3点应该是比较好的解决方案,但需要选中一个比较好且稳定的image,dockerhub