4

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

我有一个捆绑我的应用程序的构建脚本。webpack 配置已经在 preact-cli 中全局定义,但我可以从 preact.config.js 修改它。

我检查了 preact-cli 中只有一个入口点,目前还可以。

捆

并且存在一个 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,
   }));
  }
};

此配置为我提供了 rom 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 文件中。

我尝试了 3 件事,在此之前我检查了 preact-cli 中已经存在的“ScriptExtHtmlWebpackPlugin”。它是这个:

ScriptHTMLWebpackPlugin

我尝试过的事情:

  1. 将“ScriptExtHtmlWebpackPlugin”的默认属性更改为异步。这样我可以确保首先执行最小的文件,因为它将首先下载。在我的 preact.config.js 文件中添加任何插件之前,我编写了这段代码:

    let scriptPlugin = helpers.getPluginsByName(config, 'ScriptExtHtmlWebpackPlugin')[0].plugin;
    scriptPlugin.options.defaultAttribute = 'async';
    

    现在我得到了错误:

    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
    

    脚本文件加载到 build 文件夹的 index.html 中,如下所示:

    <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. 让属性仍然是'defer',但是改变加载文件的顺序,希望manifest.js比bundle.js更早加载。所以我在'HtmlWebpackPlugin'中编写了这个配置。

    htmlPlugin.options.chunksSortMode = function(entry1, entry2) {
        if(entry1.names[0] === "manifest") return -1;
        else return 1;
    }
    

    现在我得到了错误:

    Uncaught ReferenceError: webpackJsonp is not defined
        at bundle.9b6d3.js:1
    

    build 文件夹的 index.html 文件按以下顺序加载脚本:

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

    注意:在上述两种方法中,我的代码都不会影响 bundle.js 文件位置的任一属性。

  3. 通过preact-cli构建后,手动改变加载脚本的顺序,所以我把manifest.js放在bundle.js上面。所以它看起来像这样:

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

    我收到了这个错误:

    Uncaught TypeError: Cannot read property 'call' of undefined
        at n (bootstrap 4da816313a3eaaa2f964:54)
        at window.webpackJsonp (bootstrap 4da816313a3eaaa2f964:25)
        at bundle.9b6d3.js:1
    

现在我没有选择了,我需要帮助。

4

2 回答 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"
}

然后我在file.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$/ ];
于 2018-10-24T07:27:59.723 回答
0

根据webpack 的 github 中类似问题的这个答案CommonChunksPlugin,它可能是和之间的冲突HtmlWebpackPlugin

您是否尝试将chunksSortMode选项设置HtmlWebpackPlugin'dependency'

于 2018-01-19T11:41:18.073 回答