From c4b9169575de17e9c7617e1ae89b5f993448b252 Mon Sep 17 00:00:00 2001 From: "gaoyuan.1226" Date: Fri, 9 Aug 2024 19:10:40 +0800 Subject: [PATCH 1/5] feat: supportbundlePackages when bundle dts --- packages/core/src/config.ts | 3 +- packages/plugin-dts/src/apiExtractor.ts | 5 +- packages/plugin-dts/src/dts.ts | 97 ++++++++++++++++++ packages/plugin-dts/src/index.ts | 12 ++- packages/plugin-dts/tests/external.test.ts | 108 +++++++++++++++++++++ packages/plugin-dts/vitest.config.ts | 9 ++ 6 files changed, 229 insertions(+), 5 deletions(-) create mode 100644 packages/plugin-dts/tests/external.test.ts create mode 100644 packages/plugin-dts/vitest.config.ts diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index 98fa4e3a..9e499616 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -396,7 +396,7 @@ const composeDtsConfig = async ( libConfig: LibConfig, dtsExtension: string, ): Promise => { - const { dts, bundle, output } = libConfig; + const { dts, bundle, output, autoExternal } = libConfig; if (dts === false || dts === undefined) return {}; @@ -408,6 +408,7 @@ const composeDtsConfig = async ( distPath: dts?.distPath ?? output?.distPath?.root ?? './dist', abortOnError: dts?.abortOnError ?? true, dtsExtension, + autoExternal, }), ], }; diff --git a/packages/plugin-dts/src/apiExtractor.ts b/packages/plugin-dts/src/apiExtractor.ts index a92e1a00..54d09821 100644 --- a/packages/plugin-dts/src/apiExtractor.ts +++ b/packages/plugin-dts/src/apiExtractor.ts @@ -15,6 +15,7 @@ export type BundleOptions = { dtsExtension: string; entry?: string; tsconfigPath?: string; + bundledPackages?: string[]; }; export async function bundleDts(options: BundleOptions): Promise { @@ -25,6 +26,7 @@ export async function bundleDts(options: BundleOptions): Promise { dtsExtension, entry = 'index.d.ts', tsconfigPath = 'tsconfig.json', + bundledPackages = [], } = options; try { const start = Date.now(); @@ -35,8 +37,7 @@ export async function bundleDts(options: BundleOptions): Promise { ); const internalConfig = { mainEntryPointFilePath: entry, - // TODO: use !externals - // bundledPackages: [], + bundledPackages, dtsRollup: { enabled: true, untrimmedFilePath, diff --git a/packages/plugin-dts/src/dts.ts b/packages/plugin-dts/src/dts.ts index d6babe2e..8af1d089 100644 --- a/packages/plugin-dts/src/dts.ts +++ b/packages/plugin-dts/src/dts.ts @@ -1,3 +1,4 @@ +import fs from 'node:fs'; import { basename, dirname, join, relative } from 'node:path'; import { logger } from '@rsbuild/core'; import color from 'picocolors'; @@ -6,6 +7,95 @@ import * as ts from 'typescript'; import { emitDts } from './tsc'; import { ensureTempDeclarationDir, loadTsconfig } from './utils'; +const isObject = (obj: unknown): obj is Record => + Object.prototype.toString.call(obj) === '[object Object]'; + +// use !externals +export const calcBundledPackages = (options: { + autoExternal: DtsGenOptions['autoExternal']; + cwd: string; + userExternals?: DtsGenOptions['userExternals']; +}): string[] => { + const { autoExternal, cwd, userExternals } = options; + + let pkgJson: { + dependencies?: Record; + peerDependencies?: Record; + devDependencies?: Record; + }; + + try { + const content = fs.readFileSync(join(cwd, 'package.json'), 'utf-8'); + pkgJson = JSON.parse(content); + } catch (err) { + logger.warn( + 'The type of third-party packages will not be bundled due to read package.json failed', + ); + return []; + } + + const externalOptions = autoExternal + ? { + dependencies: true, + peerDependencies: true, + devDependencies: false, + ...(autoExternal === true ? {} : autoExternal), + } + : { + dependencies: false, + peerDependencies: false, + devDependencies: false, + }; + + // User externals should not bundled + // Only handle the case where the externals type is string / (string | RegExp)[] / plain object, function type is too complex. + const getUserExternalsKeys = ( + value: typeof userExternals, + ): (string | RegExp)[] => { + if (!value) { + return []; + } + + if (typeof value === 'string' || value instanceof RegExp) { + return [value]; + } + + if (Array.isArray(value)) { + return value.flatMap((v) => getUserExternalsKeys(v)); + } + + if (isObject(userExternals)) { + return Object.keys(userExternals); + } + return []; + }; + + const externals: (string | RegExp)[] = getUserExternalsKeys(userExternals); + + const allDeps: string[] = []; + + for (const type of [ + 'dependencies', + 'peerDependencies', + 'devDependencies', + ] as const) { + const deps = pkgJson[type] && Object.keys(pkgJson[type]); + if (deps) { + if (externalOptions[type]) { + externals.push(...deps); + } + allDeps.push(...deps); + } + } + + const bundledPackages = allDeps.filter( + (d) => + !externals.some((e) => (typeof e === 'string' ? d === e : e.test(d))), + ); + + return Array.from(new Set(bundledPackages)); +}; + export async function generateDts(data: DtsGenOptions): Promise { const { bundle, @@ -16,6 +106,8 @@ export async function generateDts(data: DtsGenOptions): Promise { cwd, isWatch, dtsExtension = '.d.ts', + autoExternal = true, + userExternals, } = data; logger.start(`Generating DTS... ${color.gray(`(${name})`)}`); const configPath = ts.findConfigFile(cwd, ts.sys.fileExists, tsconfigPath); @@ -62,6 +154,11 @@ export async function generateDts(data: DtsGenOptions): Promise { entry, tsconfigPath, dtsExtension, + bundledPackages: calcBundledPackages({ + autoExternal, + cwd, + userExternals, + }), }); } }; diff --git a/packages/plugin-dts/src/index.ts b/packages/plugin-dts/src/index.ts index 648c506b..3269bb1d 100644 --- a/packages/plugin-dts/src/index.ts +++ b/packages/plugin-dts/src/index.ts @@ -1,12 +1,19 @@ import { fork } from 'node:child_process'; import { extname, join } from 'node:path'; -import { type RsbuildPlugin, logger } from '@rsbuild/core'; +import { type RsbuildConfig, type RsbuildPlugin, logger } from '@rsbuild/core'; export type PluginDtsOptions = { bundle?: boolean; distPath?: string; abortOnError?: boolean; dtsExtension?: string; + autoExternal?: + | boolean + | { + dependencies?: boolean; + devDependencies?: boolean; + peerDependencies?: boolean; + }; }; export type DtsGenOptions = PluginDtsOptions & { @@ -15,6 +22,7 @@ export type DtsGenOptions = PluginDtsOptions & { isWatch: boolean; entryPath?: string; tsconfigPath?: string; + userExternals?: NonNullable['externals']; }; interface TaskResult { @@ -27,7 +35,6 @@ export const PLUGIN_DTS_NAME = 'rsbuild:dts'; // use ts compiler API to generate bundleless dts // use ts compiler API and api-extractor to generate dts bundle // TODO: support incremental build, to build one or more projects and their dependencies -// TODO: support autoExtension for dts files // TODO: deal alias in dts export const pluginDts = (options: PluginDtsOptions): RsbuildPlugin => ({ name: PLUGIN_DTS_NAME, @@ -56,6 +63,7 @@ export const pluginDts = (options: PluginDtsOptions): RsbuildPlugin => ({ const dtsGenOptions: DtsGenOptions = { ...options, + userExternals: config.output.externals, // TODO: temporarily use main as dts entry, only accept single entry entryPath: config.source?.entry?.main as string, tsconfigPath: config.source.tsconfigPath, diff --git a/packages/plugin-dts/tests/external.test.ts b/packages/plugin-dts/tests/external.test.ts new file mode 100644 index 00000000..6578a3c3 --- /dev/null +++ b/packages/plugin-dts/tests/external.test.ts @@ -0,0 +1,108 @@ +import fs from 'node:fs'; +import { logger } from '@rsbuild/core'; +import { describe, expect, it, vi } from 'vitest'; +import { calcBundledPackages } from '../src/dts'; + +const commonPkgJson = { + dependencies: { + foo: '1.0.0', + }, + peerDependencies: { + baz: '1.0.0', + }, + devDependencies: { + baz: '1.0.0', + bar: '1.0.0', + }, +}; + +describe('should calcBundledPackages correctly', () => { + it('autoExternal is true', () => { + vi.spyOn(fs, 'readFileSync').mockImplementation(() => + JSON.stringify(commonPkgJson), + ); + + const result = calcBundledPackages({ + autoExternal: true, + cwd: 'pkg/to/root', + }); + + expect(result).toEqual(['bar']); + }); + + it('autoExternal is object', () => { + vi.spyOn(fs, 'readFileSync').mockImplementation(() => + JSON.stringify(commonPkgJson), + ); + const result = calcBundledPackages({ + autoExternal: { + dependencies: false, + peerDependencies: false, + devDependencies: true, + }, + cwd: 'pkg/to/root', + }); + + expect(result).toEqual(['foo']); + }); + + it('autoExternal is false', () => { + vi.spyOn(fs, 'readFileSync').mockImplementation(() => + JSON.stringify(commonPkgJson), + ); + const result = calcBundledPackages({ + autoExternal: false, + cwd: 'pkg/to/root', + }); + + expect(result).toEqual(['foo', 'baz', 'bar']); + }); + + it('autoExternal with user externals', () => { + vi.spyOn(fs, 'readFileSync').mockImplementation(() => + JSON.stringify({ + devDependencies: { + baz: '1.0.0', + bar: '1.0.0', + react: '1.0.0', + }, + }), + ); + + expect( + calcBundledPackages({ + autoExternal: true, + cwd: 'pkg/to/root', + userExternals: [/react/, 'baz'], + }), + ).toEqual(['bar']); + + expect( + calcBundledPackages({ + autoExternal: true, + cwd: 'pkg/to/root', + userExternals: 'baz', + }), + ).toEqual(['bar', 'react']); + + expect( + calcBundledPackages({ + autoExternal: true, + cwd: 'pkg/to/root', + userExternals: { + react: 'react', + }, + }), + ).toEqual(['baz', 'bar']); + }); + + it('read package.json failed', () => { + vi.spyOn(logger, 'warn').mockImplementation(() => {}); + const result = calcBundledPackages({ + autoExternal: true, + cwd: 'pkg/to/root', + }); + + expect(result).toEqual([]); + }); +}); diff --git a/packages/plugin-dts/vitest.config.ts b/packages/plugin-dts/vitest.config.ts new file mode 100644 index 00000000..56140a38 --- /dev/null +++ b/packages/plugin-dts/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'vitest/config'; +import { shared } from '../../vitest.workspace'; + +export default defineConfig({ + test: { + ...shared, + name: 'dts-unit', + }, +}); From c692412937ace6a02ea7b3b3bace8a68f0d803c7 Mon Sep 17 00:00:00 2001 From: "gaoyuan.1226" Date: Mon, 12 Aug 2024 11:10:51 +0800 Subject: [PATCH 2/5] test: add dts external test case --- e2e/cases/auto-external/default/package.json | 1 + .../auto-external/default/rslib.config.ts | 17 ++- e2e/cases/auto-external/default/src/index.ts | 7 ++ e2e/cases/auto-external/default/tsconfig.json | 8 ++ e2e/cases/auto-external/false/package.json | 1 + e2e/cases/auto-external/false/rslib.config.ts | 8 +- e2e/cases/auto-external/false/src/index.ts | 7 ++ e2e/cases/auto-external/false/tsconfig.json | 8 ++ e2e/cases/auto-external/index.test.ts | 23 ++-- e2e/scripts/shared.ts | 49 +++++++- pnpm-lock.yaml | 113 ++++++++++++++++++ 11 files changed, 227 insertions(+), 15 deletions(-) create mode 100644 e2e/cases/auto-external/default/src/index.ts create mode 100644 e2e/cases/auto-external/default/tsconfig.json create mode 100644 e2e/cases/auto-external/false/src/index.ts create mode 100644 e2e/cases/auto-external/false/tsconfig.json diff --git a/e2e/cases/auto-external/default/package.json b/e2e/cases/auto-external/default/package.json index 604cb35a..e9904419 100644 --- a/e2e/cases/auto-external/default/package.json +++ b/e2e/cases/auto-external/default/package.json @@ -1,6 +1,7 @@ { "name": "auto-external-default-test", "dependencies": { + "ora": "8.0.1", "react": "^18.3.1" } } diff --git a/e2e/cases/auto-external/default/rslib.config.ts b/e2e/cases/auto-external/default/rslib.config.ts index 549d8c88..f33fff2f 100644 --- a/e2e/cases/auto-external/default/rslib.config.ts +++ b/e2e/cases/auto-external/default/rslib.config.ts @@ -2,10 +2,23 @@ import { generateBundleCjsConfig, generateBundleEsmConfig } from '@e2e/helper'; import { defineConfig } from '@rslib/core'; export default defineConfig({ - lib: [generateBundleEsmConfig(__dirname), generateBundleCjsConfig(__dirname)], + lib: [ + { + ...generateBundleEsmConfig(__dirname), + dts: { + bundle: true, + }, + }, + { + ...generateBundleCjsConfig(__dirname), + dts: { + bundle: true, + }, + }, + ], source: { entry: { - main: '../__fixtures__/src/index.ts', + main: './src/index.ts', }, }, }); diff --git a/e2e/cases/auto-external/default/src/index.ts b/e2e/cases/auto-external/default/src/index.ts new file mode 100644 index 00000000..63ab5393 --- /dev/null +++ b/e2e/cases/auto-external/default/src/index.ts @@ -0,0 +1,7 @@ +import type { oraPromise } from 'ora'; +import React from 'react'; + +export type { oraPromise }; +export const foo = () => { + return React.version; +}; diff --git a/e2e/cases/auto-external/default/tsconfig.json b/e2e/cases/auto-external/default/tsconfig.json new file mode 100644 index 00000000..4eb494f9 --- /dev/null +++ b/e2e/cases/auto-external/default/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true + }, + "include": ["src/**/*"] +} diff --git a/e2e/cases/auto-external/false/package.json b/e2e/cases/auto-external/false/package.json index ac906f30..ea09403e 100644 --- a/e2e/cases/auto-external/false/package.json +++ b/e2e/cases/auto-external/false/package.json @@ -1,6 +1,7 @@ { "name": "auto-external-false-test", "dependencies": { + "ora": "8.0.1", "react": "^18.3.1" } } diff --git a/e2e/cases/auto-external/false/rslib.config.ts b/e2e/cases/auto-external/false/rslib.config.ts index 05923f5e..0b48f88b 100644 --- a/e2e/cases/auto-external/false/rslib.config.ts +++ b/e2e/cases/auto-external/false/rslib.config.ts @@ -6,15 +6,21 @@ export default defineConfig({ { ...generateBundleEsmConfig(__dirname), autoExternal: false, + dts: { + bundle: true, + }, }, { ...generateBundleCjsConfig(__dirname), autoExternal: false, + dts: { + bundle: true, + }, }, ], source: { entry: { - main: '../__fixtures__/src/index.ts', + main: './src/index.ts', }, }, }); diff --git a/e2e/cases/auto-external/false/src/index.ts b/e2e/cases/auto-external/false/src/index.ts new file mode 100644 index 00000000..63ab5393 --- /dev/null +++ b/e2e/cases/auto-external/false/src/index.ts @@ -0,0 +1,7 @@ +import type { oraPromise } from 'ora'; +import React from 'react'; + +export type { oraPromise }; +export const foo = () => { + return React.version; +}; diff --git a/e2e/cases/auto-external/false/tsconfig.json b/e2e/cases/auto-external/false/tsconfig.json new file mode 100644 index 00000000..4eb494f9 --- /dev/null +++ b/e2e/cases/auto-external/false/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true + }, + "include": ["src/**/*"] +} diff --git a/e2e/cases/auto-external/index.test.ts b/e2e/cases/auto-external/index.test.ts index c47715f0..2c37b76c 100644 --- a/e2e/cases/auto-external/index.test.ts +++ b/e2e/cases/auto-external/index.test.ts @@ -1,18 +1,22 @@ import { join } from 'node:path'; -import { buildAndGetResults } from '@e2e/helper'; +import { buildAndGetAllResults, buildAndGetResults } from '@e2e/helper'; import { expect, test } from 'vitest'; test('auto external default should works', async () => { const fixturePath = join(__dirname, 'default'); - const { entries } = await buildAndGetResults(fixturePath); + const { js, dts } = await buildAndGetAllResults(fixturePath); - expect(entries.esm).toContain( + expect(js.entries.esm).toContain( 'import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react"', ); - expect(entries.cjs).toContain( + expect(js!.entries.cjs).toContain( 'var external_react_namespaceObject = require("react");', ); + + // dts should externalized + expect(dts.entries.esm).toContain("import type { oraPromise } from 'ora';"); + expect(dts.entries.cjs).toContain("import type { oraPromise } from 'ora';"); }); test('auto external sub path should works', async () => { @@ -36,15 +40,20 @@ test('auto external sub path should works', async () => { test('auto external false should works', async () => { const fixturePath = join(__dirname, 'false'); - const { entries } = await buildAndGetResults(fixturePath); + const { js, dts } = await buildAndGetAllResults(fixturePath); - expect(entries.esm).not.toContain( + expect(js.entries.esm).not.toContain( 'import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react"', ); - expect(entries.cjs).not.toContain( + expect(js.entries.cjs).not.toContain( 'var external_react_namespaceObject = require("react");', ); + + // dts should bundled + expect(dts.entries.esm).toContain('export declare function oraPromise'); + + expect(dts.entries.cjs).toContain('export declare function oraPromise'); }); test('externals should overrides auto external', async () => { diff --git a/e2e/scripts/shared.ts b/e2e/scripts/shared.ts index f67d48fb..2bf3944a 100644 --- a/e2e/scripts/shared.ts +++ b/e2e/scripts/shared.ts @@ -102,10 +102,7 @@ export async function getResults( }; } -export const buildAndGetResults = async ( - fixturePath: string, - type: 'js' | 'dts' = 'js', -): Promise<{ +type BuildResult = { contents: Record>; files: Record; entries: Record; @@ -113,7 +110,12 @@ export const buildAndGetResults = async ( rspackConfig: InspectConfigResult['origin']['bundlerConfigs']; rsbuildConfig: InspectConfigResult['origin']['rsbuildConfig']; isSuccess: boolean; -}> => { +}; + +export const buildAndGetResults = async ( + fixturePath: string, + type: 'js' | 'dts' = 'js', +): Promise => { const rslibConfig = await loadConfig(join(fixturePath, 'rslib.config.ts')); process.chdir(fixturePath); const rsbuildInstance = await build(rslibConfig); @@ -132,3 +134,40 @@ export const buildAndGetResults = async ( isSuccess: Boolean(rsbuildInstance), }; }; + +export const buildAndGetAllResults = async ( + fixturePath: string, +): Promise<{ + js: BuildResult; + dts: BuildResult; +}> => { + const rslibConfig = await loadConfig(join(fixturePath, 'rslib.config.ts')); + process.chdir(fixturePath); + const rsbuildInstance = await build(rslibConfig); + const { + origin: { bundlerConfigs, rsbuildConfig }, + } = await rsbuildInstance.inspectConfig({ verbose: true }); + + const jsResults = await getResults(rslibConfig, fixturePath, 'js'); + const dtsResults = await getResults(rslibConfig, fixturePath, 'dts'); + return { + js: { + contents: jsResults.contents, + files: jsResults.files, + entries: jsResults.entries, + entryFiles: jsResults.entryFiles, + rspackConfig: bundlerConfigs, + rsbuildConfig: rsbuildConfig, + isSuccess: Boolean(rsbuildInstance), + }, + dts: { + contents: dtsResults.contents, + files: dtsResults.files, + entries: dtsResults.entries, + entryFiles: dtsResults.entryFiles, + rspackConfig: bundlerConfigs, + rsbuildConfig: rsbuildConfig, + isSuccess: Boolean(rsbuildInstance), + }, + }; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 432e421c..222eb019 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -104,6 +104,9 @@ importers: e2e/cases/auto-external/default: dependencies: + ora: + specifier: 8.0.1 + version: 8.0.1 react: specifier: ^18.3.1 version: 18.3.1 @@ -116,6 +119,9 @@ importers: e2e/cases/auto-external/false: dependencies: + ora: + specifier: 8.0.1 + version: 8.0.1 react: specifier: ^18.3.1 version: 18.3.1 @@ -1534,6 +1540,10 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -1668,10 +1678,18 @@ packages: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} + cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cli-spinners@2.6.1: resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} engines: {node: '>=6'} + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1846,6 +1864,9 @@ packages: electron-to-chromium@1.4.827: resolution: {integrity: sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==} + emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2041,6 +2062,10 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} @@ -2191,6 +2216,10 @@ packages: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -2219,6 +2248,14 @@ packages: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + + is-unicode-supported@2.0.0: + resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==} + engines: {node: '>=18'} + is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -2320,6 +2357,10 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -2491,6 +2532,10 @@ packages: resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} engines: {node: '>=10'} + ora@8.0.1: + resolution: {integrity: sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==} + engines: {node: '>=18'} + os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} @@ -2736,6 +2781,10 @@ packages: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} + restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -2891,6 +2940,10 @@ packages: std-env@3.7.0: resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -2902,6 +2955,10 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -2909,6 +2966,10 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -4502,6 +4563,8 @@ snapshots: ansi-regex@5.0.1: {} + ansi-regex@6.0.1: {} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 @@ -4655,8 +4718,14 @@ snapshots: dependencies: restore-cursor: 3.1.0 + cli-cursor@4.0.0: + dependencies: + restore-cursor: 4.0.0 + cli-spinners@2.6.1: {} + cli-spinners@2.9.2: {} + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -4791,6 +4860,8 @@ snapshots: electron-to-chromium@1.4.827: {} + emoji-regex@10.3.0: {} + emoji-regex@8.0.0: {} encodeurl@1.0.2: {} @@ -5078,6 +5149,8 @@ snapshots: get-caller-file@2.0.5: {} + get-east-asian-width@1.2.0: {} + get-func-name@2.0.2: {} get-intrinsic@1.2.4: @@ -5207,6 +5280,8 @@ snapshots: is-interactive@1.0.0: {} + is-interactive@2.0.0: {} + is-number@7.0.0: {} is-plain-obj@4.1.0: {} @@ -5225,6 +5300,10 @@ snapshots: is-unicode-supported@0.1.0: {} + is-unicode-supported@1.3.0: {} + + is-unicode-supported@2.0.0: {} + is-windows@1.0.2: {} is-wsl@2.2.0: @@ -5311,6 +5390,11 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 + log-symbols@6.0.0: + dependencies: + chalk: 5.3.0 + is-unicode-supported: 1.3.0 + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -5509,6 +5593,18 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 + ora@8.0.1: + dependencies: + chalk: 5.3.0 + cli-cursor: 4.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.0.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 + strip-ansi: 7.1.0 + os-tmpdir@1.0.2: {} outdent@0.5.0: {} @@ -5725,6 +5821,11 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 + restore-cursor@4.0.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + reusify@1.0.4: {} rollup-plugin-dts@6.1.1(rollup@4.18.1)(typescript@5.5.3): @@ -5898,6 +5999,8 @@ snapshots: std-env@3.7.0: {} + stdin-discarder@0.2.2: {} + string-argv@0.3.2: {} string-hash@1.1.3: {} @@ -5908,6 +6011,12 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@7.2.0: + dependencies: + emoji-regex: 10.3.0 + get-east-asian-width: 1.2.0 + strip-ansi: 7.1.0 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -5916,6 +6025,10 @@ snapshots: dependencies: ansi-regex: 5.0.1 + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.0.1 + strip-bom@3.0.0: {} strip-final-newline@3.0.0: {} From b28cb7e8ab7d23223a85bd6cc5040a9d6b99805b Mon Sep 17 00:00:00 2001 From: "gaoyuan.1226" Date: Mon, 12 Aug 2024 11:32:07 +0800 Subject: [PATCH 3/5] fix: update --- packages/plugin-dts/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/plugin-dts/src/index.ts b/packages/plugin-dts/src/index.ts index 64f256a0..b47fa2ce 100644 --- a/packages/plugin-dts/src/index.ts +++ b/packages/plugin-dts/src/index.ts @@ -41,6 +41,7 @@ export const PLUGIN_DTS_NAME = 'rsbuild:dts'; // use ts compiler API to generate bundleless dts // use ts compiler API and api-extractor to generate dts bundle // TODO: support incremental build, to build one or more projects and their dependencies +// TODO: support autoExtension for dts files // TODO: deal alias in dts export const pluginDts = (options: PluginDtsOptions): RsbuildPlugin => ({ name: PLUGIN_DTS_NAME, From 43dcbe2a19a10fbd6d9a4a4b254b5f0cf7f77fcb Mon Sep 17 00:00:00 2001 From: "gaoyuan.1226" Date: Mon, 12 Aug 2024 14:21:07 +0800 Subject: [PATCH 4/5] fix: ut script --- package.json | 4 ++-- packages/plugin-dts/vitest.config.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 7cf5eb35..062902ed 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ "test:artifact": "vitest run --project artifact", "test:artifact:watch": "vitest --project artifact", "test:e2e": "cd e2e && pnpm run test", - "test:unit": "vitest run --project unit", - "test:unit:watch": "vitest --project unit", + "test:unit": "vitest run --project unit*", + "test:unit:watch": "vitest --project unit*", "watch": "pnpm build --watch" }, "simple-git-hooks": { diff --git a/packages/plugin-dts/vitest.config.ts b/packages/plugin-dts/vitest.config.ts index 56140a38..e517c716 100644 --- a/packages/plugin-dts/vitest.config.ts +++ b/packages/plugin-dts/vitest.config.ts @@ -4,6 +4,6 @@ import { shared } from '../../vitest.workspace'; export default defineConfig({ test: { ...shared, - name: 'dts-unit', + name: 'unit-dts', }, }); From f494c8290da80b073b70a4b789215ad465840bd1 Mon Sep 17 00:00:00 2001 From: "gaoyuan.1226" Date: Mon, 12 Aug 2024 16:07:23 +0800 Subject: [PATCH 5/5] fix: ut --- .../auto-external/default/rslib.config.ts | 10 +-- e2e/cases/auto-external/false/rslib.config.ts | 10 +-- e2e/cases/auto-external/index.test.ts | 6 +- e2e/scripts/shared.ts | 80 +++++++++---------- 4 files changed, 50 insertions(+), 56 deletions(-) diff --git a/e2e/cases/auto-external/default/rslib.config.ts b/e2e/cases/auto-external/default/rslib.config.ts index f33fff2f..455ac503 100644 --- a/e2e/cases/auto-external/default/rslib.config.ts +++ b/e2e/cases/auto-external/default/rslib.config.ts @@ -3,18 +3,16 @@ import { defineConfig } from '@rslib/core'; export default defineConfig({ lib: [ - { - ...generateBundleEsmConfig(__dirname), + generateBundleEsmConfig(__dirname, { dts: { bundle: true, }, - }, - { - ...generateBundleCjsConfig(__dirname), + }), + generateBundleCjsConfig(__dirname, { dts: { bundle: true, }, - }, + }), ], source: { entry: { diff --git a/e2e/cases/auto-external/false/rslib.config.ts b/e2e/cases/auto-external/false/rslib.config.ts index 0b48f88b..79f695b9 100644 --- a/e2e/cases/auto-external/false/rslib.config.ts +++ b/e2e/cases/auto-external/false/rslib.config.ts @@ -3,20 +3,18 @@ import { defineConfig } from '@rslib/core'; export default defineConfig({ lib: [ - { - ...generateBundleEsmConfig(__dirname), + generateBundleEsmConfig(__dirname, { autoExternal: false, dts: { bundle: true, }, - }, - { - ...generateBundleCjsConfig(__dirname), + }), + generateBundleCjsConfig(__dirname, { autoExternal: false, dts: { bundle: true, }, - }, + }), ], source: { entry: { diff --git a/e2e/cases/auto-external/index.test.ts b/e2e/cases/auto-external/index.test.ts index 2c37b76c..88c739dc 100644 --- a/e2e/cases/auto-external/index.test.ts +++ b/e2e/cases/auto-external/index.test.ts @@ -1,10 +1,10 @@ import { join } from 'node:path'; -import { buildAndGetAllResults, buildAndGetResults } from '@e2e/helper'; +import { buildAndGetResults } from '@e2e/helper'; import { expect, test } from 'vitest'; test('auto external default should works', async () => { const fixturePath = join(__dirname, 'default'); - const { js, dts } = await buildAndGetAllResults(fixturePath); + const { js, dts } = await buildAndGetResults(fixturePath, 'all'); expect(js.entries.esm).toContain( 'import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react"', @@ -40,7 +40,7 @@ test('auto external sub path should works', async () => { test('auto external false should works', async () => { const fixturePath = join(__dirname, 'false'); - const { js, dts } = await buildAndGetAllResults(fixturePath); + const { js, dts } = await buildAndGetResults(fixturePath, 'all'); expect(js.entries.esm).not.toContain( 'import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react"', diff --git a/e2e/scripts/shared.ts b/e2e/scripts/shared.ts index 2bf3944a..c0a53503 100644 --- a/e2e/scripts/shared.ts +++ b/e2e/scripts/shared.ts @@ -112,16 +112,51 @@ type BuildResult = { isSuccess: boolean; }; -export const buildAndGetResults = async ( +export async function buildAndGetResults( fixturePath: string, - type: 'js' | 'dts' = 'js', -): Promise => { + type: 'all', +): Promise<{ + js: BuildResult; + dts: BuildResult; +}>; +export async function buildAndGetResults( + fixturePath: string, + type?: 'js' | 'dts', +): Promise; +export async function buildAndGetResults( + fixturePath: string, + type: 'js' | 'dts' | 'all' = 'js', +) { const rslibConfig = await loadConfig(join(fixturePath, 'rslib.config.ts')); process.chdir(fixturePath); const rsbuildInstance = await build(rslibConfig); const { origin: { bundlerConfigs, rsbuildConfig }, } = await rsbuildInstance.inspectConfig({ verbose: true }); + if (type === 'all') { + const jsResults = await getResults(rslibConfig, fixturePath, 'js'); + const dtsResults = await getResults(rslibConfig, fixturePath, 'dts'); + return { + js: { + contents: jsResults.contents, + files: jsResults.files, + entries: jsResults.entries, + entryFiles: jsResults.entryFiles, + rspackConfig: bundlerConfigs, + rsbuildConfig: rsbuildConfig, + isSuccess: Boolean(rsbuildInstance), + }, + dts: { + contents: dtsResults.contents, + files: dtsResults.files, + entries: dtsResults.entries, + entryFiles: dtsResults.entryFiles, + rspackConfig: bundlerConfigs, + rsbuildConfig: rsbuildConfig, + isSuccess: Boolean(rsbuildInstance), + }, + }; + } const results = await getResults(rslibConfig, fixturePath, type); return { @@ -133,41 +168,4 @@ export const buildAndGetResults = async ( rsbuildConfig: rsbuildConfig, isSuccess: Boolean(rsbuildInstance), }; -}; - -export const buildAndGetAllResults = async ( - fixturePath: string, -): Promise<{ - js: BuildResult; - dts: BuildResult; -}> => { - const rslibConfig = await loadConfig(join(fixturePath, 'rslib.config.ts')); - process.chdir(fixturePath); - const rsbuildInstance = await build(rslibConfig); - const { - origin: { bundlerConfigs, rsbuildConfig }, - } = await rsbuildInstance.inspectConfig({ verbose: true }); - - const jsResults = await getResults(rslibConfig, fixturePath, 'js'); - const dtsResults = await getResults(rslibConfig, fixturePath, 'dts'); - return { - js: { - contents: jsResults.contents, - files: jsResults.files, - entries: jsResults.entries, - entryFiles: jsResults.entryFiles, - rspackConfig: bundlerConfigs, - rsbuildConfig: rsbuildConfig, - isSuccess: Boolean(rsbuildInstance), - }, - dts: { - contents: dtsResults.contents, - files: dtsResults.files, - entries: dtsResults.entries, - entryFiles: dtsResults.entryFiles, - rspackConfig: bundlerConfigs, - rsbuildConfig: rsbuildConfig, - isSuccess: Boolean(rsbuildInstance), - }, - }; -}; +}