diff --git a/.changeset/windows-path-module-names.md b/.changeset/windows-path-module-names.md new file mode 100644 index 00000000..13b40b45 --- /dev/null +++ b/.changeset/windows-path-module-names.md @@ -0,0 +1,5 @@ +--- +"webpack-bundle-analyzer": patch +--- + +Keep modules in the report when their names use Windows path separators, which happens when a module is resolved from another drive and Webpack keeps its absolute path as the module name. diff --git a/src/tree/utils.js b/src/tree/utils.js index 83a2157d..8f2910c4 100644 --- a/src/tree/utils.js +++ b/src/tree/utils.js @@ -21,8 +21,8 @@ export function getModulePathParts(moduleData) { const loaders = moduleData.name.split("!"); // Removing loaders from module path: they're joined by `!` and the last part is a raw module path const parsedPath = loaders[loaders.length - 1] - // Splitting module path into parts - .split("/") + // Splitting module path into parts, module names use both `/` and `\` separators + .split(/[\\/]/u) // Removing first `.` .slice(1) // Replacing `~` with `node_modules` diff --git a/test/analyzerUtils.js b/test/analyzerUtils.js index e493b553..3d4ae820 100644 --- a/test/analyzerUtils.js +++ b/test/analyzerUtils.js @@ -96,6 +96,64 @@ describe("getViewerData", () => { expect(chunksAccessCount).toBe(1); }); + it("handles modules whose names use Windows path separators", () => { + const stats = { + assets: [ + { + name: "bundle.js", + size: 150, + chunks: [1], + }, + ], + chunks: [ + { + id: 1, + modules: [ + { + id: 1, + identifier: "./src/index.js", + name: "./src/index.js", + size: 100, + chunks: [1], + depth: 0, + }, + { + // Webpack keeps the absolute path in module names when the module is + // located on another drive, so the name keeps the Windows separator. + id: 2, + identifier: "D:\\shared\\lib\\util.js", + name: "D:\\shared\\lib\\util.js", + size: 50, + chunks: [1], + depth: 1, + }, + ], + }, + ], + }; + + const chartData = getViewerData(stats); + const modulePaths = []; + const collectModulePaths = (groups) => { + for (const group of groups) { + if (group.groups) { + collectModulePaths(group.groups); + } else { + modulePaths.push(group.path); + } + } + }; + + collectModulePaths(chartData[0].groups); + + expect(modulePaths).toEqual([ + "./src/index.js", + // The drive letter is cut off by the same rule that cuts off the leading `.` + "./shared/lib/util.js", + ]); + expect(chartData[0].statSize).toBe(150); + }); + it("handles child compilations with missing or undefined assets without throwing", () => { const stats = { children: [