18

I wrote a module with es6 and publish to the npm, I want to use it in another project, so I type like this:

import {ActionButton} from 'rcomponents'

But it didn't work:

D:\github\blog\node_modules\rcomponents\src\actionButton.jsx:1
(function (exports, require, module, __filename, __dirname) { import React fro
                                                              ^^^^^^
SyntaxError: Unexpected reserved word
    at exports.runInThisContext (vm.js:73:16)
    at Module._compile (module.js:443:25)
    at Module._extensions..js (module.js:478:10)
    at Object.require.extensions.(anonymous function) [as .jsx] (D:\github\blog\
node_modules\babel\node_modules\babel-core\lib\api\register\node.js:214:7)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at D:\github\blog\node_modules\rcomponents\src\index.js:3:19
    at Object.<anonymous> (D:\github\blog\node_modules\rcomponents\src\index.js:
7:3)

Here is my js loader configuration in webpack:

{ test: /\.jsx?$/, loader: `babel?cacheDirectory=${babelCache}` }

When I try to import a module which is not from node_modules, babel works good. But import a module from node_modules, babel seems not work?

Leo Gao
  • 629
  • 1
  • 6
  • 17

3 Answers3

25

See the babel docs:

NOTE: By default all requires to node_modules will be ignored. You can override this by passing an ignore regex.

Generally the expectation is that modules in node_modules will already have been transpiled ahead of time, so they are not processed by Babel. If you will not be doing that, then you need to tell it what files it can process. ignore allows that.

require("babel/register")({
    // Ignore everything in node_modules except node_modules/rcomponents.
    ignore: /node_modules\/(?!rcomponents)/
});
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • 2
    In case you want to use the same approach with babel-node you can do `babel-node --ignore '/node_modules/(?!my_module1|my_module2)' script.js` – cuadraman Sep 19 '15 at 15:22
  • 11
    This is not a suitable answer for Babel 6, I've run into a similar situation and cannot seem to find any way to transpile modules from a node module. Just as an addendum to those still looking for a solution in Babel 6. – BTC Jan 19 '16 at 22:03
  • I agree, I'm unable to compile node_modules module too with babel 6 – Alphapage Jan 21 '16 at 21:12
  • 1
    Feel free to drop by Babel's support channel on Slack if you have a specific reproducible example. This should work in Babel 6 though. – loganfsmyth Jan 21 '16 at 22:21
  • https://phabricator.babeljs.io/T7008 and https://phabricator.babeljs.io/T7016 I think this is a temporary bug – Alphapage Jan 22 '16 at 08:43
  • @Alphapage My answer is about `babel/register` so it is correct. If you're using some other approach like the CLI, then yes this may not work. – loganfsmyth Jan 22 '16 at 17:30
  • @loganfsmyth could you take a look at http://stackoverflow.com/questions/35040978/babel-unexpected-token-import-when-running-mocha-tests ? – ThinkingInBits Jan 27 '16 at 16:10
  • I can confirm this works for me and I am using babel 6. – bdougie Apr 07 '16 at 13:53
  • Those babel issues have migrated to GitHub, they're now [T7008](https://github.com/babel/babel/issues/3746) and [T7016](https://github.com/babel/babel/issues/4022). – Wilfred Hughes Sep 19 '16 at 13:41
  • I've created this tool to solve this problem: https://github.com/oztune/babel-register-deep – oztune Sep 15 '17 at 18:18
  • Where is that "require" supposed to go? Can I add the setting for it in .babelrc.js? – remino Jan 05 '21 at 05:33
  • 1
    @remino It needs to run as part of the application code, and it needs to be in a file the loads _before_ any file container code that needs to be compiled, so you could have a root file that loads babel and then `require("./app.js");` after Babel to run your application code. – loganfsmyth Jan 05 '21 at 05:43
  • I see. Thanks for pointing that out. I see now I can’t simply add this to my config, unfortunately. – remino Jan 10 '21 at 02:37
4

Generally, packages uploaded to npm should be precompiled, so users receive normal JS and don't require a build step. Use npm prepublish for this.

However, if you're using webpack, you can specify an exclude function in your webpack configuration (see the webpack docs):

module: {
  loaders: [{
    test: /.jsx?$/,
    loader: 'babel-loader',
    exclude(file) {
      if (file.startsWith(__dirname + '/node_modules/this-package-is-es6')) {
        return false;
      }
      return file.startsWith(__dirname + '/node_modules');
    },

If you're using babel directly, you can write a similar ignore function in the require hook.

Wilfred Hughes
  • 29,846
  • 15
  • 139
  • 192
  • > If you're using babel directly, you can write a similar ignore function in the require hook. Where does this go though? Where do you add the `require('@babel/register')` statement? In each file that uses an ES6 module? – Jens Bodal Mar 11 '20 at 21:39
1

You can use https://www.npmjs.com/package/babel-node-modules for this case

npm install --save-dev babel-node-modules
require('babel-node-modules')([
  'helloworld' // add an array of module names here 
]);

and then it compiles listed modules as other files

Nedudi
  • 5,639
  • 2
  • 42
  • 37