Vite: npm for multiple platforms - How to resolve the problem ‘Cannot find module @rollup/rollup-linux-x64-gnu’
The vite
platform has some dependencies that are binaries that are specific to architecture and platform: they are different on Mac, Windows, Linux, and for x86 vs arm.
However, by default, npm
only installs the dependencies for the platform on which you build the package-lock.json
file when you run npm
.
This can result in the following error, or similar ones:
Error: Cannot find module @rollup/rollup-linux-x64-gnu. npm has a bug related to optional dependencies
(https://github.com/npm/cli/issues/4828). Please try `npm i` again after removing both package-lock.json
and node_modules directory.
A conversation with Gemini
I’m builiding a vite project on mac os, but then trying to deploy it on CI/CD systems and docker containers that use linux.
I’m getting this:
Error: Cannot find module @rollup/rollup-linux-x64-gnu. npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). Please try
npm i
again after removing both package-lock.json and node_modules directory.I suspect that it may be because I need to do something special when I build my package-lock.json to ensure that versions of dependencies for linux-x64-gnu are included along with version for MacOS. Am I on the right track? Can you help me figure out what needs to go in package.json or my workflow to fix this?
You’re on the right track. The error occurs because npm
on macOS only installs optional dependencies for the Mac operating system. When you then try to build the project on a Linux-based CI/CD system or Docker container, it can’t find the necessary Linux packages, causing the build to fail.
The Fix
The solution is to tell npm
to install all optional dependencies, regardless of the platform. You do this by setting the npm_config_platform
environment variable before running npm install
.
Here’s a step-by-step guide:
- Remove existing lock files and
node_modules
:rm -rf package-lock.json node_modules
- Install dependencies for all platforms: The best way to do this with
npm
is to setnpm_config_platform
to a value that doesn’t match a real platform (likeall
). This forcesnpm
to download all optional dependencies.npm_config_platform=all npm install
Workflow Integration
You should add this command to your CI/CD workflow before the build step. For a typical .yml
workflow, it might look something like this:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies for all platforms
run: npm_config_platform=all npm install
- name: Build project
run: npm run build
Some more information from Copilot
Cleaning and Installing Node Modules with frontend-maven-plugin
If you are using the frontend-maven-plugin (e.g., com.github.eirslett:frontend-maven-plugin
), you don’t have direct shell access to run commands like rm -rf node_modules package-lock.json
in your CI workflow. Instead, you can leverage npm scripts and the plugin’s configuration to ensure a clean install.
Why Is This Needed?
Sometimes, npm (especially with packages like rollup
and its native bindings) can run into issues with optional dependencies or incorrect package-lock states. To work around this, it can help to remove both node_modules
and package-lock.json
before installing dependencies.
Step-by-Step Instructions
1. Add a Clean Script in package.json
Add a script in your frontend/package.json
to remove node_modules
and package-lock.json
:
"scripts": {
"clean-lock": "rm -rf node_modules package-lock.json"
}
Note:
- On Windows runners, use rimraf for cross-platform compatibility:
"clean-lock": "rimraf node_modules package-lock.json"
and add rimraf as a dev dependency:
npm install --save-dev rimraf
2. Update pom.xml
to Call the Clean Script
Add an execution phase to your frontend-maven-plugin
block to run the clean script before install:
<execution>
<id>npm clean-lock</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run clean-lock</arguments>
</configuration>
</execution>
3. Use npm install
with the Correct Environment Variable
Update your install step to use install
(instead of ci
), and set the npm_config_platform
variable:
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
<environmentVariables>
<npm_config_platform>all</npm_config_platform>
</environmentVariables>
</configuration>
</execution>
4. Full Example Plugin Block
Here is how your full frontend-maven-plugin
configuration might look:
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.12.1</version>
<configuration>
<workingDirectory>frontend</workingDirectory>
<installDirectory>${project.build.directory}</installDirectory>
<skip>${frontend.skip}</skip>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v22.18.0</nodeVersion>
</configuration>
</execution>
<execution>
<id>npm clean-lock</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run clean-lock</arguments>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
<environmentVariables>
<npm_config_platform>all</npm_config_platform>
</environmentVariables>
</configuration>
</execution>
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
Additional Notes
- Always verify that your clean script runs successfully in your CI logs.
- Make sure your CI pipeline is not caching old
node_modules
orpackage-lock.json
between runs. - If you are on Windows, scripts using
rm -rf
will fail. Use a cross-platform solution likerimraf
.
Summary
To reliably resolve optional dependency and lockfile issues with npm in Maven-based projects, use an npm clean script plus a fresh install via the frontend-maven-plugin
. This approach ensures that your dependencies are always re-installed from scratch, minimizing platform-specific issues.