Search code examples
node.jsbazel

Bazel running a nodejs target and expressing dependencies


I am building a simple nodejs application and would like to get it to run using Bazel (newbie in bazel) - Using bazel version 0.28.1

enter image description here

My package.json

{
  "name": "nodeapp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node index.js"
  },
  "dependencies": {
    "lodash": "4.17.15"
  },
  "author": "",
  "license": "ISC"
}

My index.js

const _ = require("lodash")
const ver = _.VERSION
console.log(ver);

My BUILD.bazel

load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")

nodejs_binary(
  name = "app",
  install_source_map_support = False,
  data = [
    "index.js",
    "@npm//lodash",
  ],
  entry_point = "index.js",
)

My WORKSPACE

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

RULES_NODEJS_VERSION = "0.32.2"
RULES_NODEJS_SHA256 = 
"6d4edbf28ff6720aedf5f97f9b9a7679401bf7fca9d14a0fff80f644a99992b4"
http_archive(
  name = "build_bazel_rules_nodejs",
  sha256 = RULES_NODEJS_SHA256,
  url =`"https://github.com/bazelbuild/rules_nodejs/releases/download/%s/rules_nodejs-%s.tar.gz" % (RULES_NODEJS_VERSION, RULES_NODEJS_VERSION),`
)


load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories", "npm_install")

# Setup the Node.js toolchain & install our npm dependencies into @npm
npm_install(
  name = "npm",
  package_json = "//:package.json",
  package_lock_json = "//:package-lock.json",
)

From the node_app directory, I execute bazel clean && bazel run //:app and it works fine

enter image description here

Now questions that I have are

  1. Any way to get the nodejs_binary to spread all of node_modules as opposed to going in and listing them as "@npm//lodash" in the BUILD.bazel file (like using a filegroup perhaps)
  2. If I delete the node_modules directory, the bazel execution stops working after that. It feels like it did not see the need to do "npm install" again. What am I missing?
  3. If I do not change the package.json but add more code to index.js, are subsequent builds intelligent enough to not do "npm install" since it is not required?

Solution

  • Any way to get the nodejs_binary to spread all of node_modules as opposed to going in and listing them as "@npm//lodash" in the BUILD.bazel file (like using a filegroup perhaps)

    This behaviour was deprecated in version 0.13.0 of rules_nodejs, the recommended approach is to use fine grained npm dependencies which are setup with the yarn_install or npm_install rules. This helps with reducing the time required to setup runfiles for targets. The full example and explanation is in the docs for the node_modules attribute in the nodejs_binary builtin rule here: https://bazelbuild.github.io/rules_nodejs/Built-ins.html

    If I do not change the package.json but add more code to index.js, are subsequent builds intelligent enough to not do "npm install" since it is not required?

    Yes, bazel shouldn't run another npm install or rebuild the node_module directory for a source change like that. Infact, running bazel run with only changing a line in a js file should be near instant.