webpack: Symlinks in project - loader not working when using include?

Can webpack read through symlinks? I have a simple symlink under /src with .jsx files. I have { test: /\.jsx?$/, loader: 'babel-loader?...', include: path.resolve(__dirname, 'src') } but it won’t load files with babel-loader, I get ES5 compilation error.

If I replace the symlink with the actual folder and files - it works. If I replace the include with exclude: /node_modules/ it also works.

Bug, or am I doing it wrong?

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 65
  • Comments: 42 (2 by maintainers)

Commits related to this issue

Most upvoted comments

Try setting resolve.symlinks: false (https://webpack.js.org/configuration/resolve/#resolve-symlinks), worked for me, YMMV.

I was able to fix this by doing the following in webpack.config.js (this is for importing our components library using the jsx files rather than the compiled umd):

var includePaths = [
  fs.realpathSync(__dirname + '/app'),
  fs.realpathSync(__dirname + '/node_modules/my-repo/lib'),
];

And then later:

module: {
    loaders: [{
      test: /\.js?$/,
      include: includePaths,
      loader: 'babel'
    }, {
      test: /\.jsx?$/,
      include: includePaths,
      loader: 'babel'
    },{
      test: /\.json?$/,
      loader: 'json'
    }, {
      test: /\.css$/,
      loader: 'style!css?modules&localIdentName=[name]---[local]---[hash:base64:5]'
    }]
  },

I think that the main issue here is that webpack resolves symlinks and it actually ‘sees’ this files by their absolute path. And this absolute path doesn’t match your include directive or test regexp.

Could you please check this?

Now with npm 5 all file dependencies are symlinks. So this just become a bigger issue. Can we add native support in webpack for these cases? Something like a parameter says if this is a symlink or not…

Trying to remove the emotion here, but this really needs to be fixed: Ticket still unresolved for 68 weeks…

+1, I have this exact problem, the loader (babel) does not seem to be getting applied to files under a symlink. Replacing the symlink with an actual directory works.

@sebelga can you post your code examples? Is the alias pointing to the symlink or no? Tried this with 3 and it didn’t work…

I got this to work by setting the includePaths but also by setting both resolve.root and resolveLoader.root to path.resolve(__dirname, 'node_modules') (or wherever you want those external sources to be able to resolve modules). @jraede I think that worked for you only because your include paths both had node_modules in an ancestor directory. You need to set both so files external to your project that you want to import can themselves (a) import other modules from your project’s node_modules, and (b) so your loaders can be resolved (otherwise you get cannot resolve module ‘babel’, etc).


  resolve: {
    alias: { src: srcPath, common: commonPath },
    extensions: ['', '.js', '.scss', '.json'],
    root: [path.resolve(__dirname, 'node_modules')]
  },

  resolveLoader: {
    root: [path.resolve(__dirname, 'node_modules')]
  },

I experience similar problem in monorepo created with lerna, where application built with webpack requires a module that is installed in node_modules as a link. That module is not transpiled.

I have created example repository that reproduces this problem: https://github.com/mass85/no_transpilation_with_lerna

For me (webpack 4.46.0) I needed to add both resolve.symlinks: false and add an include path to the rule.

{
  module: {
    rules: [
      {
        oneOf: [
          {
            //The rule I want to fix
            // This is to also include monorepo packages
            include: [/node_modules\/@organization/]
          }
        ]
      }
    ],
  },
  resolve: {
    symlinks: false
  }
}

I figured out that babel-loader can not resolve modules outside of the project. For example I am using lerna@3 and webpack@4.41.2. After debugging I ended up that @babel/parser is responsible for the “issue” (I do not think it’s an issue, more a CWD problem) because the plugins and loaders could not be resolved to node_modules. There is also an interesting article about that in the babel configuration: https://babeljs.io/docs/en/config-files#monorepos

However, after moving all my babel configs (originally from package.json#babel) to my webpack.config.js it works without any problems:

// [...]
{
    test: /\.tsx$/,
    exclude: /(disposables)/,
    use: {
        loader: "babel-loader?cacheDirectory",
        options: require("./package.json")).babel
    }
}
// [...]

References:

Having a similar issue with symlinks… I have all my modules under a /src folder in the root. Inside that /src folder I created a symlink to a directory /globals which is outside the root. Importing modules through the symlink works fine, however the loaders (in this case babel) don’t transform these modules properly which causes:

1:61 error Parsing error: Illegal export declaration ... You may need an appropriate loader to handle this file type.

Tried a few things in the config such adding the actual path of the directory I symlinked to in resolveLoader.modulesDirectories and in loader.include.

This issue seems similar but none of the solutions there solved the issue. Feel like I’m missing something obvious…

Try setting resolve.symlinks: false (https://webpack.js.org/configuration/resolve/#resolve-symlinks), worked for me, YMMV.

This work for me.

Try this solution when using lerna(monorepo with symlink) with webpack, you might find the loader trying to load what should be excluded. It’s because webpack resolve it to nearest relative path, so the path don’t have a node_modules in it, thus not excluded.

Keywords for search engine: typescript ts-loader symlink lerna webpack Keywords: export was not found in Hope people in trouble can find this solution.

Try setting resolve.symlinks: false (https://webpack.js.org/configuration/resolve/#resolve-symlinks), worked for me, YMMV.

Also worked for us! If you have a symlink to a folder outside of your project root, this seems to be the way. Because otherwise the symlinked folder is resolved in an absolute path which is outside the project root and is then being ignored

@earnubs, It did not help.

@Undistraction correct, but the idea is to have webpack only include the other module without transpiling it with babel-loader. It’s already compiled by babel on its own, and looks like any other ES5 module.

Updating followers of this ticket:

I ditched the symlink approach; instead, I created another node module which compiles on its own with babel that is locally linked. That package has this in package.json:

"name": "awesome-module",
"main": "lib/index.js",
"scripts": {
  "build:clean": "rimraf dist lib",
  "build:ensure": "mkdir -p lib",
  "build:js": "npm run build:ensure && babel -d lib/ src/ -s inline",
  "build": "npm run build:clean && npm run build:ensure && npm run build:js",
  "watch:js": "npm run build:js -- -w",
  "watch": "npm run build && npm run watch:js",
  "postinstall": "npm run build",
  // ...
}

And src/index.js etc.

Then execute npm link in that dir, which registers the module globally on my machine, and npm link awesome-module in my initial module. That way, webpack isn’t responsible for that module.

Also running npm run watch to have files updated on save.

I am on the latest webpack 2.11.1 and latest wds. These lines allow me to use my file:… linked packages in package.json for local dev symlinked and have them update when I change it. The key is the path.resolve you want to make sure you point it to the TOP and only the top node_modules.

           modules: [
                path.resolve(path.join(__dirname, 'node_modules'))
            ],
            symlinks: true

@mass85 Pity.

Worked in my case because babel-loader when symlinks aren’t resolved to an absolute path that is outside of project root, webpack is no longer passing that babel-core, babel-core was then no longer looking outside of project root for a .babelrc and not finding it and not compiling. Maybe there is an option to make that fail more loudly … but I guess it would be with babel-core?

Some info about this behavior can be found here https://github.com/webpack/webpack/issues/554

hi,

i have been working on a web app using reactjs but when i run “npm start” it always print “Failed to compile. Error in Cannot find module ‘commondir’ @ multi main”

is there anything i can do to solve this please.

i tried running npm install commondir but still did not work. and also remove node_modules and install again nothing seems to change.

thanks

The solution of @jraede worked for me when using the following configuration:

  • Windows user (symlinks and webpack seem to work without any workaround in Linux - I use Ubuntu 16.04 LTS, but it failed with my colleague using Windows 7)
  • private scoped npm package
  • less, styles, css, babel and ngannotate loaders
  • webpack 1

Just added to webpack.config.js as he suggested:

const fs = require('fs');
const includes = [
 fs.realpathSync(`${__dirname}/src`),
 fs.realpathSync(`${__dirname}/node_modules/@organization/projects`),
];
config.module = [
  {
    test: /\.js$/,
    loader: 'ng-annotate!babel',
    include: includes,
    exclude: /node_modules/,
  }, {
    test: /\.less$/,
    loader: 'style!css!less',
    include: includes,
  }
];

For anyone trying the resolveLoader approach with Webpack 2, the Webpack 2 equivalent of root seems to be modules, however this doesn’t work. The only solution that works for me with Webpack 2 was to use fs.realpathSync.

Anyway, @eagsalazar’s suggestion of using an absolute path for the value of root (or now modules might be problematic - see docs).