Today I was listening to the NodeUp episode 70, which is all about the npm command line client. And there is tons of useful information in this episode. It is all about where npm is at the moment and what the plans are for the future. Especially the recent changes inside of the command line client are a heavy discussed topic and I highly recommend to listen to this episode, when you are dealing with npm on a daily basis.
An npm install within the context of an npm project will download packages into the project's nodemodules folder according to package.json specifications, upgrading the package version (and in turn regenerating package-lock.json) wherever it can based on ^ and version matching. Running scripts via npm The configuration file for any project based on node and npm is the package.json. This file includes meta information like name, version and author of the depending project, but also defines all dependencies, which need to be installed via calling npm install. NPMVERSION: defaults to the version preinstalled with your version of Node.js. Accepts any released version number. NPMFLAGS: flags to pass to the npm install command. NPMTOKEN: use for authentication when installing private npm modules.
- This fast, production ready, zero dependency loader is all you need to support ECMAScript modules in Node 6+. See the release post and video for details! New projects. Run npm init esm or yarn create esm. ? Use the -y flag to answer “yes” to all prompts. Existing projects. Run npm i esm or yarn add esm. Getting started.
- Sep 03, 2020 This will instruct npm to add an entry to the dependencies section of your package.json file, install the package (in a nodemodulesdirectory), and create and/or update a package-lock.json file with info about the version it installed.
Semantic Versioning Npm
One thing that is mentioned and really gets me excited is the change regarding the functionality to run scripts via npm which was introduced in the latest major version of npm – [email protected].
So let us reassess how to run scripts via npm, have a look at what has changed in version 2.0.0 and check why this is such a big deal. Stock software parabola tanaka t22 rambo 5.
Running scripts via npm
The configuration file for any project based on node and npm is the
package.json
. This file includes meta information like name, version and author of the depending project, but also defines all dependencies, which need to be installed via calling npm install
. If you are not familiar with this file, there is an excellent interactive cheat sheet out there and you may want to check it out.One thing to notice is that you can also run scripts and execute commands via npm. To do so you can define an optional object as the
scripts
property inside of the package.json
and define your wished commands. @substack wrote a great article about how to use this functionality extensively.There is not much magic about this.
And then you can use
npm run
to kick it off – pretty straight forward.This functionality had one downside so far. It was not able to pass arguments to the
npm run
command. And that is why you had to hardcode the arguments, which made the whole thing less flexible and harder to use. The only solution for having similar commands with different arguments was to define specific named scripts inside of the package.json
including different arguments.Passing arguments to npm run
Since version 2.0.0 it is now possible to pass arguments to the scripts defined in the
package.json
. And this is a big improvement on flexibility and makes the whole thing much more powerful. The package.json
above including two scripts running the echo
command can be combined into one and can accept the wished arguments.The syntax to pass arguments to the defined scripts is as follows. Nfs the run free for mac. You have to use
npm run
and then devided by two dashes(--
) you can pass any arguments you like to the command.Setting up Grunt and gulp without the global dependency
Using the
echo
command might not seem really useful, but we will come to a much more useful example now. I am doing mostly frontend development and that is why in almost every project that I work on either Grunt or gulp is included. Grunt and gulp are task runners, that come with huge plugin registries to help automate any task you can think of.When you check the getting started guide of both projects you will find the instruction to install them globally.
This is absolutely fine when you are working alone and these tools are only supposed to be executed on your machine. But when you work together with other colleagues on a project or your process includes a continuous integration system, then every global dependency can be quite troublesome. It simply moves the entry barrier a bit higher and increases the complexity to get everything up and running.
So let us have a look how to avoid that. First step is to install the needed modules in our project and not globally anymore.
By calling
npm install
npm will install the module and depending, if it has the bin
property defined, it will create a .bin
folder inside of the node_modules
folder. This means that this folder will include all defined command line interfaces of your installed modules. In this case the .bin
folder includes the binaries gulp
and grunt
.Npm Install Specific Version
If you want to use either Grunt or gulp via the
npm run
command now, you can set them up inside of your package.json
.![Npm Dependency Version Syntax Npm Dependency Version Syntax](https://raw.githubusercontent.com/afawcett/dependencies-cli/master/img/example2.png)
And then you can easily run your defined tasks with npm.
But wait, it comes even better!
To make it a bit nicer npm provides a nifty feature, when setting up custom scripts. It puts
./node_modules/.bin
in the PATH
environment, when it executes the script.This means, we can make the
package.json
a bit cleaner.Scissor sister ta dah rar. For me this is pure awesomeness!
It means not only dropping a global dependency but rather simplifying the whole work and setup flow.
Getting everything up and running is not
- installing node (which will install npm also)
- installing dependencies
- installing global dependencies
- and run e.g. Grunt
anymore.
It becomes
Npm Semver Syntax
- installing node
- installing dependencies
- and run everything via npm scripts
only.
If you want to play around with this I set up an example repository, which includes Grunt and gulp ready to use without any global installation.
Sum up
For me it is clear, that I will drop any project required global dependency that can be installed via npm in the future, because having less global dependencies just means less troubles and quicker setup.
And that is it for now and if you have any comments or ideas on that, please let me know. I hope you enjoyed it. :)
As a developer I am lazy. I don’t build everything by myselfbecause others have done it already. So, when I come upon a problem someone has already solved and that someoneput that solution into some library, I simply pull that library into my own - I declare a dependency to that library.
This post describes an important caveat when declaring “soft” dependencies using NPM and how to lock these dependenciesto avoid problems.
package.json
In the javascript world, NPM is the de-facto standard package manager which takes care of pulling mydependencies from the web into my own application. Those dependencies are declared in a file called
package.json
and look like this (example from an angular app):Unstable Dependencies
In the
package.json
you can declare a dependency using certain matchers:![Versioning Versioning](https://www.stoutsystems.com/ssd_wordpress/wp-content/uploads/2018/06/Figure-3.png)
'4.2.4'
matches exactly version 4.2.4'~4.2.4
matches the latest 4.2.x version'^4.2.4
matches the latest 4.x.x version'latest'
matches the very latest version'>4.2.4'
/'<=4.2.4'
matches the latest version greater than / less or equal to 4.2.4)*
matches any version.
Matchers like
~
and ^
provide a mechanism to declare a dependency to a range of versions instead of a specific version. This can be very dangerous, since the maintainer of your dependency might update to a version that does no longer workwith your application. The next time you build your app, it might fail - and the reasons for that failure will bevery hard to find.Stable Dependencies with package-lock.json
Each time I create a javascript app whose dependencies are managed by NPM, the first thing I’m doing is to remove all matchers in
package.json
and define the exact versions of the dependencies I’m using.Sadly, that alone does not solve the “unstable dependencies” problem. My dependencies can have their own dependencies.And those may have used one of those matchers to match a version range instead of a specific version. Thus, even thoughI declared explicit versions for my direct dependencies, versions of my transitive dependencies might changefrom one build to another.
To lock even the versions of my transitive dependencies to a specific version, NPM has introduced package locks with version 5.
When calling
npm install
, npm automatically generates a file called package-lock.json
which contains alldependencies with the specific versions that were resolved at the time of the call. Future calls of npm run build
will then use those specific versions instead of resolving any version ranges.Simply check-in
package-lock.json
into version control and you will have stable builds.Not Working?
NPM doesn’t generate a
package-lock.json
? Or the versions in package-lock.json
are not honored when callingnpm run build
? Make sure that your NPM version is 5 or above and if it isn’t, call npm install npm@latest
(you may also provide a specific version to npm install
, if you prefer :)).Follow me on Twitter for more tips on how to become a better software developer.