Skip to content

Latest commit

 

History

History

linker

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

node package linker

It's not obvious why a "linker" is needed in nodejs. After all, programs use dynamic lookups at runtime so we expect no need for static linking.

However, in the monorepo case, you develop a package and also reference it by name in the same repo. This means you need a workflow like npm link to symlink the package from the node_modules/name directory to packages/name or wherever the sources live. lerna does a similar thing, but at a wider scale: it links together a bunch of packages using a descriptor file to understand how to map from the source tree to the runtime locations.

Under Bazel, we have exactly this monorepo feature. But, we want users to have a better experience than lerna: they shouldn't need to run any tool other than bazel test or bazel run and they expect programs to work, even when they require() some local package from the monorepo.

To make this seamless, we run a linker as a separate program inside the Bazel action, right before node. It does essentially the same job as Lerna: make sure there is a $PWD/node_modules tree and that all the semantics from Bazel (such as module_name/module_root attributes) are mapped to the node module resolution algorithm, so that the node runtime behaves the same way as if the packages had been installed from npm.

Note that the behavior of the linker depends on whether the package to link was declared as:

  1. a runtime dependency of a binary run by Bazel, which we call "statically linked", and which is resolved from Bazel's Runfiles tree or manifest
  2. a dependency declared by a user of that binary, which we call "dynamically linked", and which is resolved from the execution root

In the future the linker should also generate package.json files so that things like main and typings fields are present and reflect the Bazel semantics, so that we can entirely eliminate custom loading and pathmapping logic from binaries we execute.