Aller au contenu
thumbnail

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:

  1. Edit package.json, run npm install
  2. 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)

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

Example

  1. npm i earcut -> No completion, Could not find a declaration file for module 'earcut'.
  2. 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, babylon 7.x would have been added to the dep tree, making the gui 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

  1. npm create <framework-template> in a temp location
  2. Diff new project folder with your project folder (for example with Meld) and fetch wanted changes
  3. 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

  1. Run npx npm-check-updates
  2. Note any new version in red -> breaking changes
  3. Check the changelog for those packages
  4. 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

  1. Run npx npm-check-updates
  2. Check for breaking changes that any critical feature you use hasn't been removed
  3. Run npx npm-check-updates -u this will edit your package.json
  4. Run npm i then your build script (probably npm run build)
  5. 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.