Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support for multi-linked first party dependencies
Adds the ability to link first party deps to subdirectories and adds a new `links` to `yarn_install` and `npm_install` which simplifies linking first party deps into `yarn_install` and `npm_install` managed `node_modules` trees. The first release of the multi-linker, which landed in 3.2.0, supported linking only 3rd party deps to subdirectories. ------------------------------ This new feature is enabled by new `npm_link` which can add a `LinkablePackageInfo` to any target. If a target already provides a `LinkablePackageInfo`, it provides a new `LinkablePackageInfo` with a new provided values for `package_path` and `package_name` which informs the linker into which `${package_path}/node_modules/${package_name}` folder to link the package into. For example, given ``` lib_a/BUILD.bazel: js_library( name = "lib_a", srcs = [ "index.js", "package.json", ], package_name = "@somescope/lib-a" ) ``` which makes `//lib_a:lib_a` link to the root node_modules at `node_modules/@somescope/lib-a` `npm_link` can be used to create a new `lib_a` target that links elsewhere: ``` sub/BUILD.bazel: npm_link( name = "lib_a", target = "//lib_a", package_path = "sub", package_name = "@somescope/lib-a", ) ``` which makes `//sub:lib_a` linked to `sub/node_modules/@somescope/lib-a`. Note: a target may depend on both `//lib_a:lib_a` and `//sub:lib_a` in its `deps` and the linker will link the library to both `node_modules/@somescope/lib-a` and `sub/node_modules/@somescope/lib-a` respectively. Alternately, `npm_link` can add a `LinkablePackageInfo` provider to a target that doesn't yet have a `package_name` associated with it, For example, ``` lib_b/BUILD.bazel: js_library( name = "lib_b", srcs = [ "index.js", "package.json", ], ) ``` ``` sub/BUILD.bazel: npm_link( name = "lib_b", target = "//lib_b", package_path = "sub", package_name = "@somescope/lib-b", ) ``` which makes `//sub:lib_b` linked to `sub/node_modules/@somescope/lib-b` while `//lib_b:lib_b` is not linked at all. The linked target can be of any type, including a simple filegroup. For example, ``` lib_c/BUILD.bazel: filegroup( name = "lib_c", srcs = [ "index.js", "package.json", ], ) ``` ``` sub/BUILD.bazel: npm_link( name = "lib_c", target = "//lib_c", package_path = "sub", package_name = "@somescope/lib-c", ) ``` which makes `//sub:lib_c` linked to `sub/node_modules/@somescope/lib-c` while `//lib_c:lib_c` is not linked at all. ------------------------------ With the above abilities, we've also added syntactical sugar to `yarn_install` and `npm_install` which uses `npm_link` under the hood. For example, given a `sub/package.json` we can define its `yarn_install` as, ``` WORKSPACE: yarn_install( name = “@sub_npm_deps”, package_json = "//sub:package.json", package_path = "sub", links = { "@somescope/lib-a": "//lib_a:lib_a", "@somescope/lib-b": "//lib_b:lib_b", } ) ``` which generates two `npm_link` under the hood: ``` @sub_npm_deps//@somescope/lib-a:BUILD.bazel: npm_link( name = "lib-a", target = "//lib_a:lib_a", package_path = "sub", package_name = "@somescope/lib-a", ) ``` ``` @sub_npm_deps//@somescope/lib-b:BUILD.bazel: npm_link( name = "lib-b", target = "//lib_b:lib_b", package_path = "sub", package_name = "@somescope/lib-b", ) ``` which are both linked to `sub/node_modules` (`sub/node_modules/@somescope/lib-a` and `sub/node_modules/@somescope/lib-b` respectively). This allows the downstream syntactical sugar of depending on first party deps by their package names from the external workspace they are "linked" to. ``` sub/BUILD.bazel: nodejs_binary( name = "bin", entry_point = "bin.js", data = [ "bin.js" "@sub_npm_deps//@somescope/lib-a", "@sub_npm_deps//@somescope/lib-b", ] ) ``` and those deps will be available to the application in `sub/node_modules` where you would expect them to be if they had been defined in the `sub/package.json` itself using yarn workspaces outside of bazel. `sub/bin.js` can then require those libs with, ``` const liba = require('@somescope/lib-a') const libb = require('@somescope/lib-b') ``` and those will be resolved to `sub/node_modules/@somescope/lib-a/index.js` and `sub/node_modules/@somescope/lib-b/index.js` with standard node_modules resolution.
- Loading branch information