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

resolveLoader.root not being taken into account? #166

Closed
julen opened this issue Nov 25, 2015 · 23 comments
Closed

resolveLoader.root not being taken into account? #166

julen opened this issue Nov 25, 2015 · 23 comments

Comments

@julen
Copy link

julen commented Nov 25, 2015

(I'm not sure if this issue/question belongs here so apologies if that's not the case)

I'm using Babel 6 and I'm trying to use babel-loader for code which lives in a 3rd party directory, i.e. it's not a parent folder of webpack.config.js. This is accessible to webpack via resolve.root.
Besides that, I'm setting resolveLoader: { root: path.join(__dirname, 'node_modules') } as described in the webpack documentation.

This seems to work as the Babel code is run. However, it complains about the es2015 preset being missing:

Module build failed: Error: Couldn't find preset "es2015" relative to directory "myDirectory"
    at OptionManager.mergePresets (~/node_modules/babel-core/lib/transformation/file/options/option-manager.js:327:17)
    at OptionManager.mergeOptions (~/node_modules/babel-core/lib/transformation/file/options/option-manager.js:287:12)
    at OptionManager.init (~/node_modules/babel-core/lib/transformation/file/options/option-manager.js:416:10)
    at File.initOptions (~/node_modules/babel-core/lib/transformation/file/index.js:190:75)
    at new File (~/node_modules/babel-core/lib/transformation/file/index.js:121:22)
    at Pipeline.transform (~/node_modules/babel-core/lib/transformation/pipeline.js:42:16)
    at transpile (~/node_modules/babel-loader/index.js:14:22)
    at ~/node_modules/babel-loader/lib/fs-cache.js:140:16
    at ReadFileContext.callback (~/node_modules/babel-loader/lib/fs-cache.js:27:23)
    at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:324:13)
 @ multi editor

(here myDirectory is the 3rd party directory).

Of course if I npm install babel-loader babel-core babel-preset-es2015 in the 3rd party directory it works, however, if I understand it correctly, that defeats the purpose of webpack's resolveLoader.root.

Am I missing something? Is there something wrong in my understanding? And more importantly, does anyone have any suggestions on how to proceed? Thanks in advance!

@fkling
Copy link

fkling commented Dec 1, 2015

Would also like to see a proper fix for this. Using require.resolve seems to be workaround:

    query: {
      presets: [
        require.resolve('babel-preset-es2015'),
        require.resolve('babel-preset-react'),
        require.resolve('babel-preset-stage-0'),
      ],
    },

@julen
Copy link
Author

julen commented Dec 2, 2015

Thank you @fkling, using require.resolve works around this — ideally this shouldn't be needed though.

@jcreamer898
Copy link

I'm having a very similar issue.

We have an application which consumes a node module that contains ES6 code.

The main app has a webpack config and I develop locally with npm link. All works fine in 5.x of Babel, but when I tried to upgrade I got all kinds of issues related to paths.

Will try to isolate the situation in an example.

@liupengke
Copy link

I have the same error. It happens when i used webpack in node using require. But it works perfect in mode of cli.
errors like this:
...build failed: Error: Couldn't find preset "es2015" relative to directory..

@Aaronius
Copy link

We're having the same issue as @jcreamer898.

@skipjack
Copy link

Having the same issue when using symlinks...

@Duan112358
Copy link

3ks, babel ^6.0.0 break the .babelrc of ^5.0.0

@mqklin
Copy link

mqklin commented Jan 3, 2016

@barroudjo
Copy link

+1

@barroudjo
Copy link

BTW here is the workaround when you use multiple loaders:

var queryObject = {presets: [require.resolve('babel-preset-es2015')]};
var query = require('querystring').stringify(queryObject);
config.loaders = [{
    test: /\.js$/,
    loaders: ['ng-annotate', 'babel?' + query]
}];

@mking
Copy link

mking commented Jan 9, 2016

👍 I am running into this as well.

@dschissler
Copy link

I finally just got up and running with Babel 6. Is anyone having trouble setting up the bluebird polyfill?

Also Babel 6 breaks my nunjucks template translation global functions that I use like {{ t('search here') }}. The translation messages are brought over asyncronously after the language has been figured out. I use my fairly popular po-loader to get the job done. Does anyone have an idea about this?

[edit] To clarify, this hack does not fix my use case.

      test: /\.nunjucks$/,
      loader: "nunjucks",
      query: {
        config: `${devRoot}/nunjucks.config.js`,
        // Don't show the 'Cannot configure nunjucks environment before precompile' warning
        quiet: true
      }

nunjucks.config.js

'use strict';
// let locale = require('locale');
let locale = require.resolve('locale');

module.exports = function(env) {
  env.addGlobal('gettext', function(message) {
    return locale.gettext(message);
  });
  env.addGlobal('t', function(message) {
    return locale.gettext(message);
  });
  env.addGlobal('ngettext', function(msg1, msg2, n) {
    return locale.ngettext(msg1, msg2, n);
  });
  env.addGlobal('n', function(msg1, msg2, n) {
    return locale.ngettext(msg1, msg2, n);
  });
};

@EvHaus
Copy link

EvHaus commented Feb 16, 2016

FYI: The resolve hack for this is also needed for plugins as well:

plugins: [
    require.resolve("babel-plugin-add-module-exports"),
    require.resolve("babel-plugin-transform-decorators-legacy")
],
presets: [
    require.resolve("babel-preset-es2015"),
    require.resolve("babel-preset-stage-0"),
    require.resolve("babel-preset-react")
]

@dschissler
Copy link

dschissler commented Feb 20, 2016

This is a fairly important bug and I'm hoping that people migrating to Webpack 2 and then wanting to use Babel 6 to be able to remove ES6 module plugin to allow Webpack 2 to handle it for tree shaking will all come together to put some qualified people on getting this to work. I'm far from release but I've outright lost the ability to use a Promise polyfill and also to access the locale gettext messages in my templates.

[edit] I've long since moved over to using Buble instead. Its not ideal since I don't have access to certain features but then on the other hand it just works. I recently tried to get Babel working again and still the similar issues. I'm convinced that Babel devs just don't use and don't care about directory structures that aren't JS centric. Another option would be for me to to try using Typescript to see if their pathing for unusual directory structures works. Using Buble I've only hit one small issue and that is needing to put a semi-colon at the end of some export statements but other than that it works as advertised. I wasted so much time on the constant churn of Babel with an incredible amount of breaking issues. Setting up Webpack and maintaining it consumed huge amounts of time and looking back Buble was about half of that. After the Webpack 2 upgrade with many config changes it has been smooth sailing and everything just works over long periods of time. I was compelled to write this by a recent comment alert that this crap is still an issue.

@lukeadams
Copy link

@globexdesigns
Instead of using require.resolve for each entry, I did this:
(not JSON; I'm using the Babel require hook)

plugins: [
    "babel-plugin-add-module-exports",
    "babel-plugin-transform-decorators-legacy"
].map(require.resolve),
presets: [
    "babel-preset-es2015",
    "babel-preset-stage-0",
    "babel-preset-react"
].map(require.resolve)

Especially useful if you have a bunch of entries.

If you want, you can add babel-{preset, plugin} with the map function, allowing you to use an unmodified plugin/preset stanza (but I prefer using the npm name).

briandipalma added a commit to briandipalma/babel-loader that referenced this issue Apr 5, 2016
briandipalma added a commit to briandipalma/babel-loader that referenced this issue Apr 6, 2016
By specifying the `babelWD` as being the process cwd we allow preset and
plugin resolution to occur relative to the directory where webpack is
running. This should resolve issues where presets and plugins could not
be resolved.

closes: babel#166, babel#179
@dvodonnell
Copy link

+1

1 similar comment
@matt-tock
Copy link

+1

@creeperyang
Copy link
Contributor

Good job!

@vladimiry
Copy link

Btw you can also pass plugins/presets arrays filled with references, not the strings. You require needed stuff first:

    const babelPresets = [
        require('babel-preset-es2015')
    ];
    const babelPlugins = [
        require('babel-plugin-transform-class-properties')
    ];

And then you connect that to the webpack's config with babel property name:

        babel: {
            presets: babelPresets,
            plugins: babelPlugins,
            cacheDirectory: true
        }

In this case obviously babel doesn't resolve plugins/presets locations by string names, but uses passed by the reference instances. But it's not a very flexible way since it's a global config, not the per loader config. Passing instantiated plugins/presets references to the loader's query property doesn't work since webpack converts references to strings.

I did a brief issue debugging and so far for me it looks like that it's not in babel-loader power to make resolveLoader.root webpack's property work for babel since babel resolves plugins/presets modules locations based on the processed file and babel has no explicit option like modules root directory.

@bardiharborow
Copy link

bardiharborow commented Sep 15, 2016

I'm running into this even without using resolveLoader.root. I need to use require.resolve('./node_modules/babel-plugin-name/src') for it to work.

@eladchen
Copy link

eladchen commented Aug 6, 2017

Almost 2018 - Has this been addressed ? Or require.resolve is still in play ?

Update: Seems that creating a symlink pointing to the node_modules is also a viable workaround.

@telekid
Copy link

telekid commented Oct 30, 2017

To support passing preset / plugin configuration along with declarations, I've created a tiny function that I call localResolve:

function localResolve(preset) {
    return Array.isArray(preset) ?
           [require.resolve(preset[0]), preset[1]] :
           require.resolve(preset);
}

which I then use like this:

{
    test: /\.js?$/,
    loader: "babel-loader",
    exclude: /node_modules/,
        query: {
            presets: [
                ["babel-preset-env", {
                    modules: false,
                    "targets": {
                        "browsers": ["last 2 versions"]
                    },
                }],
                "babel-preset-stage-3",
            ].map(localResolve),

            "plugins": [
                "babel-plugin-transform-runtime"
            ].map(localResolve),
        },
    },
}

@loganfsmyth
Copy link
Member

resolveLoader only affects modules referenced within the code being bundled, not things loaded by the loaders themselves, like babel-loader's plugins.

babel-loader resolves all of it's arguments relative to the current working directory, so you should either explicitly require plugins/presets that you want to use, or consider setting cwd to the conceptual root of your project. Which of these you do kind of depends on why your dependencies aren't already resolvable.

Note: This working-directory-relative behavior is new in Babel 7. Babel 6 resolved things relative to each individual file, which was definitely terrible, so hopefully that reduces the need to handle this stuff manually anyway.

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