Webpack 2:将库,供应商和应用程序拆分为不同的文件

时间:2017-04-04 14:30:13

标签: webpack webpack-2 code-splitting commonschunkplugin

想象一下,我有一个丰富的应用程序,它使用了很多第三方模块,包括 lodash 时刻 axios 反应

如果我在最后将所有内容捆绑在一起,那么大小将高于1MB。

我希望webpack以我们存储的方式打包我的库:

    分别
  1. lodash
  2. 分别
  3. 时刻
  4. 所有其他 node_modules 存储在供应商包
  5. 应用程序的代码存储在单独的文件中
  6. 我尝试以不同的方式使用 CommonsChunkPlugin ,但从未收到我想要的结果。

    我已准备好示例存储库来说明我的问题: https://github.com/PavelPolyakov/webpack-react-bundles

    Webpack条目部分(conf/webpack.base.config.js):

    entry: {
        lodash: 'lodash',
        moment: 'moment',
        app: [
            'react-hot-loader/patch',
            'webpack-dev-server/client?http://localhost:3001',
            'webpack/hot/only-dev-server',
            './app/index.js']
    }
    

    这是生产配置(conf/webpack.production.config.js),尝试分离模块:

    plugins: [
            new webpack.DefinePlugin({
                'process.env': {
                    'NODE_ENV': JSON.stringify('production')
                }
            }),
            new webpack.optimize.CommonsChunkPlugin({
                name: 'vendor',
                minChunks: function (module) {
                    // this assumes your vendor imports exist in the node_modules directory
                    return module.context &&
                        module.context.indexOf('node_modules') !== -1;
                }
            }),
            new webpack.optimize.UglifyJsPlugin({
                minimize: true,
                compress: {
                    warnings: true
                }
            })]
    

    这种情况下,片刻和lodash仍将出现在供应商包中。我希望将它们放在两个单独的包中。

    任何想法都赞赏。

2 个答案:

答案 0 :(得分:3)

最后,我在github问题上收到了@sokra的帮助: https://github.com/webpack/webpack/issues/4638

对于那些将面临同样问题的人来说,这是完整的webpack配置,它解决了问题中描述的问题:

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: {
        app: ['./app/index.js']
    },
    output: {
        filename: '[name].bundle.js',
        sourceMapFilename: '[name].bundle.map',
        path: path.resolve(__dirname, './dist')
    },
    devServer: {
        port: 3001,
        contentBase: path.resolve(__dirname, './dist'),
        historyApiFallback: true
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: [['es2015', { 'modules': false }], 'react'],
                            plugins: ['transform-async-to-generator',
                                'transform-decorators-legacy',
                                'transform-runtime',
                                'react-html-attrs',
                                'react-hot-loader/babel'],
                        }
                    }
                ]
            },
            {
                test: /\.css/,
                use: ['style-loader', 'css-loader', 'postcss-loader']
            },
            {
                test: /\.(eot|svg|ttf|woff|woff2|gif|jpg|png)$/,
                use: 'file-loader'
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index.html',
            inject: "body"
        }),
        new webpack.optimize.UglifyJsPlugin({
            minimize: true,
            compress: {
                warnings: true
            }
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            minChunks: (m) => /node_modules/.test(m.context)
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'lodash',
            minChunks: (m) => /node_modules\/(?:lodash|moment)/.test(m.context)
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'moment',
            minChunks: (m) => /node_modules\/(?:moment)/.test(m.context)
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: "manifest",
            minChunks: Infinity
        })
    ],
    resolve: {
        extensions: ['.js', '.jsx']
    },
    devtool: 'source-map'
}

感谢所有试图提供帮助的人!

答案 1 :(得分:1)

如果您从CDN中包含它们并使用external,这可能是最简单的。

这不是每个定义代码拆分,但可能接近您想要完成的任务:减少包大小。某些用户已经从另一个站点缓存了CDN版本的优点。