How to package a node app with their dependencies
Tags: archlinux, bash, linux, node
Published: 2020-10-14 09:56:17

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](https://semver.org/), (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](https://aur.archlinux.org/packages/webtorrent-cli) for [webtorrent-cli](https://github.com/webtorrent/webtorrent-cli), powered by [feross](https://github.com/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`:

```bash
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:

```bash
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.

```bash
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](https://wiki.archlinux.org/index.php/creating_packages#check()) 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.

```bash
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](https://github.com/nvm-sh/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](https://www.archlinux.org/packages/community/x86_64/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`:

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

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

```bash
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](https://dev-to-uploads.s3.amazonaws.com/i/pqy724jc51ao9ulmv6r5.png)