From c5ed4f8455ced58c2975cfb7f78ec458749c3ab9 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Thu, 8 Apr 2021 23:52:56 +1000 Subject: [PATCH] feat(esbuild): add output_css flag to esbuild() (#2545) --- packages/esbuild/esbuild.bzl | 14 +++++ packages/esbuild/test/css/BUILD.bazel | 67 ++++++++++++++++++++++++ packages/esbuild/test/css/bundle_test.js | 25 +++++++++ packages/esbuild/test/css/dep.ts | 3 ++ packages/esbuild/test/css/external.css | 2 + packages/esbuild/test/css/main.ts | 3 ++ 6 files changed, 114 insertions(+) create mode 100644 packages/esbuild/test/css/BUILD.bazel create mode 100644 packages/esbuild/test/css/bundle_test.js create mode 100644 packages/esbuild/test/css/dep.ts create mode 100644 packages/esbuild/test/css/external.css create mode 100644 packages/esbuild/test/css/main.ts diff --git a/packages/esbuild/esbuild.bzl b/packages/esbuild/esbuild.bzl index 41218731ec..28ae5b77cb 100644 --- a/packages/esbuild/esbuild.bzl +++ b/packages/esbuild/esbuild.bzl @@ -28,6 +28,9 @@ def _esbuild_impl(ctx): elif hasattr(dep, "files"): deps_depsets.append(dep.files) + if DefaultInfo in dep: + deps_depsets.append(dep[DefaultInfo].data_runfiles.files) + if NpmPackageInfo in dep: deps_depsets.append(dep[NpmPackageInfo].sources) npm_workspaces.append(dep[NpmPackageInfo].workspace) @@ -100,6 +103,9 @@ def _esbuild_impl(ctx): fail("output_map must be specified if sourcemap is not set to 'inline'") outputs.append(js_out_map) + if ctx.outputs.output_css: + outputs.append(ctx.outputs.output_css) + if ctx.attr.format: args.add_joined(["--format", ctx.attr.format], join_with = "=") @@ -219,6 +225,14 @@ See https://esbuild.github.io/api/#splitting for more details mandatory = False, doc = "Name of the output source map when bundling", ), + "output_css": attr.output( + mandatory = False, + doc = """Declare a .css file will be output next to output bundle. + +If your JS code contains import statements that import .css files, esbuild will place the +content in a file next to the main output file, which you'll need to declare. If your output +file is named 'foo.js', you should set this to 'foo.css'.""", + ), "platform": attr.string( default = "browser", values = ["node", "browser", "neutral", ""], diff --git a/packages/esbuild/test/css/BUILD.bazel b/packages/esbuild/test/css/BUILD.bazel new file mode 100644 index 0000000000..ba92332014 --- /dev/null +++ b/packages/esbuild/test/css/BUILD.bazel @@ -0,0 +1,67 @@ +load("//packages/esbuild/test:tests.bzl", "esbuild") +load("//packages/jasmine:index.bzl", "jasmine_node_test") +load("//packages/typescript:index.bzl", "ts_library") +load("@build_bazel_rules_nodejs//:index.bzl", "copy_to_bin") + +copy_to_bin( + name = "external_copied", + srcs = ["external.css"], +) + +ts_library( + name = "dep", + srcs = [ + "dep.ts", + ], + data = [ + ":external_copied", + ], + deps = [ + "@npm//@types/node", + ], +) + +ts_library( + name = "main", + srcs = [ + "main.ts", + ], + deps = [ + ":dep", + "@npm//@types/node", + ], +) + +esbuild( + name = "default", + args = [ + "--keep-names", + "--resolve-extensions=.mjs,.js", + ], + entry_point = "main.ts", + deps = [ + ":main", + ], +) + +esbuild( + name = "with_css", + args = [ + "--keep-names", + "--resolve-extensions=.mjs,.js", + ], + entry_point = "main.ts", + output_css = "with_css.css", + deps = [ + ":main", + ], +) + +jasmine_node_test( + name = "bundle_test", + srcs = ["bundle_test.js"], + data = [ + ":default", + ":with_css", + ], +) diff --git a/packages/esbuild/test/css/bundle_test.js b/packages/esbuild/test/css/bundle_test.js new file mode 100644 index 0000000000..1632f47fd2 --- /dev/null +++ b/packages/esbuild/test/css/bundle_test.js @@ -0,0 +1,25 @@ +const { readFileSync } = require("fs"); +const path = require("path"); + +const helper = require(process.env.BAZEL_NODE_RUNFILES_HELPER); +const locationBase = "build_bazel_rules_nodejs/packages/esbuild/test/css/"; + +const cssExpected = helper.resolve(path.join(locationBase, "with_css.css")); + +describe("esbuild css", () => { + it("no css by default", () => { + if (process.platform === "win32") { + // Windows has no sandbox, and the runfiles helper will return files + // that happen to exist in the folder, even if they are not declared outputs + return; + } + expect(() => + helper.resolve(path.join(locationBase, "default.css")) + ).toThrow(); + }); + + it("css if requested", () => { + const contents = readFileSync(cssExpected, { encoding: "utf8" }); + expect(contents).toContain("external-content"); + }); +}); diff --git a/packages/esbuild/test/css/dep.ts b/packages/esbuild/test/css/dep.ts new file mode 100644 index 0000000000..711419a21f --- /dev/null +++ b/packages/esbuild/test/css/dep.ts @@ -0,0 +1,3 @@ +import "./external.css"; + +export function dep() {} diff --git a/packages/esbuild/test/css/external.css b/packages/esbuild/test/css/external.css new file mode 100644 index 0000000000..b89198537f --- /dev/null +++ b/packages/esbuild/test/css/external.css @@ -0,0 +1,2 @@ +.external-content { +} diff --git a/packages/esbuild/test/css/main.ts b/packages/esbuild/test/css/main.ts new file mode 100644 index 0000000000..a352fe7016 --- /dev/null +++ b/packages/esbuild/test/css/main.ts @@ -0,0 +1,3 @@ +import { dep } from "./dep"; + +dep();