diff --git a/docs/canary/concepts/builder.md b/docs/canary/concepts/builder.md new file mode 100644 index 00000000000..e9c3dd1cf16 --- /dev/null +++ b/docs/canary/concepts/builder.md @@ -0,0 +1,84 @@ +--- +description: | + The Builder class is used to generate optimized assets for production. +--- + +The `Builder` class in Fresh is where you'll do everything related to builds. +You'll typically find it being created inside your project's `dev.ts` file. + +```ts dev.ts +import { Builder } from "fresh/dev"; + +const builder = new Builder({ target: "safari12" }); + +if (Deno.args.includes("build")) { + // This creates a production build + await builder.build(); +} else { + // This starts a development server with live reload + await builder.listen(() => import("./main.ts")); +} +``` + +## Options + +You can customize the builder by passing options. + +```ts +const builder = new Builder({ + // Browser target for generated code. Maps to https://esbuild.github.io/api/#target + target?: string | string[]; + // The root directory of the project. All other paths will be resolved + // against this if they're relative. (Default: `Deno.cwd()`) + root?: string; + // Where to write generated files when doing a production build. + // (default: `/_fresh/`) + outDir?: string; + // Path to static file directory. (Default: `/static/`) + staticDir?: string; + // Path to island directory. (Default: `/islands`) + islandDir?: string; + // Path to routes directory. (Default: `/routes`) + routeDir?: string; + // File paths which should be ignored + ignore?: RegExp[]; +}) +``` + +## Registering islands + +The builder is where you'll register files that contain islands. This is the +same API that Fresh uses internally. + +```ts +const builder = new Builder(); + +// Path to local island +builder.registerIsland("path/to/my/Island.tsx"); +// File urls work too +builder.registerIsland("file:///path/to/my/Island.tsx"); +// Also islands from jsr +builder.registerIsland("jsr:@marvinh-test/fresh-island"); +``` + +## Adding build plugins + +The `Builder` has a very simple processing mechanism for static files. + +```ts +builder.onTransformStaticFile({ + pluginName: "My cool plugin", + filter: /\.css$/, +}, (args) => { + // Prepend `body { background: red }` to every `.css` file + const code = `body { background: red } ${args.text}`; + + return { + content: code, + map: undefined, // Optional: source maps + }; +}); +``` + +> [info]: Only static files in `static/` or the value you set `staticDir` to +> will be processed. The builder won't process anything else. diff --git a/docs/canary/testing/index.md b/docs/canary/testing/index.md index f3049b6e83e..9f3ec28831f 100644 --- a/docs/canary/testing/index.md +++ b/docs/canary/testing/index.md @@ -103,3 +103,37 @@ Deno.test("MyLayout - renders heading and content", async () => { expect(text).toContain("Hello"); }); ``` + +## Testing with file routes and islands + +[File routes](/docs/canary/concepts//file-routing) are collected by the +[`Builder`](/docs/canary/concepts/builder) class and not just by +[`App`](/docs/concepts/app) alone. We can generate a snapshot and re-use it for +many app instances in our test suite. + +```ts my-app.test.ts +// Best to do this once instead of for every test case for +// performance reasons. +const builder = new Builder(); +const applySnapshot = await builder.build({ snapshot: "memory" }); + +function testApp() { + const app = new App() + .get("/", () => new Response("hello")) + .fsRoutes(); + + // Applies build snapshot to this app instance. + applySnapshot(app); +} + +Deno.test("My Test", () => { + const handler = testApp().handler(); + + const response = await handler(new Request("http://localhost")); + const text = await response.text(); + + if (text !== "hello") { + throw new Error("fail"); + } +}); +``` diff --git a/docs/toc.ts b/docs/toc.ts index 5aa1a7d2a90..4105f1613d1 100644 --- a/docs/toc.ts +++ b/docs/toc.ts @@ -39,6 +39,7 @@ const toc: RawTableOfContents = { ["islands", "Islands", "link:canary"], ["static-files", "Static files", "link:canary"], + ["builder", "Builder", "link:canary"], ["file-routing", "File routing", "link:canary"], ], },