control file not to generate a new dependency chunk on the top

37 Views Asked by At

I'm new to writing Webpack plugins.

I want to add a new feature to an existing Webpack plugin repo.

The feature is to resolve a sub-package's structure in a .json file, then the dependencies below the sub-package roots should be split from the main package vendor bundler.

for example, my app.json:

{
  "pages":[
    "pages/one/one",
    "pages/two/two"
  ],
  "subPackages": [
    {
      "root": "pages/sub",
      "pages": [
        "one",
        "two"
      ]
    }
  ]
}

so if my project's src structure looks like:

--pages
   --one
     --one.js
     --one.html
     --one.css
     --one.service.js
   --two
     --two.js
     --two.html
     --two.css
     --two.service.js
   --sub
     --folder
       --test.js
     --one.js
     --one.html
     --one.css
     --one.service.js

then I expect its dist output to be like:

[[ CASE A ]]
--pages
   --one
     --one.js
     --one.html
     --one.css
   --two
     --two.js
     --two.html
     --two.css
   --sub
     --folder
       --test.js
     --one.js
     --one.html
     --one.css
     --one.service.js
--vendor.js

or:

--pages
   --one
     --one.js
     --one.html
     --one.css
   --two
     --two.js
     --two.html
     --two.css
   --sub
     --one.js
     --one.html
     --one.css
     --vendor.js
--vendor.js

The current repo's ability is to chunk all the dependencies together and output it to the root path's vendor file.

So my code is:

// waiting For Compiling And Deal By SingleEntryPlugin
async getEntryResources() {
    const appJSONFile = resolve(base, 'app.json');
    const { pages = [], subPackages = [] } = await readJson(
        appJSONFile
    );

    const subDepFiles = [];
    for (const subPackage of subPackages) {
        const { root, pages = [] } = subPackage;
        const scripts = pages.map(w => resolve(base, join(root, w)));

        const subFiles = await globby(join(root, '**/*'), {
            cwd: base,
            nodir: true,
            realpath: true
        });

        subFiles.forEach(resource => {
            const name = stripExt(resource)
            if (/\.js$/.test(resource) && scripts.indexOf(name) < 0) {
                subDepFiles.push(name.slice(name.indexOf(root)));
            }
        })

    }

    this.subRoots = subPackages.map(v => v.root);

    // pages + subpages + subpages' dependencies
    return [
        ...pages,
        ...subDepFiles,
        ...[].concat(...subPackages.map(v => v.pages.map(w => join(v.root, w))))
    ];
}

then my applyCommonsChunk filters the dependencies from the sub-package roots:

applyCommonsChunk(compiler) {
    const scripts = entryResources.map(::this.getFullScriptPath);

    compiler.apply(
        new CommonsChunkPlugin({
            name: 'vendor',
            minChunks: ({ resource }) => {
                if (resource) {
                    const inSubPackage = this.subRoots.find(v => resource.match(v))
                    return /\.js$/.test(resource) && scripts.indexOf(resource) < 0 && !inSubPackage;
                }
                return false;
            }
        })
    );
}

then my vendor.js is ok, and can output like [[ CASE A ]], but the sub/one.js has a copy of the service, instead of import from the sub/one.service.js.

0

There are 0 best solutions below