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

fix: respect noExternal option with Tsup node #720

Merged
merged 4 commits into from Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 2 additions & 1 deletion docs/README.md
Expand Up @@ -64,7 +64,8 @@ tsup automatically excludes packages specified in the `dependencies` and `peerDe
tsup-node src/index.ts
```

All other CLI flags still apply to this command.
All other CLI flags still apply to this command. You can still use the `noExternal` option to reinclude packages in the bundle,
for example packages that belong to a local monorepository.

**If the regular `tsup` command doesn't work for you, please submit an issue with a link to your repo so we can make the default command better.**

Expand Down
27 changes: 18 additions & 9 deletions src/esbuild/external.ts
Expand Up @@ -28,23 +28,32 @@ export const externalPlugin = ({
if (match(args.path, resolvePatterns)) {
return
}
// Respect explicit external/noExternal conditions
if (match(args.path, noExternal)) {
eric-burel marked this conversation as resolved.
Show resolved Hide resolved
return
}
if (match(args.path, external)) {
return { external: true }
}
// Exclude any other import that looks like a Node module
if (NON_NODE_MODULE_RE.test(args.path)) {
return {
path: args.path,
external: true,
}
}
})
} else {
build.onResolve({ filter: /.*/ }, (args) => {
// Respect explicit external/noExternal conditions
if (match(args.path, noExternal)) {
return
}
if (match(args.path, external)) {
return { external: true }
}
})
}

build.onResolve({ filter: /.*/ }, (args) => {
if (match(args.path, noExternal)) {
return
}
if (match(args.path, external)) {
return { external: true }
}
})
},
}
}
1 change: 1 addition & 0 deletions src/options.ts
Expand Up @@ -116,6 +116,7 @@ export type Options = {
silent?: boolean
/**
* Skip node_modules bundling
* Will still bundle modules matching the `noExternal` option
*/
skipNodeModulesBundle?: boolean
/**
Expand Down
44 changes: 44 additions & 0 deletions test/__snapshots__/index.test.ts.snap
Expand Up @@ -135,6 +135,50 @@ var answer = 42;
"
`;

exports[`noExternal are respected when skipNodeModulesBundle is true 1`] = `
"\\"use strict\\";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === \\"object\\" || typeof from === \\"function\\") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, \\"__esModule\\", { value: true }), mod);

// input.ts
var input_exports = {};
__export(input_exports, {
bar: () => import_bar.bar,
baz: () => import_baz.baz,
foo: () => foo
});
module.exports = __toCommonJS(input_exports);

// node_modules/foo/index.ts
var foo = \\"foo\\";

// input.ts
var import_bar = require(\\"bar\\");
var import_baz = require(\\"baz\\");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
bar,
baz,
foo
});
"
`;

exports[`node protocol 1`] = `
"\\"use strict\\";
var __create = Object.create;
Expand Down
22 changes: 22 additions & 0 deletions test/index.test.ts
Expand Up @@ -360,6 +360,28 @@ test('external', async () => {
expect(output).toMatchSnapshot()
})

test('noExternal are respected when skipNodeModulesBundle is true', 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 {
skipNodeModulesBundle: true,
noExternal: [/foo/]
}
`,
})
expect(output).toMatchSnapshot()
})

test('disable code splitting to get proper module.exports =', async () => {
const { output } = await run(
getTestName(),
Expand Down