Add multistage build proposal

This commit is contained in:
Colin McDonnell
2023-04-04 20:22:59 -07:00
parent 7c2bb689cd
commit 629317b642
3 changed files with 94 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
# RFCs
| Number | Name | Issue |
| ------ | ----------------- | ---------------------------- |
| 1 | `Bun.Bundler` API | (Proposal)[./bun-bundler.ts] |
| Number | Name | Issue |
| ------ | ----------------- | --------------------------------- |
| 1 | `Bun.Bundler` API | (`Bun.Bundler`)[./bun-bundler.ts] |

View File

@@ -125,15 +125,17 @@ interface BuildOptions extends BundlerOptions {
entrypoints: string[];
rootDir?: string; // equiv. outbase
naming?: {
/** Documentation: https://esbuild.github.io/api/#entry-names */
entry?: string;
/** Documentation: https://esbuild.github.io/api/#chunk-names */
chunk?: string;
/** Documentation: https://esbuild.github.io/api/#asset-names */
asset?: string;
extensions?: { [ext: string]: string };
};
naming?:
| string
| {
/** Documentation: https://esbuild.github.io/api/#entry-names */
entry?: string;
/** Documentation: https://esbuild.github.io/api/#chunk-names */
chunk?: string;
/** Documentation: https://esbuild.github.io/api/#asset-names */
asset?: string;
extensions?: { [ext: string]: string };
};
/** Documentation: https://esbuild.github.io/api/#external */
external?: {
@@ -210,12 +212,12 @@ type BuildResult<T> = {
};
type LazyBuildResult = {
then(cb: (result: LazyBuildResult) => BuildOptions): LazyBuildResult;
then(cb: (context: any) => BuildOptions): LazyBuildResult;
run(): Promise<BuildResult<Blob>>;
write(dir: string): Promise<BuildResult<FileBlob>>;
};
declare class Bundler {
export declare class Bundler {
constructor(options: BundlerOptions);
makeBuild: (options: BuildOptions) => LazyBuildResult;
handle: (

View File

@@ -0,0 +1,78 @@
import { Bundler } from "./bun-bundler";
const bundler = new Bundler({
// ...
});
const router = new Bun.FileSystemRouter({
dir: "./app",
style: "nextjs",
});
const multistageBuild = bundler
.makeBuild({
// server build
target: "bun",
entrypoints: Object.values(router.routes),
bundle: true,
splitting: true,
naming: "rsc/[dir]/[name]-[hash].[ext]", // write to <builddir>/rsc
plugins: [
{
name: "rsc",
setup(build: any) {
// new hook: onBuild
// this is where we'd support various AST transforms in the future
build.onBuild(
{ directive: "client" },
(args: {
path: string;
resolveDir: string;
module: {
directive?: string;
id: string;
exports: string[];
};
}) => {
// per-build `context` object
// initialized to {}
build.context.clientModules = build.context.clientModules || {};
build.context.clientModules[args.resolveDir + "/" + args.path] = true;
// future APIs
// client references
const exports: any = {};
for (const key in args.module.exports) {
exports[key] = {
$$typeof: Symbol.for("react.client.element"),
$$id: args.module.id,
$$async: true,
};
}
return {
loader: "object",
exports,
};
},
);
},
},
],
})
.then(context => ({
entrypoints: ["./client-entry.tsx", ...Object.keys(context.clientModules)],
target: "browser",
bundle: true,
splitting: true,
naming: "client/[dir]/[name]-[hash].[ext]",
plugins: [],
}))
.then(context => ({
entrypoints: ["./ssr-entry.tsx", ...Object.keys(context.clientModules)],
target: "bun",
bundle: true,
splitting: true,
naming: "ssr/[dir]/[name]-[hash].[ext]",
plugins: [],
}))
.write("/.build");