webpack: [BUG?] npm link causes Webpack to look for babel-plugin in linked package node_modules.

I’ve linked a package that is outside of the project by first running npm link in the outside package, then npm link name-of-package inside the project.

I am now getting this error:

Module build failed: ReferenceError: Unknown plugin "transform-es2015-arrow-functions" specified in "base" at 0, attempted to resolve relative to "/path/to/location/far/away/from/project/name-of-package"

Of course there’s no babel plugin there.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 82
  • Comments: 41 (3 by maintainers)

Commits related to this issue

Most upvoted comments

try to add resolve: { symlinks: false }, to your webpack.config

I’m also having the same issue using babel-plugin-transform-async-to-generator, I just downgraded from babel-core@6.7.2 to babel-core@6.1.21 and it works…

Update: Found a workaround:

query: {
  presets: ['es2015', 'stage-0'],
  plugins: ['babel-plugin-transform-async-to-generator'].map(require.resolve)
}

More info https://github.com/babel/babel-loader/issues/166#issuecomment-196888445

Any update on this?

My workaround (for webpack 3) which is compatible with webpack-dev-server:

First set the resolve.modules property:

resolve: { modules: [path.resolve(__dirname, 'node_modules'] }

It is important that you supply the abs path to your node_modules

The, for each babel preset and plugin, explicitly use require.resolve.

query: {
    plugins: [ require.resolve('babel-plugin-transform-object-rest-spread')],
   presets: [ require.resolve('babel-preset-react') ..etc.. ]
}

Note this means you need to explicitly move any babel setup you have in a babelrc file into your webpack config (in my case it was moving the plugins defs)

This compiles and when I make a change in a yarn link’d module, dev-server is picking up the changes

{symlinks: false} fixes the error, however it disrupts webpack’s watch function (and therefore webpack-dev-server will not recompile when changing files in the “linked” dependency).

Anybody found another solution?

Any updates on this issue? 😄

I’m avoiding the issue by sticking with babel-core@6.1.21, the latest version I’ve found that works with npm link. I’ve been able to upgrade other babel loaders, plugins, and presets without issue in the meantime. I also have the latest webpack and webpack-dev-server. Just going to wait for a solution.

If you’re here you’re probably looking for this solution (at least I was):

http://webpack.github.io/docs/troubleshooting.html#npm-linked-modules-doesn-t-find-their-dependencies

Symlink false does not work with Gatsby which uses webpack 1.

+1

Just a note that the require.resolve workaround only works up until Webpack version 1.12.15. Later versions use acorn instead of esprima as the JS parser, and this seems to prevent parsing of the JSON in the query string somehow.

Ah, the require.resolve trick makes it absolute, circumventing Webpack from looking for the plugin in the wrong place during build? Good workaround!

Had a special use case which wasn’t solved by adding symlinks: false, and even when I added an exclude rule that made it work, IE10 in a VM wasn’t able to render the page.

Since this is the main issue for this kind of problems (at least the first one I landed to), I wanted to share that as suggested by @ganmor here, using https://github.com/wix/wml and avoiding symlinks entirely solved all my issues immediately.

@basham Indeed, babel-core@6.1.21 works! I’m using that for now, as being able to npm link makes dev life a lot easier.

I need symlinks for Lerna so I cannot do the symlinks:false trick. @JamesRamm solution worked for me.

I’m avoiding the issue by sticking with babel-core@6.1.21, the latest version I’ve found that works with npm link. I’ve been able to upgrade other babel loaders, plugins, and presets without issue in the meantime. I also have the latest webpack and webpack-dev-server. Just going to wait for a solution.

Thanks a million @basham! I have been trying to get npm link to work with webpack and babel for some time now, and now it finally works with babel-core@6.1.21.

This is my webpack config if it helps anyone

const fs = require('fs')
const path = require('path')
const webpack = require('webpack')

const reactMdlSelectfieldPath = fs.realpathSync(
  path.resolve(__dirname, '..', 'node_modules', 'react-mdl-selectfield', 'src')
)

module.exports = {
  name: 'client',
  target: 'web',
  devtool: 'cheap-module-inline-source-map',
  entry: [
    'react-hot-loader/patch',
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    path.resolve(__dirname, '..', 'client', 'index'),
  ],
  output: {
    path: path.resolve(__dirname, '..', 'dist'),
    filename: 'app.js',
    publicPath: '/static/',
  },
  resolve: {
    root: path.resolve(__dirname, '..', 'node_modules'),
    fallback: path.resolve(__dirname, '..', 'node_modules'),
    extensions: ['', '.js', '.scss', '.css'],
    alias: {
      config: path.resolve(__dirname, '..', 'config'),
      apollo: path.resolve(__dirname, '..', 'client', 'apollo'),
      components: path.resolve(__dirname, '..', 'client', 'components'),
      containers: path.resolve(__dirname, '..', 'client', 'containers'),
      reducers: path.resolve(__dirname, '..', 'client', 'reducers'),
      routes: path.resolve(__dirname, '..', 'client', 'routes'),
      store: path.resolve(__dirname, '..', 'client', 'store'),
      i18n: path.resolve(__dirname, '..', 'client', 'i18n'),
      'react-mdl-selectfield': reactMdlSelectfieldPath,
    }
  },
  resolveLoader: {
    root: path.resolve(__dirname, '..', 'node_modules'),
    fallback: path.resolve(__dirname, '..', 'node_modules'),
  },
  module: {
    loaders: [{
      test: /\.js$/,
      loader: 'babel',
      exclude: /(node_modules)/,
      include: [
        path.resolve(__dirname, '..', 'config'),
        path.resolve(__dirname, '..', 'client'),
        reactMdlSelectfieldPath,
      ],
    },{
      test: /\.(scss|css)$/,
      loader: 'style!css?sourceMap!sass?sourceMap!postcss',
    },{
      test: /\.(png|jpg|svg)$/,
      loader: 'url-loader?limit=8192',
    },{
      test: /masonry|imagesloaded|fizzy\-ui\-utils|desandro\-|outlayer|get\-size|doc\-ready|eventie|eventemitter/,
      loader: 'imports?define=>false&this=>window',
    }]
  },
  sassLoader: {
    includePaths: [path.resolve(__dirname, '..', 'client', 'styles')],
  },
  postcss: function() {
    return [
      require('autoprefixer'),
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"development"'
      },
      __DEV__: true,
      __PROD__: false,
    }),
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /sl/),
    new webpack.HotModuleReplacementPlugin(),
  ]
}

I investigated a bit more and I can reproduce this problem without any usage of babel. A simple npm linked module and using the brfs transform loader triggers the same issue:

    module: {
      loaders: [ { loader: "transform?brfs" } ]
    }

I don’t currently have any good workaround for this, except ensuring that you only npm link fully transformed modules. Also, browserify seems to handle all this pretty well (although that’s not a good workaround seen from the perspective of this project 😕 )

This sounds a bit like webpack isn’t correctly excluding node_modules. Perhaps there’s a symlink resolution issue causing it to run the babel loader on npm linked modules, even though the links are located in node_modules. Browserify had a very similar bug a while ago, and I experience this bug to be of similar nature.

Update: It looks like this is indeed the case, but that’s not the real cause of this issue. I can force webpack to exclude npm linked modules by adding my module name to the list of excludes:

      loaders: [ {
        exclude: [/node_modules/, /my-module/],
        loader: "transform?brfs"
      } ]

Of course, this only helps if you don’t want to run the transform. If you do, the originally reported issue is still present. See below for more info.