We want to use this plugin because it is really great, but we couldn't easily get it working our serverside-rendering app.
.babelrc
{
"presets": [
"es2015-loose", "stage-1", "react"
],
"plugins": [
[
"module-alias",
[
{ "src": "./src/js-modules/modules", "expose": "modules" }
]
]
]
}
services/v8/serverside.js
...
require('babel-register')({
only: /src\/js-modules/
});
When we now try to transform a file with import a from 'modules/abc'; we receive an error:
Error: Cannot find module '../../../../../services/v8/src/js-modules/modules/abc'
So it seems that the paths are not relative to the babelrc file, but to something else. Did we make something wrong?
Thanks @danez for reporting the issue. I believe we've found the root cause of this issue.
Unfortunately I'm really busy this week and will be out of town this weekend, but I'll be working on a new version of the plugin with hopefully a fix for you next week! I wanted to give you an update on this issue so you know I'm reading the tickets ;)
@tleunen Any status on this bugfix? Happy to help out!
Yes sorry, I tried to find a way but couldn't achieve what I wanted. Basically, inside the plugin, I'd need to know from where the configuration is loaded (ie. find the path of babelrc file), but I don't know how to do it.
Paths inside the module-alias configuration must be relative to the configuration (which is usually the case for the users, but the plugin then transform them based on the working directory (which is wrong). That's why I need to find a way to get the path from the configuration file.
I wonder, could you setup a small project to easily reproduce this error? It would help me a lot :)
Thanks.
Okay I created a test repository here: https://github.com/danez/babel-plugin-module-resolver-issue-61
I just updated the sample repo again, it now uses version 1.6. I wasn't able to reproduce this issue with 2.0. I'm now gonna try to integrate it again into our codebase that has several uses of the plugin (plain babel compile, webpack, node for server-side rendering and tests). I report back later.
Ok I was finally able to reproduce. Once again this is the repo that now yields an errror. https://github.com/danez/babel-plugin-module-resolver-issue-61
Hey @danez, thank you very much for the test repo. Indeed, I was able to easily reproduce the issue, and I believe, as you may also noticed, the current implementation of the plugin has a "small" limitation.
The plugin calculates the path based on the working directory, so if your babelrc is at the root of the project, that's ok and you specify the paths (root/alias) based on that. But this also means if you run babel node or the babel register in a node environment, you have to run it at the root of your project.
So instead of writing
cd ./node/service; BABEL_DISABLE_CACHE=1 node index.js
Use this:
BABEL_DISABLE_CACHE=1 node ./node/service/index.js
I'm hoping to change this "working directory" behavior but at the moment, I haven't found a good way to know the path/source of the babelrc file when calculating the paths.
Yes the call for node was just for illustration. In our real environment pm2 is starting up the node service and I'm not entirely sure how or if it changes the cwd.
I thought about searching for the closest babelrc, but this would probably not work if people have their config in package.json, webpack or supplying it directly to babel-register.
I have a way to find the closest configuration file (either babelrc/package.json using find-babel-config) but running it for every imports/require seems wrong. Especially if babel already has the configuration somewhere.
That's why I created this ticket on the Babel side to hopefully have a way to know the source of the configuration.
The thing I was hoping for is to know the file path of the configuration, but if it comes from babel-register, then I'd need to fallback on something, like the working directory.
Is there any workaround for this issue for now? Btw thank you for an awesome plugin 😊
I'm thinking of introducing a global environment variable allowing to setup the "working directory" for the plugin. Do you think it could resolve your issue?
For pm2, have you read this? https://github.com/Unitech/pm2/issues/96
So there is no way to find path of .babelrc once and then use it as a global variable for absolute imports?
Maybe when the file is "executed". I'd need to investigate and try a few things here :) Especially if there're multiple babelrc files in a project, I'd need to know if the configuration is retrieved when the node process is executed, or on a per-file basis. But I'm guessing it's only when babel starts.. Otherwise it would produce a bad performance.
@valerybugakov What we currently do is reading the .babelrc ourselfs, transforming the paths and then supplying the config to babel-register. It is not really nice.
var babelCfg = JSON.parse(fs.readFileSync(path.join(rootPath, '.babelrc'), 'utf8'));
babelCfg.plugins.forEach((plugin, index) => {
if (typeof plugin === 'string' || plugin[0] !== 'module-resolver') return;
Object.keys(plugin[1].alias).forEach(alias => {
plugin[1].alias[alias] = path.join(rootPath, plugin[1].alias[alias]);
});
});
babelCfg.babelrc = false;
require('babel-register')(babelCfg);
@tleunen Yes that should work I think, I'm looking into the pm2 options now maybe that helps.
@tleunen I fixed my problem by setting the correct cwd in pm2.
Just a heads up that if a user has multiple .babelrc throughout their project the file being transpiled will use the closest .babelrc file.
So you do really need to look up per file if you want to handle how people currently use babel.
You're right @luke-john, that's what was done in #71 but I wonder the performance impact that this could have.
Because most projects only have 1 babelrc configuration anyway I guess...
If any of you are trying to get this working with Ava, I came up with a solution. This works on both my local machine and Travis.
v6.5.2v0.16.0v2.2.01) Setup your package.json like so:
"scripts": {
"test": "BABEL_DISABLE_CACHE=1 PWD=$(pwd) NODE_ENV=test ava",
"test:watch": "npm test -- --watch"
},
"ava": {
"verbose": true,
"babel": "inherit",
"require": [
"babel-register",
"./test/helpers/pwd.js",
"./test/helpers/setup-browser-env.js"
]
},
2) Change the pwd before each test (I implemented in test/helpers/pwd.js):
/**
Note: Set the PWD to the root of the project (see package.json where we set the ENV variable)
We need to do this to get `babel-plugin-module-resolver` working with Ava. The issue
is that Ava changes the PWD to each test's location.
*/
process.chdir(process.env.PWD)
Or, to avoid adding a load of hacks, use https://github.com/jshanson7/babel-plugin-resolver.
I'd like to switch to this module because it has an eslint-plugin-import resolver but this AVA bug is stopping me.
babel-plugin-resolver seems to use the same root as the one containing node_modules, which could be incorrect as well...
Could you describe the structure of your app @MethodGrab ? Where is the babel conf file compared of the root app?
@MethodGrab Did my solution not work for you?
@tleunen It's in the root. The structure looks something like this:
api
bin/api.js // main entry point that loads babel-register, babel-polyfill and requires ../api/index.js
src
lib
node_modules
test
.babelrc
package.json
babel-plugin-module-resolver works fine for the main application code, it's just the AVA tests that can't resolve modules correctly.
@timkendall I'm on Windows so I can't set inline environment variables unfortunately.
Gotcha, so #71 should resolve the issue.. I'll try to find some time this weekend to get this in
Hopefully! Thanks :+1:
Is it because ava sets a custom pwd when it runs? Would you have a small test project so I can take a look how it works?
I'm still having doubts on the proper way to manage all this. I wonder if the paths should be always relative to the root project, or based on babelrc/package.json file if a babel config is found there. But with babel-register, what should be set then? :s
Heres a minimal test case that should allow you to reproduce the issue: https://github.com/MethodGrab/babel-plugin-module-resolver-ava-test-case.
The problem seems to be with trying to import from inside files in the helpers dir.
This might be a separate issue from the one originally mentioned in this thread.
Thanks @MethodGrab, this helps a lot.
So indeed, from what I see, ava is changing the working directory for each test.
I'm updating my branch with the custom pwd based on each file, I'll release a beta version so people can test it in their project first and see if there're any big slowdown because of that.
I have just released 3.0.0-beta.1. I tested it in my own project and it seems to work fine. Released as beta for now because I want to make sure it resolves the issues for everyone, so please test and let me know it all's good :)
Also, with this 3.0.0-beta.1, you must also update eslint-import-resolver-babel-module to 3.0.0-beta.1, otherwise you'll get false eslint errors.
Unfortunately 3.0.0-beta.1 doesn't seem to have resolved the issue in my test case, it still has the same missing module error.
Note: I haven't committed 3.0.0-beta.1 so if you clone the repo, you'll need to update to 3.0.0-beta.1 manually (npm install babel-plugin-module-resolver@beta).
Are you sure?
I'm seeing this:
foo-helper.js :: process.cwd() /Users/tommy.leunen/.Trash/ava-test2/test/unit
========== begin foo.spec.js ==========
foo.spec.js :: process.cwd() /Users/tommy.leunen/.Trash/ava-test2/test/unit
foo.js :: process.cwd() /Users/tommy.leunen/.Trash/ava-test2/test/unit
✔ #foo should return 'foo'
Hmm, this is odd. On Windows (the machine I've been using to test so far) I'm still seeing the errors with 3.0.0-beta.1 (even after trashing my node_modules dir and reinstalling), but on my Mac both 2.2.0 and 3.0.0-beta.1 work fine!
This was the first time I ran the test case on my Mac so maybe its being cached somewhere other than node_modules 🤔.
I was testing on the mac and I can say I had the error with 2.2.0 but no errors with 3.0 beta.
I'll try on windows later today.
You can also set Babel to not cache anything BABEL_DISABLE_CACHE=1
Ah, with BABEL_DISABLE_CACHE=1 2.2.0 does error on my Mac. And BABEL_DISABLE_CACHE=1 also fixes the Windows build!
I assumed ava --no-cache would prevent all caching, I guess not.
Great work on the fix :+1: !
Did anyone find any issue with the beta version?
It's been working fine for me :+1:
Just to let you know I've just release a version 2.3.0. with the changes I initially made for 3.0 but I moved them behind a custom cwd option value.
So you can safely downgrade your 3.0.0-beta.1 version for the 2.3.0, benefits from the recent fixes and use the cwd option in your plugin configuration if you'd like. More on that here: https://github.com/tleunen/babel-plugin-module-resolver#options
Most helpful comment
Thanks @danez for reporting the issue. I believe we've found the root cause of this issue.
Unfortunately I'm really busy this week and will be out of town this weekend, but I'll be working on a new version of the plugin with hopefully a fix for you next week! I wanted to give you an update on this issue so you know I'm reading the tickets ;)