The __dirname option in webpack
Webpack does have the option to control the value of __dirname
in bundled code. However, the description of the API (link) is difficult to understand without a concreted example.
From the docs
node.__dirname
string
boolean = false
Options:
-true
: The dirname of the input file relative to thecontext
option.
-false
: The regular Node.js__dirname
behavior. The dirname of the output file when run in a Node.js environment.
-'mock'
: The fixed value'/'
.
Let's see how this option works
➜ dirname pwd
/home/transang/dirname
➜ dirname cat package.json
{
"name": "dirname",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
➜ dirname node --version
v14.0.0
➜ dirname yarn --version
1.22.4
➜ dirname cat webpack.config.js
exports.default = () => ({
entry: './s1/s2/index.js',
output: {
path: `${__dirname}/d1/d2/d3/d4`
},
target: 'node',
node: {__dirname: 'mock'}
})
➜ dirname cat s1/s2/index.js
console.log(__dirname)
➜ dirname yarn webpack --mode=development
yarn run v1.22.4
$ /home/transang/dirname/node_modules/.bin/webpack --mode=development
Hash: d6da97334da34a12f504
Version: webpack 4.43.0
Time: 41ms
Built at: 05/04/2020 11:36:21 AM
Asset Size Chunks Chunk Names
main.js 3.9 KiB main [emitted] main
Entrypoint main = main.js
[./s1/s2/index.js] 23 bytes {main} [built]
Done in 0.44s.
➜ dirname cd e1
➜ e1 pwd
/home/transang/dirname/e1
➜ e1 node ../d1/d2/d3/d4/main.js
/
I made an experiment with a very simple webpack config
exports.default = () => ({
entry: './s1/s2/index.js',
output: {
path: `${__dirname}/d1/d2/d3/d4`
},
target: 'node',
node: {__dirname: 'mock'}
})
The __dirname
option is changed to true
, false
, 'mock'
to test their behaviors.
The bundled code is placed in d1/d2/d3/d4
.
In s1/s2
, there is index.js
console.log(__dirname, require('path').resolve(__dirname))
I made a directory e1
in the root directory, cd to this directory and run the bundled code (with node ../d1/d2/d3/d4/main.js
). Then, I cd back to the root directory, and run the bundled code again (with node d1/d2/d3/d4/main.js
)
Experiment result
__dirname | output (run from e1) | output (run from root) |
---|---|---|
mock | / / | / / |
true | s1/s2 /home/transang/dirname/e1/s1/s2 | s1/s2 /home/transang/dirname/s1/s2 |
false | /home/transang/dirname/d1/d2/d3/d4 /home/transang/dirname/d1/d2/d3/d4 | /home/transang/dirname/d1/d2/d3/d4 /home/transang/dirname/d1/d2/d3/d4 |
The results of __dirname
are the same regardless of the value of cwd
. However, when resolved to an absolute path, __dirname = true
has its disadvantage that the result varies on cwd
.
My practical solution is to set __dirname
as false
(webpack default value), determine your target bundle location statically (assume that it is two-level from the root dir), and export as a variable to be used in the whole project.
export rootDir = path.resolve(__dirname, '../..') // bundled code is in two level-depth from the root dir