mvnpm (Maven NPM) allows to consume the NPM Registry packages as dependencies directly from a Maven project:
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>{package-name}</artifactId>
<version>{package-version}</version>
<scope>{runtime/provided}</scope>
</dependency>
or from a Gradle project:
dependencies {
runtimeOnly/compileOnly("org.mvnpm:{package-name}:{package-version}")
}
Use org.mvnpm.at.{namespace}
as groupId for a particular namespace (i.e. @hotwired/stimulus
becomes org.mvnpm.at.hotwired:stimulus
).
A lot of packages are already synced on Central, which mean they can directly be used from you pom.xml or build.gradle. You may check if a package version is available by looking at the "Maven central" badge on the Browse page. If it's not:
You should use the Maven Central repository for production builds.
The mvnpm Maven repository is a facade on top of the NPM Registry, it is handy when starting (or updating versions) on a project with many non synchronised packages (which will become more and more unlikely in the future).
To use it in your local Maven settings add the following to your settings.xml (typically /home/your-username/.m2/settings.xml
)
<settings>
<profiles>
<profile>
<id>mvnpm-repo</id>
<repositories>
<repository>
<id>central</id>
<name>central</name>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>mvnpm.org</id>
<name>mvnpm</name>
<url>https://repo.mvnpm.org/maven2</url>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>mvnpm-repo</activeProfile>
</activeProfiles>
</settings>
The mvnpm
repository can be configured as any other repositories in your project.
Since Gradle honnors the repository order when fetching dependencies, it is recommended to declare it after maven-central.
This way it will only be used as fallback, when the dependency is absent from maven-central.
In addition it is a good practice to configure repository content filtering to help Gradle to understand which dependencies can be fetched from the mvnpm
repository and avoid uncessary lookups.
repositories {
mavenCentral()
maven {
name = "mvnpm"
url = uri("https://repo.mvnpm.org/maven2")
content {
includeGroupByRegex "org\\.mvnpm.*"
}
}
}
mvnpm continuously monitor the NPM Registry for any previously synchronized packages. When it detects a new version, a synchronization process will be initiated. So tools like dependabot will be able to propose the new version in your pull requests.
The mvnpm locker Maven Plugin will create a version locker profile for your org.mvnpm and org.webjars dependencies. Allowing you to mimick the package-lock.json and yarn.lock files in a Maven world.
It is essential as NPM dependencies are typically deployed using version ranges, without locking your builds will use different versions of dependencies between builds if any of your transitive NPM based dependencies are updated.
In addition when using the locker, the number of files Maven need to download is considerably reduced as it no longer need to check all possible version ranges (better for reproducibility, contributors and CI).
Gradle provides a native version locking system, to install it, add this:
build.gradle
dependencyLocking {
lockAllConfigurations()
}
Then run gradle dependencies --write-locks
to generate the lockfile.