Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow to exclude dependencies from specific package.json #717

Merged
merged 2 commits into from Oct 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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