evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
38.19k stars 1.15k forks source link

[Feature] banner and footer based on chunk #3196

Open domcoleman opened 1 year ago

domcoleman commented 1 year ago

Feature Request

As a continuation of #482 I'd like to propose an option to have the banner set by chunk, as seen in Rollup and documented here.

Use case

With React now having server components, and files in Next.js using "use client" to indicate a client component, it has made bundling libraries with tsup/esbuild a pain. I'm now running multiple dev scripts using different config files for server/client components.

I did have a look at creating a plugin but from what I could tell I'd then have to do all the typescript transpiling within the plugin as well?

domcoleman commented 1 year ago

I'll keep this open just in case anyone decides to add it, was fairly simple creating a plugin though:

import { Plugin } from "esbuild";
import fs from "fs/promises";

interface ESBuildUseClientOptions {
  filter?: RegExp;
}

export const esbuildUseClient = ({
  filter = /\/.client\.tsx?$/,
}: ESBuildUseClientOptions = {}): Plugin => ({
  name: "use-client",
  setup(build): void {
    build.onLoad({ filter }, async (args) => {
      const source = await fs.readFile(args.path, "utf8");
      const loader = args.path.endsWith(".tsx") ? "tsx" : "ts";

      const data = await build.esbuild.transform(source, {
        loader,
        banner: '"use client";',
      });

      return {
        warnings: data.warnings,
        contents: data.code + `//# sourceMappingURL=${data.map}`,
      };
    });
  },
});