lerna: Lerna bootstrap does not link local dependencies

I have configured two modules in a mono repo to use lerna with a local dependency. I expected that

$ lerna bootstrap
$ lerna run test

would be sufficient to download all external dependencies, link a local dependency and execute and pass all tests in all modules.

Expected Behavior

As per the lerna bootstrap documentation:

  1. Symlink together all Lerna packages that are dependencies of each other.

Thus, I expected that lerna bootstrap would create a symlink in module-b/node_modules below that points to module-a (which then would allow the tests to be executed and pass).

Current Behavior

No linking occurs, which cause the tests to fail:

lerna ERR! yarn run test exited 1 in ‘module-b’ lerna ERR! yarn run test stdout: yarn run v1.19.1 $ jest info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

lerna ERR! yarn run test stderr: FAIL ./import.test.js ● Test suite failed to run

Cannot find module 'module-a' from 'import.test.js'

> 1 | const moduleA = require('module-a');
    | ^
  2 | 
  3 | test('should import module-a', () => {
  4 |   moduleA();

  at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:259:17)
  at Object.<anonymous> (import.test.js:1:1)

Steps to Reproduce

  1. Create the folder structure below
  2. Copy the files inlined to their corresponding directory
  3. Execute $ lerna bootstrap followed by $ lerna run test
project-root
   + packages
   |       + module-a
   |       |      + package.json
   |       |      + index.js
   |       |
   |       + module-b
   |       |      + package.json
   |       |      + import.test.js
   |
   +  lerna.json     
packages/module-a/package.json

{
  "name": "module-a",
  "version": "1.0.0",
  "private": true,
  "main": "index.js",
  "scripts": {
    "test": "echo \"Test passed in module-a\""
  }
}

packages/module-a/index.js

module.exports = () => console.log('Log in module-a');

packages/module-b/package.json

{
  "name": "module-b",
  "version": "1.0.0",
  "private": true,
  "main": "index.js",
  "scripts": {
    "test": "jest"
  },
  "dependencies": {
    "module-a": "file:../module-a"
  },
  "devDependencies": {
    "jest": "^24.9.0"
  }
}

packages/module-b/import.test.js

const moduleA = require('module-a');

test('should import module-a', () => {
  moduleA();
});

lerna.json

{
  "npmClient": "yarn",
  "packages": [
    "packages/*"
  ],
  "version": "independent"
}

Observation

Executing lerna link --force-local does not change status quo, the test still fails because module-b/node_modules/ still does not contain a reference to module-a.

Context

I would like to have a build script that executes all tests in all modules as well as having a simple instruction for new project members so that they can be productive in our multi-module project.

I cannot use yarn workspaces because module-b is an Electron app and the electron builder expects its dependencies to be installed in the packages/module-b/node_modules/ folder.

Your Environment

Executable Version
lerna --version 3.18.4
npm --version 6.11.3
yarn --version 1.19.1
node --version v12.12.0
OS Version
NAME VERSION
macOS Mojave 10.14.6

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 76
  • Comments: 33 (1 by maintainers)

Commits related to this issue

Most upvoted comments

I am also experiencing this issue. Even when using file: ../module-a to symlink packages together.

I also thought that lerna bootstrap --force-local takes care of everything (at least it promises that in the docs), however some local packages are linked, but most are not. I don’t know what the pattern is either.

Luckily, this workaround at least added the local links (however, it did not link all hoisted dependencies, only some; again, seemingly at random):

lerna bootstrap --force-local && lerna link --force-local

For me it suddenly stopped working today (yesterday it works for me and team members).

I was able to resolve it using lerna link.

Don’t know why because Lerna bootstrap used to do this and if you look at the help it should still do (reverting to a older version did nothing) 🤷

Ok in fact, if I directly use the correct version of my “shared” project instead of a local link it work, I get a symlink to my shared projet in my api node_modules, which seem to be the logical way to do this…

  • lerna.json
  • packages
    • api package.json with dependency ( “shared” : “1.0.0” )
    • shared package.json ( name : “shared”, version : “1.0.0” )

The problem is that “1.0.0” is not on a repository, so it make “npm ci” fail since my package.json is not correct

Same issue here !

Tweaking @NiGhTTraX’s skeleton example, I can confirm that changing a dependency from "^1.0.0" to "file:../foo" prevents bootstrap from creating the node_modules symlink iff it’s not in the root package.json. Specifically, utils/symlink-dependencies/symlink-dependencies.js skips symlink creation if (resolved.type === “directory”).

I can confirm two workarounds for this issue:

  1. use the versioned dependency (which needs updating every time you change a major number).
  2. add devDependencies in the root package.json: "@nighttrax/foo": "file:packages/foo" (works for anything robust enough to crawl up the directory hierarchy looking for package.jsons; worked for typescript).

Disabling that if made the symlink appear as expected; see below for PR.

P.S. Any tips for running lerna in a debugger?

Some clarity on this in the docs would be appreciated. The docs make it seem like “magic” but then it’s very difficult to know what is being done by bootstrap or link.

It would be great if it outputs what all packages were linked, or what local packages were not linked because of a version mismatch.

With loglevel debug, current output of lerna link is like:

lerna sill actions finished test-example
lerna sill actions finished @scope/deploy
lerna sill actions finished @scope/test
lerna sill actions finished @scope/template

I’m using @scope/test in test-example with file:../test in package.json. I don’t know if it is working because of the file or because of lerna link.

Started to face this issue when running lerna bootstrap on Linux machine as well after altering package.json

Running lerna link explicitly before lerna bootstrap had helped us to workaround the issue with Lerna bootstrap command not recognizing local symlinked packages

I’ve tried every fix here, nothing has worked. What is even the point of using lerna if the main attraction doesn’t work.

if you use babel or any parser, may be you need build first before test.

Facing the same issue with Lerna 4.0.0. Build runs fine on github workspaces when using windows 2016 server. However build fails when running on Ubuntu 20.0 LTS. Error thrown: Cannot find module ‘pack.a’ One observations: The package json for ‘pack.a’ has the name field set to “pack.a”, however the directory containing it is named packrepo.a Using npm, node v12 Any solutions, suggestions?

Looks like lerna do not link package if package’s “version” field is empty or not satisfy pattern “a.b.c”