Problem to Solve
In tsconfig.json
, we specify:
"compilerOptions": {
"module": "commonjs"
}
This option causes the TypeScript compiler tsc
to output modules in the CommonJS format which is fully supported by NodeJS.
However, this option is roundly ignored by the Bazel rule ts_library
:
load("@npm//@bazel/typescript:index.bzl", "ts_library")
ts_library(
name = "_client_nodejs",
[...]
tsconfig = "tsconfig.json",
)
According to Bazel (source: https://docs.bazel.build/versions/master/build-javascript.html#building-typescript):
Bazel controls parts of the tsconfig.json
file that define locations of input and output files, manage dependencies on typings, and produce JavaScript output that’s readable by downstream tooling. Currently, this format is unbundled UMD modules, wrapping noth named (non-anonymous) AMD modules and commonjs
modules.
UMD modules are incompatible with Webpack, the most popular front-end JS code bundler. This is particularly inconvenient for us as Grakn Workbase uses VueJS which uses Webpack.
Reproducible Steps
- Run
npm install
in the root directory of client-nodejs to install all dependencies
- Run
tsc
, which will produce a number of .js
and .d.ts
files in a folder named dist
- Run
bazel build //:_client_nodejs
, which will produce corresponding .js
and .d.ts
files in bazel-bin
- Compare the first few lines of (for example)
dependencies_internal.js
between the two:
Lines 20-30 of dist/dependencies_internal.js
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
Lines 19-33 of bazel-bin/dependencies_internal.js
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
};
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
We need the version in dist
to be deployed to npm
, but currently, we deploy the version in bazel-bin
to npm
.
Current Workaround
We can run tsc
on our local machines to generate a working grakn-client
, and then copy that into the Workbase source code.
Proposed Solution
We need to, somehow, use tsc
to compile the .js
and .d.ts
files, and bundle those into an npm
package using Bazel. The npm
package is built by the pkg_npm
rule. This currently takes in :_client_nodejs
as a dependency. Probably we just need to update that dependency to a group of files produced by tsc
.