shellscape / webpack-manifest-plugin

webpack plugin for generating asset manifests
MIT License
1.44k stars 185 forks source link

Wrong asset-manifest with two ExtractTextPlugin instances #114

Closed adoyle-h closed 6 years ago

adoyle-h commented 6 years ago

webpack config

I am intended to handle the styles in different ways between my source codes and node_modules.

The styles from node_modules will extracted to static/css/node_module_styles_[md5:contenthash:base64:6].css, and the styles from my source codes will be extracted to static/css/main.8a41ccd7.css.

rules:

// absPath is the function which returns a absolute path
{
    test: /\.css$/,
    oneOf: [
        {
            include: absPath('src'),
            exclude: /\.plain\.css$/,
            use: [
                {
                    loader: 'style-loader',
                    options: {
                        sourceMap: env === 'development',
                    }
                },
                {
                    loader: 'css-loader',
                    options: {
                        importLoaders: 1,
                        camelCase: true,
                        sourceMap: env === 'development',
                        modules: true,
                        localIdentName,
                    },
                },
                'postcss-loader',
            ],
        },
        {
            include: absPath('node_modules'),
            use: ExtractTextPlugin.extract({
                fallback: 'style-loader',
                use: ['css-loader'],
            }),
        }
    ],
}

plugins:

[
    new ManifestPlugin(),
    new ExtractTextPlugin({
        filename: 'static/css/[name].[contenthash:8].css',
    }),
    new ExtractTextPlugin({
        filename: 'static/css/node_module_styles.[md5:contenthash:base64:6].css',
    }),
]

I find that default behavior to generate a manifest:

manifest = files.reduce(function (manifest, file) {
    manifest[file.name] = file.path;
    return manifest;
}, seed);

https://github.com/danethurber/webpack-manifest-plugin/blob/ae03fbdcd4ba8073f66efd7b97eec8df318b0c87/lib/plugin.js#L148

Actually the files are most same.

// main.css
{
    path: '/static/css/main.8a41ccd7.css',
    name: 'main.css',
    isInitial: true,
    isChunk: true,
    isAsset: false,
    isModuleAsset: false
}

//  extracted texts from main.css
{
    path: '/static/css/node_module_styles.24Lqg8.css',
    name: 'main.css',
    isInitial: true,
    isChunk: true,
    isAsset: false,
    isModuleAsset: false,
}

The names of two chunks are same. Refer to the code in extract-text-webpack-plugin: https://github.com/webpack-contrib/extract-text-webpack-plugin/blob/master/src/index.js#L135

The later item of files array will overwrite the the former. So the asset-manifest file would be wrong.

Actually result

{
  "main.css": "/static/css/node_module_styles_24Lqg8.css",
  "main.js": "/static/js/main.7a857630.js",
}

What I expect

{
  "node_module_styles.css": "/static/css/node_module_styles_24Lqg8.css",
  "main.css": "/static/css/main.8a41ccd7.css",
  "main.js": "/static/js/main.7a857630.js",
}

webpack-manifest-plugin: 1.3.2 extract-text-webpack-plugin: 3.0.2 webpack: 3.8.1

mastilver commented 6 years ago

ATM this is not something we are going to fix: see #30

Just use the map options to change the name according to what you need