我已经成功地让 Webpack 和 CommonsChunkPlugin 将我的代码分成两部分 - 一个包含我的代码库,一个包含从 node_modules 导入的所有内容。那是相对容易的一点。
我试图在我的应用程序中实现的下一件事是动态导入一个“子应用程序”,它具有完全不同的供应商包要求(例如 React - 我的主应用程序不使用它,但我的子应用程序使用它) ,所有这些包都没有出现在主供应商文件中。
如果我添加了 import(),但我的 Webpack 配置相对保持不变,我最终会得到 4 个包
- Webpack 运行时
- 主应用程序代码库
- 供应商捆绑包含在主应用程序代码库中导入的所有内容
- 动态导入的包,也包含所有导入的 node_modules :(
这是不可取的。我也希望从我的子应用程序的主代码库中获得“我的代码与供应商代码”的相同好处。理想情况下,我最终会得到 5 个捆绑包,上面列表中的 #4 分为两个。当动态导入在运行时发生时,它会以某种方式神奇地加载到我的子应用程序代码包和随附的子应用程序供应商包中。理想情况下,子供应商捆绑包不包含主供应商捆绑包中存在的任何内容。
在尝试了我在各种博客文章中找到的很多东西之后,我遇到了一种情况,我手动选择了我想包含在单独的供应商包中的 node_modules 目录,但问题是它不会包含他们的自动依赖,所以我的子应用程序包中仍然会有很多 node_modules - 我没有专门导入的那些。
如果我能让它正常工作,那么我想将它复制到我的主应用程序的更多子应用程序中。
更新 1
我的 Webpack 配置分为 3 个文件 - common、dev 和 prod。只有 common 和 dev 与此相关,所以我将在这里分享它们。
webpack.common.js
const webpack = require('webpack');
const path = require('path');
const NameAllModulesPlugin = require('name-all-modules-plugin');
module.exports = {
entry: {
/**
* main.js - our global platform JS
*/
main: './src/app.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: [
[
'env',
{
'targets': {
'browsers': ['last 3 versions', 'ie >= 11']
}
}
],
'react'
],
plugins: [
'transform-class-properties',
'transform-object-rest-spread',
// Followed instructions here to get dynamic imports working
// http://docs1.w3cub.com/webpack~2/guides/code-splitting-import/
'syntax-dynamic-import',
'transform-async-to-generator',
'transform-regenerator',
'transform-runtime'
]
}
}
]
},
resolve: {
alias: {
src: path.resolve(__dirname, 'src/')
}
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
CodeMirror: 'codemirror'
}),
new webpack.NamedModulesPlugin(),
new webpack.NamedChunksPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: (m) => /node_modules/.test(m.context)
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'runtime',
minChunks: Infinity
}),
new NameAllModulesPlugin()
]
};
webpack.dev.js
const webpack = require('webpack');
const path = require('path');
const merge = require('webpack-merge');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const common = require('./webpack.common.js');
module.exports = merge(common, {
devtool: 'inline-source-map',
output: {
filename: '[name].js',
chunkFilename: '[name]-chunk.js', // used for async chunks (those loaded via import())
path: path.resolve(__dirname, 'build'),
publicPath: '/js/build/'
},
plugins: [
// Uncomment and run build, to launch the bundle analyzer webpage
new BundleAnalyzerPlugin(),
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify('dev') }
})
]
});
更新 2
我偶然发现了一个似乎有效的配置。它甚至在实际导入的同时自动加载到子应用的供应商块中。
// For the main app's modules
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: (m, count) => /node_modules/.test(m.context)
}),
// For my sub app's modules
new webpack.optimize.CommonsChunkPlugin({
name: 'any-name-here', // doesn't appear to be used anywhere, but prevents 'main' from showing up in the chunk filename (?!)
chunks: ['name-of-dynamic-import'], // this has to be the 'webpackChunkName' you've used within the import() statement
async: 'name-of-dynamic-import-vendor', // name the chunk filename
minChunks: (m, count) => /node_modules/.test(m.context)
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'runtime',
minChunks: Infinity
}),