Skip to content

Commit 8d0218c

Browse files
feat(esbuild): add 'sourcemap' option to configure sourcemap generation (#2528)
1 parent 97b3886 commit 8d0218c

File tree

4 files changed

+150
-3
lines changed

4 files changed

+150
-3
lines changed

packages/esbuild/esbuild.bzl

+25-3
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,12 @@ def _esbuild_impl(ctx):
5454
args = ctx.actions.args()
5555

5656
args.add("--bundle", entry_point.path)
57-
args.add("--sourcemap")
57+
58+
if len(ctx.attr.sourcemap) > 0:
59+
args.add_joined(["--sourcemap", ctx.attr.sourcemap], join_with = "=")
60+
else:
61+
args.add("--sourcemap")
62+
5863
args.add("--preserve-symlinks")
5964
args.add_joined(["--platform", ctx.attr.platform], join_with = "=")
6065
args.add_joined(["--target", ctx.attr.target], join_with = "=")
@@ -87,8 +92,13 @@ def _esbuild_impl(ctx):
8792
args.add_joined(["--outdir", js_out.path], join_with = "=")
8893
else:
8994
js_out = ctx.outputs.output
95+
outputs.append(js_out)
96+
9097
js_out_map = ctx.outputs.output_map
91-
outputs.extend([js_out, js_out_map])
98+
if ctx.attr.sourcemap != "inline":
99+
if js_out_map == None:
100+
fail("output_map must be specified if sourcemap is not set to 'inline'")
101+
outputs.append(js_out_map)
92102

93103
if ctx.attr.format:
94104
args.add_joined(["--format", ctx.attr.format], join_with = "=")
@@ -214,6 +224,14 @@ See https://esbuild.github.io/api/#splitting for more details
214224
See https://esbuild.github.io/api/#platform for more details
215225
""",
216226
),
227+
"sourcemap": attr.string(
228+
values = ["external", "inline", "both"],
229+
mandatory = False,
230+
doc = """Defines where sourcemaps are output and how they are included in the bundle. By default, a separate `.js.map` file is generated and referenced by the bundle. If 'external', a separate `.js.map` file is generated but not referenced by the bundle. If 'inline', a sourcemap is generated and its contents are inlined into the bundle (and no external sourcemap file is created). If 'both', a sourcemap is inlined and a `.js.map` file is created.
231+
232+
See https://esbuild.github.io/api/#sourcemap for more details
233+
""",
234+
),
217235
"sources_content": attr.bool(
218236
mandatory = False,
219237
default = False,
@@ -270,9 +288,13 @@ def esbuild_macro(name, output_dir = False, **kwargs):
270288
**kwargs
271289
)
272290
else:
291+
output_map = None
292+
sourcemap = kwargs.get("sourcemap", None)
293+
if sourcemap != "inline":
294+
output_map = "%s.js.map" % name
273295
esbuild(
274296
name = name,
275297
output = "%s.js" % name,
276-
output_map = "%s.js.map" % name,
298+
output_map = output_map,
277299
**kwargs
278300
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
load("//packages/esbuild/test:tests.bzl", "esbuild")
2+
load("//packages/jasmine:index.bzl", "jasmine_node_test")
3+
load("//packages/typescript:index.bzl", "ts_library")
4+
5+
ts_library(
6+
name = "main",
7+
srcs = [
8+
"main.ts",
9+
],
10+
deps = [
11+
"@npm//@types/node",
12+
],
13+
)
14+
15+
esbuild(
16+
name = "bundle_default",
17+
args = ["--keep-names"],
18+
entry_point = "main.ts",
19+
deps = [":main"],
20+
)
21+
22+
esbuild(
23+
name = "bundle_inline",
24+
args = ["--keep-names"],
25+
entry_point = "main.ts",
26+
sourcemap = "inline",
27+
deps = [":main"],
28+
)
29+
30+
esbuild(
31+
name = "bundle_external",
32+
args = ["--keep-names"],
33+
entry_point = "main.ts",
34+
sourcemap = "external",
35+
deps = [":main"],
36+
)
37+
38+
esbuild(
39+
name = "bundle_both",
40+
args = ["--keep-names"],
41+
entry_point = "main.ts",
42+
sourcemap = "both",
43+
deps = [":main"],
44+
)
45+
46+
jasmine_node_test(
47+
name = "bundle_test",
48+
srcs = ["bundle_test.js"],
49+
data = [
50+
":bundle_both",
51+
":bundle_default",
52+
":bundle_external",
53+
":bundle_inline",
54+
],
55+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
const {readFileSync, exists} = require('fs');
2+
const path = require('path');
3+
4+
const helper = require(process.env.BAZEL_NODE_RUNFILES_HELPER);
5+
const locationBase = 'build_bazel_rules_nodejs/packages/esbuild/test/sourcemap/';
6+
7+
// Location for :bundle_default
8+
const bundleDefaultLocation = helper.resolve(path.join(locationBase, 'bundle_default.js'));
9+
const bundleDefaultSourcemapLocation =
10+
helper.resolve(path.join(locationBase, 'bundle_default.js.map'));
11+
12+
// Location for :bundle_inline
13+
const bundleInlineLocation = helper.resolve(path.join(locationBase, 'bundle_inline.js'));
14+
15+
// Location for :bundle_external
16+
const bundleExternalLocation = helper.resolve(path.join(locationBase, 'bundle_external.js'));
17+
const bundleExternalSourcemapLocation =
18+
helper.resolve(path.join(locationBase, 'bundle_external.js.map'));
19+
20+
// Location for :bundle_both
21+
const bundleBothLocation = helper.resolve(path.join(locationBase, 'bundle_both.js'));
22+
const bundleBothSourcemapLocation = helper.resolve(path.join(locationBase, 'bundle_both.js.map'));
23+
24+
describe('esbuild sourcemap', () => {
25+
it('creates an external sourcemap by default', () => {
26+
const sourcemap = readFileSync(bundleDefaultSourcemapLocation, {encoding: 'utf8'});
27+
expect(sourcemap).toContain(
28+
'"sources": ["../../../../../../../packages/esbuild/test/sourcemap/main.ts"]');
29+
});
30+
31+
it('does not inline the sourcemap by default', () => {
32+
const bundle = readFileSync(bundleDefaultLocation, {encoding: 'utf8'});
33+
expect(bundle).toContain('//# sourceMappingURL=bundle_default.js.map');
34+
});
35+
36+
it('inlines the sourcemap when set to \'inline\'', () => {
37+
const bundle = readFileSync(bundleInlineLocation, {encoding: 'utf8'});
38+
expect(bundle).toContain('//# sourceMappingURL=data:application/json;base64');
39+
});
40+
41+
it('has no sourcemap comment when set to \'external\'', () => {
42+
const bundle = readFileSync(bundleExternalLocation, {encoding: 'utf8'});
43+
expect(bundle).not.toContain('//# sourceMappingURL=');
44+
});
45+
46+
it('creates an external sourcemap when set to \'external\'', () => {
47+
const sourcemap = readFileSync(bundleExternalSourcemapLocation, {encoding: 'utf8'});
48+
expect(sourcemap).toContain(
49+
'"sources": ["../../../../../../../packages/esbuild/test/sourcemap/main.ts"]');
50+
});
51+
52+
it('inlines the sourcemap when set to \'both\'', () => {
53+
const bundle = readFileSync(bundleInlineLocation, {encoding: 'utf8'});
54+
expect(bundle).toContain('//# sourceMappingURL=data:application/json;base64');
55+
});
56+
57+
it('creates an external sourcemap when set to \'both\'', () => {
58+
const sourcemap = readFileSync(bundleDefaultSourcemapLocation, {encoding: 'utf8'});
59+
expect(sourcemap).toContain(
60+
'"sources": ["../../../../../../../packages/esbuild/test/sourcemap/main.ts"]');
61+
});
62+
})
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export interface Foo {
2+
x: number, y: string,
3+
}
4+
5+
export const foo: Foo = {
6+
x: 123,
7+
y: 'hello',
8+
}

0 commit comments

Comments
 (0)