Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__dirname returns '/' when js file is built with webpack #1599

Closed
AJShippify opened this issue Nov 7, 2015 · 67 comments
Closed

__dirname returns '/' when js file is built with webpack #1599

AJShippify opened this issue Nov 7, 2015 · 67 comments
Labels

Comments

@AJShippify
Copy link

@AJShippify AJShippify commented Nov 7, 2015

I have a working express file, which I 'webpack' it but when the bundled file is run the __dirname global changes to '/'. I need the absolute path for certain functions as res.sendFile. Any help?

@sokra
Copy link
Member

@sokra sokra commented Nov 7, 2015

See node option in the documentation.

@AJShippify
Copy link
Author

@AJShippify AJShippify commented Nov 7, 2015

Ok, I set the

node: {
 __dirname: true
    }

But now the __dirname is empty, ''

@AJShippify
Copy link
Author

@AJShippify AJShippify commented Nov 8, 2015

Could you provide a sample code for retrieving the proper directory name?. I'm currently using a module called app-root-path but I'd like to know if there is a webpack-native way of doing it

@bebraw bebraw added the question label Nov 14, 2015
@IngwiePhoenix
Copy link
Contributor

@IngwiePhoenix IngwiePhoenix commented Nov 17, 2015

Typically, __dirname is set to options.output.publicPath. Switching to node, shouldl resolve this.
However, you also need to set target: "node".

@goodseller
Copy link

@goodseller goodseller commented Feb 4, 2016

I got the same result after trying the above config.
Here is my config:

webpack.config.js

var webpack = require('webpack');
var path = require('path');
var fs = require('fs');

var nodeModules = {};
fs.readdirSync('node_modules')
  .filter(function(x) {
    return ['.bin'].indexOf(x) === -1;
  })
  .forEach(function(mod) {
    nodeModules[mod] = 'commonjs ' + mod;
  });

var exts = ['express'];
module.exports = {
  entry: ['./server/index.js'],
  context: __dirname,
  node: {
    __filename: true,
    __dirname: true
  },
  target: 'node',
  output: {
    path: path.join(__dirname, 'build'),
    filename: '[name].bundle.js',
    chunkFilename: "[id].bundle.js"
  },
  externals: nodeModules,
  plugins: [
    new webpack.IgnorePlugin(/\.(css|less)$/),
    new webpack.BannerPlugin('require("source-map-support").install();',
                             { raw: true, entryOnly: false }),
  ],
  devtool: 'sourcemap',
}

src: ./server/index.js

...
app.use('/static', express.static(path.join(__dirname, '..', 'public')));
...

It works for directly run the source. Am I missing something?

@fritx
Copy link

@fritx fritx commented Feb 20, 2016

Same 👍
How to disable __dirname injection, leaving it as original?

---UPDATE---

For now, I use this hack:

plugins: [
  new webpack.DefinePlugin({
    $dirname: '__dirname',
  }),
]
@goodseller
Copy link

@goodseller goodseller commented Feb 20, 2016

@fritx I cannot find any related to your usage in the document. May I know how does it works?

@fritx
Copy link

@fritx fritx commented Feb 21, 2016

@goodseller Just replace __dirname with $dirname, and it works.
The $dirname would be equivalent to __dirname, regardless of the webpack injection.

@fritx
Copy link

@fritx fritx commented Feb 21, 2016

Sorry, I found the hack unnecessary.

// the webpack config just works
target: 'node',
node: {
  __dirname: false,
  __filename: false,
}
@kellyrmilligan
Copy link

@kellyrmilligan kellyrmilligan commented Mar 3, 2016

wow, that works for me too, the setting seems counterintuitive. wish we had explanations for what true, false mean in each case.

@kellyrmilligan
Copy link

@kellyrmilligan kellyrmilligan commented Mar 3, 2016

if I have a node module requiring in a module for me, through a config file, how can I have webpack include the files that are being required in for me so that they are in the build directory? basically I have a hapijs app, and am trying out webpack for the node build. Glue module reads in a config, and the __dirname is now the build directory, and the modules are still in src since they are not being required in explicitly. thoughts?

@fritx
Copy link

@fritx fritx commented Mar 8, 2016

@kellyrmilligan 😵 I think you need to make those modules (in trouble) commonjs?

plugins: [
  new webpack.ExternalsPlugin('commonjs', ['a', 'b'])
]

or just make them all commonjs:

// https://github.com/fritx/os-web/blob/dev/task%2Fwebpack.server.js
externals: [
  (ctx, req,  cb) => {
    // if (/^\.?\//.test(req)) return cb()
    if (/^\.\.?\//.test(req)) return cb() // fixed √
    cb(null, `commonjs ${req}`)
  },
],

I have a project (experimental) 😆 which webpacks both client & server side.
Check this out: https://github.com/fritx/os-web

@joegesualdo
Copy link

@joegesualdo joegesualdo commented Sep 13, 2016

if I have a node module requiring in a module for me, through a config file, how can I have webpack include the files that are being required in for me so that they are in the build directory? basically I have a hapijs app, and am trying out webpack for the node build. Glue module reads in a config, and the __dirname is now the build directory, and the modules are still in src since they are not being required in explicitly. thoughts?

@kellyrmilligan Have you found a solution?

@kellyrmilligan
Copy link

@kellyrmilligan kellyrmilligan commented Sep 13, 2016

I ended up abandoning the approach. Kept on running into brick walls

@michaeljota
Copy link

@michaeljota michaeljota commented Sep 14, 2016

I'd like to add that using node option

node: {
  __dirname: false
}

will also work if you are targeting electron.

@mmmeff
Copy link

@mmmeff mmmeff commented Oct 3, 2016

Whatever this flag is doing, setting __dirname: truefixed it for me.

@tswaters
Copy link

@tswaters tswaters commented Nov 11, 2016

Playing with this a bit, assuming I have the following:

./src
  public
    app.js
  server
    app.js

and inside server/app.js I include the following:

app.use(express.static(path.join(__dirname, '../public')))

The following happens based upon what options.node.__dirname is set to:

  • unset - leading slash, /; express will attempt to serve files from the root, /public (d'oh!)
  • true - sets it to the original path of the src filename, in this case src/server
  • false - no injection is performed, global.__dirname is used and it will be options.output.path, effectively.

The unset case seems the most counter-intuitive to me and I have a hard time understanding what the use case of injecting / as __dirname would be.... strange that this is the default.

@amasad
Copy link

@amasad amasad commented Dec 12, 2016

FWIW to get the actual behavior in node you need to write your own plugin. This is adapted from the NodeStuffPlugin (which handles the configuration discussed here). Just insert the following into your plugins array:

    {
      apply(compiler) {
        function setModuleConstant(expressionName, fn) {
          compiler.parser.plugin('expression ' + expressionName, function() {
            this.state.current.addVariable(expressionName, JSON.stringify(fn(this.state.module)));
            return true;
          });
        }

        setModuleConstant('__filename', function(module) {
          return module.resource;
        });

        setModuleConstant('__dirname', function(module) {
          return module.context;
        });
     }
@bchr02
Copy link

@bchr02 bchr02 commented Feb 17, 2017

For everyone's reference, I just posted a similar issue here: #4303

@saurabh-deep
Copy link

@saurabh-deep saurabh-deep commented Jan 23, 2019

Do we have a working solution for using __dirname with webpack + electron yet? I have spent so much time trying different things, but cannot seem to get __dirname work at all. Couldn't find anything in electron community as well.

Worse is that __dirname is used by a dependency that I am using in my app and I don't have an option to replace that dependency. Only option is to make __dirname work somehow. It has been really frustrating. Appreciate any and all the help I can get to make it work with electron.
Cheers!

@joeguerra504
Copy link

@joeguerra504 joeguerra504 commented Feb 4, 2019

Same here. I've been able to work around it by adding an environment variable tied to app.getAppPath(), but I am still frustrated that I can't understand how the __dirname stuff works with node and electron. Really makes testing tricky between dev and prod environments.

@EricTurf
Copy link

@EricTurf EricTurf commented Apr 17, 2019

@saurabh-deep

I was running into the issue where __dirname was set to / in my electron main process bundle with webpack. I added

node: {
__dirname: false
}

to my config and that did the trick

My full config 👇

const path = require('path');

module.exports = {
    entry: path.join(__dirname, '..', 'main', 'index.js'),
    output: {
        path: path.resolve(__dirname, '..', 'public'),
        filename: 'electron.js',
    },
    target: 'electron-main',
    node: {
        __dirname: false,
    },
};
@verybluebot
Copy link

@verybluebot verybluebot commented Jul 1, 2019

I have the same issue but in create-react-app and I don't want to eject the scripts, so don't have access to webpack configs... Any suggestions? getting really frustrated on this one

thanks

@Kupstas
Copy link

@Kupstas Kupstas commented Aug 19, 2019

Still doesn't understand how use it with create-react-app + electron. In dev mode I set __dirname=true; target = 'electron-renderer' and everything works fine but in a production mode it's crashing. I'm using leveldown lib for my local db and can't make it working in production mode

@bvaughn
Copy link

@bvaughn bvaughn commented Aug 19, 2019

@Kupstas you might also try process.cwd() (not sure if that would work for you, but it may be worth trying?)

@Kupstas
Copy link

@Kupstas Kupstas commented Aug 19, 2019

@bvaughn I think that problem in some other place. In dev mode in __dirname I see node_modules/leveldown but in production /Users/nikolay.kupstas/Desktop/Work/bus-inspector/dist/mac/Busman.app/Contents/Resources/app.asar/build.

@andrezsanchez
Copy link

@andrezsanchez andrezsanchez commented Oct 23, 2019

I am encountering this issue. I will get around it for now by using process.cwd() and avoiding __dirname and __filename in my app, but that's not ideal.

@royra
Copy link

@royra royra commented Nov 6, 2019

Seems like webpack incorrectly replaces __dirname and __filename for sibling modules in a monorepo (using yarn workspaces). __dirname seems to always be set to the root context (the package webpack is run at).

I got around this by applying an updated version of @amasad's custom plugin above:

    {
      apply(compiler) {
        function setModuleConstant(expressionName, fn) {
          compiler.hooks.normalModuleFactory.tap('MyPlugin', factory => {
            factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, _options) => {
              parser.hooks.expression.for(expressionName).tap('MyPlugin', expression => {
                parser.state.current.addVariable(expressionName, JSON.stringify(fn(parser.state.module)))
                return true
              })
            })
          })
        }

        setModuleConstant('__filename', function (module) {
          return module.resource;
        });

        setModuleConstant('__dirname', function (module) {
          return module.context;
        });
      }
    },
@aprilandjan
Copy link

@aprilandjan aprilandjan commented Feb 22, 2020

If you are using webpack to bundle to target electron-renderer and found some __dirname in node_modules does not output as the real path, probably you need to add this module to webpack external.

yumetodo added a commit to yumetodo/detective_connan_story_info_getter that referenced this issue May 24, 2020
Also, __dirname was disabled by webpack.
ref:
- webpack/webpack#1599
- https://qiita.com/_neko/items/0d6bb1a14ac25fbc577e
@inad9300
Copy link

@inad9300 inad9300 commented Jun 6, 2020

Related to this issue, the documentation misleadingly indicates that the default value for both __filename and __dirname is false. However, setting both to false complete changed (fixed) the behaviour for me, meaning the default must be something else.

@alexander-akait
Copy link
Member

@alexander-akait alexander-akait commented Jul 9, 2020

Fixed in webpack@5, for node, async-node and electron-main, it is false by default

@378978764
Copy link

@378978764 378978764 commented Jan 11, 2021

Same 👍
How to disable __dirname injection, leaving it as original?

---UPDATE---

For now, I use this hack:

plugins: [
  new webpack.DefinePlugin({
    $dirname: '__dirname',
  }),
]

Doesn't work.

@378978764
Copy link

@378978764 378978764 commented Jan 11, 2021

@saurabh-deep

I was running into the issue where __dirname was set to / in my electron main process bundle with webpack. I added

node: {
__dirname: false
}

to my config and that did the trick

My full config 👇

const path = require('path');

module.exports = {
    entry: path.join(__dirname, '..', 'main', 'index.js'),
    output: {
        path: path.resolve(__dirname, '..', 'public'),
        filename: 'electron.js',
    },
    target: 'electron-main',
    node: {
        __dirname: false,
    },
};

set __dirname: false worked for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet