简体   繁体   中英

webpack require with dynamic path

My colleague put something like this in our code:

const information = require('../relative/path/' + tag + '.json');

The funny thing is that it works, and I don't really see how.

I have created this minimal project:

$ head *.json main.js 
==> 1.json <==
["message #1"]

==> 2.json <==
["message two"]

==> 3.json <==
["message III"]

==> package.json <==
{
  "dependencies": {
    "webpack": "^5.38.1"
    "webpack-cli": "^4.7.2"
  }
}

==> package-lock.json <==
...
==> main.js <==
const arg = process.argv[2] ? process.argv[2] : 1;

console.log(require(`./${arg}.json`)[0]);

when I run the original program, I get this:

$ node main.js 1
message #1
$ node main.js 2
message two
$ node main.js 3
message III

so now I compile with webpack

$ node_modules/.bin/webpack ./main.js

and it creates a dist directory with a single file it in, and that new bundled program works too:

$ node dist/main.js 1
message #1
$ node dist/main.js 2
message two
$ node dist/main.js 3
message III

and when I look inside the bundle, all the info is bundled:

带有 json 内容的捆绑代码

When I remove the require from the program, and just print the arg, the bundled program is a single line.

So how does it do it?

  • somehow calculate every possible file?
  • just include everything from the current directory down?

Funny thing is in my simple example, package.json ended up in there too, but in the real one that gave me the idea, it didn't.

Does anybody know how this works?

I mean the simple practical answer for me is, never put variables in require... but I am still curious.

PS the real one is a web project. just used node and args for the example

Webpack always bundles all require 'd files into the final output file (by default called bundle.js ). You cannot require anything that was not bundled.

If you require something that is not a constant, as you pointed out, it might lead to some trouble. That is why eslint has a no-dynamic-require rule for that. But if you know what you are doing, everything is just fine.

Webpack uses some heuristics to support non-build-time-constant values (ie expressions) for require . The exact behavior is documented in webpack's documentation on dependency management .

As explained in that link, your require('../relative/path/' + tag + '.json') will lead webpack to determine:

  • Directory: ../relative/path
  • Regular expression: /^.*\.json$/

And will bundle all files matching that criterion.

When your require call is executed, it will provide that file that matches it exactly, or throw an error if that file was not bundled.

Important: This means, of course, that you cannot add files after bundling. You must have files in the right place, before bundling, so they can be found, added and ultimately resolved by webpack.

Also note that often times, you don't need to write your own webpack experiments. Webpack has plenty of official samples . Eg your case is illustrated exactly by this official webpack sample .

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