DEV Community

Cover image for How to package a node app with their dependencies
Axel Navarro for Cloud(x);

Posted on

How to package a node app with their dependencies

Building a node app is easy, but we need to check some things before packaging our apps in Arch Linux.

The dependencies

Each node app has a package.json in which it specifies its dependencies, later installed inside the node_modules folder.

Since our app is not compatible with any version of such dependencies, the package.json specifies the compatibility range by using Semantic Versioning, (a.k.a. semver).

Due to this versioning, we need to install the node_modules content inside the /usr/lib/<package-name> folder to avoid installing it globally on the system. We should build the package having that in mind. Let’s go!

For this post we're using the PKGBUILD for webtorrent-cli, powered by feross.

Installing the packages

If our node app doesn't need a build process, like converting TypeScript files to Nodejs compatible JavaScript code, we can use this simple build() function in the PKGBUILD:

build() {
  cd "$srcdir/$pkgname-$pkgver"

  npm install --production
}

We don't need to install the devDependencies declared in the package.json, so --production will reduce the package size of this app.

But, what if we have a build process? Then, our build() will be somewhat as follows:

build() {
  cd "$srcdir/$pkgname-$pkgver"
  npm install
  npm run build
  npm prune --production
}

After completing the build process, we should remove the devDependencies using the npm prune --production command.

Package the node modules

we should copy the node_modules folder inside the package as well as the app code itself.

package() {
  install -dm755 "${pkgdir}/usr/lib/${pkgname}"
  cp -a bin node_modules package.json "${pkgdir}/usr/lib/${pkgname}/"
}

💡 Tip: ${var} is another way to reference the variable $var in Bash.

Check the code before packaging

The ArchWiki recommends to use the check() function. This step happens between the build and the package, and this is the perfect place to run tests to check the compatibility with the current platform.

build() {
  cd "$srcdir/$pkgname-$pkgver"
  npm install
  npm run build
}

check() {
  cd "$srcdir/$pkgname-$pkgver"
  npm test
  npm prune --production
}

The testing libraries are commonly located in the devDepencies of our package.json, because they aren't used in production runtime. So, we should prune the node_modules in the check() step instead of build().

Building using nvm

And the last issue for today is nvm. When we must build our package in a specific node version we should use the nvm package.

We already know that Arch Linux is a rolling release so the official nodejs package is the latest version, not the latest LTS.

🧠 The node team calls this version current, and the even-numbered major version will transition to Long Term Support when a new major version appears. Nowadays, the current version is 14.x and, when the 15.0.0 is publicly released as current, the 14.x will be the latest LTS available.

We should add nvm as makedepends, and it's a good practice if we add the node version that we need as a variable in the PKGBUILD:

_nodeversion=12
makedepends=('npm' 'nvm')

Then, add the nvm to the build() function:

build() {
  source /usr/share/nvm/init-nvm.sh
  nvm use ${_nodeversion} || nvm install ${_nodeversion}
  cd "$srcdir/$pkgname-$pkgver"

  npm install --production
}

We have a few things here. First, we load the init-nvm.sh in the build() function. Now, we can use the installed 12.x version with the nvm use 12 command, if node v12 isn't installed we proceed to install it using nvm install 12.

It's done! We can ship your package. 😁

Node package delivery

Oldest comments (0)