我正在处理一个由preact-cli发起的项目。
我有一个构建脚本来打包我的应用程序。webpack配置已经在preact-cli全局定义好了,但是我可以从preact.config.js中进行修改。
我检查了preact-cli中只有一个入口点,目前来说这样很好。
还有一个CommonsChunkPlugin存在。它有这个配置:
如果我按照这个配置正常地构建应用程序,我将得到一个大捆绑文件。
所以我开始添加自己的CommonsChunkPlugin。
Preact提供了一种修改webpack配置的方法。这个是:
我的preact.config.js是:
export default (config, env, helpers) => {
let { rule } = helpers.getLoadersByName(config, 'babel-loader')[0];
let babelConfig = rule.options;
babelConfig.plugins.push('transform-decorators-legacy');
babelConfig.presets.push('flow');
config.plugins.push(new InterpolateHtmlPlugin(envs.raw));
config.plugins.push(new webpack.DefinePlugin(envs.stringified));
config.plugins.push(new WatchMissingNodeModulesPlugin(paths.appNodeModules));
rule.options.plugins.push('transform-regenerator');
rule.options.plugins.push(["transform-runtime", {
"helpers": false,
"polyfill": false,
"regenerator": true
}]);
let htmlPlugin = helpers.getPluginsByName(config, 'HtmlWebpackPlugin')[0].plugin;
htmlPlugin.options.template = `!!ejs-loader!${path.resolve(__dirname, './template.html')}`;
htmlPlugin.options.title = "JApp";
htmlPlugin.options.manifest = Object.assign({}, {
name: 'JH',
short_name: 'JApp',
theme_color: '#007DC5'
});
let commonChunksPlugin = helpers.getPluginsByName(config, 'CommonsChunkPlugin')[0].plugin;
console.log(commonChunksPlugin);
if(process.env.NODE_ENV === "production") {
config.plugins.push(new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: ({ resource }) => (
resource !== undefined &&
resource.indexOf('node_modules') !== -1
),
}));
config.plugins.push(new webpack.optimize.CommonsChunkPlugin({
name: 'preact-chunk',
filename: 'static/js/[name].[chunkhash:8].js',
minChunks: (m) => m.resource && /preact|preact-compat/.test(m.resource)
}));
config.plugins.push(new webpack.optimize.CommonsChunkPlugin({
name: 'others-chunk',
filename: 'static/js/[name].[chunkhash:8].js',
minChunks: (m) => m.resource && /redux|preact-redux|redux-form|lodash|sane-email-validation|moment|core-decorators|lodash-decorators/.test(m.resource)
}));
config.plugins.push(new webpack.optimize.CommonsChunkPlugin({
name: 'material-ui-chunk',
filename: 'static/js/[name].[chunkhash:8].js',
minChunks: (m) => m.resource && /material-design-lite|preact-mdl/.test(m.resource)
}));
config.plugins.push(new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
filename: 'static/js/[name].[chunkhash:8].js',
minChunks: Infinity,
}));
}
};
这个配置给了我所有距离bundle.js文件相隔5个块的文件。清单文件包含webpack的引导文件,就像预期的那样。我运行应用程序,但是在浏览器中出现以下错误:
bundle.9b6d3.js:1 Uncaught ReferenceError: webpackJsonp is not defined
at bundle.9b6d3.js:1
我发现manifest.js文件的加载顺序晚于bundle.js和所有脚本文件都有'defer'属性。webpackJsonp定义存在于manifest.js文件中。
我尝试了三件事情,并在此之前检查了preact-cli中已经存在的'ScriptExtHtmlWebpackPlugin'。它是这样的:
我尝试的方法:
Change the default attribute of 'ScriptExtHtmlWebpackPlugin' to async. This way I can make sure that the smallest file executes first, as it will be downloaded first. I wrote this code before adding any plugin in my preact.config.js file:
let scriptPlugin = helpers.getPluginsByName(config, 'ScriptExtHtmlWebpackPlugin')[0].plugin; scriptPlugin.options.defaultAttribute = 'async';
Now I got the error:
bootstrap b7b6d09314cc5ff6d290:54 Uncaught TypeError: Cannot read property 'call' of undefined at n (bootstrap b7b6d09314cc5ff6d290:54) at Object.<anonymous> (others-chunk.55912d9c.js:12) at Object.E/bI (others-chunk.55912d9c.js:1207) at n (bootstrap b7b6d09314cc5ff6d290:54) at Object.JkW7 (bundle.9b6d3.js:18) at n (bootstrap b7b6d09314cc5ff6d290:54) at Object.pwNi (entry.js:13) at n (bootstrap b7b6d09314cc5ff6d290:54) at window.webpackJsonp (bootstrap b7b6d09314cc5ff6d290:25) at bundle.9b6d3.js:1
The script files are loaded in index.html of build folder as follows:
<script defer="defer" src="/bundle.9b6d3.js"></script> <script>window.fetch||document.write('<script src="/polyfills.d41d8.js"><\/script>')</script> <script src="/static/js/manifest.d41d8cd9.js" async></script> <script src="/static/js/others-chunk.55912d9c.js" async></script> <script src="/static/js/preact-chunk.c2b64323.js" async></script> <script src="/static/js/node-static.916ed24c.js" async></script>
Let the attribute still be 'defer', but change the order of loading the files, hoping manifest.js will load earlier than bundle.js. So I wrote this configuration in 'HtmlWebpackPlugin'.
htmlPlugin.options.chunksSortMode = function(entry1, entry2) { if(entry1.names[0] === "manifest") return -1; else return 1; }
Now I got the error:
Uncaught ReferenceError: webpackJsonp is not defined at bundle.9b6d3.js:1
The index.html file of build folder loaded scripts in this order:
<script defer="defer" src="/bundle.9b6d3.js"></script> <script>window.fetch||document.write('<script src="/polyfills.d41d8.js"><\/script>')</script> <script src="/static/js/manifest.d41d8cd9.js" defer="defer"></script> <script src="/static/js/others-chunk.55912d9c.js" defer="defer"></script> <script src="/static/js/preact-chunk.c2b64323.js" defer="defer"></script> <script src="/static/js/node-static.916ed24c.js" defer="defer"></script>
Note: In both the above approaches, my code is not affecting either attribute of position of bundle.js file.
After building through preact-cli, manually change the order of loading scripts, so I put manifest.js above bundle.js. SO it looked like this:
<script src="/static/js/manifest.d41d8cd9.js" defer="defer"></script> <script defer="defer" src="/bundle.9b6d3.js"></script> <script>window.fetch||document.write('<script src="/polyfills.d41d8.js"><\/script>')</script> <script src="/static/js/others-chunk.55912d9c.js" defer="defer"></script> <script src="/static/js/preact-chunk.c2b64323.js" defer="defer"></script> <script src="/static/js/node-static.916ed24c.js" defer="defer"></script>
I got this error:
Uncaught TypeError: Cannot read property 'call' of undefined at n (bootstrap 4da816313a3eaaa2f964:54) at window.webpackJsonp (bootstrap 4da816313a3eaaa2f964:25) at bundle.9b6d3.js:1
现在我已经没有其他选择了,我需要在这方面寻求帮助。