Skip to content

Commit ed90d8f

Browse files
committed
docs: tell users how to run swc using their tsconfig settings
Useful as part of aspect-build/rules_ts#289 to make a migration path easier for those using tsc for transpiling
1 parent 018975c commit ed90d8f

File tree

15 files changed

+220
-6
lines changed

15 files changed

+220
-6
lines changed

.bazelignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
e2e/
1+
e2e/
2+
examples/node_modules
3+
examples/generate_swcrc/node_modules

.gitattributes

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
docs/*.md linguist-generated=true
1+
docs/repositories.md linguist-generated=true
2+
docs/swc.md linguist-generated=true

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
bazel-*
2+
node_modules

WORKSPACE

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@ nodejs_register_toolchains(
4343
node_version = DEFAULT_NODE_VERSION,
4444
)
4545

46+
load("@aspect_rules_js//npm:npm_import.bzl", "npm_translate_lock")
47+
48+
npm_translate_lock(
49+
name = "npm",
50+
pnpm_lock = "//examples:pnpm-lock.yaml",
51+
)
52+
53+
load("@npm//:repositories.bzl", "npm_repositories")
54+
55+
npm_repositories()
56+
4657
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
4758

4859
bazel_skylib_workspace()

docs/swc.md

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/tsconfig.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Synchronizing settings with tsconfig.json
2+
3+
TypeScript and SWC both need to be configured in their own files,
4+
typically `tsconfig.json` and `.swcrc`, respectively. Some settings are meant to be common between the two, such as
5+
how dependencies are resolved on the disk.
6+
7+
This is not a Bazel-specific problem, so we can just look for existing solutions in the ecosystem, and adapt those to be run under Bazel.
8+
9+
Ideally, we'd like SWC to simply read from `tsconfig.json`, as it
10+
is the "source-of-truth" for how editors understand `.ts` files.
11+
There is [an issue](https://github.com/swc-project/swc/issues/1348) already filed for this, but as of Jan 2023 it's not yet supported.
12+
13+
This document explores our options.
14+
15+
## Maintain two files
16+
17+
You might just check in both files as sources.
18+
19+
Since both `tsconfig.json` and `.swcrc` are JSON files, we recommend adding an [`assert_json_matches`](https://docs.aspect.build/rules/aspect_bazel_lib/docs/testing#assert_json_matches) rule to guarantee that they don't accidentally diverge.
20+
21+
A typical example looks like this:
22+
23+
```python
24+
load("@aspect_bazel_lib//lib:testing.bzl", "assert_json_matches")
25+
26+
# Verify that the "paths" entry is the same
27+
# between swc and TS language service (in the editor)
28+
assert_json_matches(
29+
name = "check_paths",
30+
file1 = "tsconfig.json",
31+
file2 = ".swcrc",
32+
filter1 = ".compilerOptions.paths",
33+
filter2 = ".jsc.paths",
34+
)
35+
```
36+
37+
## Generate the .swcrc
38+
39+
Another option provided by the community is to convert the `tsconfig.json` file. Under Bazel we can model this as a codegen step that happens automatically.
40+
41+
The relevant package is [tsconfig-to-swcconfig](https://www.npmjs.com/package/tsconfig-to-swcconfig). Let's see how to wire it up.
42+
43+
There's a corresponding CLI tool, tswc, but it doesn't work well to just generate the `.swcrc` file,
44+
see <https://github.com/Songkeys/tswc/issues/1>
45+
46+
So we'll make our own tiny CLI for the underlying package:
47+
48+
```javascript
49+
const {convert} = require('tsconfig-to-swcconfig');
50+
const [tsconfig] = process.argv.slice(2);
51+
console.log(JSON.stringify(convert(tsconfig), undefined, 2));
52+
```
53+
54+
And a bit of BUILD file content to invoke it (you might wrap this in a macro for better developer experience):
55+
56+
```python
57+
js_binary(
58+
name = "converter",
59+
entry_point = "write_swcrc.js",
60+
data = [":node_modules/tsconfig-to-swcconfig"],
61+
)
62+
63+
js_run_binary(
64+
name = "write_swcrc",
65+
tool = "converter",
66+
chdir = package_name(),
67+
args = ["./tsconfig.json"],
68+
srcs = ["tsconfig.json"],
69+
stdout = ".swcrc",
70+
)
71+
```
72+
73+
Now you can just use the standard `swc` rule with the `swcrc` attribute.
74+
See `/examples/generate_swcrc` for a full example.

examples/BUILD.bazel

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
load("@npm//:defs.bzl", "npm_link_all_packages")
2+
3+
# Required to create the virtual store at the root of the pnpm workspace
4+
# We don't have any node_modules to lay out in this directory.
5+
npm_link_all_packages()

examples/generate_swcrc/BUILD.bazel

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
load("@aspect_bazel_lib//lib:testing.bzl", "assert_json_matches")
2+
load("@aspect_rules_swc//swc:defs.bzl", "swc")
3+
load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_run_binary")
4+
load("@npm//:defs.bzl", "npm_link_all_packages")
5+
6+
npm_link_all_packages(name = "node_modules")
7+
8+
# Doesn't work: https://github.com/Songkeys/tswc/issues/1
9+
# load("@npm//examples/generate_swcrc:tswc/package_json.bzl", "bin")
10+
# bin.tswc(
11+
# name = "convert",
12+
# srcs = ["tsconfig.json"],
13+
# stdout = ".swcrc0",
14+
# args = ["--debug"],
15+
# )
16+
17+
js_binary(
18+
name = "converter",
19+
data = [":node_modules/tsconfig-to-swcconfig"],
20+
entry_point = "write_swcrc.js",
21+
)
22+
23+
js_run_binary(
24+
name = "write_swcrc",
25+
srcs = ["tsconfig.json"],
26+
args = ["./tsconfig.json"],
27+
chdir = package_name(),
28+
stdout = ".swcrc",
29+
tool = "converter",
30+
)
31+
32+
# Demonstrate that it works
33+
swc(
34+
name = "compile",
35+
swcrc = ".swcrc",
36+
)
37+
38+
# Verify that our options got passed through
39+
assert_json_matches(
40+
name = "test",
41+
file1 = ".swcrc",
42+
file2 = "tsconfig.json",
43+
filter1 = ".jsc.target",
44+
filter2 = ".compilerOptions.target",
45+
)

examples/generate_swcrc/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"private": true,
3+
"devDependencies": {
4+
"tsconfig-to-swcconfig": "~2.0.1"
5+
}
6+
}

examples/generate_swcrc/some.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const a = 1;

0 commit comments

Comments
 (0)