I have a lerna repo for a project under development. It has several packages that depend on each other. To make development easier, none of the packages are published and they depend on the latest version of each other.
Directory tree
foo/
packages/
core/
package.json
errors/
package.json
foo/packages/core/package.json
{
...
dependencies: {
"#foo/errors": "*"
}
}
I have another project, bar, that I'm using to test the lerna project. Currently I'm linking to its dependencies using a local file: dependency:
bar/package.json
{
...
dependencies: {
"#foo/core": "../foo/packages/core"
}
}
This approach has given me a world of trouble.
Using npm, I'm constantly hit with ENOENT .DELETE errors. Removing my package-lock.json and reinstalling has taken years off my life.
Using yarn, I've been unable to yarn install in bar. Yarn follows the file: dependency to #foo/core, sees that it depends on #foo/errors and doesn't know about lerna's symlink. This causes it to fail, telling me it can't find #foo/errors.
This has made writing actual code for this project secondary to this mess of dependency management.
How can I make this (I feel fairly simple?) project structure work? Open to lerna/yarn/npm/pnpm/shell scripts/MS DOS at this point.
You should be able to accomplish this with npm link. Although I have not tried this using a local dependency that is not published on npm.
Directory tree
foo/
packages/
core/
package.json
errors/
package.json
bar/
package.json
foo/packages/core/package.json
{
...
dependencies: {
"#foo/errors": "*"
}
}
bar/package.json
{
...
dependencies: {
"#foo/core": "../foo/packages/core"
}
}
Run the following commands
cd foo
npx lerna clean
npx lerna bootstrap --hoist
npm run build # command to build your projects
cd packages/core
npm link
cd ../../../bar
npm i
npm link #foo/core
Removing package-lock.json files usually does more harm then good! And about not being able to find #foo/errors, if you ran npm bootstrap, #foo/core should be symlinked to #foo/errors. One possibility could be that your lerna scripts are using npm while you where running install/link with yarn.
Can you move your lerna up to a directory which hold both 'foo' and 'bar'?
Is that possible?
root/
foo/
packages/
core/
package.json
errors/
package.json
bar/
package.json
lerna.json
And in your lerna file, you can add your repos to packages
{
"lerna": "2.9.0",
"packages": [
"foo/packages/*",
"bar/",
],
}
Under slightly different conditions where one of the npm modules you are working is not part of your lerna repo, you can use lerna to exec the npm link command.
npx lerna exec -- npm link <npm_package_name>
This will npm link the external package in all of your lerna modules.
This should not be confused with lerna link which will do something similar for all submodules in your your lerna repo and is the current solution to the question.
Use can try like that:
foo/packages/core/package.json
{
...
dependencies: {
"#foo/errors": "file:../errors"
}
}
bar/package.json
{
...
dependencies: {
"#foo/core": "file:../foo/packages/core"
}
}
Related
Given an npm workspace with the following structure
workspace
package.json
packages
package-a
package.json
package-b
package.json
When I run an install command in package-a this will generate a package-lock.json file in the root of the workspace but not in the package.json file itself.
Is there a way to also generate it in the packages?
I don't know if this solves your problem, but you can specifie the folder in which you would install with --prefix
npm install --prefix ./install/here
you can use the lerna tool to manage your workspace and install dependencies in each package. you can generate package-lock.json files in each package in your workspace.
The Original Tool for JavaScript Monorepos. Monorepo means a repository with multiple packages.
lerna.js.org
I hope this answer will show you the right direction.
In most cases, running npm install within that package directory should do the job. But as you said that this is creating a global package-lock.json. This might be because the package you are installing might be specifying the global path using the prefix field.
The "prefix" field, specifies the location where the package's dependencies should be installed.
So one thing you can do is to go to the package.json in package-a and then either remove the prefix field from the package.json file OR set its value as following :
{
"name": "my-package",
"version": "1.0.0",
"prefix": "./",
"dependencies": {
...
}
}
Now when you run npm install it should install the packages locally and make a local 'package-lock.json`.
I have my own NPM package in bitbucket as private repository which I installed in my main project as following:
"devDependencies": {
"my-package": "git+ssh://git#bitbucket.org/{name}/my-package.git"
}
This works like a charm, but there's a problem with the package itself. It contains a package.json with its own dependencies, but my main NPM is not installing this, it does not seem to keep in consideration what my package's package.json contains.
E.g: I am now missing packages that my own packages requires.
What can I do to make NPM always install my package packages defined in package.json?
Structure wise:
MyApp
- package.json (I run npm install on this one)
- some other php files..
- node_modules
- my-package
- package.json <-- This contains dependencies, which are not installed
Solved it, problem was that we defined our packages in the devDependencies, which should be in the dependencies.
I am in the process of switching my monorepo (back) from yarn (with workspaces) to lerna/npm, because yarn is too slow and unstable. However, I made an surprising discovery. With the following trivial package.json:
{
"devDependencies": { "lerna": "^2.11.0" },
"dependencies": { "typescript": "^2.9.1" }
}
and an empty lerna.json (in other words, no packages at all), then when I run
$ lerna bootstrap
it does not install anything at all in any top-level node_modules directory. And if for some reason I have a node_modules directory with no .bin subdirectory, then lerna bootstrap fails to create or populate the .bin subdirectory.
Is lerna not designed to actually specify top-level packages which are to be installed (along with their binaries in .bin)? I do notice that if I try lerna add on a lerna monorepo with no packages, it complains that "lerna WARN No packages found in scope where tslint can be added."
I could not find anything related to this in the documentation. With yarn/workspaces, I was using the ability to install global (top-level) versions of things like TypeScript for use in my build scripts while maintaining control over the version installed.
From the Lerna docs:
You can add the root as a managed location (in the packages array of lerna.json) - if that's something you need. This would cause lerna to link root's dependencies to your packages' directories, run postinstall script along with the others, etc.
I have a npm package which reference an other local package. It has a structure like so.
deploy
typescriptapp.tgz
references
mydependency
package.json
app.js
app.css
typescriptapp
package.json
webapp
My typescriptapp package.json has the following dependencies
"dependencies": {
"mydependency": "file:../references/mydependency"
},
My webapp package.json has the following dependencies
"dependencies": {
"typescriptapp": "file:../deploy/typescriptapp-1.0.0.tgz"
},
When I use npm pack it work fine, but it is not included in the tarball. I also move the tarball to a deploy folder
When I try npm install, it doesn't work because the reference folder does not exist in the deploy folder.
I also tried to change the dependencies for bundledDependencies
"bundledDependencies": [
"file:../references/mydependency"
]
But it does not seem to work either.
How do I pack my typescript app to be able to install it in my webapp with a single file?
I'm building a grunt javascript project with grunt, and I have a package.json file that looks something like:
{
... name, author, etc here ...
"dependencies": {
"grunt-html":"0.2.1"
}
}
I can run npm install to install grunt-html and this works just fine. But when I add new dependencies, all developers on the team must know to run npm install again. Is there a way to automatically install any packages that have not yet been installed? Should I just run npm install always to ensure I'm up to date?
Yes npm install is the easiest way IMO. Getting everyone familiar with the other npm commands makes managing deps easier as well. Such as:
npm ls to list out the currently installed modules.
Or the --save flag ie, npm install grunt-html --save to install and insert the package and version into your package.json.
npm prune to remove modules not included in your package.json.
Other ways to manage dependencies are to commit the node_modules folder in your repository to avoid other devs from having to run npm install. Or for more complex projects consider using npm shrinkwrap to lock down dependencies to specific versions: npm shrinkwrap docs.
I have not tried grunt-install-dependencies (https://github.com/ahutchings/grunt-install-dependencies), but it seems this may fullfill your needs. Just add the command install-dependencies as first task within your custom definfed grunt tasts, e.g.
grunt.registerTask('build', [ 'install-dependencies', 'useminPrepare', ... ]);