Search code examples
javascriptnode.jssvgwebpackwebpack-plugin

How can i get a flat list of file dependencies filtered by entry point from the compilation in webpack 5


I'm trying to update the svg-chunk-webpack-plugin from webpack v4 to v5. The plugin used the compilation object and needs a flat list of file dependencies filtered by entry point to extract all SVGs for each entry points.

Example of a nested dependency tree with an entry point app-a

- app-a.js
    - svg1.svg
    - module1.js
        - svg2.svg
        - svg3.svg
        - module2.js
            - svg4.svg
            - svg5.svg

With webpack v4, the following code works and returns an array of all SVG files used by each entry points

const path = require('path');

function getSvgsDependenciesByEntrypoint(entryName) {
    let listSvgs = [];

    compilation.entrypoints.get(entryName).chunks.forEach((chunk) => {
        chunk.getModules().forEach((module) => {
            module.buildInfo &&
                module.buildInfo.fileDependencies &&
                module.buildInfo.fileDependencies.forEach((filepath) => {
                    const extension = path.extname(filepath).substr(1);
                    if (extension === 'svg') {
                        listSvgs.push(filepath);
                    }
                });
        });
    });
    return listSvgs;
}

const svgs = getSvgsDependenciesByEntrypoint('app-a');
console.log(svgs) // ["svg1.svg", "svg2.svg", "svg3.svg", "svg4.svg", "svg5.svg"]

With webpack v5, I've tried the following code which produce different results between development and production build.

const path = require('path');

function getSvgsDependenciesByEntrypoint(entryName) {
    let listSvgsDependencies = [];

    compilation.entrypoints.get(entryName).chunks.forEach((chunk) => {
        compilation.chunkGraph.getChunkModules(chunk).forEach((module) => {
            module.dependencies.forEach((dependency) => {
                const extension = path.extname(dependency.userRequest).substr(1);
                if (extension === 'svg') {
                    const moduleDependency = compilation.moduleGraph.getModule(dependency);
                    listSvgsDependencies.push(moduleDependency);
                }
            });
        });
    });

    return listSvgsDependencies;
}

In development build

const svgs = getSvgsDependenciesByEntrypoint('app-a');
console.log(svgs) // ["svg1.svg", "svg2.svg", "svg3.svg", "svg4.svg", "svg5.svg"]

In production build

const svgs = getSvgsDependenciesByEntrypoint('app-a');
console.log(svgs) // ["svg1.svg"]

Nested dependencies are not find with the production build


Solution

  • I fixed the bug with the webpack team on issue #12202.

    This behavior is related to the side effects of the module. The webpack release v5.10.3 includes a fix which allows to manually specify the module has side effects. You could do that either in module rules or within the loader directly.