生产环境中webpack构建出现问题

4

我正在处理一个由preact-cli发起的项目。

我有一个构建脚本来打包我的应用程序。webpack配置已经在preact-cli全局定义好了,但是我可以从preact.config.js中进行修改。

我检查了preact-cli中只有一个入口点,目前来说这样很好。

Bundle

还有一个CommonsChunkPlugin存在。它有这个配置:

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'。它是这样的:

ScriptHTMLWebpackPlugin

我尝试的方法:

  1. 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>
    
  2. 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.

  3. 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
    

现在我已经没有其他选择了,我需要在这方面寻求帮助。


一些易于实现的方案,我猜您在使用“production”等于“NODE_ENV”时编译捆绑包大小已经有所不同了? - carpeliam
2个回答

0

我注意到在 preact-cli 中,插件 HtmlWebpackPlugin 有一个选项:excludeAssets:[/(polyfills|bundle)(\..*)?\.js$/]

而模板包含了这一行:

<script>window.fetch||document.write('<script src="<%= htmlWebpackPlugin.files.chunks["bundle"].entry %>"><\/script>')</script>

所以,我写了另一个没有上面那行的模板。然后我修改了脚本:

"scripts": {
    "start": "if-env NODE_ENV=production && npm run -s serve || npm run -s dev",
    "build": "preact build --template=src/template.ejs",
    "build-nr": "preact build --no-prerender --template=src/template.ejs",
    "serve": "preact build --template=src/template.ejs && preact serve",
    "dev": "preact watch --template=src/template.ejs",
    "lint": "eslint src",
    "test": "jest"
}

然后我在文件.preact.js中修改了HtmlWebpackplgin的选项:

const p = helpers.getPluginsByName(config, 'HtmlWebpackPlugin')[0].plugin;
p.options.chunksSortMode='dependency'; // I dont't know if it's useful
p.options.excludeAssets: [/(polyfills)(\..*)?\.js$/ ];

0
根据 webpack 的 github 上类似问题的 这个答案,可能是 CommonChunksPluginHtmlWebpackPlugin 之间的冲突。
你尝试过在 HtmlWebpackPlugin 中设置 chunksSortMode 选项为 'dependency' 吗?

将尝试chunkSortMode。 - Vineet 'DEVIN' Dev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接