ES6, Webpack, Karma path resolution

In Meteor 1.3, we can do this:

import actions from '/actions/index.js'; //actions is from the project root
import actions from 'actions/index.js'; //actions is from the current directory
import actions from '../actions/index.js'; //actions is a sibling directory

However, the first scenario fails with my Karma config:

import actions from '/actions/index.js'; //actions is from the project root

// Gives:
ERROR in ../enums/maps.js
Module not found: Error: Cannot resolve 'file' or 'directory' /actions/index.js in /home/mordrax/code/cotwmtor/enums
 @ ../enums/maps.js 12:13-41

But if I was to use the third example (relative path) ../actions/indexjs it’s fine.

But! I want to use absolute paths (relative from project root) because it’s easier on my brain to keep track of one file location rather than the relationship between one and another so I use webpack’s resolve.root to tell Karma to look from specific paths:

//karma.conf.js
resolve  : {
  root: [
    path.resolve('..') //note, karma.conf.js is under PROJECT_ROOT/tests so this takes me to PROJECT_ROOT
  ],
  extensions: ['', '.js', '.jsx']
}

And now, I can do this:

//actions is relative to the path.resolve from webpack, ie equivalent to /actions/index.js
import actions from 'actions/index.js'; 

However, now both Meteor and Webstorm are complaining.
Meteor says:
Error: Can't find npm module 'actions/index.js'. Did you forget to call 'Npm.depends' in package.js within the 'modules-runtime' package?
Which makes sense because it doesn’t know about webpack or resolve.root

Webstorm can’t find the file because actions/index.js is not relative to the file importing it so any future refactoring of files/folders won’t pick this up.

Anyway, I’m in a pickle as to how to do absolute imports but make Karma happy.

For root slash imports outside of Meteor (in webpack and karma), check out https://www.npmjs.com/package/babel-root-slash-import.

As for the middle one, no, for a non-relative path beginnig without a slash, i.e. actions/index.js this is going to try load index.js from an npm package called actions, if it’s installed.

To find an actions/index.js that’s relative to the current directory, you have to write it ./actions/index.js.

1 Like

Ohhh, that root slash import looks like what I was after. My ordinary brain assumes something like this to be built into import… no?

In any case the following works a treat! Now I can have all my absolute paths back… bummer I made them all relative before asking the question though.

plugins: [
  ['babel-root-slash-import', {
    "rootPathSuffix": ".."}] //because my karma.conf.js is under tests folder (ignored by meteor)
]

Thanks @gadicc!

Sure. I forgot to mention something important though. babel-root-slash-import breaks Meteor :slight_smile: Currently this only affects you if you’re using gadicc:ecmascript-hot, except, .babelrc support will be in Meteor core soon too. So take care to only use this outside of Meteor… My code only uses a project root .babelrc and in the server/client files. So if you have the above in tests and that works you’re all good!

Yes, lucky that’s how my tests is setup. When I decided to go the karma/jasmine route, I had blissfully forgotten Meteor would try to compile my karma.conf.js and tests.webpack.js (I picked these up from some tuts).

So moving them to tests seems to have worked out. They are separated, imports my mostly pure components/reducers for testing and does not get in the way of Meteor! It’s a bit fiddly but the result is sweet!

Also, inside of meteor, import '/actions/index.js' works as expected, importing from the root folder so you don’t need the plugin.

1 Like