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
733export 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