Skip to content

Commit 329d7cc

Browse files
committed
feat: update build process to use esbuild for TypeScript bundling
1 parent acd10b2 commit 329d7cc

3 files changed

Lines changed: 44 additions & 21 deletions

File tree

index.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@
1313
<pre style="color: #888; font-size: 12px; margin: 0; padding: 0">loading module-tsx library...</pre>
1414
</div>
1515
</body>
16-
<script src="./dist/index.umd.js"></script>
17-
<script>
18-
const { instance, ModuleTSX } = window.ModuleTSX; // the UMD global variable
16+
<!-- <script src="./dist/index.umd.js"></script> -->
17+
<script type="module">
18+
import { instance, ModuleTSX } from "./dist/index.mjs"; // the ESM module
19+
// const { instance, ModuleTSX } = window.ModuleTSX; // the UMD global variable
1920
instance.addEventListener("*", (event) => {
2021
const { type, payload } = event.detail;
2122

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@
99
"types": "dist/index.d.ts",
1010
"browser": "dist/index.mjs",
1111
"scripts": {
12-
"build": "tsdown"
12+
"build": "tsdown",
13+
"test": "node --experimental-strip-types --test 'src/*.test.ts'"
1314
},
1415
"dependencies": {
1516
"typescript": "^5.9.3"
1617
},
1718
"devDependencies": {
1819
"@types/node": "^24.12.0",
19-
"tsdown": "^0.20.3"
20+
"esbuild": "^0.27.5",
21+
"tsdown": "^0.21.7"
2022
},
2123
"author": "YieldRay",
2224
"license": "MIT",

tsdown.config.ts

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,34 @@
1-
import { defineConfig } from "tsdown";
2-
import { createRequire } from "node:module";
1+
import { defineConfig, type UserConfig } from "tsdown";
2+
import * as esbuild from "esbuild";
33

4-
const require = createRequire(import.meta.url);
5-
const tsVersion: string = require("typescript/package.json").version;
4+
const esbuildTypescript = await esbuild.build({
5+
entryPoints: ["node_modules/typescript/lib/typescript.js"],
6+
bundle: true,
7+
format: "esm",
8+
platform: "browser",
9+
minify: true,
10+
write: false,
11+
});
12+
13+
/**
14+
* Rolldown cannot bundle TypeScript directly due to its use of Node.js-specific features and dynamic imports.
15+
* To work around this, we pre-bundle TypeScript using esbuild, which can handle these features and produce a browser-compatible ESM bundle.
16+
* We then create a custom plugin for tsdown that serves this pre-bundled TypeScript whenever the "typescript" module is imported.
17+
*/
18+
const bundleTypescriptPlugin: UserConfig["plugins"] = {
19+
name: "bundle-typescript-with-esbuild",
20+
resolveId: {
21+
order: "pre",
22+
handler(id: string) {
23+
if (id === "typescript") return "virtual:typescript-esm";
24+
},
25+
},
26+
async load(id: string) {
27+
if (id === "virtual:typescript-esm") {
28+
return esbuildTypescript.outputFiles[0].text;
29+
}
30+
},
31+
};
632

733
export default defineConfig([
834
// index.js — ESM, unbundled (external deps)
@@ -16,22 +42,16 @@ export default defineConfig([
1642
entryFileNames: "[name].js",
1743
},
1844
},
19-
// index.mjs — ESM, bundled (typescript externalized to esm.sh for browser compatibility)
45+
// index.mjs — ESM, bundled (typescript bundled via esbuild for browser compatibility)
2046
{
2147
dts: false,
2248
entry: { index: "./src/index.ts" },
2349
format: "esm",
2450
platform: "browser",
2551
target: ["esnext"],
26-
noExternal: () => true,
27-
plugins: [
28-
{
29-
name: "resolve-typescript-to-esm-sh",
30-
resolveId(id) {
31-
if (id === "typescript") return { id: `https://esm.sh/typescript@${tsVersion}`, external: true };
32-
},
33-
},
34-
],
52+
deps: { alwaysBundle: (id) => id !== "typescript", onlyBundle: false },
53+
minify: true,
54+
plugins: bundleTypescriptPlugin,
3555
outputOptions: {
3656
entryFileNames: "[name].mjs",
3757
},
@@ -43,9 +63,9 @@ export default defineConfig([
4363
format: "umd",
4464
platform: "browser",
4565
target: ["esnext"],
46-
noExternal: () => true,
47-
inlineOnly: false,
66+
deps: { alwaysBundle: (id) => id !== "typescript", onlyBundle: false },
4867
minify: true,
68+
plugins: bundleTypescriptPlugin,
4969
outputOptions: {
5070
name: "ModuleTSX",
5171
entryFileNames: "[name].umd.js",

0 commit comments

Comments
 (0)