Skip to content

Commit

Permalink
feat: allow to exclude dependencies from specific package.json (#717)
Browse files Browse the repository at this point in the history
  • Loading branch information
ArcherGu committed Oct 6, 2022
1 parent fb248e4 commit 8d7ce9e
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 16 deletions.
2 changes: 1 addition & 1 deletion docs/README.md
Expand Up @@ -52,7 +52,7 @@ This will output `dist/index.js` and `dist/cli.js`.

### Excluding packages

By default tsup bundles all `import`-ed modules but `dependencies` and `peerDependencies` in your `packages.json` are always excluded, you can also use `--external <module>` flag to mark other packages as external.
By default tsup bundles all `import`-ed modules but `dependencies` and `peerDependencies` in your `packages.json` are always excluded, you can also use `--external <module|pkgJson>` flag to mark other packages or other special `package.json`'s `dependencies` and `peerDependencies` as external.

### Excluding all packages

Expand Down
2 changes: 1 addition & 1 deletion src/cli-main.ts
Expand Up @@ -58,7 +58,7 @@ export async function main(options: Options = {}) {
'Replace a global variable with an import from another file'
)
.option('--define.* <value>', 'Define compile-time constants')
.option('--external <name>', 'Mark specific packages as external')
.option('--external <name>', 'Mark specific packages / package.json (dependencies and peerDependencies) as external')
.option('--global-name <name>', 'Global variable name for iife format')
.option('--jsxFactory <jsxFactory>', 'Name of JSX factory function', {
default: 'React.createElement',
Expand Down
43 changes: 32 additions & 11 deletions src/esbuild/index.ts
Expand Up @@ -58,6 +58,27 @@ const getOutputExtensionMap = (
}
}

/**
* Support to exclude special package.json
*/
const generateExternal = async (external: (string | RegExp)[]) => {
const result: (string | RegExp)[] = []

for (const item of external) {
if (typeof item !== 'string' || !item.endsWith('package.json')) {
result.push(item)
continue
}

let pkgPath: string = path.isAbsolute(item) ? path.dirname(item) : path.dirname(path.resolve(process.cwd(), item))

const deps = await getDeps(pkgPath)
result.push(...deps)
}

return result
}

export async function runEsbuild(
options: NormalizedOptions,
{
Expand All @@ -79,7 +100,7 @@ export async function runEsbuild(
const external = [
// Exclude dependencies, e.g. `lodash`, `lodash/get`
...deps.map((dep) => new RegExp(`^${dep}($|\\/|\\\\)`)),
...(options.external || []),
...(await generateExternal(options.external || [])),
]
const outDir = options.outDir

Expand All @@ -103,8 +124,8 @@ export async function runEsbuild(
format === 'iife'
? false
: typeof options.splitting === 'boolean'
? options.splitting
: format === 'esm'
? options.splitting
: format === 'esm'

const platform = options.platform || 'node'
const loader = options.loader || {}
Expand All @@ -131,12 +152,12 @@ export async function runEsbuild(
// esbuild's `external` option doesn't support RegExp
// So here we use a custom plugin to implement it
format !== 'iife' &&
externalPlugin({
external,
noExternal: options.noExternal,
skipNodeModulesBundle: options.skipNodeModulesBundle,
tsconfigResolvePaths: options.tsconfigResolvePaths,
}),
externalPlugin({
external,
noExternal: options.noExternal,
skipNodeModulesBundle: options.skipNodeModulesBundle,
tsconfigResolvePaths: options.tsconfigResolvePaths,
}),
options.tsconfigDecoratorMetadata && swcPlugin({ logger }),
nativeNodeModulesPlugin(),
postcssPlugin({ css, inject: options.injectStyle }),
Expand Down Expand Up @@ -199,8 +220,8 @@ export async function runEsbuild(
TSUP_FORMAT: JSON.stringify(format),
...(format === 'cjs' && injectShims
? {
'import.meta.url': 'importMetaUrl',
}
'import.meta.url': 'importMetaUrl',
}
: {}),
...options.define,
...Object.keys(env).reduce((res, key) => {
Expand Down
9 changes: 7 additions & 2 deletions test/__snapshots__/index.test.ts.snap
Expand Up @@ -74,19 +74,24 @@ var input_exports = {};
__export(input_exports, {
bar: () => import_bar.bar,
baz: () => baz,
foo: () => import_foo.foo
foo: () => import_foo.foo,
qux: () => import_qux.qux
});
module.exports = __toCommonJS(input_exports);
var import_foo = require(\\"foo\\");
var import_bar = require(\\"bar\\");
// node_modules/baz/index.ts
var baz = \\"baz\\";
// input.ts
var import_qux = require(\\"qux\\");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
bar,
baz,
foo
foo,
qux
});
"
`;
Expand Down
6 changes: 5 additions & 1 deletion test/index.test.ts
Expand Up @@ -344,16 +344,20 @@ test('external', async () => {
'input.ts': `export {foo} from 'foo'
export {bar} from 'bar'
export {baz} from 'baz'
export {qux} from 'qux'
`,
'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"}`,
'node_modules/qux/index.ts': `export const qux = 'qux'`,
'node_modules/qux/package.json': `{"name":"qux","version":"0.0.0"}`,
'another/package.json': `{"name":"another-pkg","dependencies":{"qux":"0.0.0"}}`,
'tsup.config.ts': `
export default {
external: [/f/, 'bar']
external: [/f/, 'bar', 'another/package.json']
}
`,
})
Expand Down

0 comments on commit 8d7ce9e

Please sign in to comment.