From 75e057ae7105c58bd9d1e162f367a1c95b2edf68 Mon Sep 17 00:00:00 2001 From: XGHeaven Date: Tue, 21 Apr 2026 20:47:24 +0800 Subject: [PATCH] feat: update v2 docs and support declaration.allowJs --- .changeset/migrate-generate-types-for-js.md | 5 + packages/pkg/src/config/schema.ts | 2 +- packages/pkg/src/config/userConfig.ts | 4 - packages/pkg/src/core/init.ts | 2 + packages/pkg/src/helpers/dts.ts | 4 +- packages/pkg/src/tasks/declaration.ts | 6 +- packages/pkg/src/types.ts | 13 +- pnpm-lock.yaml | 49 +- website/docs/ai.md | 13 + website/docs/cli.md | 31 + website/docs/config/alias.md | 20 + website/docs/config/bundle.md | 239 ++++++ website/docs/config/declaration.md | 75 ++ website/docs/config/define.md | 45 ++ website/docs/config/entry.md | 32 + website/docs/config/helpers.md | 34 + website/docs/config/index.md | 38 + website/docs/config/jsx-runtime.md | 36 + website/docs/config/pkgs.md | 125 +++ website/docs/config/plugins.md | 21 + website/docs/config/server.md | 144 ++++ website/docs/config/source-maps.md | 24 + website/docs/config/transform.md | 115 +++ website/docs/guide/build-modes.md | 211 ++++++ website/docs/guide/build.md | 288 +++++-- website/docs/guide/configure.md | 58 ++ website/docs/guide/css.md | 93 +++ website/docs/guide/engine.md | 96 +++ website/docs/guide/jsx-plus.md | 30 +- website/docs/guide/mf.md | 2 +- website/docs/guide/monorepo.md | 163 +--- website/docs/guide/preview.md | 74 +- website/docs/guide/scenario/library.md | 56 ++ website/docs/guide/scenario/node.md | 40 + website/docs/guide/scenario/react.md | 159 ++++ website/docs/guide/server.md | 15 + website/docs/guide/test.md | 199 +---- website/docs/guide/typescript.md | 121 +++ website/docs/index.md | 51 +- website/docs/migration/v1-to-v2.md | 145 ++++ website/docs/plugin/development.md | 629 +++++++++++++++ website/docs/plugin/usage.md | 84 +++ website/docs/quick-start.md | 30 +- website/docs/reference/cli.md | 29 - website/docusaurus.config.ts | 61 +- website/package.json | 1 + website/sidebars.js | 75 +- website/versioned_docs/version-v1/faq.md | 36 + .../version-v1}/guide/Button.tsx | 0 .../version-v1}/guide/abilities.md | 9 +- .../versioned_docs/version-v1/guide/build.md | 192 +++++ .../version-v1/guide/jsx-plus.md | 171 +++++ .../version-v1/guide/monorepo.md | 229 ++++++ .../version-v1/guide/preview.md | 713 ++++++++++++++++++ .../version-v1}/guide/publish.md | 11 +- .../version-v1}/guide/scenarios.md | 47 +- .../versioned_docs/version-v1/guide/test.md | 257 +++++++ website/versioned_docs/version-v1/index.md | 52 ++ .../versioned_docs/version-v1/quick-start.md | 74 ++ .../version-v1/reference/cli.md | 29 + .../version-v1}/reference/config.md | 76 +- .../reference/plugins-development.md | 20 +- .../version-v1-sidebars.json | 24 + website/versions.json | 1 + 64 files changed, 5072 insertions(+), 656 deletions(-) create mode 100644 .changeset/migrate-generate-types-for-js.md create mode 100644 website/docs/ai.md create mode 100644 website/docs/cli.md create mode 100644 website/docs/config/alias.md create mode 100644 website/docs/config/bundle.md create mode 100644 website/docs/config/declaration.md create mode 100644 website/docs/config/define.md create mode 100644 website/docs/config/entry.md create mode 100644 website/docs/config/helpers.md create mode 100644 website/docs/config/index.md create mode 100644 website/docs/config/jsx-runtime.md create mode 100644 website/docs/config/pkgs.md create mode 100644 website/docs/config/plugins.md create mode 100644 website/docs/config/server.md create mode 100644 website/docs/config/source-maps.md create mode 100644 website/docs/config/transform.md create mode 100644 website/docs/guide/build-modes.md create mode 100644 website/docs/guide/configure.md create mode 100644 website/docs/guide/css.md create mode 100644 website/docs/guide/engine.md create mode 100644 website/docs/guide/scenario/library.md create mode 100644 website/docs/guide/scenario/node.md create mode 100644 website/docs/guide/scenario/react.md create mode 100644 website/docs/guide/server.md create mode 100644 website/docs/guide/typescript.md create mode 100644 website/docs/migration/v1-to-v2.md create mode 100644 website/docs/plugin/development.md create mode 100644 website/docs/plugin/usage.md delete mode 100644 website/docs/reference/cli.md create mode 100644 website/versioned_docs/version-v1/faq.md rename website/{docs => versioned_docs/version-v1}/guide/Button.tsx (100%) rename website/{docs => versioned_docs/version-v1}/guide/abilities.md (93%) create mode 100644 website/versioned_docs/version-v1/guide/build.md create mode 100644 website/versioned_docs/version-v1/guide/jsx-plus.md create mode 100644 website/versioned_docs/version-v1/guide/monorepo.md create mode 100644 website/versioned_docs/version-v1/guide/preview.md rename website/{docs => versioned_docs/version-v1}/guide/publish.md (96%) rename website/{docs => versioned_docs/version-v1}/guide/scenarios.md (87%) create mode 100644 website/versioned_docs/version-v1/guide/test.md create mode 100644 website/versioned_docs/version-v1/index.md create mode 100644 website/versioned_docs/version-v1/quick-start.md create mode 100644 website/versioned_docs/version-v1/reference/cli.md rename website/{docs => versioned_docs/version-v1}/reference/config.md (84%) rename website/{docs => versioned_docs/version-v1}/reference/plugins-development.md (87%) create mode 100644 website/versioned_sidebars/version-v1-sidebars.json create mode 100644 website/versions.json diff --git a/.changeset/migrate-generate-types-for-js.md b/.changeset/migrate-generate-types-for-js.md new file mode 100644 index 00000000..3ee2f38d --- /dev/null +++ b/.changeset/migrate-generate-types-for-js.md @@ -0,0 +1,5 @@ +--- +'@ice/pkg': major +--- + +feat: migrate `generateTypesForJs` to `declaration.allowJs` diff --git a/packages/pkg/src/config/schema.ts b/packages/pkg/src/config/schema.ts index e78ae393..7d1481e5 100644 --- a/packages/pkg/src/config/schema.ts +++ b/packages/pkg/src/config/schema.ts @@ -59,7 +59,6 @@ export const userConfigSchema = z.object({ .record(z.string(), z.union([z.string(), z.boolean(), z.number(), z.null(), z.record(z.string(), z.any())])) .optional(), sourceMaps: z.union([z.boolean(), z.enum(['inline'])]).optional(), - generateTypeForJs: z.boolean().optional(), jsxRuntime: z.enum(['classic', 'automatic']).optional(), plugins: z.any().array().optional(), helpers: z.enum(['external', 'inline']).optional(), @@ -71,6 +70,7 @@ export const userConfigSchema = z.object({ z.object({ outputMode: z.enum(['multi', 'unique']).optional(), generator: z.enum(['tsc', 'oxc']).optional(), + allowJs: z.boolean().optional(), }), ]), server: z.union([z.boolean(), serverSchema]).optional(), diff --git a/packages/pkg/src/config/userConfig.ts b/packages/pkg/src/config/userConfig.ts index 1c5665d1..b05800cf 100644 --- a/packages/pkg/src/config/userConfig.ts +++ b/packages/pkg/src/config/userConfig.ts @@ -24,10 +24,6 @@ function getUserConfig() { name: 'jsxRuntime', defaultValue: 'automatic', }, - { - name: 'generateTypesForJs', - defaultValue: false, - }, { name: 'declaration', defaultValue: true, diff --git a/packages/pkg/src/core/init.ts b/packages/pkg/src/core/init.ts index 7d114762..21600c80 100644 --- a/packages/pkg/src/core/init.ts +++ b/packages/pkg/src/core/init.ts @@ -28,6 +28,7 @@ const defaultBundleUserConfig: BundleUserConfig = { const defaultDeclarationUserConfig = { outputMode: 'multi', generator: 'tsc', + allowJs: false, } satisfies DeclarationUserConfig; export function initContextTasks(ctx: Context) { @@ -159,6 +160,7 @@ export function initDeclarationTask(buildTask: BuildTask, options: InitTaskOptio } else { config.outputMode ??= declarationConfig?.outputMode ?? defaultDeclarationUserConfig.outputMode; config.generator ??= declarationConfig?.generator ?? defaultDeclarationUserConfig.generator; + config.allowJs ??= declarationConfig?.allowJs ?? defaultDeclarationUserConfig.allowJs; } const allOutputDirs = allTasks diff --git a/packages/pkg/src/helpers/dts.ts b/packages/pkg/src/helpers/dts.ts index 2fd2bc7e..ef61923d 100644 --- a/packages/pkg/src/helpers/dts.ts +++ b/packages/pkg/src/helpers/dts.ts @@ -47,6 +47,7 @@ export interface DtsCompileOptions { rootDir: string; outputDir: string; usingOxc: boolean; + allowJs?: boolean; } function formatAliasToTSPathsConfig(alias: TaskConfig['alias']) { @@ -79,6 +80,7 @@ export async function dtsCompile({ outputDir, alias, usingOxc, + allowJs = false, }: DtsCompileOptions): Promise { if (!files.length) { return []; @@ -88,7 +90,7 @@ export async function dtsCompile({ const defaultTSConfig: TsConfigJson = { compilerOptions: { - allowJs: true, + allowJs, declaration: true, emitDeclarationOnly: true, incremental: true, diff --git a/packages/pkg/src/tasks/declaration.ts b/packages/pkg/src/tasks/declaration.ts index 80a3331f..a69d0359 100644 --- a/packages/pkg/src/tasks/declaration.ts +++ b/packages/pkg/src/tasks/declaration.ts @@ -33,9 +33,12 @@ class DeclarationRunner extends Runner { context.buildContext.rootDir, (context.buildTask.config.entry! as Record) ?? {}, ); + const filePattern = (context.buildTask.config as DeclarationTaskConfig).allowJs + ? '**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}' + : '**/*.{ts,tsx,mts,cts}'; const result = await Promise.all( entryDirs.map((entry) => - globby('**/*.{ts,tsx,mts,cts}', { + globby(filePattern, { cwd: entry, onlyFiles: true, ignore: ['**/*.d.{ts,mts,cts}'], @@ -64,6 +67,7 @@ class DeclarationRunner extends Runner { outputDir: buildConfig.outputDir!, alias: buildConfig.alias, usingOxc: buildConfig.generator === 'oxc', + allowJs: buildConfig.allowJs ?? false, }, ]); diff --git a/packages/pkg/src/types.ts b/packages/pkg/src/types.ts index 486e050c..84a8bc22 100644 --- a/packages/pkg/src/types.ts +++ b/packages/pkg/src/types.ts @@ -176,6 +176,13 @@ export interface DeclarationUserConfig { * @default 'tsc' */ generator?: 'tsc' | 'oxc'; + + /** + * Whether to generate declaration files for JavaScript files. + * Useful when using JSDoc type annotations in JS files. + * @default false + */ + allowJs?: boolean; } export interface PkgUserConfig @@ -278,12 +285,6 @@ export interface UserConfig { * but not include it in the result object. */ sourceMaps?: boolean | 'inline'; - /** - * Whether or not to generate declaration files for Ecmascript - * @default false - */ - generateTypesForJs?: boolean; - /** * Generate .d.ts files from TypeScript files in your project. * @default true diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8ea72d1f..e25b15cb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,7 +46,7 @@ importers: version: 20.19.25 '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.0.8(vitest@4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1)) + version: 4.0.8(vitest@4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3)) axios: specifier: ^0.23.0 version: 0.23.0 @@ -85,7 +85,7 @@ importers: version: 5.9.2 vitest: specifier: 'catalog:' - version: 4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1) + version: 4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3) examples/application: dependencies: @@ -192,7 +192,7 @@ importers: version: 29.0.5(@babel/core@7.28.5)(@jest/types@29.4.3)(babel-jest@29.4.3(@babel/core@7.28.5))(jest@29.4.3(@types/node@20.19.25)(ts-node@10.8.2(@swc/core@1.15.7(@swc/helpers@0.5.17))(@types/node@20.19.25)(typescript@5.9.2)))(typescript@5.9.2) vitest: specifier: 'catalog:' - version: 4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1) + version: 4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3) examples/react-multi-components: dependencies: @@ -358,7 +358,7 @@ importers: version: 5.9.2 vitest: specifier: 'catalog:' - version: 4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1) + version: 4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3) packages/pkg: dependencies: @@ -748,6 +748,9 @@ importers: '@types/react': specifier: ^18.0.0 version: 18.0.15 + docusaurus-plugin-llms: + specifier: ^0.3.1 + version: 0.3.1(@docusaurus/core@3.9.2(@mdx-js/react@3.1.1(@types/react@18.0.15)(react@18.2.0))(@rspack/core@1.3.12(@swc/helpers@0.5.17))(@swc/core@1.15.7(@swc/helpers@0.5.17))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.2)) typescript: specifier: 'catalog:' version: 5.9.2 @@ -5377,6 +5380,12 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} + docusaurus-plugin-llms@0.3.1: + resolution: {integrity: sha512-2RsDC4czy1pt2kauIACOcLvSaGmjF3X0pgcVtL6fblzzZMgkasQJrOLN0pRur11j7rQkiaiCGR9NsU3mp4M8fg==} + engines: {node: '>=18.0'} + peerDependencies: + '@docusaurus/core': ^3.0.0 + dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} @@ -10916,6 +10925,11 @@ packages: engines: {node: '>= 14'} hasBin: true + yaml@2.8.3: + resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + engines: {node: '>= 14.6'} + hasBin: true + yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} @@ -15266,7 +15280,7 @@ snapshots: '@vercel/oidc@3.0.3': {} - '@vitest/coverage-v8@4.0.8(vitest@4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1))': + '@vitest/coverage-v8@4.0.8(vitest@4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3))': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.0.8 @@ -15279,7 +15293,7 @@ snapshots: magicast: 0.5.1 std-env: 3.10.0 tinyrainbow: 3.0.3 - vitest: 4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1) + vitest: 4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3) transitivePeerDependencies: - supports-color @@ -15292,13 +15306,13 @@ snapshots: chai: 6.2.1 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.8(vite@7.2.2(@types/node@20.19.25)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1))': + '@vitest/mocker@4.0.8(vite@7.2.2(@types/node@20.19.25)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.0.8 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.2.2(@types/node@20.19.25)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1) + vite: 7.2.2(@types/node@20.19.25)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3) '@vitest/pretty-format@4.0.8': dependencies: @@ -16803,6 +16817,13 @@ snapshots: dependencies: esutils: 2.0.3 + docusaurus-plugin-llms@0.3.1(@docusaurus/core@3.9.2(@mdx-js/react@3.1.1(@types/react@18.0.15)(react@18.2.0))(@rspack/core@1.3.12(@swc/helpers@0.5.17))(@swc/core@1.15.7(@swc/helpers@0.5.17))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.2)): + dependencies: + '@docusaurus/core': 3.9.2(@mdx-js/react@3.1.1(@types/react@18.0.15)(react@18.2.0))(@rspack/core@1.3.12(@swc/helpers@0.5.17))(@swc/core@1.15.7(@swc/helpers@0.5.17))(debug@4.4.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.9.2) + gray-matter: 4.0.3 + minimatch: 9.0.5 + yaml: 2.8.3 + dom-accessibility-api@0.5.16: {} dom-converter@0.2.0: @@ -23107,7 +23128,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite@7.2.2(@types/node@20.19.25)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1): + vite@7.2.2(@types/node@20.19.25)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) @@ -23123,12 +23144,12 @@ snapshots: sass: 1.94.0 sass-embedded: 1.89.2 terser: 5.44.1 - yaml: 2.7.1 + yaml: 2.8.3 - vitest@4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1): + vitest@4.0.8(@types/debug@4.1.12)(@types/node@20.19.25)(jiti@2.4.2)(jsdom@21.1.0)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3): dependencies: '@vitest/expect': 4.0.8 - '@vitest/mocker': 4.0.8(vite@7.2.2(@types/node@20.19.25)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1)) + '@vitest/mocker': 4.0.8(vite@7.2.2(@types/node@20.19.25)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3)) '@vitest/pretty-format': 4.0.8 '@vitest/runner': 4.0.8 '@vitest/snapshot': 4.0.8 @@ -23145,7 +23166,7 @@ snapshots: tinyexec: 0.3.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.2.2(@types/node@20.19.25)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.7.1) + vite: 7.2.2(@types/node@20.19.25)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.89.2)(sass@1.94.0)(terser@5.44.1)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 @@ -23547,6 +23568,8 @@ snapshots: yaml@2.7.1: {} + yaml@2.8.3: {} + yargs-parser@18.1.3: dependencies: camelcase: 5.3.1 diff --git a/website/docs/ai.md b/website/docs/ai.md new file mode 100644 index 00000000..3cd50003 --- /dev/null +++ b/website/docs/ai.md @@ -0,0 +1,13 @@ +# 在 AI 中使用 + +ICE PKG 遵循 [llmstxt.org](https://llmstxt.org/) 标准,提供两个文件帮助 AI 工具理解项目文档: + +| 文件 | 链接 | 描述 | +| ------------- | ---------------------------------- | ------------------------------------------------------ | +| llms.txt | https://pkg.ice.work/llms.txt | 包含所有文档页面的标题、链接和简要描述的结构化索引文件 | +| llms-full.txt | https://pkg.ice.work/llms-full.txt | 将每个文档页面的完整内容合并到单个文件中 | + +## 如何选择 + +- **llms.txt**:体积较小,消耗 token 少,适合 AI 按需获取特定页面内容的场景 +- **llms-full.txt**:包含完整文档内容,适合需要 AI 全面理解 ICE PKG 的场景,但会消耗更多 token,最适合支持大上下文窗口的 AI 工具 diff --git a/website/docs/cli.md b/website/docs/cli.md new file mode 100644 index 00000000..cd7e5e4b --- /dev/null +++ b/website/docs/cli.md @@ -0,0 +1,31 @@ +# CLI + +## start + +启动本地调试服务,监听文件变更并自动重新编译。配置文件变更时会自动重启。 + +```bash +$ ice-pkg start [options] +``` + +| 选项 | 类型 | 说明 | +| :-------------------: | :-------: | ----------------------------- | +| `--config ` | `string` | 指定配置文件路径 | +| `--rootDir ` | `string` | 指定应用运行的根目录 | +| `--analyzer` | `boolean` | Bundle 模式下开启体积构建分析 | +| `--port ` | `number` | 覆盖预览服务端口号 | +| `--host ` | `string` | 覆盖预览服务 host | + +## build + +执行编译或打包构建,输出构建产物。 + +```bash +$ ice-pkg build [options] +``` + +| 选项 | 类型 | 说明 | +| :-------------------: | :-------: | ----------------------------- | +| `--config ` | `string` | 指定配置文件路径 | +| `--rootDir ` | `string` | 指定应用运行的根目录 | +| `--analyzer` | `boolean` | Bundle 模式下开启体积构建分析 | diff --git a/website/docs/config/alias.md b/website/docs/config/alias.md new file mode 100644 index 00000000..fdd3ed5f --- /dev/null +++ b/website/docs/config/alias.md @@ -0,0 +1,20 @@ +# alias + +- 类型:`Record` +- 默认值:`{}` + +配置路径别名。 + +比如,将 `@` 指向 `./src` 目录: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + alias: { + '@': './src', + }, +}); +``` + +然后代码里 `import '@/foo'` 会被改成 `import '/path/to/your/project/foo'`。 diff --git a/website/docs/config/bundle.md b/website/docs/config/bundle.md new file mode 100644 index 00000000..90811f46 --- /dev/null +++ b/website/docs/config/bundle.md @@ -0,0 +1,239 @@ +# bundle + +该字段定义 [Bundle 模式](../guide/build-modes#bundle-模式) 下额外的配置,若开启,默认生成 `dist` 文件目录。 + +## formats + +:::tip +推荐使用 [`pkgs`](./pkgs) 替代 `formats` 来配置多产物输出,`pkgs` 提供更灵活的差异化配置能力。 +::: + +- 类型:`['esm', 'umd', 'cjs', 'es2017']` +- 默认值:`['esm', 'es2017']` + +输出的类型,默认是输出 `esm` 和 `es2017` 产物。 + +```shell title=root/dist +- index.esm.es5.production.js # 输出 ES module + es5 产物 +- index.esm.es2017.production.js # 输出 ES module + es2017 产物 +``` + +若只需要产出 umd 规范产物,可配置为: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + bundle: { + formats: ['umd', 'es2017'], + }, +}); +``` + +则输出以下产物: + +```shell title=root/dist +- index.umd.es5.production.js # 输出 umd + es5 产物 +- index.umd.es2017.production.js # 输出 umd + es2017 产物 +``` + +注意,如果需要打包生成 umd 规范产物,不能够配置多个 entry(入口),否则会报错 `Error: Invalid value "umd" for option "output.format" - UMD and IIFE output formats are not supported for code-splitting builds.` + +cjs 规范产物同理将 `formats` 配置为 `['cjs', 'es2017']` 即可。 + +:::tip +Bundle 模式的 formats 如果单独配置 `['es2017']` 将不会生效,因为其仅决定产物语法层面规范,而无法决定产物的模块规范。因此其必须与 `'esm'`、`'umd'` 和 `'cjs'` 中的至少一项搭配配置才能正常生成对应模块规范的 ES2017 产物。 +::: + +## modes + +- 类型:`Array<'development' | 'production'>` +- 默认值:`['production']` + +指定输出的产物是否经过压缩。默认情况下输出的产物是压缩过的。 + +```shell title="root/dist" +- index.esm.es5.production.js # 输出 ES module + es5 产物 +- index.esm.es2017.production.js # 输出 ES module + es2017 产物 +``` + +增加 `'development'` 时,会额外输出一份**未压缩的**的产物,这也意味着用户可以在开发态使用该产物获得更多的开发时信息。 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + bundle: { + modes: ['production', 'development'], + }, +}); +``` + +```shell title="root/dist" +- index.esm.es5.development.js # 输出未压缩产物(ES module + es5) +- index.esm.es5.production.js # 输出压缩产物 (ES module + es5) +- index.esm.es2017.development.js # 输出未压缩产物 (ES module + es2017) +- index.esm.es2017.production.js # 输出压缩产物 (ES module + es2017) +``` + +## name + +- 类型:`string` +- 默认值:`package.name` + +library 导出的名称,可以通过 `window[name]` 访问,一般配合打包 `umd` 产物时使用。默认值为 `package.json` 配置的 `name` 字段。 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + bundle: { + name: 'ICEPKG', + }, +}); +``` + +## externals + +- 类型:`boolean | Record | (string | RegExp | Record)[]` +- 默认值:`false` + +默认情况下,bundle 的产物包含所有依赖产物。该选项可修改这一结果。 + +若想要 Bundle 不包含依赖产物,可以传入 `true`,其会解析 `package.json` 并将所有依赖 external 掉,包括 node 的依赖。适合针对 Node 环境的构建。 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + bundle: { + externals: true, + }, +}); +``` + +若想要自定义配置 externals,则可以直接传入想要 external 的依赖,支持字符串和正则表达式。 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + bundle: { + externals: ['react', 'react-dom', /^@ice($|\/)/], + }, +}); +``` + +如果你选择构建 umd 格式,默认情况下会根据一定的规则生成从全局对象上获取依赖的名字,如果你想自定义,则可以直接传入一个对象来配置。 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + bundle: { + externals: { + react: 'React', + 'react-dom': 'ReactDOM', + }, + }, +}); +``` + +## minify + +- 类型:`boolean | { js?: boolean | ((mode: string, command: string) => boolean | { options?: swc.JsMinifyOptions }); css?: boolean | ((mode: string, command: string) => boolean | { options?: cssnano.Options });}` +- 默认值:build 阶段且 mode 是 `production` 时为 `true`,否则为 `false` + +是否压缩 JS 和 CSS 资源。 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + bundle: { + // production 产物和 development 产物不压缩 + minify: false, + // 修改 JS 和 CSS 压缩参数 + minify: { + js: (mode, command) => ({ + options: { + /* */ + }, + }), + css: (mode, command) => ({ + options: { + /* */ + }, + }), + }, + }, +}); +``` + +## polyfill + +- 类型:`false | 'entry' | 'usage'` +- 默认值:`false` + +配置处理 polyfill 的逻辑。不同值的含义: + +- `false`: 不引入任何 polyfill +- `'entry'`: 根据配置的 format 值在每个文件开头都引入对应的 polyfill +- `'usage'`: 根据源码中使用到的代码按需引入 polyfill + +## compileDependencies + +- 类型:`boolean | RegExp[] | string[]` +- 默认值:`false` + +配置是否编译 node_modules 中的依赖。如果值为 `true`,则 node_modules 中的依赖都会编译;如果值为 false 则都不编译;如果值为数组,则只会编译对应的依赖。 + +```js title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + bundle: { + compileDependencies: ['antd'], + }, +}); +``` + +## browser + +- 类型: `boolean` +- 默认值: `false` + +配置解析 Node 模块的时候,是否优先读取 package.json 中的 `browser` 字段。如果你的模块**只运行**在浏览器端,可以开启此选项只 bundle 浏览器相关的代码。 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + bundle: { + browser: true, + }, +}); +``` + +## codeSplitting + +- 类型:`boolean` +- 默认值:`true` + +是否开启代码分割。Bundle 模式默认启用,会将 `node_modules` 中的公共依赖提取到 `vendor` chunk,多入口之间的共享模块也会被提取。 + +若关闭代码分割,所有模块将合并输出为单一文件,适合对产物结构有严格要求的场景(如 UMD 发布): + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + bundle: { + codeSplitting: false, + }, +}); +``` + +:::tip +UMD 格式由于 Rollup 限制,已默认启用 `inlineDynamicImports`,分包设置对 UMD 产物不生效。 +::: diff --git a/website/docs/config/declaration.md b/website/docs/config/declaration.md new file mode 100644 index 00000000..cf55c2cf --- /dev/null +++ b/website/docs/config/declaration.md @@ -0,0 +1,75 @@ +# declaration + +- 类型:`boolean | { outputMode?: 'multi' | 'unique'; generator?: 'tsc' | 'oxc' }` +- 默认值:`true` + +配置 `.d.ts` 类型文件的生成行为。默认会为 TypeScript 文件自动生成类型文件。 + +## outputMode + +- 类型:`'multi' | 'unique'` +- 默认值:`'multi'` + +控制类型文件的输出位置: + +- `'multi'`:将 `.d.ts` 文件输出到每个 Transform 产物目录下(如 `esm/`、`es2017/`) +- `'unique'`:将所有 `.d.ts` 文件统一输出到根目录的 `typings/` 文件夹 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + declaration: { + outputMode: 'unique', + }, +}); +``` + +## generator + +- 类型:`'tsc' | 'oxc'` +- 默认值:`'tsc'` + +选择生成类型文件的工具: + +- `'tsc'`:使用 TypeScript 官方编译器生成类型文件 +- `'oxc'`:使用 [oxc-transform](https://oxc.rs/) 生成 isolated declaration,速度更快,但要求源码符合 [isolated declarations](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) 规范 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + declaration: { + generator: 'oxc', + }, +}); +``` + +## allowJs + +- 类型:`boolean` +- 默认值:`false` + +是否为 JavaScript 文件生成类型文件。当项目使用 [JSDoc](https://jsdoc.app/) 为 JavaScript 添加了类型注解时,开启此选项可以生成对应的 `.d.ts` 文件。 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + declaration: { + allowJs: true, + }, +}); +``` + +## 禁用类型生成 + +若不需要生成类型文件,可将其设置为 `false`: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + declaration: false, +}); +``` diff --git a/website/docs/config/define.md b/website/docs/config/define.md new file mode 100644 index 00000000..ce44a852 --- /dev/null +++ b/website/docs/config/define.md @@ -0,0 +1,45 @@ +# define + +- 类型:`Record` +- 默认值:`{ __DEV__: 'true' | 'false', 'process.env.NODE_ENV': '"development"' | '"production"', 'import.meta.vitest': 'undefined' }` + +定义编译时环境变量,会在编译时被替换。注意:属性值会经过一次 `JSON.stringify()` 转换。 + +例如,希望在代码中注入版本号,用全局变量 `__VERSION__` 来替代: + +```ts title="build.config.mts" +import pkg from './package.json' assert { type: 'json' }; +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + define: { + __VERSION__: pkg.version, + }, +}); +``` + +在编译时,所有 `__VERSION__` 都会被替换为项目的版本号。 + +:::tip + +在 TS 项目中,需要在 `typings.d.ts` 或其他类型声明文件中,声明 `define` 所设置的属性,以便通过类型检查,并获得类型提示。比如: + +```ts title=typings.d.ts +declare const __VERSION__: string; +``` + +::: + +ICE PKG 默认注入了 `__DEV__` 全局变量,用于标识开发态环境。这个变量在输出一些仅在 development 环境的信息时非常有用。比如,输出在用户开发态才显示的警告信息。 + +```ts title=index.ts +if (__DEV__) { + console.warn('请注意,这可能会产生错误!'); +} +``` + +:::info 发生了什么? +实际上,在编译时,`__DEV__` 会被替换为 `process.env.NODE_ENV !== 'production'`。 +::: + +另外,ICE PKG 默认会将 `import.meta.vitest` 替换为 `undefined`。这意味着在源码里使用 Vitest 的 [in-source test](https://vitest.dev/guide/in-source.html) 写法时,非测试构建默认不会把对应测试逻辑保留到产物中。 diff --git a/website/docs/config/entry.md b/website/docs/config/entry.md new file mode 100644 index 00000000..6c7b44c8 --- /dev/null +++ b/website/docs/config/entry.md @@ -0,0 +1,32 @@ +# entry + +- 类型:`string | string[] | { [entryAlias: string]: string }` +- 默认值:`'./src/index'` + +指定构建入口。支持配置单入口或者多个入口。 + +指定单个入口: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + entry: './src/index', +}); +``` + +指定多个入口: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + // 数组形式 + entry: ['./src/foo', './src/bar'], + // 对象形式,key 值作为 chunk name + entry: { + foo: './src/foo', + bar2: './src/bar', + }, +}); +``` diff --git a/website/docs/config/helpers.md b/website/docs/config/helpers.md new file mode 100644 index 00000000..094ff95f --- /dev/null +++ b/website/docs/config/helpers.md @@ -0,0 +1,34 @@ +# helpers + +- 类型:`'external' | 'inline'` +- 默认值:`'external'` + +配置 SWC 编译时辅助函数(helper functions)的处理方式。 + +- **`'external'`(默认)**:从 `@swc/helpers` 包中导入 helper 函数,产物体积更小,但需要消费方的运行环境中存在该依赖。 +- **`'inline'`**:将 helper 函数内联到每个文件中,无需外部依赖,适合对外发布的独立类库。 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + helpers: 'inline', +}); +``` + +也可以在 [`pkgs`](./pkgs) 中为某个产物单独配置: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + pkgs: [ + { module: 'esm', target: 'es2017' }, + { + module: 'umd', + bundle: true, + helpers: 'inline', // 仅 UMD 产物内联 helpers + }, + ], +}); +``` diff --git a/website/docs/config/index.md b/website/docs/config/index.md new file mode 100644 index 00000000..be00c19d --- /dev/null +++ b/website/docs/config/index.md @@ -0,0 +1,38 @@ +# 构建配置 + +## 配置文件 + +若希望对 ICE PKG 的能力进行配置,推荐在项目根目录中添加名为 `build.config.mts` 的配置文件: + +```ts title=build.config.mts +import { defineConfig } from '@ice/pkg'; + +// 使用 defineConfig 工具函数以获得更好的类型提示 +export default defineConfig({ + // 配置选项 +}); +``` + +注:ICE PKG 支持的配置文件类型包括: + +- `build.config.mts` +- `build.config.mjs` +- `build.config.ts` +- `build.config.js` + +## 配置项总览 + +| 配置项 | 说明 | +| ---------------------------- | ----------------------- | +| [entry](./entry) | 构建入口 | +| [alias](./alias) | 路径别名 | +| [define](./define) | 编译时环境变量 | +| [sourceMaps](./source-maps) | 是否生成 sourcemap | +| [jsxRuntime](./jsx-runtime) | JSX 转换方式 | +| [plugins](./plugins) | 插件配置 | +| [helpers](./helpers) | SWC helper 函数处理方式 | +| [server](./server) | 内置预览服务器配置 | +| [declaration](./declaration) | 类型文件生成配置 | +| [transform](./transform) | Transform 模式配置 | +| [bundle](./bundle) | Bundle 模式配置 | +| [pkgs](./pkgs) | 多构建单元配置 | diff --git a/website/docs/config/jsx-runtime.md b/website/docs/config/jsx-runtime.md new file mode 100644 index 00000000..adf974c5 --- /dev/null +++ b/website/docs/config/jsx-runtime.md @@ -0,0 +1,36 @@ +# jsxRuntime + +- 类型:`'automatic' | 'classic'` +- 默认值:`'automatic'` + +设置 [JSX 转换](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html)的方式,并交给编译工具(SWC)编译处理 JSX 语法。 + +假设有这样一段 JSX 代码: + +```jsx +import React from 'react'; + +function App() { + return

Hello World

; +} +``` + +当 `jsxRuntime` 的值是 `automatic`,编译结果是: + +```js +import { jsx as _jsx } from 'react/jsx-runtime'; + +function App() { + return _jsx('h1', { children: 'Hello world' }); +} +``` + +当 `jsxRuntime` 的值是 `classic`,编译结果是: + +```js +import React from 'react'; + +function App() { + return React.createElement('h1', null, 'Hello world'); +} +``` diff --git a/website/docs/config/pkgs.md b/website/docs/config/pkgs.md new file mode 100644 index 00000000..acf93d57 --- /dev/null +++ b/website/docs/config/pkgs.md @@ -0,0 +1,125 @@ +# pkgs + +`@ice/pkg` 2.0 引用的新式配置方式 + +- 类型:`Array` +- 默认值:`undefined` + +配置多个构建单元(package),每个 pkg 可以独立控制构建模式、格式、入口、输出目录等。适用于需要同时输出多种格式或多个子包的场景。 + +## PresetPkg(预设格式) + +最简单的用法是直接传入预设格式字符串,快速开启对应产物: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + pkgs: ['esm', 'cjs', '!umd'], +}); +``` + +支持的预设值: + +- Transform 格式(直接字符串):`'esm'`、`'cjs'`、`'es2017'` +- Bundle 格式(以 `!` 为前缀):`'!esm'`、`'!cjs'`、`'!es2017'`、`'!umd'`、`'!mf'` + +## PkgUserConfig 配置项 + +### id + +- 类型:`string` + +当前 pkg 的唯一标识,可在其他 pkg 的 `extends` 中引用。 + +### module + +- 类型:`'esm' | 'cjs' | 'umd' | 'mf'` +- 默认值:`'esm'` + +产物的模块规范: + +- `'esm'`:输出 ES Module 格式,使用 `import/export` 语法,对 Tree-Shaking 友好,适合被打包工具消费的组件库或工具库 +- `'cjs'`:输出 CommonJS 格式,使用 `require/module.exports`,兼容所有版本的 Node.js,适合 Node 模块 +- `'umd'`:输出 UMD 格式,同时兼容 ESM、CJS 和浏览器全局变量,适合需要通过 ` + + + + + +``` + +**场景二:通过 ES Module 方式加载** + +在 ` + + +``` + +## 构建配置 + +前端类库通常使用 [Bundle 模式](../build-modes#bundle-模式) 构建,以将所有依赖打包到产物中: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + pkgs: [ + { + bundle: true, + module: 'umd', + name: 'YourLibName', // 配置 umd 模块导出的名字,通过 `window[name]` 访问 + }, + ], +}); +``` + +更多 UMD 产物配置请参考 [构建产物 — UMD 产物](../build#umd-产物)。 diff --git a/website/docs/guide/scenario/node.md b/website/docs/guide/scenario/node.md new file mode 100644 index 00000000..22378254 --- /dev/null +++ b/website/docs/guide/scenario/node.md @@ -0,0 +1,40 @@ +# Node 模块 + +如果现在有相同的工具函数在多个 Node 应用被消费,可以把这些公共的函数抽成一个 npm 包,供多个 Node 应用使用。支持经过 Transform 模式生成 CommonJS 产物和 ES Module 产物。 + +```ts title="src/index.ts" +import fs from 'fs'; + +export function writeLicenseToFileHeader(absFilePath: string) { + const newFileContent = '/* LICENSE */' + fs.readFileSync(absFilePath, 'utf-8'); + fs.writeFileSync(absFilePath, newFileContent); +} +``` + +推荐使用以下配置,同时生成 CJS 和 ESM 产物以兼容不同版本的 Node.js: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + pkgs: ['cjs', 'es2017'], +}); +``` + +然后在 `package.json` 中配置 `exports` 产物导出: + +```json +{ + "exports": { + ".": { + "import": "./es2017/index.js", + "require": "./cjs/index.js", + "default": "./cjs/index.js" + } + } +} +``` + +:::tip +不同版本的 Node.js 支持的 ECMAScript 语法可参考 [Node Green 网站](https://node.green/)。Node 12.20.0 及以上已支持 ES Module 和 ES2017 全部语法。 +::: diff --git a/website/docs/guide/scenario/react.md b/website/docs/guide/scenario/react.md new file mode 100644 index 00000000..a0d28ec3 --- /dev/null +++ b/website/docs/guide/scenario/react.md @@ -0,0 +1,159 @@ +# React 组件 + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +如果你在多个不同的项目中共同使用了一个或多个 React 组件,那么你可以考虑把这些公共的 React 组件抽成一个 npm 包,这样你就可以在不同的项目中复用组件了。 + +## 单组件 + +假设一个 npm 包仅导出一个 React 组件,推荐使用以下目录结构和写法: + +```md +src +├── Header # 子组件 Header +│ ├── index.css +│ └── index.tsx +└── index.tsx +``` + + + + +```tsx +import Header from './Header'; + +// 通过 export default 方式导出 +export default function Component() { + return ( +
+
+ ... +
+ ); +} +``` + +
+ + + +```tsx +import './index.css'; + +export default function Header() { + return
Header
; +} +``` + +
+
+ +这样在消费处可以通过 `import Component from 'your-component-name'` 的方式导入组件了。 + +## 组件库 + +假如一个 npm 包要导出多个不同的组件(即组件库),推荐使用以下的目录组织结构和写法: + +```md +src +├── Button +│ ├── index.css +│ └── index.tsx +├── Input +│ ├── index.css +│ └── index.tsx +└── index.ts +``` + + + + +```ts +export * from './Button'; +export * from './Input'; +``` + + + + + +```tsx +import * as React from 'react'; + +export function Button() { + return ; +} +``` + + + + +`src/index.ts` 作为组件库的入口文件,然后统一导出不同的 React 组件,这样就可以通过 `import { Button, Input } from 'your-component-name';` 导入组件了。 + +:::tip +有关样式的说明和写法请参考 [CSS](../css) 文档。 +::: + +## JSX 支持 + +ICE PKG 对 `.jsx` 和 `.tsx` 原生支持,使用 [SWC](https://swc.rs/docs/configuration/swcrc) 编译,无需任何额外配置即可直接使用。 + +JSX 的转换方式可通过 [`jsxRuntime`](../../config/jsx-runtime) 配置项调整,默认使用 `automatic` 模式(无需手动引入 `React`)。 + +## 发布配置 + +### exports + +推荐在 `package.json` 中配置 `exports` 字段声明 npm 包的入口: + +```json +{ + "exports": { + ".": { + "import": "./esm/index.js", + "require": "./cjs/index.js", + "es2017": "./es2017/index.js", + "default": "./cjs/index.js" + }, + "./feature": { + "import": "./esm/feature.js", + "require": "./cjs/feature.js", + "es2017": "./es2017/feature.js", + "default": "./cjs/feature.js" + } + } +} +``` + +如果需要兼容较低版本的 Node.js,还需同时配置 `main` 字段: + +```json +{ + "main": "./cjs/index.js" +} +``` + +:::tip +`exports` 的优先级高于 `main`,两者可以同时配置以兼容不同环境。更多导出规则可参考 [Node.js 文档](https://nodejs.org/dist/latest-v18.x/docs/api/packages.html#package-entry-points)。 +::: + +### sideEffects + +`sideEffects` 用于告知打包工具(如 Webpack)当前模块是否有副作用,从而开启更激进的 Tree Shaking。默认值为 `true`。 + +如果你的组件库代码没有副作用,可以设置为 `false`: + +```json +{ + "sideEffects": false +} +``` + +如果部分文件(如全局样式)确实有副作用,可以单独列出: + +```json +{ + "sideEffects": ["*.css", "*.less"] +} +``` diff --git a/website/docs/guide/server.md b/website/docs/guide/server.md new file mode 100644 index 00000000..07f0947a --- /dev/null +++ b/website/docs/guide/server.md @@ -0,0 +1,15 @@ +# 开发服务器 + +ICE PKG 内置了一个轻量的开发服务器,可在 `start` 模式下直接预览 Bundle 产物,无需额外搭建服务。 + +通过 [`server`](../config/server) 配置项启用: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + server: true, +}); +``` + +启动后访问 `http://localhost:5138` 即可预览产物。支持端口、host、HTTPS、代理、CORS 等配置,详见 [server 配置项](../config/server)。 diff --git a/website/docs/guide/test.md b/website/docs/guide/test.md index aa4f2836..889193a0 100644 --- a/website/docs/guide/test.md +++ b/website/docs/guide/test.md @@ -1,212 +1,83 @@ # 测试 -ICE PKG 不耦合任意一个测试框架,开发者可自由选择 [Jest](https://jestjs.io/) 或 [Vitest](https://vitest.dev/) 开展单元测试。 - -## 相关链接 - -- [Jest 官方文档](https://jestjs.io/docs/getting-started) -- [Vitest 官方文档](https://vitest.dev/guide/) -- [ts-jest 配置指南](https://kulshekhar.github.io/ts-jest/docs/getting-started/installation) -- [@swc/jest](https://www.npmjs.com/package/@swc/jest) -- [Testing Library React](https://testing-library.com/docs/react-testing-library/intro/) -- [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) +ICE PKG 不耦合任意一个测试框架,开发者可自由选择 [Jest](https://jestjs.io/) 或 [Vitest](https://vitest.dev/) 以及社区其他框架开展单元测试。 ## Jest -### 安装依赖 +请先参考 [Jest 官方文档](https://jestjs.io/docs/getting-started)完成基础安装和配置。 -```bash -$ npm i jest ts-jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom -D -``` +### 与 ICE PKG 配置对齐 -### 配置 +测试框架直接运行源码,如果 `build.config.mts` 中配置了 `alias` 或 `define`,需要在 Jest 配置中做对应设置。 -快速开始时,可以先在项目根目录创建 `jest.config.mjs`: +**alias**:使用 `moduleNameMapper` 映射路径别名: ```js title="jest.config.mjs" export default { preset: 'ts-jest', testEnvironment: 'jest-environment-jsdom', - setupFilesAfterEnv: ['/jest-setup.ts'], + moduleNameMapper: { + '^@/(.*)$': '/src/$1', + }, }; ``` -再创建 `jest-setup.ts`: - -```ts title="jest-setup.ts" -import '@testing-library/jest-dom'; -``` - -并在 `package.json` 中添加脚本: - -```diff title="package.json" -{ - "scripts": { -+ "test": "jest" - } -} -``` - -如果你希望改用 `@swc/jest` 编译 TS/TSX,可以改成: +**define**:使用 `globals` 定义编译时变量。ICE PKG 默认注入了 `__DEV__` 等变量,测试时需要显式声明: ```js title="jest.config.mjs" export default { - transform: { - '^.+\\.(t|j)sx?$': [ - '@swc/jest', - { - jsc: { - transform: { - react: { - runtime: 'automatic', - }, - }, - }, - }, - ], + preset: 'ts-jest', + testEnvironment: 'jest-environment-jsdom', + globals: { + __DEV__: true, }, }; ``` -### 编写测试用例 - -#### 非 UI 测试 - -假设现在要测试 `add()` 函数如下: - -```ts title="src/utils/add.ts" -export default function add(a, b) { - return a + b; -} -``` - -新建一个测试用例: - -```ts title="tests/add.spec.ts" -import add from '../src/add'; - -test('add function', () => { - expect(add(1, 2)).toBe(3); -}); -``` - -这时,运行 `npm run test` 查看测试结果了。 - -#### UI 测试 - -组件 UI 测试推荐使用 [@testing-library/react](https://www.npmjs.com/package/@testing-library/react) 和 [@testing-library/jest-dom](https://www.npmjs.com/package/@testing-library/jest-dom)。上面的快速开始配置已经包含这两个库常用的 jsdom 环境和 matcher 设置。 - -假设现在要测试一个 Header 组件: - -```tsx title="src/components/Header.tsx" -export default function Header() { - return

Jest Test

; -} -``` - -编写组件的测试用例: - -```tsx title="tests/Header.spec.tsx" -import { render, screen } from '@testing-library/react'; -import Header from '../src/components/Header'; - -test('test Header component', () => { - render(
); - expect(screen.getByTestId('title')).toHaveTextContent('Jest Test'); -}); -``` - -最后,运行 `npm run test` 就可以查看测试结果了。 +如果你在 `build.config.mts` 中配置了自定义的 `define`,同样需要在此处补充对应的定义。 ## Vitest -### 安装依赖 +请先参考 [Vitest 官方文档](https://vitest.dev/guide/)完成基础安装和配置。 -```bash -$ npm i vitest jsdom @testing-library/react @testing-library/jest-dom -D -``` +### 与 ICE PKG 配置对齐 -### 配置 +测试框架直接运行源码,如果 `build.config.mts` 中配置了 `alias` 或 `define`,需要在 Vitest 配置中做对应设置。 -快速开始时,可以先在项目根目录创建 `vitest.config.mts`: +**alias**:使用 `resolve.alias` 映射路径别名: -```js title="vitest.config.mts" +```ts title="vitest.config.mts" import { defineConfig } from 'vitest/config'; export default defineConfig({ + resolve: { + alias: { + '@': new URL('./src', import.meta.url).pathname, + }, + }, test: { environment: 'jsdom', - setupFiles: ['./vitest-setup.ts'], - globals: true, }, }); ``` -默认情况下,ICE PKG 构建时会将 `import.meta.vitest` 替换为 `undefined`,因此可以直接使用 Vitest 的 in-source test 写法,而不会把测试分支带入最终产物。 - -再创建 `vitest-setup.ts`: - -```ts title="vitest-setup.ts" -import matchers from '@testing-library/jest-dom/matchers'; -import { expect } from 'vitest'; - -expect.extend(matchers); -``` - -并在 `package.json` 中添加脚本: - -```diff title="package.json" -{ - "scripts": { -+ "test": "vitest" - } -} -``` - -可直接传入 [vitest 配置](https://vitest.dev/config/)。 - -以修改 `include` 参数为例: +**define**:使用 `define` 定义编译时变量。ICE PKG 默认注入了 `__DEV__` 等变量,测试时需要显式声明: -```diff title="vitest.config.mts" +```ts title="vitest.config.mts" import { defineConfig } from 'vitest/config'; export default defineConfig({ -+ test: { -+ environment: 'jsdom', -+ setupFiles: ['./vitest-setup.ts'], -+ globals: true, -+ include: ['**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], -+ }, + define: { + __DEV__: true, + }, + test: { + environment: 'jsdom', + }, }); ``` -### 编写测试用例 - -#### 非 UI 测试 - -请见 [Jest 非 UI 测试章节](#非-ui-测试)。 - -组件 UI 测试时,上面的快速开始配置已经包含 jsdom 环境、全局 API 和 matcher 扩展。 - -假设现在测试一个 Header 组件: - -```tsx title="src/components/Header.tsx" -export default function Header() { - return

Vitest Test

; -} -``` - -编写组件的测试用例: +如果你在 `build.config.mts` 中配置了自定义的 `define`,同样需要在此处补充对应的定义。 -```tsx title="tests/Header.spec.tsx" -import { test, expect } from 'vitest'; -import { render, screen } from '@testing-library/react'; -import Header from '../src/components/Header'; - -test('test Header component', () => { - render(
); - expect(screen.getByTestId('title')).toHaveTextContent('Vitest Test'); -}); -``` +### In-source Test -最后,运行 `npm run test` 就可以查看测试结果了。 +ICE PKG 构建时会将 `import.meta.vitest` 替换为 `undefined`,因此可以直接使用 Vitest 的 [in-source test](https://vitest.dev/guide/in-source.html) 写法,测试逻辑不会被带入最终产物。 diff --git a/website/docs/guide/typescript.md b/website/docs/guide/typescript.md new file mode 100644 index 00000000..9693e629 --- /dev/null +++ b/website/docs/guide/typescript.md @@ -0,0 +1,121 @@ +# TypeScript + +ICE PKG 原生支持引入和使用 `.ts`/`.tsx` 文件。使用 [SWC](https://swc.rs/docs/configuration/swcrc) 进行编译,相比 `tsc` 有着数十倍的编译速度提升,同时热更新的时间也有明显的减少。 + +## 类型声明 + +默认情况下,我们使用的一些模块(比如 `.module.css`、`.jpg` 等)或者全局变量(比如 `NODE_ENV` 等)类型是未定义的,在编辑器中是有报错提示。为此 ICE PKG 默认提供一份类型声明,你可以在项目中新增一个 `d.ts` 类型声明文件并加入以下的内容: + +```ts title="src/typings.d.ts" +/// +``` + +## 声明文件 + +ICE PKG 默认会为 Transform 模式下的 TypeScript 文件自动生成 `.d.ts` 类型声明文件,并将其输出到每个 Transform 产物目录下(如 `esm/`、`es2017/`): + +``` +esm/ +├── index.d.ts +└── index.js +es2017/ +├── index.d.ts +└── index.js +``` + +### 选择生成器 + +通过 `declaration.generator` 可以选择生成类型文件所使用的工具: + +**tsc(默认)**:使用 TypeScript 官方编译器,兼容性最好,支持所有 TypeScript 语法。 + +**oxc(实验性)**:使用 [oxc-transform](https://oxc.rs/) 生成 isolated declaration,速度比 tsc 快很多。但有以下限制: + +- 源码必须符合 [isolated declarations](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) 规范,即每个导出的类型必须可以独立推断,不依赖跨文件的类型推导 +- 需要在 `tsconfig.json` 中开启 `isolatedDeclarations: true` + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + declaration: { + generator: 'oxc', + }, +}); +``` + +### 控制输出位置 + +通过 `declaration.outputMode` 可以控制类型文件的输出位置: + +- **`multi`(默认)**:将 `.d.ts` 文件输出到每个 Transform 产物目录下 +- **`unique`**:将所有 `.d.ts` 文件统一输出到根目录的 `typings/` 文件夹,适合只需要一份类型文件的场景 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + declaration: { + outputMode: 'unique', + }, +}); +``` + +使用 `unique` 模式时,需要在 `package.json` 中通过 `types` 字段指向类型文件: + +```json +{ + "types": "./typings/index.d.ts" +} +``` + +### 为 JS 文件生成类型 + +对于使用 [JSDoc](https://jsdoc.app/) 为 JavaScript 添加了类型注解的项目,可以通过 `declaration.allowJs` 开启对 JS 文件的类型生成: + +```js +/** + * @param {number} a + * @param {number} b + * @returns {number} + */ +export function add(a, b) { + return a + b; +} +``` + +为 JavaScript 文件开启 [`declaration.allowJs`](../config/declaration#allowjs) 配置: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + declaration: { + allowJs: true, + }, +}); +``` + +则会生成一个 `add.d.ts` 文件,内容如下: + +```ts +export function add(a: number, b: number): number; +``` + +:::warning 谨慎使用该配置 +若贸然为没有使用 JSDoc 注解的 JavaScript 代码开启该配置,可能会出现自动类型推断错误的情况。 +::: + +### 禁用类型生成 + +若不需要生成类型文件,可将 `declaration` 设置为 `false`: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + declaration: false, +}); +``` + +完整配置说明请参考 [declaration 配置项](../config/declaration)。 diff --git a/website/docs/index.md b/website/docs/index.md index a226a6ca..725f3dc8 100644 --- a/website/docs/index.md +++ b/website/docs/index.md @@ -1,51 +1,28 @@ -# ICE PKG +# 简介 -ICE PKG 是飞冰开源的 NPM 包开发解决方案,默认支持 React 组件、Rax 组件、Node 模块、前端类库等多场景 NPM 包的研发。 +ICE PKG 是飞冰开源的 NPM 包开发解决方案,默认支持 React 组件、Node 模块、前端类库等多场景 NPM 包的研发。 ## 特性 -- **📈 更快**:使用 [SWC](https://swc.rs/docs/configuration/swcrc) 编译和压缩,提升数十倍编译速度 +- **📈 更快**:支持使用 [SWC](https://swc.rs/docs/configuration/swcrc)/[Rolldown](https://rolldown.rs/) 编译和压缩,提升数十倍编译速度 - **🎊 双模式**:同时提供 Transform + Bundle 两种构建模式 - **🅾️ 零配置**:无需任何配置,提供内建的 TypeScript、JSX 等构建支持 - **☄️ 面向未来**:提供 ES2017 产物,打包出面向现代浏览器支持的产物 -- **☘️ 文档预览**:基于 [Docusaurus](https://docusaurus.io/) 提供预览文档、生成静态文档能力 +- **🖥️ 内置开发服务器**:提供内置 Dev Server,开箱即用,无需额外配置 +- **📦 模块联邦支持**:支持 Module Federation(MF),便于跨应用共享模块 +- **🏗️ 多产物构建**:支持同时构建多种格式产物(ESM、CJS、UMD 等),一次命令输出所有目标格式 -### 更快 +## 为什么需要 ICE PKG -使用 SWC 与 [tsc](https://www.typescriptlang.org/)、[Babel](https://babeljs.io/) 编译同一个项目之间耗时对比: +在开发组件库或工具库时,开发者不仅需要专注于实现项目逻辑,还需要处理与代码本身无关的繁琐工作,例如构建、调试、文档预览和测试。社区中虽然有许多工具可以解决其中部分问题,但开发者往往需要同时协调多个工具,面临配置繁琐、生态割裂等困境。 -
- benchmark +ICE PKG 提供了一套面向 NPM 包研发的一体化解决方案,重点解决以下问题: -
Above: benchmark 使用 飞冰 fusion pro 模板
-
- -### 双模式 - -社区的众多方案如 [Microbundle](https://github.com/developit/microbundle)、[tsup](https://github.com/egoist/tsup) 均只支持打包模式 (将所有依赖文件打包成一个文件输出,下称 Bundle 模式)。但 Bundle 模式[并非总是最佳选择](https://github.com/ice-lab/icepkg/issues/301)。其中最为**显著的问题**在于:**对 Tree-Shaking 不友好**,无用的依赖总是会被打包到最终的输出产物中,继而影响应用的体积。 - -ICE PKG 除支持 Bundle 模式外,也默认支持了 Transform 模式(将文件挨个编译到输出目录)。更多内容请参考[构建能力 — 双模式构建](./guide/abilities#双模式构建)。 - -### ES2017 产物 - -为现代浏览器提供 ES2017 产物,可以减少产物体积,亦可加快执行速度。更多内容参考 [构建能力 — es2017 产物](./guide/abilities#es2017-产物)。 - -### 多场景 - -依赖 ICE PKG 强大的[双模式](#双模式)能力,支持多类场景的开发需求。包括但不限定于以下场景: - -+ React 组件 -+ Rax 组件 -+ Node 模块 -+ 前端类库 - -### 文档预览 - -结合 [Docusaurus](https://docusaurus.io/),ICE PKG 升级了文档预览的能力。更多内容参考 [指南 - 文档预览](./guide/preview)。 +- **构建模式单一**:社区大多数工具仅支持 Bundle 模式,对 Tree-Shaking 不友好,导致最终产物体积虚高。ICE PKG 默认支持 Transform 和 Bundle 双模式,开发者可按需选择最合适的构建方式。 +- **配置成本高**:从零搭建一个支持 TypeScript、JSX、多格式产物输出的构建流程往往需要大量配置。ICE PKG 做到真正零配置开箱即用,内建对 TypeScript、JSX、CSS 等的支持。 +- **构建性能瓶颈**:传统基于 Babel/tsc 的构建工具在大型项目中速度较慢。ICE PKG 集成高性能的 SWC 编译器,构建速度提升数十倍,并支持实验性的 Rolldown 引擎进一步加速。 +- **研发链路割裂**:构建、文档预览、测试等环节往往依赖不同的独立工具。ICE PKG 将这些能力整合到统一的工具链中,降低研发链路的维护成本。 +- **生态协同成本高**:在飞冰(ICE)体系下开发组件或工具包时,往往需要额外适配工程配置。ICE PKG 作为飞冰生态的官方 NPM 包研发方案,与 [ice.js](https://v3.ice.work/) 等工具无缝衔接,真正做到生态内开箱即用。 ## 社区 diff --git a/website/docs/migration/v1-to-v2.md b/website/docs/migration/v1-to-v2.md new file mode 100644 index 00000000..8f689e14 --- /dev/null +++ b/website/docs/migration/v1-to-v2.md @@ -0,0 +1,145 @@ +# V1 迁移到 V2 + +本文档帮助你从 ICE PKG V1 迁移到 V2 版本,列出所有不兼容的变更及对应的迁移方式。 + +## 升级依赖 + +```bash +pnpm add @ice/pkg@latest +``` + +--- + +## Breaking Changes + +### 移除 `development` 配置项 + +`bundle.development` 已移除,请改用 `bundle.modes`: + +```diff +export default defineConfig({ + bundle: { +- development: true, ++ modes: ['development', 'production'], + }, +}); +``` + +--- + +### `polyfill` 默认值从 `'usage'` 改为 `false` + +V1 中 `polyfill` 默认值为 `'usage'`,会自动注入 `core-js` polyfill。V2 中默认值改为 `false`,不再自动注入。 + +如果你的产物需要 polyfill,请显式配置: + +```ts +export default defineConfig({ + bundle: { + polyfill: 'usage', // 或 'entry' + }, +}); +``` + +--- + +### `externals` 字符串不再匹配子路径 + +V1 中配置字符串 `externals` 会模糊匹配子路径(如 `'lodash'` 会同时 external 掉 `lodash/get`)。V2 改为精确匹配,字符串只匹配完整包名。 + +如需 external 子路径,请改用正则或数组形式: + +```ts +export default defineConfig({ + bundle: { + // V1: externals: { lodash: 'lodash' } // 会匹配 lodash 及所有子路径 + // V2: 只匹配 'lodash',不匹配 'lodash/get' + externals: [/^lodash/], // 使用正则匹配所有 lodash 子路径 + }, +}); +``` + +--- + +### 移除 `defineJestConfig` / `defineVitestConfig` + +V1 中 `@ice/pkg` 导出了 `defineJestConfig` 和 `defineVitestConfig` 帮助函数,用于将构建配置中的 `alias`、`define` 等同步到测试框架。V2 已移除这两个方法。 + +请直接在测试框架配置中手动配置 alias 等选项: + +```ts +// vitest.config.ts +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + alias: { + '@': './src', + }, + }, +}); +``` + +同时,V2 支持 [Vitest In-Source Testing](https://vitest.dev/guide/in-source),`import.meta.vitest` 会在构建产物中被自动替换为 `undefined`,无需额外配置。 + +--- + +### UMD 产物默认启用 `inlineDynamicImports` + +V2 中 UMD 构建模式下默认启用 `inlineDynamicImports`,所有动态导入会被内联到单个产物文件中。这是为了避免 UMD 产物因分包导致运行时无法加载依赖 chunk 的问题。 + +如果你之前依赖 UMD 产物的分包行为,需要注意产物结构会发生变化。 + +--- + +### ES5 构建模式下默认编译所有依赖 + +V2 中 Bundle 模式使用 `es5` 语法目标时,会默认对 `node_modules` 中的依赖代码一并编译降级,确保产物语法兼容性。V1 中依赖代码默认不会被编译。 + +如果你的依赖已经是 ES5,这不会有影响;若依赖包含高版本语法,V2 会自动处理,无需额外配置。 + +--- + +### `generateTypesForJs` 迁移到 `declaration.allowJs` + +顶级配置项 `generateTypesForJs` 已移除,改为 `declaration.allowJs`: + +```diff +export default defineConfig({ +- generateTypesForJs: true, ++ declaration: { ++ allowJs: true, ++ }, +}); +``` + +--- + +## AI 迁移 Prompt + +如果你使用支持 Agent 模式的 AI 工具(如 Claude Code、Cursor、Copilot Workspace 等),可以使用以下模板让 AI 自动完成迁移: + +``` +你是一个专业的前端工程师,请帮我将当前项目的 ICE PKG 构建配置从 V1 迁移到 V2。 + +## 任务 + +1. 读取项目根目录下的 `build.config.mts`(或 `build.config.ts` / `build.config.mjs`) +2. 检查并修复以下所有 Breaking Changes +3. 如有涉及测试框架配置(`jest.config.*` / `vitest.config.*`),一并读取并修复 +4. 直接修改文件,完成后输出变更摘要 + +## Breaking Changes 检查清单 + +- [ ] `bundle.development: true` → 替换为 `bundle.modes: ['development', 'production']` +- [ ] `bundle.polyfill` 未配置但原本依赖默认注入 → 根据需要显式设为 `'usage'` 或 `'entry'` +- [ ] `externals` 使用字符串且需要匹配子路径 → 改用正则,例如 `'lodash'` → `/^lodash/` +- [ ] 从 `@ice/pkg` 导入了 `defineJestConfig` 或 `defineVitestConfig` → 移除,手动配置测试框架的 alias 等选项 +- [ ] `generateTypesForJs: true` → `declaration: { allowJs: true }` + +## 注意事项 + +- 只修改需要变更的部分,保持其他配置不变 +- 如果某项 Breaking Change 在当前项目中不涉及,跳过即可 +- 修改前先读取文件,确认当前内容后再做变更 +``` diff --git a/website/docs/plugin/development.md b/website/docs/plugin/development.md new file mode 100644 index 00000000..b4c02bd9 --- /dev/null +++ b/website/docs/plugin/development.md @@ -0,0 +1,629 @@ +# 开发插件 + +ICE PKG 基于 [build-scripts](https://github.com/ice-lab/build-scripts) 插件系统。通过 build-scripts 插件,可以极大地扩展 ICE PKG 的能力。 + +## 插件示例 + +### 本地插件 + +假设在项目根目录下有一个自定义插件 my-plugin: + +```js title="plugin.mjs" +/** + * @type {import('@ice/pkg').Plugin} + */ +const plugin = (api, options) => { + console.log('api: ', api); +}; + +export default plugin; +``` + +然后在 `build.config.mts` 中引入插件: + +```diff +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ ++ plugins: [ ++ './plugin.mjs', ++ ], +}); +``` + +### 发布插件到 npm + +推荐插件目录是: + +```md +my-plugin +├── package.json +├── tsconfig.json +├── src +| └── index.ts // 插件入口 +``` + +```ts src/index.ts +import type { Plugin } from '@ice/pkg'; + +const plugin: Plugin = (api) => {}; + +export default plugin; +``` + +对插件代码进行编译后,在 package.json 中指定插件的入口: + +```json +{ + "name": "my-plugin", + "main": "./esm/index.js", + "exports": { + // ... + } +} +``` + +把插件发布到 npm 后,需要把插件添加到 `build.config.mts` 构建配置中: + +```diff +import { defineConfig } from '@ice/pkg'; + +export default defineConfig(() => ({ + plugins: [ ++ 'my-plugin', + ], +})); +``` + +## 插件 API + +### context + +`context` 包含构建时的上下文信息: + +- `command`:当前运行命令,start/build/test +- `commandArgs`:script 命令执行时接受到的参数 +- `rootDir`:项目根目录 +- `userConfig`:用户在构建配置文件 build.config.mts 中配置的内容 +- `pkg`:项目 package.json 中的内容 + +```js +const plugin = (api) => { + console.log(api.context); +}; +``` + +### pluginScope + +`pluginScope` 标识当前插件的运行范围,可用于区分插件是在全局还是在某个 pkg 的上下文中被调用: + +- `'global'`:插件通过顶级 `plugins` 配置注册,作用于所有构建任务 +- `'pkg'`:插件通过 `pkgs[].plugins` 配置注册,仅作用于当前 pkg + +```js +const plugin = (api) => { + const { pluginScope } = api; + + if (pluginScope === 'pkg') { + // 仅在 pkg 级别执行的逻辑 + } else { + // 全局执行的逻辑 + } +}; +``` + +同一个插件可以同时被全局和 pkg 级别引用,通过 `pluginScope` 可以在插件内部针对不同场景执行不同的逻辑。 + +### onGetConfig + +ICE PKG 会根据用户配置注册对应的构建任务,通过 `onGetConfig` API 可以修改每个任务的配置项。 + +**不指定任务名**时,行为因插件注册方式不同而有所区别: + +- 通过顶级 `plugins` 注册的插件(`pluginScope: 'global'`):修改会对**所有任务**生效 +- 通过 `pkgs[].plugins` 注册的插件(`pluginScope: 'pkg'`):修改仅对**当前 pkg 的任务**生效,无法影响其他 pkg;若指定了其他 pkg 的任务名,会产生警告并被忽略 + +**指定任务名**时,任务名与配置方式有关: + +使用 `pkgs` 配置时,任务名格式为 `{bundle|transform}-{id}`,其中 `id` 的生成逻辑如下: + +- 若 pkg 配置了 `id` 字段,则直接使用该值 +- 否则默认取 `module` 值(如 `esm`、`cjs`) +- 若已有同名 id,则追加 `target`,变为 `{module}-{target}`(如 `esm-es2017`) +- 若仍有冲突,则在末尾追加数字后缀(如 `esm-1`) + +例如以下配置: + +```ts title="build.config.mts" +export default defineConfig({ + pkgs: [ + { module: 'esm', target: 'es2017' }, // 任务名:transform-esm + { module: 'esm', target: 'es5' }, // 任务名:transform-esm-es5(已有 esm,追加 target) + { id: 'my-cjs', module: 'cjs', bundle: true }, // 任务名:bundle-my-cjs(使用自定义 id) + ], +}); +``` + +:::caution +`pkgs` 的任务名由运行时动态生成,可能因配置顺序变化而改变。建议通过**不指定任务名**的方式让修改对所有任务生效,仅在确实需要精准定位某个任务时才依赖任务名,并配合显式 `id` 字段保证稳定性。 +::: + +使用传统 `transform.formats` / `bundle.formats` 时,任务名规则如下: + +- `transform-esm`:默认启动 +- `transform-es2017`:默认启动 +- `transform-cjs`:当 Transform 配置了 `formats: ['cjs']` 启动 +- `bundle-es5`:当 Bundle 配置了 `formats: ['esm']` 或者 `formats: ['cjs']` 或者 `formats: ['umd']` 时启动 +- `bundle-es2017`:当 Bundle 配置了 `formats: ['es2017']` 时启动 + +通过 `onGetConfig` API,可以修改每个 Task 任务的配置项。 + +当不指定任务名时,修改的配置会对所有任务生效: + +```js +const plugin = (api) => { + const { onGetConfig } = api; + // 不指定 Task name + onGetConfig((config) => { + return { + ...config, + entry: './component/index', + }; + }); +}; +``` + +你也可以指定修改某个任务的配置,比如: + +```js +const plugin = (api) => { + const { onGetConfig } = api; + // 仅仅修改 transform-esm 任务的配置 + onGetConfig('transform-esm', (config) => { + return { + ...config, + entry: './component/index', + }; + }); +}; +``` + +有以下参数可以配置: + +#### entry + +- 类型:`string | string[] | { [entryAlias: string]: string }` +- 默认值:`'./src/index'` + +指定构建入口。支持配置单入口或者多个入口。 + +指定单个入口: + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig((config) => { + return { + ...config, + entry: './component/index', + }; + }); +}; +``` + +指定多个入口: + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig((config) => { + return { + ...config, + // 1. 数组形式 + entry: ['./src/foo', './src/bar'], + // 2. 对象形式,key 值作为 chunk name + entry: { + foo: './src/foo', + bar2: './src/bar', + }, + }; + }); +}; +``` + +#### define + +- 类型:`Record` +- 默认值:`{ 'process.env.NODE_ENV': 'development' | 'production', __DEV__: true | false }` + +定义编译时环境变量,会在编译时被替换。注意:属性值会经过一次 `JSON.stringify()` 转换。 + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig((config) => { + return { + ...config, + define: { + VERSION: '1.0.0', + }, + }; + }); +}; +``` + +#### sourcemap + +- 类型:`boolean | 'inline'` +- 默认值:start 阶段为 `true`,build 阶段为 `false` + +配置是否生成源码调试映射。 + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig((config) => { + return { + ...config, + sourcemap: true, + }; + }); +}; +``` + +#### alias + +- 类型:`Record` +- 默认值:`{}` + +配置模块引入的别名。比如,将 `@` 指向 `./src` 目录: + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig((config) => { + return { + ...config, + alias: { + '@': './src', + }, + }; + }); +}; +``` + +然后代码里 `import '@/foo'` 会被改成 `import '/path/to/your/project/foo'`。 + +#### modifyRollupOptions + +- 类型:`Array<(rollupOptions: RollupOptions) => RollupOptions>` +- 默认值:`[]` + +修改默认的 [Rollup 选项](https://rollupjs.org/guide/en/#rolluprollup)。仅在使用 `rollup` 或 `rolldown` 引擎时生效。 + +```js +import svelte from 'rollup-plugin-svelte'; + +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig((config) => { + config.modifyRollupOptions ??= []; + config.modifyRollupOptions.push((rollupOptions) => { + rollupOptions.plugins.push(svelte({})); + return rollupOptions; + }); + }); +}; +``` + +#### modifyRslibConfig + +- 类型:`Array<(rslibConfig: RslibConfig) => RslibConfig>` +- 默认值:`[]` + +修改默认的 [Rslib 配置](https://lib.rsbuild.dev/config/)。仅在使用 `rslib` 引擎时生效。支持直接修改传入的配置对象,也可以返回新的配置对象。 + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig((config) => { + config.modifyRslibConfig ??= []; + config.modifyRslibConfig.push((rslibConfig) => { + // 修改 rslib 配置 + rslibConfig.output ??= {}; + rslibConfig.output.cssModules = { localIdentName: '[hash:base64:8]' }; + return rslibConfig; + }); + }); +}; +``` + +#### babelPlugins + +- 类型:`babel.PluginItem[] | undefined` +- 默认值:`undefined` + +配置额外的 babel 插件。当配置此选项后,将会先使用 babel 对代码进行编译,然后再经过 swc 编译。 + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig((config) => { + config.babelPlugins = []; + }); +}; +``` + +#### modifySwcCompileOptions + +- 类型:`(config: swc.Config) => swc.Config` +- 默认值:`undefined` + +用于修改 SWC 编译选项,函数入参是内置的 SWC 配置。具体编译选项可参考 [SWC 配置](https://swc.rs/docs/configuration/swcrc)。 + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig((config) => { + config.modifySwcCompileOptions = (originOptions) => { + const newOptions = { ...originOptions, env: {} }; + return newOptions; + }; + }); +}; +``` + +#### swcCompileOptions + +- 类型:`swc.Config` +- 默认值:`{}` + +:::tip +推荐使用 [modifySwcCompileOptions](#modifyswccompileoptions) 来修改 SWC 编译选项。 +::: + +设置 SWC 编译选项,会与内置的选项合并。优先级低于 `modifySwcCompileOptions`。具体编译选项可参考 [SWC 配置](https://swc.rs/docs/configuration/swcrc)。 + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig((config) => { + config.swcCompileOptions = { + // config + }; + }); +}; +``` + +#### outputDir + +> 仅对 Bundle 模式生效。Transform 模式按照配置的 format 值分别输出到对应目录,比如 esm、cjs、es2017 + +- 类型:`string` +- 默认值:`dist` + +配置 Bundle 模式下组件编译产物的输出目录。 + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig('bundle-es5', (config) => { + return { + ...config, + outputDir: 'build', + }; + }); +}; +``` + +#### modifyStylesOptions + +> 仅对 Bundle 模式生效 + +- 类型 `Array<(options: StylesRollupPluginOptions) => StylesRollupPluginOptions>` +- 默认值:`[]` + +ICE PKG 默认使用 [rollup-plugin-styles](https://www.npmjs.com/package/rollup-plugin-styles) 处理样式文件,可以通过 `modifyStylesOptions` 方式修改插件的配置。 + +```js +import PostcssPluginRpxToVw from 'postcss-plugin-rpx2vw'; + +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig('bundle-es5', (config) => { + config.modifyStylesOptions ??= []; + config.modifyStylesOptions.push((stylesOptions) => { + stylesOptions.plugins ||= []; + stylesOptions.plugins.push(PostcssPluginRpxToVw()); + return stylesOptions; + }); + return config; + }); +}; +``` + +#### extensions + +> 仅对 Bundle 模式生效 + +- 类型 `string[]` +- 默认值:`['.mjs', '.js', '.json', '.node', '.jsx', '.ts', '.tsx', '.mts', '.cjs', '.cts']` + +配置解析的文件后缀名,这样在引入模块时不需要带后缀名,配置后会与默认值合并。 + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig('bundle-es5', (config) => { + config.extensions = ['.xtpl']; + return config; + }); +}; +``` + +#### name + +> 仅对 Bundle 模式生效 + +- 类型:`string` +- 默认值:`package.name` + +Bundle 导出名称。一般用于 umd 产物中通过 `window[name]` 拿到产物模块内容。 + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig('bundle-es5', (config) => { + config.name = 'ICEPKG'; + return config; + }); +}; +``` + +#### modes + +> 仅对 Bundle 模式生效 + +- 类型:`Array<'development' | 'production' | string>` +- 默认值:`['production']` + +指定输出的产物是否经过压缩。默认情况下输出的产物是压缩过的(也就是开启了 `production`)。 + +```js +const plugin = (api) => { + const { onGetConfig } = api; + onGetConfig('bundle-es5', (config) => { + // 同时生成一份未压缩的产物和一份压缩产物 + config.modes = ['development', 'production']; + return config; + }); +}; +``` + +#### externals + +> 仅对 Bundle 模式生效 + +- 类型:`boolean | Record | Array>` +- 默认值:`{}` + +设置哪些模块不打包,转而通过 ` - - - - + + + + + + ``` @@ -160,10 +160,7 @@ import { createElement } from 'rax'; import styles from './index.module.css'; export default function Component() { - - return ( -
Hello
- ); + return
Hello
; } ``` diff --git a/website/versioned_docs/version-v1/guide/test.md b/website/versioned_docs/version-v1/guide/test.md new file mode 100644 index 00000000..a6cac861 --- /dev/null +++ b/website/versioned_docs/version-v1/guide/test.md @@ -0,0 +1,257 @@ +# 测试 + +
+ 示例 + +
+ +ICE PKG 不耦合任意一个测试框架,开发者可自由选择。目前提供开箱即用 [Jest](https://jestjs.io/) 和 [Vitest](https://vitest.dev/) 配置,以便快速开始单元测试。 + +## Jest + +### 安装依赖 + +```bash +$ npm i jest ts-jest -D +``` + +### 配置 + +首先需要在项目的根目录下新建 `jest.config.mjs` 文件,并加入以下内容: + +```js +import pkgService, { defineJestConfig } from '@ice/pkg'; + +export default defineJestConfig(pkgService, { + // 你也可以使用 @swc/jest 编译 TS 代码 + preset: 'ts-jest', +}); +``` + +`defineJestConfig()` 方法返回的是 ice.js 默认配置好的 Jest 配置,支持在第二个参数中传入自定义的 [Jest 配置](https://jestjs.io/docs/configuration),第二个参数的类型是: + +```ts +type UserJestConfig = jest.Config | () => Promise +``` + +以添加 `@swc/jest` 为例: + +```js title="jest.config.mjs" +import pkgService, { defineJestConfig } from '@ice/pkg'; + +export default defineJestConfig(pkgService, { + transform: { + '^.+\\.(t|j)sx?$': [ + '@swc/jest', + { + jsc: { + transform: { + react: { + runtime: 'automatic', + }, + }, + }, + }, + ], + }, +}); +``` + +然后在 `package.json` 中加入 `test` 脚本: + +```diff +{ + "scripts": { ++ "test": "jest" + } +} +``` + +### 编写测试用例 + +#### 非 UI 测试 + +假设现在要测试 `add()` 函数如下: + +```ts title="src/utils/add.ts" +export default function add(a, b) { + return a + b; +} +``` + +新建一个测试用例: + +```ts title="tests/add.spec.ts" +import add from '../src/add'; + +test('add function', () => { + expect(add(1, 2)).toBe(3); +}); +``` + +这时,运行 `npm run test` 查看测试结果了。 + +#### UI 测试 + +组件 UI 测试推荐使用 [@testing-library/react](https://www.npmjs.com/package/@testing-library/react) 和 [@testing-library/jest-dom](https://www.npmjs.com/package/@testing-library/jest-dom)。 + +首先安装依赖: + +```bash +$ npm i @testing-library/react jest-environment-jsdom @testing-library/jest-dom -D +``` + +然后在项目根目录下新建 `jest-setup.ts` 并写入以下内容,以扩展匹配器(matchers): + +```ts title="jest-setup.ts" +import '@testing-library/jest-dom'; +``` + +最后在 `jest.config.mjs` 中加入以下内容: + +```diff title="jest.config.mjs" +import pkgService, { defineJestConfig } from '@ice/pkg'; + +export default defineJestConfig(pkgService, { ++ setupFilesAfterEnv: ['/jest-setup.ts'], ++ testEnvironment: 'jest-environment-jsdom', +}); +``` + +假设现在要测试一个 Header 组件: + +```tsx title="src/components/Header.tsx" +export default function Header() { + return

Jest Test

; +} +``` + +编写组件的测试用例: + +```tsx title="tests/Header.spec.tsx" +import { render, screen } from '@testing-library/react'; +import Header from '../src/components/Header'; + +test('test Header component', () => { + render(
); + expect(screen.getByTestId('title')).toHaveTextContent('Jest Test'); +}); +``` + +最后,运行 `npm run test` 就可以查看测试结果了。 + +## Vitest + +### 安装依赖 + +```bash +$ npm i vitest -D +``` + +### 配置 + +首先需要在项目的根目录下新建 `vitest.config.mts` 文件,并加入以下内容: + +```js title="vitest.config.mts" +import pkgService, { defineVitestConfig } from '@ice/pkg'; + +export default defineVitestConfig(pkgService, {}); +``` + +`defineVitestConfig()` 方法返回的是 ice.js 默认配置好的 vitest 配置,支持传入自定义的 [vitest 配置](https://vitest.dev/config/)。 + +defineVitestConfig 第二个入参支持以下三种类型: + +- `vitest.UserConfig` +- `Promise` +- `(env) => Promise` + +以修改 `include` 参数为例: + +```diff title="vitest.config.mts" +import pkgService, { defineVitestConfig } from '@ice/pkg'; + +export default defineVitestConfig(pkgService, { ++ test: { ++ include: ['**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'] ++ } +}); +``` + +然后在 `package.json` 中加入 `test` 脚本: + +```diff title="package.json" +{ + "scripts": { ++ "test": "vitest" + } +} +``` + +### 编写测试用例 + +#### 非 UI 测试 + +请见 [Jest 非 UI 测试章节](#非-ui-测试)。 + +首先安装依赖: + +```bash +$ npm i @testing-library/react jsdom @testing-library/jest-dom -D +``` + +然后在项目根目录下新建 `vitest-setup.ts` 并写入以下内容,以扩展匹配器(matchers): + +```ts title="vitest-setup.ts" +import matchers from '@testing-library/jest-dom/matchers'; +import { expect } from 'vitest'; + +expect.extend(matchers); +``` + +最后在 `vitest.config.mts` 中加入以下内容: + +```diff title="vitest.config.mts" +import pkgService, { defineVitestConfig } from '@ice/pkg'; + +export default defineVitestConfig(pkgService, { ++ test: { ++ environment: 'jsdom', ++ setupFiles: ['./vitest-setup.ts'], ++ }, +}); +``` + +假设现在测试一个 Header 组件: + +```tsx title="src/components/Header.tsx" +export default function Header() { + return

Vitest Test

; +} +``` + +编写组件的测试用例: + +```tsx title="tests/Header.spec.tsx" +import { test, expect } from 'vitest'; +import { render, screen } from '@testing-library/react'; +import Header from '../src/components/Header'; + +test('test Header component', () => { + render(
); + expect(screen.getByTestId('title')).toHaveTextContent('Vitest Test'); +}); +``` + +最后,运行 `npm run test` 就可以查看测试结果了。 diff --git a/website/versioned_docs/version-v1/index.md b/website/versioned_docs/version-v1/index.md new file mode 100644 index 00000000..b1d3beb5 --- /dev/null +++ b/website/versioned_docs/version-v1/index.md @@ -0,0 +1,52 @@ +# ICE PKG + +ICE PKG 是飞冰开源的 NPM 包开发解决方案,默认支持 React 组件、Rax 组件、Node 模块、前端类库等多场景 NPM 包的研发。 + +## 特性 + +- **📈 更快**:使用 [SWC](https://swc.rs/docs/configuration/swcrc) 编译和压缩,提升数十倍编译速度 +- **🎊 双模式**:同时提供 Transform + Bundle 两种构建模式 +- **🅾️ 零配置**:无需任何配置,提供内建的 TypeScript、JSX 等构建支持 +- **☄️ 面向未来**:提供 ES2017 产物,打包出面向现代浏览器支持的产物 +- **☘️ 文档预览**:基于 [Docusaurus](https://docusaurus.io/) 提供预览文档、生成静态文档能力 + +### 更快 + +使用 SWC 与 [tsc](https://www.typescriptlang.org/)、[Babel](https://babeljs.io/) 编译同一个项目之间耗时对比: + +
+ benchmark + +
Above: benchmark 使用 飞冰 fusion pro 模板
+
+ +### 双模式 + +社区的众多方案如 [Microbundle](https://github.com/developit/microbundle)、[tsup](https://github.com/egoist/tsup) 均只支持打包模式 (将所有依赖文件打包成一个文件输出,下称 Bundle 模式)。但 Bundle 模式[并非总是最佳选择](https://github.com/ice-lab/icepkg/issues/301)。其中最为**显著的问题**在于:**对 Tree-Shaking 不友好**,无用的依赖总是会被打包到最终的输出产物中,继而影响应用的体积。 + +ICE PKG 除支持 Bundle 模式外,也默认支持了 Transform 模式(将文件挨个编译到输出目录)。更多内容请参考[构建能力 — 双模式构建](./guide/abilities#双模式构建)。 + +### ES2017 产物 + +为现代浏览器提供 ES2017 产物,可以减少产物体积,亦可加快执行速度。更多内容参考 [构建能力 — es2017 产物](./guide/abilities#es2017-产物)。 + +### 多场景 + +依赖 ICE PKG 强大的[双模式](#双模式)能力,支持多类场景的开发需求。包括但不限定于以下场景: + +- React 组件 +- Rax 组件 +- Node 模块 +- 前端类库 + +### 文档预览 + +结合 [Docusaurus](https://docusaurus.io/),ICE PKG 升级了文档预览的能力。更多内容参考 [指南 - 文档预览](./guide/preview)。 + +## 社区 + +如果你有疑问或者需要帮助,可以通过 [GitHub Issues](https://github.com/ice-lab/icepkg/issues) 来寻求帮助。 diff --git a/website/versioned_docs/version-v1/quick-start.md b/website/versioned_docs/version-v1/quick-start.md new file mode 100644 index 00000000..7bcb7b2c --- /dev/null +++ b/website/versioned_docs/version-v1/quick-start.md @@ -0,0 +1,74 @@ +# 快速开始 + +## 环境准备 + +### 1. Node.js + +使用 ICE PKG 开发前需要安装 [Node.js](https://nodejs.org),并确保 node 版本是 16.14 或以上。 + +### 2. 包管理工具 + +安装 Node.js 后,默认会包含 npm。在国内使用 npm 安装依赖可能会比较慢。建议使用 [cnpm](https://www.npmjs.com/package/cnpm) 的国内镜像源进行加速: + +```bash +$ npm install -g cnpm --registry=https://registry.npmmirror.com +# 验证 cnpm 安装是否成功 +$ cnpm -v +``` + +除此之外,你还可以使用 [pnpm](https://pnpm.io/)、[yarn](https://yarnpkg.com/) 等其他包管理工具。本文档仍以 npm 作为示例。 + +## 初始化 + +以 React 组件类型为例,通过以下命令,可以快速初始化一个项目: + +```bash +$ npm init @ice/pkg@latest react-component +``` + +选择 React 组件项目类型: + +```bash +? 请选择项目类型 (Use arrow keys) +❯ React 组件 + Node 模块 + 前端类库 + Rax 组件 +``` + +你还可以通过附加的命令行选项的方式指定你想要的模板和 npm 包名,比如: + +```bash +$ npm init @ice/pkg@latest react-component --template @ice/template-pkg-react --npmName my-react-component +``` + +## 启动项目 + +```bash +$ cd react-component +$ npm start +``` + +现在,访问 `http://localhost:4000`,即可查看组件 README 文档: + +![demo-readme](https://img.alicdn.com/imgextra/i2/O1CN01OctOw81JXuHCC6FhP_!!6000000001039-2-tps-1110-720.png) + +访问 `http://localhost:4000/usage`,即可预览组件: + +![component-preview](https://img.alicdn.com/imgextra/i3/O1CN01uEHuWp1DtXHv6uwax_!!6000000000274-2-tps-1160-540.png) + +## 生成构建产物 + +```shell +$ npm run build +``` + +## 发布产物 + +1. 在 `package.json` 中修改包名 + +2. 执行发布命令: + +```bash +$ npm publish +``` diff --git a/website/versioned_docs/version-v1/reference/cli.md b/website/versioned_docs/version-v1/reference/cli.md new file mode 100644 index 00000000..68e8357a --- /dev/null +++ b/website/versioned_docs/version-v1/reference/cli.md @@ -0,0 +1,29 @@ +# CLI + +## start + +启动本地调试服务。 + +```bash +$ ice-pkg start [options] +``` + +| 选项 | 类型 | 说明 | +| :-------------------: | :-------: | ----------------------------- | +| `--config ` | `string` | 指定配置文件路径 | +| `--rootDir ` | `string` | 指定应用运行的根目录 | +| `--analyzer` | `boolean` | Bundle 模式下开启体积构建分析 | + +## build + +执行编译或者打包构建,输出构建产物。 + +```bash +$ ice-pkg build [options] +``` + +| 选项 | 类型 | 说明 | +| :-------------------: | :-------: | ----------------------------- | +| `--config ` | `string` | 指定配置文件路径 | +| `--rootDir ` | `string` | 指定应用运行的根目录 | +| `--analyzer` | `boolean` | Bundle 模式下开启体积构建分析 | diff --git a/website/docs/reference/config.md b/website/versioned_docs/version-v1/reference/config.md similarity index 84% rename from website/docs/reference/config.md rename to website/versioned_docs/version-v1/reference/config.md index 97795171..fe051049 100644 --- a/website/docs/reference/config.md +++ b/website/versioned_docs/version-v1/reference/config.md @@ -78,7 +78,7 @@ export default defineConfig({ ### define - 类型:`Record` -- 默认值:`{ __DEV__: 'true' | 'false', 'process.env.NODE_ENV': '"development"' | '"production"', 'import.meta.vitest': 'undefined' }` +- 默认值:`{ __DEV__: 'true' | 'false', 'process.env.NODE_ENV': '"development"' | '"production"' }` 定义编译时环境变量,会在编译时被替换。注意:属性值会经过一次 `JSON.stringify()` 转换。 @@ -119,8 +119,6 @@ if (__DEV__) { 实际上,在编译时,`__DEV__` 会被替换为 `process.env.NODE_ENV !== 'production'`。 ::: -另外,ICE PKG 默认会将 `import.meta.vitest` 替换为 `undefined`。这意味着在源码里使用 Vitest 的 [in-source test](https://vitest.dev/guide/in-source.html) 写法时,非测试构建默认不会把对应测试逻辑保留到产物中。 - ### sourceMaps - 类型:`boolean | 'inline'` @@ -264,61 +262,18 @@ export default defineConfig({ - es2017 # ES module + ES2017 产物 ``` -#### entryRoot - -- 类型:`string` -- 默认值:自动推导(已配置 entry 父目录的最近公共祖先) - -用于控制 Transform 模式输出路径的相对根目录。该配置只影响产物路径映射,不影响文件处理范围。 - -例如,当 entry 是 `./src/a/b/c/index.ts`: - -- `entryRoot: './src/a/b'` 时,输出为 `esm/c/index.js` -- `entryRoot: './src'` 时,输出为 `esm/a/b/c/index.js` - -```ts title="build.config.mts" -import { defineConfig } from '@ice/pkg'; - -export default defineConfig({ - entry: './src/a/b/c/index.ts', - transform: { - formats: ['esm'], - entryRoot: './src/a/b', - }, -}); -``` - -当使用 `pkgs` 配置时,`pkgs[].entryRoot` 的优先级高于 `transform.entryRoot`。 - -```ts title="build.config.mts" -import { defineConfig } from '@ice/pkg'; - -export default defineConfig({ - transform: { - entryRoot: './src', - }, - pkgs: [ - { - id: 'button', - entry: './src/components/button/index.ts', - entryRoot: './src/components', - }, - ], -}); -``` - #### excludes - 类型:`string | string[]` -- 默认值:`['**/__tests__/**']` +- 默认值:`undefined` -排除无需编译的文件。默认会排除 `__tests__` 目录下文件。比如,我们还不想编译 `src` 下以 `*.test.[j|t]s` 结尾的测试文件。 +排除无需编译的文件。比如,我们不想编译 `src` 下的所有测试文件,其中测试文件包含在 `__tests__` 目录下,或以 `*.test.[j|t]s` 结尾。 ```ts title="build.config.mts" import { defineConfig } from '@ice/pkg'; export default defineConfig({ - transform: { + transfrom: { excludes: ['**/__tests__/**', '*.test.[j|t]s'], }, }); @@ -419,12 +374,10 @@ export default defineConfig({ #### externals -- 类型:`boolean | Record | (string | RegExp | Record)[]` -- 默认值:`false` +- 类型:`boolean | Record` +- 默认值:`true` -默认情况下,bundle 的产物包含所有依赖产物。该选项可修改这一结果。 -若想要 Bundle 不包含依赖产物,可以传入 `true`,其会解析 `package.json` 并将所有依赖 external 掉,包括 node 的依赖。 -适合针对 Node 环境的构建。 +默认情况下,bundle 的产物包含所有依赖产物。该选项可修改这一结果。若想要 Bundle 不包含依赖产物,可如下配置: ```ts title="build.config.mts" import { defineConfig } from '@ice/pkg'; @@ -436,18 +389,7 @@ export default defineConfig({ }); ``` -若想要自定义配置 externals,则可以直接传入想要 external 的依赖,支持字符串和正则表达式。 - -```ts title="build.config.mts" -import { defineConfig } from '@ice/pkg'; -export default defineConfig({ - bundle: { - externals: ['react', 'react-dom', /^@ice($|\/)/], - }, -}); -``` - -如果你选择构建 umd 格式,默认情况下会根据一定的规则生成从全局对象上获取依赖的名字,如果你想自定义,则可以直接传入一个对象来配置。 +若想要自定义配置 externals,参考如下配置: ```ts title="build.config.mts" import { defineConfig } from '@ice/pkg'; @@ -462,8 +404,6 @@ export default defineConfig({ }); ``` -当然,也可以进行混合使用。 - #### minify - 类型:`boolean | { js?: boolean | ((mode: string, command: string) => boolean | { options?: swc.JsMinifyOptions }); css?: boolean | ((mode: string, command: string) => boolean | { options?: cssnano.Options });}` diff --git a/website/docs/reference/plugins-development.md b/website/versioned_docs/version-v1/reference/plugins-development.md similarity index 87% rename from website/docs/reference/plugins-development.md rename to website/versioned_docs/version-v1/reference/plugins-development.md index 148cb7a9..37299a4a 100644 --- a/website/docs/reference/plugins-development.md +++ b/website/versioned_docs/version-v1/reference/plugins-development.md @@ -496,19 +496,19 @@ ICE PKG 插件提供以下生命周期钩子: - build 命令: -| 生命周期 | 参数 | 调用时机 | -| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ | -| before.build.load | `{ args: CommandArgs; config: PkgConfig[] }` | 获取所有任务配置后 | -| before.build.run | `{ args: CommandArgs; config: PkgConfig[] }` | 编译执行之前 | -| after.build.compile | `{ taskName: string; outputFiles: OutputFile[]; outputs?: Array; modules?: rollup.RollupCache['modules'] }` | 编译结束 | +| 生命周期 | 参数 | 调用时机 | +| :------------------ | :----- | :----------------- | +| before.build.load | Object | 获取所有任务配置后 | +| before.build.run | Object | 编译执行之前 | +| after.build.compile | Object | 编译结束 | - start 命令 -| 生命周期 | 参数 | 调用时机 | -| ------------------- | -------------------------------------------------------------------------------- | ------------------ | -| before.start.load | `{ args: CommandArgs; config: PkgConfig[] }` | 获取所有任务配置后 | -| before.start.run | `{ args: CommandArgs; config: PkgConfig[] }` | 编译执行之前 | -| after.start.compile | `{ taskName: string; outputFiles: OutputFile[]; modules?: rollup.ModuleJSON[] }` | 编译结束 | +| 生命周期 | 参数 | 调用时机 | +| :------------------ | :----- | :----------------- | +| before.start.load | Object | 获取所有任务配置后 | +| before.start.run | Object | 编译执行之前 | +| after.start.compile | Object | 编译结束 | ### registerTask diff --git a/website/versioned_sidebars/version-v1-sidebars.json b/website/versioned_sidebars/version-v1-sidebars.json new file mode 100644 index 00000000..0f90a0e5 --- /dev/null +++ b/website/versioned_sidebars/version-v1-sidebars.json @@ -0,0 +1,24 @@ +{ + "tutorialSidebar": [ + { "type": "doc", "id": "index" }, + { "type": "doc", "id": "quick-start" }, + { "type": "doc", "id": "guide/abilities" }, + { "type": "doc", "id": "guide/scenarios" }, + { "type": "doc", "id": "guide/build" }, + { "type": "doc", "id": "guide/publish" }, + { "type": "doc", "id": "guide/test" }, + { "type": "doc", "id": "guide/preview" }, + { "type": "doc", "id": "guide/jsx-plus" }, + { "type": "doc", "id": "guide/monorepo" }, + { + "type": "category", + "label": "参考", + "items": [ + { "type": "doc", "id": "reference/cli" }, + { "type": "doc", "id": "reference/config" }, + { "type": "doc", "id": "reference/plugins-development" } + ] + }, + { "type": "doc", "id": "faq", "label": "常见问题" } + ] +} diff --git a/website/versions.json b/website/versions.json new file mode 100644 index 00000000..868a38e3 --- /dev/null +++ b/website/versions.json @@ -0,0 +1 @@ +["v1"]