diff --git a/src/index.ts b/src/index.ts index a44702e..68fdb26 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,6 +16,7 @@ import { FSWatcher } from 'chokidar' import glob from 'globby' import { PrettyError } from './errors' import { postcssPlugin } from './plugins/postcss' +import { externalPlugin } from './plugins/external' const textDecoder = new TextDecoder('utf-8') @@ -58,7 +59,7 @@ export type Options = { } sourcemap?: boolean /** Don't bundle these packages */ - external?: string[] + external?: (string | RegExp)[] /** Transform the result with `@babel/core` */ babel?: boolean /** @@ -136,7 +137,12 @@ export async function runEsbuild( jsxFragment: options.jsxFragment, sourcemap: options.sourcemap, target: options.target === 'es5' ? 'es2016' : options.target, - plugins: [postcssPlugin], + plugins: [ + // esbuild's `external` option doesn't support RegExp + // So here we use a custom plugin to implement it + externalPlugin(external), + postcssPlugin, + ], define: { ...options.define, ...Object.keys(env).reduce((res, key) => { @@ -146,7 +152,6 @@ export async function runEsbuild( } }, {}), }, - external, outdir: options.legacyOutput && format !== 'cjs' ? join(outDir, format) diff --git a/src/plugins/external.ts b/src/plugins/external.ts new file mode 100644 index 0000000..2bb2375 --- /dev/null +++ b/src/plugins/external.ts @@ -0,0 +1,25 @@ +import { Plugin } from 'esbuild' + +export const externalPlugin = (patterns?: (string | RegExp)[]): Plugin => { + return { + name: `external`, + + setup(build) { + if (!patterns || patterns.length === 0) return + + build.onResolve({ filter: /.*/ }, (args) => { + const external = patterns.some((p) => { + if (p instanceof RegExp) { + return p.test(args.path) + } + return args.path === p + }) + if (external) { + return { path: args.path, external } + } + // return without `path` to use default path resolution logic + return {} + }) + }, + } +} diff --git a/test/index.test.ts b/test/index.test.ts index 812b6c2..558792f 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -363,3 +363,37 @@ test('import css', async () => { ] `) }) + +test('external', async () => { + const { output } = await run(getTestName(), { + 'input.ts': `export {foo} from 'foo' + export {bar} from 'bar' + export {baz} from 'baz' + `, + 'node_modules/foo/index.ts': `export const foo = 'foo'`, + 'node_modules/foo/package.json': `{"name":"foo","version":"0.0.0"}`, + 'node_modules/bar/index.ts': `export const bar = 'bar'`, + 'node_modules/bar/package.json': `{"name":"bar","version":"0.0.0"}`, + 'node_modules/baz/index.ts': `export const baz = 'baz'`, + 'node_modules/baz/package.json': `{"name":"baz","version":"0.0.0"}`, + 'tsup.config.ts': ` + export default { + external: [/f/, 'bar'] + } + `, + }) + expect(output).toMatchInlineSnapshot(` + "\\"use strict\\";Object.defineProperty(exports, \\"__esModule\\", {value: true});// input.ts + var _foo = require('foo'); + var _bar = require('bar'); + + // node_modules/baz/index.ts + var baz = \\"baz\\"; + + + + + exports.bar = _bar.bar; exports.baz = baz; exports.foo = _foo.foo; + " + `) +})