diff --git a/articles/building-apps/components/package-component.adoc b/articles/building-apps/components/package-component.adoc index cba0e24085..13c8ff50b2 100644 --- a/articles/building-apps/components/package-component.adoc +++ b/articles/building-apps/components/package-component.adoc @@ -141,6 +141,53 @@ If you want the CSS to be included in the frontend bundle instead of served as a See <> for details on shadow DOM styling. +[role="since:com.vaadin:vaadin@V25.3"] +== Pinning npm Versions + +`@NpmPackage` declares which npm package a component needs, but the version that ends up installed can still be decided elsewhere — by another add-on, or by a transitive dependency of one. To decide it yourself, ship a versions file in the JAR. Vaadin reads every `.json` file in `META-INF/VAADIN/versions/` on the classpath, from whichever JAR ships it, and installs the packages they name at the versions they give. + +---- +src/main/resources/META-INF/VAADIN/versions/my-components.json +---- + +[source,json] +---- +{ + "components": { + "color-picker": { + "npmName": "@example/color-picker", + "npmVersion": "3.2.1" + } + } +} +---- + +An object with an `npmName` is one pinned package, and its version comes from `npmVersion` — or from `jsVersion`, which the files of the platform use. The keys around it group the entries and carry no meaning, so nest them however suits the add-on. The pinned version is written into the generated `package.json`, which is what the package manager installs from. + +An entry can also name the packages that the pinned one replaces, with an `exclusions` array. Those packages are left out of the installation, which is how a newer package supersedes the one it was split from or renamed from: + +[source,json] +---- +{ + "components": { + "color-picker": { + "npmName": "@example/color-picker", + "npmVersion": "3.2.1", + "exclusions": ["@example/legacy-color-picker"] + } + } +} +---- + +Pinning decides the version of a package that nothing else in the project asks for by name. A version that a scanned `@NpmPackage` annotation declares, or that the application sets in its own `package.json`, is used instead, so an application can still override what an add-on pins. + +Every versions file on the classpath is merged into one set of packages: + +- A package named in several files is expected to have the same version in each. Where the versions differ, the newest one is installed and a warning names both files. +- A package with neither `npmVersion` nor `jsVersion` is left unpinned, and a warning names it. +- A file that cannot be read is skipped on its own. The other files still pin what they declare. + + == Testing the Add-On The starter includes Jetty and is configured with `jetty:run`, so you can start a local server by running: