prerender-spa-plugin单页应用打包html
<p>1、 配置<code>webpack.prod.config.js</code>(及修复报 <code>webpackJsonp is not defined</code> 的BUG):</p>
<pre><code>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, //单位秒
})
}),
}</code></pre>
<p>2、 main.js:</p>
<pre><code>new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>',
mounted() {
// You'll need this for renderAfterDocumentEvent.
document.dispatchEvent(new Event('render-event'))
}
})</code></pre>
<p>3、修复报 <code>webpackJsonp is not defined</code> 的BUG的自定义配置,同级目录新建<code>my-plugin.js</code>:</p>
<pre><code>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;</code></pre>