简体   繁体   中英

Webpack with multiple roots and dynamic requires

I have webpack configured with two roots:

resolve: {
  root: [ path.resolve('./src/siteName'), path.resolve('./src/common') ]
},

Module resolve works perfectly when I require a module by name require('moduleName') . It looks in siteName folder and if it doesn't find the module there it looks in common folder.

When I try to require a module dynamically require('Pages/' + pageModuleName) , webpack adds all files from siteName/Pages to the bundle but it ignores files in common/Pages folder.

I looked into require.context but it doesn't really solve my problem as it ends up including all the files from both folders.

var req = require.context('../', true, /\/(siteName|common)\/Pages/);
var page = req(pageModuleName);

To sum up, given a file structure like the following:

common/Pages/PageA.js
common/Pages/PageB.js
siteName/Pages/PageA.js

When I do something like

require('Pages/' + pageModuleName);

Is it possible for webpack to be configured in a way that will add just

siteName/Pages/PageA.js
common/Pages/PageB.js

to the bundle and "ignore"

common/Pages/PageA.js

I don't think what you are trying to achieve.

When you

resolve: {
  root: [ path.resolve('./src/siteName'), path.resolve('./src/common') ]
},

It effectively teels webpack to use ./src/siteName/ and ./src/common as root. So if you have /pages in both directories, you end up have duplicate paths.

  //what you want                   // what webpack see
siteName/pages/PageA.js               pages/PageA.js
siteName/pages/PageB.js        =>     pages/PageB.js
common/pages/PageA.js                 pages/PageA.js
common/pages/PageB.js                 pages/PageB.js

So you need to set it to

resolve: {
  root: [ path.resolve('./src') ]
},

I am a bit late but still this problem can be actual today :)

I was trying to find the answer myself. I guess there is no "pretty" solution but I can offer an "ugly" one that just works. And yes, you have to explicitly list all physical paths you want to use with require.context , because Webpack resolves each path only once and does not do it on each potential module. So if it finds a folder it just stops searching (obviously).

function requireAll(req, cb) {
    // store moduleName => module mappings to prevent overriding
    let modules = {};
    if (!Array.isArray(req)) req = [req];
    // go trough each require.context
    for (let reqItem of req) {
        // go through each module
        for (let name of reqItem.keys()) {
            // skip module if it is already required
            if (modules.hasOwnProperty(name)) continue;
            // require module
            let module = reqItem(name);
            if (module.default) module = module.default;
            // callback
            if (cb) cb(module, name);
            // memorize module
            modules[name] = module;
        }
    }
    return modules;
}

requireAll([
    // require pririty is as follows
    require.context('path1/', true),
    require.context('path2/', true)
], (module, name) => {
    // whatever
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM