babel: Babel not working with NODE_PATH

This is a bug report - I am getting this error:


Module build failed: Error: Couldn't find preset "latest" relative to directory "/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman-browser-polyfills/modules"
    at /Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/options/option-manager.js:293:19
    at Array.map (native)
    at OptionManager.resolvePresets (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/options/option-manager.js:275:20)
    at OptionManager.mergePresets (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/options/option-manager.js:264:10)
    at OptionManager.mergeOptions (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/options/option-manager.js:249:14)
    at OptionManager.init (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/options/option-manager.js:368:12)
    at File.initOptions (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/index.js:212:65)
    at new File (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/index.js:135:24)
    at Pipeline.transform (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/pipeline.js:46:16)
    at transpile (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-loader/lib/index.js:46:20)
    at Object.module.exports (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-loader/lib/index.js:163:20)
 @ ./lib/index.js 136:9-22
 @ multi babel-polyfill ./lib/index.js

ERROR in .-browser-polyfills/modules/assert.js
Module build failed: Error: Couldn't find preset "latest" relative to directory "/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman-browser-polyfills/modules"
    at /Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/options/option-manager.js:293:19
    at Array.map (native)
    at OptionManager.resolvePresets (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/options/option-manager.js:275:20)
    at OptionManager.mergePresets (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/options/option-manager.js:264:10)
    at OptionManager.mergeOptions (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/options/option-manager.js:249:14)
    at OptionManager.init (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/options/option-manager.js:368:12)
    at File.initOptions (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/index.js:212:65)
    at new File (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/file/index.js:135:24)
    at Pipeline.transform (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-core/lib/transformation/pipeline.js:46:16)
    at transpile (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-loader/lib/index.js:46:20)
    at Object.module.exports (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/node_modules/babel-loader/lib/index.js:163:20)
 @ ./lib/index.js 131:13-30
 @ multi babel-polyfill ./lib/index.js

Webpack should be able to find the babel modules, because I am using NODE_PATH, which allows me to store Babel deps in a particular location, and I run webpack like so:

#!/usr/bin/env bash
NODE_PATH=${NODE_PATH}:~/.suman/global/node_modules webpack

I have this webpack config:

const path = require('path');

module.exports = {

  entry: ['babel-polyfill', './lib/index.js'],

  output: {
    path: path.resolve(__dirname + '/dist'),
    filename: 'suman.js'
  },

  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        options: {
          presets: ['latest'],
          plugins: ['transform-runtime']
        }
      },
      {
        test: /(\/lib\/init\/|cli.js$)/,
        loader: 'ignore-loader'
      }
    ]
  },

  resolve: {
    alias: {
      fs: require.resolve('suman-browser-polyfills/modules/fs'),
      assert: require.resolve('suman-browser-polyfills/modules/assert')
    },
    extensions: ['.js']
  },

  node: {
    // assert: true,
    buffer: true,
    child_process: 'empty',
    cluster: 'empty',
    console: true,
    constants: true,
    crypto: 'empty',
    dgram: 'empty',
    dns: 'mock',
    domain: true,
    events: true,
    // fs: 'empty',
    http: true,
    https: true,
    module: 'empty',
    net: 'mock',
    os: true,
    path: true,
    process: true,
    punycode: true,
    querystring: true,
    readline: 'empty',
    repl: 'empty',
    stream: true,
    string_decoder: true,
    timers: true,
    tls: 'mock',
    tty: true,
    url: true,
    util: true,
    v8: 'mock',
    vm: true,
    zlib: 'empty',
  }
};

as you can see, in resolve.alias, we are referencing another project. No Babel dependencies are installed in

But that should not matter, the Babel deps needed are located in the directory referenced in NODE_PATH.

What’s probably happening is that Webpack/Babel is doing a relative path lookup check for the needed Babel deps, but it should also check on NODE_PATH, if it needs to do a “pre-check”.

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 3
  • Comments: 17 (5 by maintainers)

Most upvoted comments

Notes for a quick solution: in the meanwhile, we can use babel.config.js as something like:

// babel.config.js
module.exports = {
  presets: [
    require('babel-preset-airbnb')
  ]
}

instead of .babelrc:

{
  "presets": [
    "airbnb"
  ]
}

because require respects NODE_ENV while the resolver of Babel didn’t.

This is definitely unrelated to Webpack. Babel performs plugin/preset lookups, not Webpack.

NODE_PATH is considered deprecated in Node, and Babel has not historically taken it into account.

Note the Node documentation:

These are mostly for historic reasons. You are highly encouraged to place your dependencies locally in node_modules folders. They will be loaded faster, and more reliably.

@loganfsmyth Where does it say “deprecated”? On the contrary, it says:

NODE_PATH is still supported, but is less necessary now that the Node.js ecosystem has settled on a convention for locating dependent modules.

@zetavg You don’t have to require in the whole module, you can just resolve it:

module.exports = {
    "plugins": [
        require.resolve("@babel/plugin-syntax-dynamic-import"),
        require.resolve("@babel/plugin-syntax-bigint"),
        [require.resolve("@babel/plugin-proposal-class-properties"), {"loose": true}],
        [require.resolve("@babel/plugin-proposal-nullish-coalescing-operator"), {"loose": true}],
        [require.resolve("@babel/plugin-proposal-optional-chaining"), {"loose": true}]
    ],
    ...

I suspect this will be more efficient if you use env to conditionally load some of the plugins.


My use case is for docker. I want to install the node_modules into my image and then mount my app directory. Since node_modules typically resides in the app dir, it gets overridden so I moved it somewhere else:

FROM node:lts-alpine

ENV NODE_PATH=/usr/lib/node_modules
COPY --chown=node:node package.json yarn.lock /tmp/build/
RUN cd /tmp/build && yarn install --frozen-lockfile --production=false --check-files --modules-folder "${NODE_PATH}" && rm -r /tmp/build

Was there a problem with the PR that fixed this issue? It’s been open for 4+ years, a fix has been supplied, and having Babel respect NODE_PATH would help people out. Was there some downside that led to this PR lingering for years?

ughh, resolving relative to cwd is always a nightmare, absolute paths are so much better. Forcing users to supply an absolute path really is not that big of a deal.

I would supply a +1000 for Babel 7 to force users to supply absolute paths for everything with reason. Break their code, I don’t care, it’s better for everyone in the long run.

But I guess Babel 7 might fix my problem, we’ll see. So this is actually a Babel issue?

Sure… it may do. Depends on “require”, I guess. But the thing is that you’d still have to edit every freaking package to instruct them to use a global requirement. Which is exactly what, for instance, I try to avoid.

@loganfsmyth ok then, since NODE_PATH doesn’t work, what I am planning to do is just symlink babel deps into each project (with some automated tool). Frankly it’s pretty crazy to have to do this - many of these projects don’t need babel deps at all directly, so it’s just a waste of time and (disk) space to have to install them in each project, when only a master project is the one that needs them.

Again, support for NODE_PATH does not require any extra work. Just use require() or require.resolve() and the deps will show up…

ok just kidding, actually, I think my prior plan worked, where I installed in my user’s directory, with:

cd $HOME && npm install my-babel-deps

NODE_PATH is the bomb diggity, and I love it, it probably won’t be going anywhere for a long time. Having such a feature is imperative for future edge cases, and not breaking existing code.

But yes I see that this may be a Webpack issue. One stupid trick I used was to just do:

cd $HOME && npm install my-babel-deps

now Webpack/Babel might be able to find them there, and I won’t have to install the Babel deps in several projects that don’t need Babel. I can explain why I would have projects that don’t need Babel installed -

Webpack still needs to source code from separate projects on my filesystem - When I use NPM link to source said projects, it will naturally link to projects outside of my project root, then Webpack will start complaining that it can’t find Babel deps.

Hence, a need / use case for NODE_PATH, amirite?