Package that is linked with npm link doesn't update - node.js

I have two modules - my main project and a component library - where I want to link the lib to the main project. Both is working with webpack and react. So I did:
In comp-lib dir:
npm link
In project dir:
npm link comp-lib
The package is showing up in the node_modules folder, but when I work on the component library the changes are not reflected in main project. What am I missing out?
I couldn't really find something about this issue on Google and the npm link doc just says about the example: "Now, any changes to ~/projects/node-redis will be reflected in ~/projects/node-bloggy/node_modules/node-redis/."

Had similar problem with linked package - npm link dep was picking up old version of "dep".
Running npm link (again) in "dep" folder solved the problem. Theoretically it should be called only once, but for some reason it gets out of sync sometimes.
Thus in order to reliably update linked project, execute these steps after each change:
Rebuild linked project
run npm link
In host project run npm link dep

I don't remember exactly what problems I had and I am also not sure if all of that is necessary but for me it works great.
I added the following mini script to the package.json scripts list
"scripts": {
"clean": "if exist dist ( rd /S /Q dist)",
"updateLink": "npm run clean && tsc && npm rm my-lib -g && npm link"
}
(Replace "my-lib" with your package name)
Then simply call npm run updateLink whenever you change something in the lib.
What it does:
npm run clean deletes the dist folder. Useful if you have renamed files and the typecript compiler does not delete the old files but builds new ones in parallel
tsc to compile ts->js to the dist folder
npm rm my-lib -g && npm link to remove your lib and add it again from the global modules folder. I don't remember why I had to remove it first but it solved some problem I guess.

Make sure that the Node versions of the main project and dependency project match precisely.
If you use nvm to manage multiple projects on multiple node versions, the npm link will produce the symbolic link only in the node version that npm link was initiated from (i.e., the dependency project).

It might be that you bumped version on your component, and forgot to increase the version on your main project.
Then, any npm operation will download the version indicated in the package-lock.json: the outdated version, thus removing the link set up by npm link.

My issue was that my module/package in this case was exporting the build files. I didnt fix it because we export multiple files from multiple components but if you run into this issue, change main (and exports in my case) to whatever file exports your modules
"main": "./dist/shared-lib.umd.js",
"module": "./dist/shared-lib.es.js",
"exports": {
".": {
"import": "./dist/shared-lib.es.js",
"require": "./dist/shared-lib.umd.js"
},
"./style": "./dist/style.css"
}

Related

Problem with installing react dependencies

I am trying to install react using this command: npx create-react-app .
Then I tried to run using this command: npm run start
Then I get this error:
There might be a problem with the project dependency tree.
It is likely not a bug in Create React App, but something you need to fix locally.
The react-scripts package provided by Create React App requires a dependency:
"webpack-dev-server": "3.10.3"
Don't try to install it manually: your package manager does it automatically.
However, a different version of webpack-dev-server was detected higher up in the tree:
C:\Users\oa\Desktop\node_modules\webpack-dev-server (version: 3.11.0)
Manually installing incompatible versions is known to cause hard-to-debug issues.
If you would prefer to ignore this check, add SKIP_PREFLIGHT_CHECK=true to an .env file in your project.
That will permanently disable this message but you might encounter other issues.
As suggested here [https://stackoverflow.com/questions/42308879/npm-err-code-elifecycle][1] ,
I have tried to fix it using the following commands:
delete package-lock.json
npm cache clean --force
npm install
npm start
But did not fixed for me.
Just to let you know, my npm version is 6.13.6, and node version is v13.8.0
Try to create a .env file in the root directory of the project and add this line SKIP_PREFLIGHT_CHECK=true inside the file.
then try to run yarn start or npm start.
Did you give a project name after npx create-react-app 'appName' ?
If you have multiple node_modules folders with different versions of dependencies one may conflict with the other - do the following:
Follow steps 1-4 that are initially provided in project directory and commit updated changes locally~
i. Delete package-lock.json (not package.json!) and/or yarn.lock in your project folder.
ii. Delete node_modules in your project folder.
iii. Remove "webpack" from dependencies and/or devDependencies in the package.json file in your project folder.
iv. Run npm install or yarn, depending on the package manager you use.
Find the location of the node_modules folder that is not in your project folder ~ this line - (C:\Users\oa\Desktop\node_modules\webpack-dev-server)
Go there and delete it
once done try npm start
should work :)!

npm link, without linking devDependencies

It appears that when I run npm link, it will install the project globally, and it seems to install devDependencies with it.
Is there a way to run npm link without devDependencies, perhaps with the --only=production flag?
In npm#4.x or lower
When you run npm link in other_module then you will get both dependencies and devDependencies symlinked.
The --production flag doesn't change anything, still creates a symlink to the whole directory
In npm#5.1.0
They fixed it!
If you remove node_modules and then do npm link --only=production, it runs an install before symlinking, and therefore devDependencies folder are indeed excluded.
This is currently not possible with npm link. The problem is, if you install only prod dependencies in that dependency, you're able to link it, but you're not able to develop on that dependency anymore (since missing devDependencies). And vice-versa: If you install devDependencies, you can't link anymore.
The solution: A package called npm-local-development at https://github.com/marcj/npm-local-development
It basically does the same thing as npm link, but works around the devDependency limitation by setting up a file watcher and syncs file changes automatically in the background, excluding all devDependencies/peerDependencies.
You install npm-local-development: npm i -g npm-local-development
You create file called .links.json in your root package.
You write every package name with its local relative folder path into it like so
{
"#shared/core": "../../my-library-repo/packages/core"
}
Open a console and run npm-local-development in that root package. Let it run in the background.
Disclaimer: I'm the author of this free open-source project.
A workaround I use is npm pack then point to the packed file in the example

What are the main uses for the NPM package.json file?

I read from here that the dependencies in the package.json file allow people to install the dependencies if they install your project through npm-
Finally, the dependencies field is used to list all the dependencies
of your project that are available on npm. When someone installs your
project through npm, all the dependencies listed will be installed as
well. Additionally, if someone runs npm install in the root directory
of your project, it will install all the dependencies to
./node_modules.
Where will all the dependencies be installed to if someone doesn't run npm install in the root directory of your project?
Also, what if they choose to clone this project through Github instead? It would be ready to go anyway, right? Then at that point what is the purpose of the package.json file besides giving the user meta data about the project?
Where will all the dependencies be installed to if someone doesn't run npm install in the root directory of your project?
If by that you mean 'where will they be installed if you run the command in a different directory', NPM will search upwards through the parent directories until it finds package.json, and then install the dependencies in a node_modules folder next to that file. I.E. they'll always end up in the project root.
Also, what if they choose to clone this project through Github instead? It would be ready to go anyway, right? Then at that point what is the purpose of the package.json file besides giving the user meta data about the project?
This isn't the case! Node projects just about always have a .gitignore file which explicitly excludes node_modules from being committed to version control, and expect you to run npm install after downloading the source.
There's very few good reasons to have your dependencies in your GitHub repository - as long as a project adheres to Semantic Versioning (the vast majority of packages do), npm install will never cause incompatible versions to be downloaded, and if you absolutely need to lock down the versions of your dependencies, you can just use npm shrinkwrap.
EDIT: As Matt's comment very helpfully pointed out, there's several features of NPM that go beyond simple metadata - the one I probably get the most use out of is Scripts, which allow you to create project-specific aliases for command-line operations.
An example of where this has come in handy for me is running the Webpack development server - it's installed locally to my project in the devDependencies (which you can do using the --save-dev option when installing a package), so if I was doing it manually, I would have to type something along the lines of:
"./node_modules/.bin/webpack-dev-server" --inline --hot
Which quite frankly, would be a bit of a pain. Instead, I can just add this to my package.json (note that node_modules/.bin is automatically added to the system path when using an NPM script, so you don't need to type that every time):
"scripts": {
"dev": "webpack-dev-server --inline --hot"
}
And then all I have to run is:
npm run dev
Beyond this simple use-case, there's also several 'special' script names which are automatically called upon certain events - for example, prepublish is run before publishing a package to the registry.
Each Node.js project must contain at least one package.json file, usually located in the root directory of your project. This file identifies the project and lists the packages your project depends on, making your build reproducible.
You can create a package.json file by using a text editor, but the quickest way is to run the npm init command and pass it the -y flag
npm init -y

Why doesn't npm install correctly build dependency from a fork of a package on npm?

I have a project that uses an older version of react-bootstrap
in my package.json I had
"react-boostrap": "^0.13.3"
And there is a bug in there that is causing an issue, the fix for it is very simple so I forked the repo, rolled back to the commit for v0.13.3 doing:
git reset --hard <commit-hash>
made my 1 line fix, then force pushed back to my fork.
Then I updated my package.json in the main project to point to my fork:
"react-boostrap": "mygithubrepo/react-bootstrap"
I deleted the node_modules directory and ran sudo npm cache clear to make sure everything was nice and fresh. Then I ran npm install which did pull down my version of react-bootstrap from the repo.
However, the version it now pulls down isn't in the same format in the node_modules folder. Essentially, it doesn't seem as if it's built the project.
If I use:
"react-boostrap": "^0.13.3"
then the node_modules folder contains the built code like so:
+node_modules
--+react_bootstrap
----+utils
-----Acordion.js
etc.....
But when I point it to my forked version of the repo:
"react-boostrap": "mygithubrepo/react-bootstrap"
Then I get just the source repo structure in node modules (and it doesn't seem to be built)
+node_modules
--+react_bootstrap
----+docs
----+ie8
----+src
-------+utils
--------Acordion.jsx
........etc.....
----+tools
etc.....
Now when I reference react bootstrap using require('react-bootstrap') then it doesn't work (because the files haven't been built).
So what is different between me pointing to the file on npmjs rather than on github? There isn't any prepublish/publish/postpublish script in react-bootstrap package.json so I'm not sure if they manually built it before pushing to npmjs.
Basically, I need to get my forked version automatically built when I run npm install on my main project. Any ideas?
Edit 1
The errors I get running npm install on the main project repo after updating my fork of react-bootstrap as per Jonathan Muller's answer below:
>> Local Npm module "grunt-contrib-uglify" not found. Is it installed?
>> Local Npm module "grunt-amd-wrap" not found. Is it installed?
>> Local Npm module "grunt-react" not found. Is it installed?
>> Local Npm module "grunt-contrib-clean" not found. Is it installed?
>> Local Npm module "grunt-contrib-watch" not found. Is it installed?
>> Local Npm module "grunt-contrib-copy" not found. Is it installed?
>> Local Npm module "grunt-browserify" not found. Is it installed?
>> Local Npm module "grunt-contrib-requirejs" not found. Is it installed?
Warning: Task "clean:amd" not found. Use --force to continue.
Aborted due to warnings.
In your package.json, add the following to build it when you npm install it:
{
"scripts": {
"postinstall": "grunt build"
}
}
This way the package will be built after install
Then to get it working with require, add the following to the package.json:
{
"main": "amd/react-bootstrap.js"
}
So the correct file can be found when you "require" it. Otherwise it search for index.js

How to specify local modules as npm package dependencies

I have an application which has the usual set of dependencies on third party modules (e.g. 'express') specified in the package.json file under dependencies. E.g.
"express" : "3.1.1"
I would like to structure my own code modularly and have a set of local (meaning on the file system I am currently in) modules be installed by the package.json. I know that I can install a local module by running:
npm install path/to/mymodule
However, I don't know how to make this happen via the package.json dependencies structure. Using the --save option in this command is simply putting "mymodule": "0.0.0" into my package.json (doesn't reference the filepath location). If i then remove the installed version from node_modules, and try to re-install from the package.json, it fails (because it looks for "mymodule" in the central registry, and doesn't look locally).
I'm sure the is a way of telling the "dependencies": {} structure that I want it to be installed from a file system path, but don't know how.
Anyone else had this problem?
Thanks.
npm install now supports this
npm install --save ../path/to/mymodule
For this to work mymodule must be configured as a module with its own package.json. See Creating NodeJS modules.
As of npm 2.0, local dependencies are supported natively. See danilopopeye's answer to a similar question. I've copied his response here as this question ranks very high in web search results.
This feature was implemented in the version 2.0.0 of npm. For example:
{
"name": "baz",
"dependencies": {
"bar": "file:../foo/bar"
}
}
Any of the following paths are also valid:
../foo/bar
~/foo/bar
./foo/bar
/foo/bar
syncing updates
Since npm install <folder> adds the package in the directory as a symlink in the current project any changes to the local package are automatically synced.
See: Local dependency in package.json
It looks like the answer is npm link: https://docs.npmjs.com/cli/link
I couldn't find a neat way in the end so I went for create a directory called local_modules and then added this bashscript to the package.json in scripts->preinstall
#!/bin/sh
for i in $(find ./local_modules -type d -maxdepth 1) ; do
packageJson="${i}/package.json"
if [ -f "${packageJson}" ]; then
echo "installing ${i}..."
npm install "${i}"
fi
done
After struggling much with the npm link command (suggested solution for developing local modules without publishing them to a registry or maintaining a separate copy in the node_modules folder), I built a small npm module to help with this issue.
The fix requires two easy steps.
First:
npm install lib-manager --save-dev
Second, add this to your package.json:
{
"name": "yourModuleName",
// ...
"scripts": {
"postinstall": "./node_modules/.bin/local-link"
}
}
More details at https://www.npmjs.com/package/lib-manager. Hope it helps someone.
You can just add to your package.json file in your project
"package-name" : "path/to/package"
and then run npm i in your project
At work we have a common library that is used by a few different projects all in a single repository. Originally we used the published (private) version (npm install --save rp-utils) but that lead to a lot of needless version updates as we developed. The library lives in a sister directory to the applications and we are able to use a relative path instead of a version. Instead of "rp-utils": "^1.3.34" in package.json it now is:
{
"dependencies": { ...
"rp-utils": "../rp-utils",
...
the rp-utils directory contains a publishable npm package
use install-local
I had issues with conflicting react installations from the local dependency.
I solved the error by using install-local npm package. This package does not create symlinks, which solved my issue.
Steps:
run npm i -g install-local
run npx install-local --save <local-path> inside the target repository to install the local dependency
Further reading: https://www.npmjs.com/package/install-local
The error I received, when trying to install the local package with npm install --save <local-directory>:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
If it's acceptible to simply publish your modules preinstalled in node_modules alongside your other files, you can do it like this:
// ./node_modules/foo/package.json
{
"name":"foo",
"version":"0.0.1",
"main":"index.js"
}
// ./package.json
...
"dependencies": {
"foo":"0.0.1",
"bar":"*"
}
// ./app.js
var foo = require('foo');
You may also want to store your module on git and tell your parent package.json to install the dependency from git: https://npmjs.org/doc/json.html#Git-URLs-as-Dependencies

Resources