【问题标题】:How to get a list of all files (or modules) included per chunk in Webpack如何获取 Webpack 中每个块包含的所有文件(或模块)的列表
【发布时间】:2015-07-10 01:46:07
【问题描述】:

似乎在 webpack 中找不到任何调试选项或插件来显示块中的确切内容。

我为什么需要这个?我注意到代码拆分实际上使所有内容都变得更大的情况,然后只是将所有内容粘贴在一个文件中。这有点违反直觉,因为我不相信 webpack 的引导代码有那么重要;我怀疑这可能是缩小/重复数据删除,但在不知道哪些模块实际上被分块在一起的情况下,很难进行一些孤立的测试来确认。

我的构建过程使用 gulp;如果这有什么不同的话。

【问题讨论】:

    标签: javascript webpack gulp webpack-4


    【解决方案1】:

    好像有一个叫--display-modules的参数来显示所有模块如下:

    Webpack 5.x之前:

    $ webpack --display-modules
    

    然后你会得到类似如下的使用模块列表:

                       Asset     Size  Chunks             Chunk Names
    javascripts/webpack/app.js   211 kB       0  [emitted]  javascripts/webpack/app
    stylesheets/webpack/app.js  4.13 kB       1  [emitted]    stylesheets/webpack/app
    stylesheets/webpack/app.scss  2.99 kB       1  [emitted]  stylesheets/webpack/app
    [0] ./app/webpack/js/behaviors/lory-icon-slider.js.coffee 1.1 kB {0} [optional] [built]
    [1] ./app/webpack/css/components (\.scss|\.css)$ 160 bytes {1} [built]
    [2] ./app/webpack/js/behaviors (\.js|\.js.jsx|\.js.coffee)$ 252 bytes {0} [built]
    [3] ./~/pickmeup/css/pickmeup.scss 41 bytes {1} [built]
    [4] ./app/webpack/css/app.js 205 bytes {1} [built]
    [5] ./app/webpack/js/app.js 250 bytes {0} [built]
    [6] ./app/webpack/js/behaviors/pickmeup-fixed-calendar.js 3.47 kB {0} [optional] [built]
    [7] ./~/lory.js/dist/jquery.lory.js 25 kB {0} [built]
    [8] ./~/pickmeup/js/pickmeup.js 41.4 kB {0} [built]
    [9] (webpack)/buildin/global.js 509 bytes {0} [built]
    Child extract-text-webpack-plugin:
       [0] ./~/css-loader/lib/css-base.js 1.51 kB {0} [built]
       [1] ./~/css-loader!./~/sass-loader/lib/loader.js!./~/pickmeup/css/pickmeup.scss 3.23 kB {0} [built]
    

    Webpack 5.x

    $ webpack --stats-modules-space 999
    

    注意:该参数在 Webpack 5.x 中不存在

    【讨论】:

    • Webpack@5.x 中不再存在
    • 你可以在 Webpack 5x 中使用webpack --stats-modules-space 999
    • 999 是什么意思?
    【解决方案2】:

    您可以编写一个插件来执行此操作。

    例如,

    var PrintChunksPlugin = function() {};
    PrintChunksPlugin.prototype.apply = function(compiler) {
        compiler.plugin('compilation', function(compilation, params) {
            compilation.plugin('after-optimize-chunk-assets', function(chunks) {
                console.log(chunks.map(function(c) {
                    return {
                        id: c.id,
                        name: c.name,
                        includes: c.modules.map(function(m) {
                            return m.request;
                        })
                    };
                }));
            });
        });
    };
    

    更多详情,请查看此页面http://webpack.github.io/docs/plugins.html。它包含您可以挂钩的所有地方的文档。找到使用chunks: Chunk[]chunk 调用的正确钩子,在其中您将能够访问您想要的所有内容。

    此外,stats 对象包含您需要的所有post-build 信息。它在done 插件中可用。

    【讨论】:

    • 像魅力一样工作!但是我确实注意到有时m.request 没有定义。您是否也看到这种情况发生,如果是,您知道为什么会发生这种情况吗?
    • 我一直在研究它。我认为这与 require.context 以某种方式使用有关。
    • 太棒了!帮了我不少忙。
    • @Boopathi Rajaa:这对于查找依赖项非常有用。但是,如何从依赖项中找到命名的导出?比方说,我正在从一个节点模块中导入两个组件。那么,我怎样才能只得到这两个组件。现在,它会给我模块名称,而不是从模块导入的组件。我怎么知道呢?
    • 这在较新版本的 Webpack (4+) 中不起作用。 Potter 的更新版本适合我:stackoverflow.com/a/57279355/2441655
    【解决方案3】:

    这是 Boopathi Rajaa 答案的更新版本,适用于 Webpack 的更高版本(我使用的是 4.37.0)

    这个更新版本对我有用:

    class PrintChunksPlugin {
        apply (compiler) {
            compiler.plugin('compilation', compilation => {
                compilation.plugin('after-optimize-chunk-assets', chunks => {
                    console.log(chunks.map(chunk => ({
                        id: chunk.id,
                        name: chunk.name,
                        modules: Array.from(chunk._modules).map(module => module.id)
                    })))
                })
            })
        }
    }
    

    用法:

    plugins: [
        new PrintChunksPlugin(),
    ]
    

    最大的不同是它们现在将模块信息存储在_modules 而不是modules 中,并且它不是Array.from 之前的可映射对象。我发现module.id 更接近我的需要,但如果您需要,module.request 仍然存在。

    【讨论】:

    • 不知道为什么人们不赞成你。这更新了@Boopathi 的答案以适用于较新的 Webpack 版本,并且效果很好。 (虽然我建议将module 变量重命名为mod,因为module 是保留字)
    • 哦,它只记录前几十个条目(console.log 截断其余条目);要查看全部内容,请使用 JSON.stringify(..., null, 2) 包装 chunks.map 调用。
    【解决方案4】:

    这里还有一个与 webpack4 兼容的插件,它将所有的块输出到单个 JSON 文件中。

    https://www.npmjs.com/package/chunks-2-json-webpack-plugin

    这里是你如何使用它:

    1) 在你的 webpack 配置文件中,导入插件(当然是在你安装之后:) - npm i --save-dev chunks-2-json-webpack-plugin)并在 plugins 键下实例化它。

    const Chunks2JsonPlugin = require('chunks-2-json-webpack-plugin');
    const path = require('path');
    
    const publicPath = '/app/';
    
    module.exports = {
      entry: './src/index.js',
      output: {
        filename: '[name].[hash].js',
        path: path.resolve(__dirname, 'dist'),
        publicPath
      },
      plugins: [
        new Chunks2JsonPlugin({ outputDir: 'dist/', publicPath })
      ]
    };
    

    差不多就是这样,你会得到一个 JSON 文件,看起来像这样:

    {
      "chunk-vendors": {
        "js": ["/app/js/chunk-vendors.fc40696c.js"],
        "js.map": ["/app/js/chunk-vendors.fc40696c.js.map"]
      },
      "app": {
        "css": ["/app/css/app.eb829ccc.css"],
        "js": ["/app/js/app.dd31cdcb.js"],
        "js.map": ["/app/js/app.dd31cdcb.js.map"]
      }
    }
    

    在这里,我们将所有块都放在一个 JSON 文件中。

    您可以在链接本身上找到更多信息。

    【讨论】:

    • 这个插件在构建时不输出所有模块的列表,只输出生成文件的映射。
    【解决方案5】:

    解决方案是编写一个解析 .js.map 文件的脚本,因为它们包含一个 sources 条目,可用于识别该块中包含的所有文件。


    这是一个可以完成工作的小 gulp 脚本,

    var debugWebpackMapFile = function (file) {
    
        var cleanupRules = {
            // executed in order
            '/src/client/javascript/node_modules/': '',
            '/src/client/javascript/': 'static/'
        };
    
        return new Promise(function (resolve, reject) {
            var match = /\/([^\/]+).js.map$/.exec(file);
            if (match != null) {
                var filename = match[1];
                console.log("\n  " + filename + "\n  =======================\n");
                var mapjson = JSON.parse(fs.readFileSync(file));
    
                var dependencies = [];
                var sourcefiles = [];
    
                _.each(mapjson.sources, function (srcfile) {
                    srcfile = srcfile.replace('webpack://source-code', '', srcfile);
                    var match = /^\/node_modules\/([^\/]+)/.exec(srcfile);
                    if (match == null) {
                        match = /^(\/src\/.*\.js)(\?.*)?/.exec(srcfile);
                        if (match != null) {
                            // project source file
                            srcfile = match[1];
                            _.each(cleanupRules, function (to, from) {
                                srcfile = srcfile.replace(from, to);
                            });
    
                            // the sources are in random order in the map file,
                            // so we'll need to sort before displaying anything
                            sourcefiles.push(srcfile);
                        }
                    }
                    else {
                        // dependency
                        var pkg = match[1];
                        if (dependencies.indexOf(pkg) == -1) {
                            dependencies.push(pkg);
                        }
                    }
                });
    
                sourcefiles.sort();
                _.each(sourcefiles, function (srcfile) {
                    console.log("  " + srcfile);
                });
    
                if (dependencies.length > 0) {
    
                    console.log("\n  ---- 3rd Party ------------------\n");
    
                    dependencies.sort();
                    _.each(dependencies, function (pkg) {
                        console.log("  " + pkg);
                    });
                }
            }
    
            console.log("\n\n");
    
            resolve();
        });
    }
    
    gulp.task('js:debug', function (cb) {
        var conf = webpackConf.mainjs;
        glob(conf.output.path + '/*.map', {}, function (er, files) {
            var promises = [];
            _.each(files, function (file) {
                promises.push(debugWebpackMapFile(file));
            });
    
            Promise.all(promises).lastly(cb);
        });
    });
    

    您需要修改脚本以满足您自己的配置。

    以防万一,webpack://source-code 部分是由于 webpack output 设置中的 devtool 设置,即:

    devtoolModuleFilenameTemplate: "webpack://source-code/[resource-path]",
    devtoolFallbackModuleFilenameTemplate: "webpack://source-code/[resource-path]?[hash]",
    

    webpack/internalnode_modules 来自以下规范化脚本(我不喜欢 webpack 的“~”替换功能)。

    var normalizeMaps = function (conf, cb) {
        glob(conf.output.path + '/*.map', {}, function (er, files) {
            var promises = [];
            _.each(files, function (file) {
                promises.push(replaceInFile(file, [
                    [ /\/~/g, '/node_modules' ],
                    [ /\.\//g, ''],
                    [ /source-code\/\(webpack\)/g, 'source-code/webpack/internal' ]
                ]));
            });
    
            Promise.all(promises).lastly(cb);
        });
    };
    

    【讨论】:

      猜你喜欢
      • 2011-04-24
      • 2010-10-08
      • 2018-07-07
      • 2017-11-04
      • 1970-01-01
      • 1970-01-01
      • 2016-11-04
      • 2020-02-16
      相关资源
      最近更新 更多