如何在HtmlWebpackPlugin中将Webpack中的多个条目与多个HTML文件一起使用?

时间:2018-09-20 22:24:53

标签: javascript webpack html-webpack-plugin

我们想从Webpack中获得两个输出-整个应用程序具有所有依赖项,而一个单独的页面只有一个依赖项(主应用程序不共享)。

执行此操作的方法似乎是利用Webpack配置的entry属性。但是,这还不够,因为我们还使用HtmlWebpackPlugin来输出HTML文件以及Webpack编译动态添加的build.js(以及编译的LESS等)。根据HtmlWebpackPlugin文档:

  

如果您有多个Webpack入口点,则将它们全部包括在内   在生成的HTML中包含脚本标签。

这对我们不起作用,因此我需要利用他们的filterChunks选项。这个GitHub issue response最简洁地说:

module.exports = {
  entry: {
    'page1': './apps/page1/scripts/main.js',
    'page2': './apps/page2/src/main.js'
  },
  output: {
    path: __dirname,
    filename: "apps/[name]/build/bundle.js"
  },
  plugins: [
    new HtmlWebpackPlugin({
      inject: false,
      chunks: ['page1'],
      filename: 'apps/page1/build/index.html'
    }),
    new HtmlWebpackPlugin({
      inject: false,
      chunks: ['page2'],
      filename: 'apps/page2/build/index.html'
    })
  ]
};

(在HtmlWebpackPlugin文档中,这在“过滤块”部分下)

所以,我像这样修改了我们的代码:

module.exports = {
    entry: {
        app: './public/js/ide.js',
        resetPassword: './public/js/reset_password.js'
    },
    output: {
        path: path.resolve(__dirname, '../build'),
        filename: '[name].js',
        publicPath: '/'
    },
    ...
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'public/html/ide.html',
            inject: true,
            chunks: ['app']
        }),
        new HtmlWebpackPlugin({
            filename: 'reset_password.html',
            template: 'public/html/reset_password.html',
            inject: true,
            chunks: ['resetPassword']
        }),
    ],
}

现在,当我重建项目(现在仅尝试使用WebpackDevServer)并导航到/index.html时,我可以在网络选项卡中看到庞大的捆绑文件,其中index.html的内容(基于ide.html模板),以及对各种外部资源的请求。但是,不会运行任何实际的JavaScript(例如,ide.js中的console.log)。显示文件中的所有HTML。

对于reset_password.html,将显示所有HTML,并且显示reset_password.js文件,但运行中的JavaScript均不显示。

如何确保entry文件中的JavaScript运行?

编辑:我已经ide.js工作了,因为我没有意识到以下内容是“大块的”:

optimization: {
        splitChunks: {
            cacheGroups: {
                commons: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendor',
                    chunks: 'all'
                }
            }
        }
    },

因此,我将vendor添加到了index.html HtmlWebpackPlugin chunks属性中。现在,它看起来像这样:

new HtmlWebpackPlugin({
    filename: 'index.html',
    template: 'public/html/ide.html',
    inject: true,
    chunks: ['app', 'vendor']
}),

reset_password在node_modules文件夹中不需要任何内容​​,这也不能解释为什么ide.js中根本不运行JavaScript,所以我还是很困惑。此外,reset_password仍然无法正常工作。

EDIT2 :加载reset_password.js时,通过看似附加的reset_password.html文件,可以看到这一行

eval("\n\nconsole.log('DRAGONHELLO');//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9wdWJsaWMvanMvcmVzZXRfcGFzc3dvcmQuanM/ZjY5ZSJdLCJuYW1lcyI6WyJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiOztBQUNBQSxRQUFRQyxHQUFSLENBQVksYUFBWiIsImZpbGUiOiIuL3B1YmxpYy9qcy9yZXNldF9wYXNzd29yZC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIlxuY29uc29sZS5sb2coJ0RSQUdPTkhFTExPJylcbiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./public/js/reset_password.js\n");

因此,显然我的console.log('DRAGONHELLO')是“可见的”,但我不知道为什么它没有运行。

EDIT3 :将vendor的{​​{1}}添加到chunks会导致JavaScript运行,但是我不知道为什么,这是不理想的,因为整个练习的重点是拥有两个不同的捆绑包,一个捆绑包非常小,不需要我们所有的reset_password.html

EDIT4 :我使用node_modules运行了Webpack,可以看到我没有弄错“块名称”:

profile:true

EDIT5 :我都尝试过

                 js/app.3d18b43294ebd54ed083.js   1.34 MiB       0  [emitted]  [big]  app
       js/resetPassword.198485be2b163cc258ed.js   1.02 KiB       1  [emitted]         resetPassword
                   js/2.e7f92193ea3c611a0b36.js   2.23 MiB       2  [emitted]  [big]  vendor
             js/app.3d18b43294ebd54ed083.js.map   2.71 MiB       0  [emitted]         app
   js/resetPassword.198485be2b163cc258ed.js.map   4.57 KiB       1  [emitted]         resetPassword
               js/2.e7f92193ea3c611a0b36.js.map   7.12 MiB       2  [emitted]         vendor

module.exports = {
  //...
  optimization: {
    runtimeChunk: {
      name: entrypoint => `runtime~${entrypoint.name}`
    }
  }
};

基于PlayMa256的评论和webpack docs on runtimeChunk。两者均未导致JavaScript执行。

2 个答案:

答案 0 :(得分:3)

设置时:

module.exports = {
  //...
  optimization: {
    runtimeChunk: true
  }
};

它生成一个运行时块。什么是运行时?运行时是webpack用来加载其他文件的所有代码所在的位置。这是运行build时webpack的核心。

由于您有2个单独的捆绑文件:resetPasswordapp

好的,您拥有了所需的所有文件。您可能同时也需要供应商,因为您的供应商包含了node_modules中的所有内容。所以基本上您将拥有:

html 1:appvendorruntimeChunk

html 2:reset_passwordvendorruntimeChunk

这样做,您的应用程序应该运行。

答案 1 :(得分:2)

这是一个多方面的问题。

首先,there is a bug in Html-Webpack-Plugin使其与Webpack4和多个入口点不兼容。必须至少将其升级到v4.0.0-alpha.2才能正常工作。

第二,在新版本中,您无需使用optimization.splitChunks.cacheGroups来手动分离出node_modules。进行optimization.splitChunks.chunks = 'all'足以使给定的入口点仅进入其vendors-app-{{chunk_name}}个节点模块的import块中。

所以,如果您这样做

optimization: {
    splitChunks: {
        chunks: 'all'
    },
},

结合
plugins: [
    new HtmlWebpackPlugin({
        filename: 'index.html',
        template: 'public/html/ide.html',
        inject: true,
        chunks: ['app']
    }),
    new HtmlWebpackPlugin({
        filename: 'reset_password.html',
        template: 'public/html/reset_password.html',
        inject: true,
        chunks: ['resetPassword']
    }),
]

结合
entry: {
    app: './public/js/ide.js',
    resetPassword: './public/js/reset_password.js'
},

然后,您的Webpack输出将具有

  1. 应用
  2. resetPassword
  3. vendors〜app〜resetPassword
  4. 供应商〜app
  5. 供应商〜重置密码

除非您的imports文件中没有resetPassword.js,否则它将看起来像

  1. 应用
  2. resetPassword
  3. vendors〜app〜resetPassword(必需的webpack供应商软件包)
  4. 供应商〜app

https://github.com/jantimon/html-webpack-plugin/issues/1053上的更多信息,图像和对话

请注意,对于最新版本,chunksSortMode:不再是HtmlWebpackPlugin对象上的有效选项,它显然是在webpack4中默认完成的。