diff --git a/e2e/cases/auto-external/external-sub-path/package.json b/e2e/cases/auto-external/external-sub-path/package.json new file mode 100644 index 00000000..5c98adea --- /dev/null +++ b/e2e/cases/auto-external/external-sub-path/package.json @@ -0,0 +1,6 @@ +{ + "name": "@e2e/auto-external-with-sub-path", + "dependencies": { + "react": "^18.3.1" + } +} diff --git a/e2e/cases/auto-external/external-sub-path/rslib.config.ts b/e2e/cases/auto-external/external-sub-path/rslib.config.ts new file mode 100644 index 00000000..03252f35 --- /dev/null +++ b/e2e/cases/auto-external/external-sub-path/rslib.config.ts @@ -0,0 +1,11 @@ +import { generateBundleCjsConfig, generateBundleEsmConfig } from '@e2e/helper'; +import { defineConfig } from '@rslib/core'; + +export default defineConfig({ + lib: [generateBundleEsmConfig(__dirname), generateBundleCjsConfig(__dirname)], + source: { + entry: { + main: './src/index.ts', + }, + }, +}); diff --git a/e2e/cases/auto-external/external-sub-path/src/index.ts b/e2e/cases/auto-external/external-sub-path/src/index.ts new file mode 100644 index 00000000..25bd8868 --- /dev/null +++ b/e2e/cases/auto-external/external-sub-path/src/index.ts @@ -0,0 +1,6 @@ +import React from 'react'; +import ReactJsx from 'react/jsx-runtime'; + +export const foo = () => { + return [React.version, ReactJsx.jsx]; +}; diff --git a/e2e/cases/auto-external/index.test.ts b/e2e/cases/auto-external/index.test.ts index 223a9300..c47715f0 100644 --- a/e2e/cases/auto-external/index.test.ts +++ b/e2e/cases/auto-external/index.test.ts @@ -15,6 +15,25 @@ test('auto external default should works', async () => { ); }); +test('auto external sub path should works', async () => { + const fixturePath = join(__dirname, 'external-sub-path'); + const { entries } = await buildAndGetResults(fixturePath); + + expect(entries.esm).toContain( + 'import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react"', + ); + expect(entries.esm).toContain( + 'import * as __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__ from "react/jsx-runtime"', + ); + + expect(entries.cjs).toContain( + 'var external_react_namespaceObject = require("react");', + ); + expect(entries.cjs).toContain( + 'var jsx_runtime_namespaceObject = require("react/jsx-runtime");', + ); +}); + test('auto external false should works', async () => { const fixturePath = join(__dirname, 'false'); const { entries } = await buildAndGetResults(fixturePath); diff --git a/examples/react-component/rslib.config.ts b/examples/react-component/rslib.config.ts index d9701100..561d3c6e 100644 --- a/examples/react-component/rslib.config.ts +++ b/examples/react-component/rslib.config.ts @@ -33,11 +33,5 @@ export default defineConfig({ main: './src/index.tsx', }, }, - output: { - externals: { - react: 'react', - 'react/jsx-runtime': 'react/jsx-runtime', - }, - }, plugins: [pluginReact()], }); diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index 4c5a150f..98fa4e3a 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -125,10 +125,16 @@ export const composeAutoExternalConfig = (options: { }, []) .filter((name) => !userExternalKeys.includes(name)); + const uniqueExternals = Array.from(new Set(externals)); + return externals.length ? { output: { - externals: Array.from(new Set(externals)), + externals: [ + // Exclude dependencies, e.g. `react`, `react/jsx-runtime` + ...uniqueExternals.map((dep) => new RegExp(`^${dep}($|\\/|\\\\)`)), + ...uniqueExternals, + ], }, } : {}; diff --git a/packages/core/tests/external.test.ts b/packages/core/tests/external.test.ts index 95ab8288..343b35d7 100644 --- a/packages/core/tests/external.test.ts +++ b/packages/core/tests/external.test.ts @@ -23,7 +23,14 @@ describe('should composeAutoExternalConfig correctly', () => { expect(result).toEqual({ output: { - externals: ['foo', 'foo1', 'baz'], + externals: [ + /^foo($|\/|\\)/, + /^foo1($|\/|\\)/, + /^baz($|\/|\\)/, + 'foo', + 'foo1', + 'baz', + ], }, }); }); @@ -49,7 +56,14 @@ describe('should composeAutoExternalConfig correctly', () => { expect(result).toEqual({ output: { - externals: ['foo', 'foo1', 'baz'], + externals: [ + /^foo($|\/|\\)/, + /^foo1($|\/|\\)/, + /^baz($|\/|\\)/, + 'foo', + 'foo1', + 'baz', + ], }, }); }); @@ -75,7 +89,7 @@ describe('should composeAutoExternalConfig correctly', () => { expect(result).toEqual({ output: { - externals: ['foo', 'bar'], + externals: [/^foo($|\/|\\)/, /^bar($|\/|\\)/, 'foo', 'bar'], }, }); }); @@ -109,7 +123,7 @@ describe('should composeAutoExternalConfig correctly', () => { expect(result).toEqual({ output: { - externals: ['bar'], + externals: [/^bar($|\/|\\)/, 'bar'], }, }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fe4d20c2..aea969d9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -100,6 +100,12 @@ importers: specifier: ^18.3.1 version: 18.3.1 + e2e/cases/auto-external/external-sub-path: + dependencies: + react: + specifier: ^18.3.1 + version: 18.3.1 + e2e/cases/auto-external/false: dependencies: react: