
Gestion de paquets avec NPM
Cette page reproduit les diapos d'une formation faite à un client le 26 mars 2025. Le but de cette session était de fournir un socle en gestion de dépendances JavaScript/TypeScript, en utilisant NPM (Node Package Manager).
Key points
- How are dependencies version resolved by NPM
- How to manage and update dependencies with NPM
- How to keep a project dependencies up to date
- How to setup some basic tooling for a web/js project
Focus will be on end projects, not libraries.
Semantic versioning
"version" = "1.2.3"
A.B.C
- A: Major version, breaking change
- B: Minor version, new features
- C: Patch version, bug fixes
[!warning] Before
1.0.0
Version <1.0.0
: Smallest non-zero number means breaking change
note: show Semantic Versioning 2.0.0 | Semantic Versioning
package.json
{
"name": "somekindofwebproject",
"version": "0.1.2",
// ...
"scripts": {
// ...
},
"dependencies": {
"dep-a": "^1.2.3"
// ...
},
"devDependencies": { },
"peerDependencies": { }
}
User managed, define versions for direct dependencies, package info, and scripts.
package-lock.json
{
"name": "somekindofwebproject",
"version": "0.1.2",
"lockfileVersion": 3,
"requires": true,
"node_modules/de-a": {
"version": "1.3.13",
"resolved": "https://registry.npmjs.org/1.3.13/-/vue-1.3.13.tgz",
"integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==",
"dependencies": {
// ...
},
"peerDependencies": {
// ....
}
}
}
NPM managed, define the actual resolved version for any dependency, direct or transitive.
Specifying dependencies
1.2.3
or=1.2.3
: Exact match^1.2.3
: Compatible semantic version^1.2.3
->1.2.3 <= version < 2.0.0
^0.3.6
->0.3.6 <= version < 0.4.0
<, <=, >, >=
: Explicit version comparison^1.2.3 <1.4.5
: And combination^1.2.3 || =2.0.0
: Or combination
Listing out matching version for a query + syntax cheatsheet: semver.npmjs.com
Note: demo semver website
Adding a dependency
Several possibilities:
- Edit
package.json
, runnpm install
- In a shell, run
npm <i|install> <mypackage>@"version range"
- Will edit
package.json
by default, suppress with--no-save
- Can specify dep type (`--save-prod, --save-dev, --save-peer, --save-optional)
- Will edit
note: demo adding a dep, impact on lockfile + node_modules.
Explain that adding to package-lock (big diff) not a risk as node only keep tree to actual deps in package.json with npm install (not CI!)
Considerations for Typescript
- Lots of packages used to not have Typescript definition embedded.
- Now mostly solved, but can still happen:
- Most packages with external ts definitions will be in the
@types
namespace
- Most packages with external ts definitions will be in the
Example
npm i earcut
-> No completion,Could not find a declaration file for module 'earcut'.
npm i --save-dev @types/earcut
-> OK!
note: demo with earcut
Type of dependencies
dependencies
Standard/"Runtime" dependencies
devDependencies
Build time/tooling dependencies, unavailable in a built package
optionalDependencies
Platform specific code, optional features/fallback...
peerDependencies
Enforce only one version in the dep tree, for plugins/extensions
Example:
@babylonjs/gui
7.48.3
peer depends on @babylonjs/core
^7.0.0
.
- User depends on
7.41.5
: OK,@babylonjs/gui
uses that - User depends on
6.5.4
: NOK (if it was a normal dependency, babylon7.x
would have been added to the dep tree, making thegui
lib incompatible with the user code)
Note: demo: montrer babylon + "@vitest/eslint-plugin": "1.1.25"
Ways to install a project
NPM Command | Uses existing node_modules |
Uses package.json |
Uses package-lock.json |
Existing setup | Fresh clone |
---|---|---|---|---|---|
npm install |
✅ (append) | ✅ | ✅ (can edit based on package.json ) |
Faster | Slower |
npm ci |
❌ (re-download, but can be cached) | ❌ | ✅ (strictly followed) | Slower | Faster |
note: demo: npm i vs npm ci
Setting up some tooling
Lots of option, some "standard" recommendations:
- Linting: eslint - catch errors and bad patterns
- Formatting: prettier - ensure consistant code formatting
- Build/bundling: vite - kitchen-sink build tool for minifying, bundling dependencies, adding hot-reloading...
- Typing: Typescript - Typed Javascript superset
- Testing: vitest for unit testing, Playwright for end-to-end testing
Keeping tooling up to date
Tooling and config tends to move fast with framework updates
"Solution": Use framework scaffolding to get up to date config
npm create <framework-template>
in a temp location- Diff new project folder with your project folder (for example with Meld) and fetch wanted changes
- Don't forget to update the tools corresponding to the changed configs
note: demo: create vue + meld fsi viewer
Updating a project dependencies
Why update even if I don't need new features?
- Prevent technical debt
- Roll in bugfixes
- avoid vulnerabilities: [6th most frequent vulnerability type, ~10%]
note: demo each on fsiviewer, source owasp 2021
The routine way
npm update
: package.json
is untouched, package-lock.json
is updated with the latest versions that match your package.json
requirements.
The careful way
- Run
npx npm-check-updates
- Note any new version in red -> breaking changes
- Check the changelog for those packages
- Update them 1 by 1
The nuclear way
[!danger] avoiding silent breakage Only do this if you know your direct dependency well, and your project is fully typed with Typescript
- Run
npx npm-check-updates
- Check for breaking changes that any critical feature you use hasn't been removed
- Run
npx npm-check-updates -u
this will edit yourpackage.json
- Run
npm i
then your build script (probablynpm run build
) - Have fun fixing build errors!
Reminder: always tests after updating your deps!
- Semantic versioning violation can occur
- Usage depending on bug or specific library behavior
- Use of "unstable" functions
- Unexpected non-breaking changes interfering
Thanks for listening!
Questions?
Bonus: automating dependency updates/upgrades
Dependabot, Renovate: bots for automated PR/MRs for dependencies updates/upgrades.
- GitHub: Dependabot official integration, Renovate official integration
-
GitLab: Community project based on the dependabot open-source core, Renovate official runner
-
Streamline routine deps maintenance
- No need to check manually for updates
- Allow auto setup of per-dependency MR for breaking changes