> Markdown version of [npm/pnpm/bun](https://vaadin.com/docs/next/flow/configuration/development-mode/npm-pnpm-bun). Section index: [llms.txt](https://vaadin.com/docs/next/flow/llms.txt)

# Configuring npm/pnpm/bun

[npm](https://docs.npmjs.com/cli/v8/commands/npm) is the recommended and default package manager for Vaadin projects. This page explains how to configure npm and how to change to an alternative package manager (i.e., pnpm or bun).

## <a id="install-a-custom-package"></a>Install a Custom Package

To install a custom frontend package into your project with `npm`, run `npm i xxx`. For example, to add the `mobx` package as a dependency in `package.json` as well as install it into `node_modules`, run the following command in the project directory:

```terminal
npm i mobx
```

> **Note:** Vaadin expects transitive platform dependencies to be available directly under `node_modules`. Vaadin uses the `npm` [overrides feature](https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides) (since `npm` 8.3.0) to lock the transitive platform dependencies versions.

## <a id="delayed-package-installation"></a>Delayed Installation of Recently Published Packages

By default, Vaadin only installs npm package versions that were published more than one day ago. (since V25.2) Versions published more recently than that are ignored when frontend dependencies are installed. This protects against supply-chain attacks, where a compromised package version is briefly available on the registry before it’s detected and removed.

This default changes the behavior of installing frontend dependencies: if your project depends on a package version that was published less than a day ago, the installation fails or resolves to an older version until the package version is old enough.

The minimum age is configured with the `npm.minimumFrontendPackageAgeDays` property, which takes precedence over the minimum release age setting of the package manager itself — see [Where the Minimum Age Comes From](#minimum-age-precedence). For example, to require package versions to be at least three days old, set the following system property:

```terminal
-Dvaadin.npm.minimumFrontendPackageAgeDays=3
```

To let Vaadin add no restriction of its own, set the value to `0`. A minimum release age configured for the package manager itself then decides whether recently published versions are installed.

> **Note:** When pnpm or bun is used as the package manager, this feature requires pnpm 10.16.0 or later, or bun 1.3.0 or later.

### <a id="minimum-age-precedence"></a>Where the Minimum Age Comes From (since V25.3)

npm, pnpm, and bun each have a minimum release age setting of their own, which a project may already configure in an `.npmrc` or a `pnpm-workspace.yaml`. Vaadin decides which value applies in this order:

1. A value set through `npm.minimumFrontendPackageAgeDays` is used as it stands. Vaadin passes it to the package manager on the command line, which takes precedence over every configuration file the package manager reads. A value of `0` adds no restriction of Vaadin’s own, and a minimum release age the package manager is configured with then applies instead.

2. Where nothing is set through Vaadin, the configuration of the package manager decides. Vaadin asks npm or pnpm what it resolves for its `min-release-age` or `minimumReleaseAge` setting and, where a value is configured, passes no argument at all. The build logs which value it kept, and the parameter to set to override it.

3. Where neither is configured, package versions have to be at least one day old.

Vaadin can’t ask bun what it resolves, because bun has no command for printing its configuration. A `minimumReleaseAge` in a `bunfig.toml` is therefore not detected, and the one-day default is passed on the command line instead. Set `npm.minimumFrontendPackageAgeDays` to `0` to let the bun configuration decide.

### <a id="vaadin-packages-are-exempt"></a>Vaadin Packages Are Exempt (since V25.3)

The `@vaadin` packages Vaadin publishes itself are excluded from the minimum age, so that a new Vaadin version can be used the day it’s released. Excluding them doesn’t weaken the protection: the build always installs the exact `@vaadin` versions that come with the platform, never a version range, so a newly published version of one of them is never picked up on its own.

Only the `@vaadin` packages themselves are excluded. Their own transitive dependencies still have to be old enough.

Excluding packages is done through the package manager, which needs to be recent enough to support it:

- **npm** 11.17.0 or later, which Node.js 26.4.0 and later ship with. The Node.js version Vaadin installs for itself is newer than that, so only a globally installed Node.js may need an upgrade.

- **pnpm** 10.17.0 or later. Version 10.16.0 supports the minimum age itself, but silently ignores the exclusion.

- **bun** can’t exclude packages on the command line. List the `@vaadin` packages the project depends on — spelled out one by one — in the `minimumReleaseAgeExcludes` setting of a `bunfig.toml` to get the same result.

When the package manager can’t exclude them, the build logs a warning and an installation may fail during the first day after a Vaadin release. Nothing is excluded, and nothing is warned about, when no minimum age applies in the first place.

## <a id="switch-among-npm-pnpm-bun"></a>Switch Among npm, pnpm & bun

`npm` is used as the default frontend package manager. Vaadin also supports using [*pnpm*](https://pnpm.io) (also known as, *performant npm*). To switch to `pnpm`, you can set the `vaadin.pnpm.enable` system property to `true`.

When using `pnpm`, the framework installs it locally using `npm` if it isn’t installed globally. The `package-lock.json` file that’s used by `npm` is incompatible with `pnpm` and is removed automatically if `pnpm` is used. `pnpm` uses the `pnpm-lock.yaml` file instead of `package-lock.json`. Any custom dependency configurations should go to `pnpm-lock.yaml`.

Using [*bun*](https://bun.sh) is also supported by Vaadin. With bun, packages are cached locally by default and linked — instead of downloaded — for every project. This results in reduced disk space usage, and faster recurring builds compared to npm. To switch to `bun`, you can set the `vaadin.bun.enable` system property to `true`.

When using bun, a [*binary lockfile*](https://bun.sh/docs/install/lockfile) named `bun.lockb` is used when `bun install` is run. This lockfile is not included in or used from Vaadin development bundle.

> **Note:** Vaadin does not support automatic installation of bun - instead please follow the [*installation instructions*](https://bun.sh/package-manager).

### <a id="switching-in-a-spring-boot-project"></a>Switching in a Spring Boot Project

For a Spring Boot-based project, you can add `vaadin.pnpm.enable = true` or `vaadin.bun.enable = true` to the `application.properties` file.

### <a id="switching-in-a-plain-java-or-javaee-project"></a>Switching in a Plain Java or JavaEE Project

For a plain Java or a JavaEE-based project, you can set the `pnpmEnable` or `bunEnable` configuration property inside the `vaadin-maven-plugin`.

Enable pnpm (plain Java / JavaEE)

```xml
<plugin>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-maven-plugin</artifactId>
    <version>${project.version}</version>
    <executions>
        <execution>
            <goals>
                <goal>prepare-frontend</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <pnpmEnable>true</pnpmEnable>
    </configuration>
</plugin>
```

Enable bun (plain Java / JavaEE)

```xml
<plugin>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-maven-plugin</artifactId>
    <version>${project.version}</version>
    <executions>
        <execution>
            <goals>
                <goal>prepare-frontend</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <bunEnable>true</bunEnable>
    </configuration>
</plugin>
```

Alternatively, you can use the Servlet 3.0 `@WebServlet` annotation:

Enable pnpm (via annotation)

```java
@WebServlet(urlPatterns = "/*", name = "myservlet", asyncSupported = true, loadOnStartup = 1,
  initParams = { @WebInitParam(name = "pnpm.enable", value = "true") })
public class CustomServlet extends VaadinServlet {
}
```

Enable bun (via annotation)

```java
@WebServlet(urlPatterns = "/*", name = "myservlet", asyncSupported = true, loadOnStartup = 1,
  initParams = { @WebInitParam(name = "bun.enable", value = "true") })
public class CustomServlet extends VaadinServlet {
}
```

or use the traditional `web.xml` file:

Enable pnpm (via web.xml)

```xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
  id="WebApp_ID" version="3.0"
  xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

  <servlet>
    <servlet-name>myservlet</servlet-name>
    <servlet-class>
        com.vaadin.flow.server.VaadinServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>

    <init-param>
      <param-name>pnpm.enable</param-name>
      <param-value>true</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>myservlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>
```

Enable bun (via web.xml)

```xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
  id="WebApp_ID" version="3.0"
  xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

  <servlet>
    <servlet-name>myservlet</servlet-name>
    <servlet-class>
        com.vaadin.flow.server.VaadinServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>

    <init-param>
      <param-name>bun.enable</param-name>
      <param-value>true</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>myservlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>
```

For more about how to set properties, see [Configuration Properties](https://vaadin.com/docs/next/flow/configuration/properties.md).

`B8A479EF-56AF-4F64-A52B-A2C01F1E5991`
