Skip to content

Commit

Permalink
feat(bundle): add wasm bundler
Browse files Browse the repository at this point in the history
  • Loading branch information
lowlighter committed Dec 16, 2024
1 parent 58490ce commit 2e1d93b
Show file tree
Hide file tree
Showing 8 changed files with 2,510 additions and 3 deletions.
9 changes: 8 additions & 1 deletion bundle/deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"playground": "https://libs.lecoq.io/bundle",
"tasks": {
"test:node": "sleep 0",
"test:bun": "sleep 0"
"test:bun": "sleep 0",
"build": "deno run --allow-net=deno.land --allow-write=vendored vendored/mod.ts"
},
"imports": {
"@b-fuze/deno-dom": "jsr:@b-fuze/deno-dom@^0.1.48",
Expand Down Expand Up @@ -46,5 +47,11 @@
},
"supported": {
"deno": true
},
"fmt": {
"exclude": ["**/vendored/**"]
},
"lint": {
"exclude": ["**/vendored/**"]
}
}
50 changes: 48 additions & 2 deletions bundle/ts/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

// Imports
import * as esbuild from "esbuild"
import type * as esbuild from "esbuild"
import { denoLoaderPlugin, denoResolverPlugin } from "@luca/esbuild-deno-loader"
import { encodeBase64 } from "@std/encoding/base64"
import { minify as terser } from "terser"
Expand Down Expand Up @@ -38,7 +38,8 @@ import { delay } from "@std/async/delay"
* console.log(await bundle(`console.log("Hello world")`))
* ```
*/
export async function bundle(input: URL | string, { minify = "terser", format = "esm", debug = false, banner = "", shadow = true, config, exports, raw, overrides } = {} as options): Promise<string> {
export async function bundle(input: URL | string, { builder = "binary", minify = "terser", format = "esm", debug = false, banner = "", shadow = true, config, exports, raw, overrides } = {} as options): Promise<string> {
const esbuild = builder === "wasm" ? await import("../vendored/esbuild/wasm.js") : await import("esbuild")
const url = input instanceof URL ? input : new URL(`data:application/typescript;base64,${encodeBase64(input)}`)
let code = ""
try {
Expand Down Expand Up @@ -91,15 +92,60 @@ export async function bundle(input: URL | string, { minify = "terser", format =

/** Bundle options. */
export type options = {
/**
* The builder version to use.
*
* It can be either:
* - `binary` to use the binary runtime (faster but requires permissions to run)
* - `wasm` to use the WASM runtime (slower but more portable)
*/
builder?: "binary" | "wasm"
/**
* Minify the output.
*
* It can be either:
* - `false` to disable minification
* - `basic` for basic minification using {@link https://esbuild.github.io | esbuild}
* - `terser` for advanced minification through {@link https://terser.org | Terser}
*/
minify?: false | "basic" | "terser"
/** Output format. */
format?: "esm" | "iife"
/** Global exports. */
exports?: string
/** Enable debug and source map. */
debug?: boolean
/**
* Path to the config file.
*
* It is advised to leave this option empty as the deno plugin now resolves the configuration automatically.
*/
config?: URL
/**
* Banner to prepend to the output, useful for licensing information.
*
* It is automatically formatted as a comment.
*/
banner?: string
/** Replace local URLs with shadow URLs. */
shadow?: boolean
/**
* Raw options to esbuild.
*
* These options can also be used to override the default behavior of the bundler.
* Note that these options are excluded from the breaking changes policy.
*
* @see {@link https://esbuild.github.io/api/#build-api | esbuild} for more information.
*/
raw?: Record<PropertyKey, unknown>
/** Overrides. */
overrides?: {
/**
* Override imports.
*
* Can be used to replace imports with custom values before deno resolution.
* The key is the matching import path (as it appears in the source code) and the value is what it should be replaced with.
*/
imports?: Record<string, string>
}
}
Expand Down
5 changes: 5 additions & 0 deletions bundle/ts/bundle_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ test("`bundle()` handles banner option", async () => {
await expect(bundle(url, { config, banner: "license\ncopyright" })).resolves.toContain("/**\n * license\n * copyright\n */")
}, { permissions: { read: true, net: ["jsr.io"], env: true, run: true } })

test("`bundle()` handles builder version", async () => {
const url = new URL("test_bundle.ts", base)
await expect(bundle(url, { config, builder: "wasm" })).resolves.toContain("success")
}, { permissions: { read: true, run: ["deno"] } })

test("`bundle()` handles minify option", async () => {
const url = new URL("test_minify.ts", base)
await expect(bundle(url, { config, minify: false })).not.resolves.toBe(`console.log("hello world");`)
Expand Down
Binary file added bundle/vendored/esbuild/esbuild.wasm
Binary file not shown.
Loading

0 comments on commit 2e1d93b

Please sign in to comment.