fwouts / bazel-javascript

JavaScript and TypeScript rules for Bazel (React friendly)
MIT License
65 stars 17 forks source link

Transpiling typescript twice #12

Closed enriched closed 6 years ago

enriched commented 6 years ago

Is there a reason to transpile the typescript twice in the ts_library rule? It would seem that if you are already running the full compilation that you don't need to run the faster transpilation. And it could be an optional parameter to this rule.

It would also free up the output folders so that the compiled sources could reside in a folder that is the name of the target. Or is that frowned on in Bazel?

fwouts commented 6 years ago

Hi Rich,

Thanks for asking. I introduced transpilation in the interest of speed when building large graphs, especially when working on a hot-reloading TypeScript app with ibazel.

Imagine for example that you have a chain of five ts_library targets, all depending on the previous one: A -> B -> C -> D -> E. If we change a source file in A, we need to wait until A is compiled before we can start compiling B, because it depends on A's type definitions. This gets quite slow in a large graph. On the other hand, they can all be transpiled at the same time because transpilation doesn't require type definitions.

When you build a JavaScript library (js_library target) and/or a web application (web_bundle target), you don't need type definitions at all. This is why when a js_library target depends on a ts_library target, it only depends on the transpiled version. This allows a web_bundle to be recompiled relatively quickly. However, this also means that you lose type safety, and still need to rely on compiling each ts_library on its own to verify this.

I must admit this is a bit clunky. Even with the transpiled version, it's not nearly as fast as a single webpack compilation! I'm now exploring whether there are smarter ways to do modular TypeScript builds, possibly without Bazel.

Open to suggestions and pull requests of course.


Regarding the _transpiled and _compiled suffixes: Bazel indeed discourages naming a generated folder the same as its target. Here's the warning it shows if you change compiled_dir from "%{name}_compiled" to just "${name}":

$ bazel build //tests/...
WARNING: /Users/work/dev/bazel-javascript/tests/ts-example/src/nested/BUILD.bazel:5:1: target 'constants' is both a rule and a file; please choose another name for the rule
WARNING: /Users/work/dev/bazel-javascript/tests/ts-example/src/nested/BUILD.bazel:18:1: target 'nodeps' is both a rule and a file; please choose another name for the rule
WARNING: /Users/work/dev/bazel-javascript/tests/ts-example/src/testing/BUILD.bazel:6:1: target 'sum' is both a rule and a file; please choose another name for the rule
WARNING: /Users/work/dev/bazel-javascript/tests/ts-example/src/testing/BUILD.bazel:14:1: target 'sum_test_lib' is both a rule and a file; please choose another name for the rule
WARNING: /Users/work/dev/bazel-javascript/tests/ts-example/src/BUILD.bazel:12:1: target 'main' is both a rule and a file; please choose another name for the rule
WARNING: /Users/work/dev/bazel-javascript/tests/ts-example/src/BUILD.bazel:22:1: target 'logger' is both a rule and a file; please choose another name for the rule
WARNING: /Users/work/dev/bazel-javascript/tests/ts-example/src/react/BUILD.bazel:12:1: target 'storybook' is both a rule and a file; please choose another name for the rule
WARNING: /Users/work/dev/bazel-javascript/tests/ts-example/src/react/BUILD.bazel:23:1: target 'component_story' is both a rule and a file; please choose another name for the rule
WARNING: /Users/work/dev/bazel-javascript/tests/ts-example/src/react/BUILD.bazel:34:1: target 'component' is both a rule and a file; please choose another name for the rule
enriched commented 6 years ago

Thanks for the great explanation François! And I would be really interested in whatever you figure out for modular typescript builds.