lerna: Hoisting seems broken with npm5

Expected Behavior

lerna bootstrap --hoist should hoist dependencies when using npm@5

Current Behavior

The correct package.json is generated in the root directory but none of the hoisted deps are installed when a package-lock.json is present…which as far as I can tell (thanks npm docs!) can’t be toggled off.

lerna.json

{
  "lerna": "2.0.0-rc.5",
  "version": "4.0.0-rc.6",
  "hoist": true,
  "packages": [
    "packages/*"
  ]
}

Your Environment

Executable Version
lerna --version 2.0.0-rc.5
npm --version 5.0.0
OS Version
macOS ?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 15
  • Comments: 38 (14 by maintainers)

Commits related to this issue

Most upvoted comments

might be worth making a note of somewhere, node8 is coming out today and ships with (or soon will ship with npm5) Don’t want ya’ll overrun by folks with the same issue 😃

I’m not sure if it’s related to hoisting or not, but I found that lerna works way better when the package locks are disabled.

To disable them in all packages managed by lerna you can run:

lerna exec "echo package-lock=false >> .npmrc"

Not everything seems to be working properly with npm@5.3.

lerna bootstrap --hoist does not report errors, but neither does it install all dependencies. If you go into a package and try to npm i to remedy the issue npm does not appear to honor symlinks to other packages in your repo, though the symlinks are there. I end up with:

npm ERR! code E404
npm ERR! 404 Not Found: @myorg/mypackage@*

Workaround to force npm 4.6 despite a global npm 5, at least when running lerna in the root of your monorepo:

  • npm install --save-dev npm@4.6.1
  • set npmClient to node_modules/.bin/npm in your lerna.json

Looks that way. The package-lock.json file is happily coexisting with lerna bootstrap --hoist using npm@5.3.

Follow up: I just tried the above for JupyterLab here, and not all of the packages are ending up in the top level node_modules after hoisting, meaning we still can’t use npm@5.

@rgbkrk, something like this should work (adapted from a JuypterLab script):

var path = require('path');
var glob = require('glob');

/**
 * Handle an individual package on the path - get its dependencies.
 */
function handlePackage(packagePath, data) {
  // Read in the package.json.
  var packagePath = path.join(packagePath, 'package.json');
  try {
    var package = require(packagePath);
  } catch (e) {
    console.log('Skipping package ' + packagePath);
    return;
  }

  var deps = package.dependencies || [];
  for (let dep in deps) {
    data.dependencies[dep] = deps[dep];
  }
}

var data = require('./package.json');

// Handle all of the packages.
var basePath = path.resolve('.');
var files = glob.sync(path.join(basePath, 'packages/*'));
for (var j = 0; j < files.length; j++) {
  handlePackage(files[j], data);
}
console.log(JSON.stringify(data.dependencies, null, 2));

I was running into some trouble with that workflow last night but think I finally got things cleaned up and functioning more cleanly!

Thanks for your patience as I stumbled through this process.

I think this works now with npm@~5.1.0?

see https://github.com/npm/npm/pull/17508

Confirmed that npm config set package-lock false is enough to get us going for now, thanks @Tallyb!

package-lock.json can be disabled using npm config set package-lock false You probably also want to add in npm config set save false