Legendary

李洋的学习笔记


prerender-spa-plugin单页应用打包html

1、 配置webpack.prod.config.js(及修复报 webpackJsonp is not defined 的BUG):

const baseWebpackConfig = require('./webpack.base.conf')
...
//引入自定义配置及相关依赖
const MyPlugin = require('./my-plugin.js')
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;

module.exports = {
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      chunks: ['manifest', 'vendor', 'app'],
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'
    }),
    // 配置PrerenderSPAPlugin
    new PrerenderSPAPlugin({
      // 生成文件的路径,也可以与webpakc打包的一致。
      staticDir: path.join(__dirname, '../dist'),

      // 对应自己的路由文件,比如index有参数,就需要写成 /index/param1。
      routes: ['','/'],

      // 这个很重要,如果没有配置这段,也不会进行预编译
      renderer: new Renderer({
        inject: {
          foo: 'bar'
        },
        headless: false,
        // 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。
        renderAfterDocumentEvent: 'render-event',
        captureAfterTime: 5, //单位秒
      })
    }),
}

2、 main.js:

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>',
  mounted() {
  // You'll need this for renderAfterDocumentEvent.
    document.dispatchEvent(new Event('render-event'))
  }
})

3、修复报 webpackJsonp is not defined 的BUG的自定义配置,同级目录新建my-plugin.js

function MyPlugin(options) {
    this.options = options;
}
MyPlugin.prototype.apply = function(compiler) {
    compiler.plugin('compilation', function(compilation) {
        /*
        出现 webpackJsonp is not defined 是因为 manifest.js 加载在vendor文件后面了,下面我们调整manifest.js文件在头部加载
        这里使用插件:html-webpack-plugin-alter-asset-tags
        来修改manifest.js到顶部加载
        */
        compilation.plugin('html-webpack-plugin-alter-asset-tags', function(htmlPluginData, callback) {
            console.log(33333333333)
            console.log(htmlPluginData.head)
            console.log(htmlPluginData.body)
            //**********************修改manifest开始*********
            //因为manifest存在于htmlPluginData.body里
            //先获取manifest.js
            let manifest = '';
            if (htmlPluginData.body && htmlPluginData.body.length) {
                let index = 0;
                let manifestindex = 0;
                htmlPluginData.body.forEach(item => {
                    if (item.attributes) {
                        let src = item.attributes.src;
                        if(src.indexOf('manifest') !== -1){
                            manifest = item
                            manifestindex = index;
                        }
                    }
                    index++;
                });
                if(manifest){
                    htmlPluginData.body.splice(manifestindex,1)
                }
            }
            //修改头部数据
            //把每个 href 带有 css/ 字符串的标签加上 id
            if (htmlPluginData.head && htmlPluginData.head.length) {
                htmlPluginData.head.forEach(item => {
                    if (item.attributes) {
                        let href = item.attributes.href;
                        item.attributes.id = href.substring(href.indexOf('css/') + 4, href.indexOf('.'));
                    }
                });
            }
            //把 manifest.js 插入到头部中去
            htmlPluginData.head.unshift(manifest)
            console.log(htmlPluginData.head)
            console.log(htmlPluginData.body)
            //**********************修改manifest结束*********

            callback(null, htmlPluginData);
        });
    });
};
module.exports = MyPlugin;

页面列表

ITEM_HTML