Conversation
- Add scripts/add-esm-extensions.mjs to append .js extension to relative imports in es/ output - Update build script to run add-esm-extensions after father build - Fixes build failures with strict ESM tools (Rspack, Vite, Webpack 5 + type: module) - ESM spec requires fully specified paths (e.g. ./card/index.js not ./card) Co-authored-by: 陈帅 <wasd2144@hotmail.com>
|
Cursor Agent can help with this pull request. Just |
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes. 💤 Files selected but had no reviewable changes (1)
You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 Walkthrough漫游该变更将项目的构建工具链从 Father 迁移为 tsup + Father 的混合方案。tsup 现在负责生成 ESM 和 CJS 产物,而 Father 仅负责 UMD 构建。新增脚本用于重新组织输出结构和规范化 ESM 导入路径。 变更
预计代码审查工作量🎯 3 (中等) | ⏱️ ~25 分钟 诗歌
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @chenshuai2144, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 此拉取请求旨在增强项目对现代 ESM 构建工具的兼容性。通过引入一个自动化的构建后脚本,它确保所有 ESM 产物中的相对导入和导出路径都包含必要的 Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
| function resolveFullySpecifiedPath(baseDir, specifier) { | ||
| if (EXTENSION_PATTERN.test(specifier)) return specifier; | ||
|
|
||
| const resolvedPath = path.resolve(baseDir, specifier); | ||
|
|
||
| if (fs.existsSync(resolvedPath + '.js')) return specifier + '.js'; | ||
|
|
||
| if (fs.existsSync(path.join(resolvedPath, 'index.js'))) { | ||
| return (specifier.endsWith('/') ? specifier : specifier + '/') + 'index.js'; | ||
| } | ||
|
|
||
| return specifier + '.js'; | ||
| } |
There was a problem hiding this comment.
resolveFullySpecifiedPath 函数在处理无扩展名的导入路径时,可能不够健壮。当前实现会优先检查 .js 文件和 index.js,但对于其他类型的文件(如 .json),即使存在,它最终也会错误地回退到添加 .js 扩展名。例如,import data from './config' 在 config.json 存在的情况下会被错误地转换为 import data from './config.js'。
为了更准确地解析路径,建议在回退到默认添加 .js 之前,检查 EXTENSION_PATTERN 中定义的所有可能的文件扩展名(如 .js, .mjs, .cjs, .json)。
function resolveFullySpecifiedPath(baseDir, specifier) {
if (EXTENSION_PATTERN.test(specifier)) return specifier;
const resolvedPath = path.resolve(baseDir, specifier);
for (const ext of ['.js', '.mjs', '.cjs', '.json']) {
if (fs.existsSync(resolvedPath + ext)) {
return specifier + ext;
}
}
if (fs.existsSync(path.join(resolvedPath, 'index.js'))) {
return (specifier.endsWith('/') ? specifier : specifier + '/') + 'index.js';
}
return specifier + '.js';
}| function processFile(filePath) { | ||
| const content = fs.readFileSync(filePath, 'utf8'); | ||
| const baseDir = path.dirname(filePath); | ||
| const relativePathRegex = /(?:from|import)\s+['"](\.\.[\/\\][^'"]*|\.\/[^'"]*)['"]/g; |
| for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { | ||
| const fullPath = path.join(dir, entry.name); | ||
| if (entry.isDirectory()) walkDir(fullPath, callback); | ||
| else if (entry.name.endsWith('.js')) callback(fullPath); |
- Add tsup for ESM and CJS build (es/, lib/) - Configure father to only generate UMD (dist/) - Add scripts/tsup-restructure.mjs for output reorganization - Add tsup.config.ts with legacyOutput for es/lib structure Co-authored-by: 陈帅 <wasd2144@hotmail.com>
There was a problem hiding this comment.
Pull request overview
该 PR 通过在构建后对 es/ 产物进行一次“补全相对导入/导出 .js 扩展名”的处理,解决严格 ESM 工具链(Rspack / Vite / Webpack5 + "type":"module" 等)下因未 fully-specified 导致的构建失败问题。
Changes:
- 新增构建后脚本
scripts/add-esm-extensions.mjs,遍历es/下的.js文件并补全相对导入/导出路径的.js扩展名 - 调整
package.json的build脚本,在father build后执行该补全脚本
Reviewed changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| scripts/add-esm-extensions.mjs | 新增构建后处理脚本,尝试将 es/ 产物中的相对导入/导出路径改为 fully-specified(补 .js) |
| package.json | 将补全脚本串联进 build 流程,确保发布前产物被修正 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const EXTENSION_PATTERN = /\.(js|mjs|cjs|json)$/; | ||
|
|
||
| function resolveFullySpecifiedPath(baseDir, specifier) { | ||
| if (EXTENSION_PATTERN.test(specifier)) return specifier; |
There was a problem hiding this comment.
EXTENSION_PATTERN only treats .js/.mjs/.cjs/.json as “already fully specified”. If a relative specifier already has some other extension (e.g. .css/.svg/.wasm), this script will incorrectly append .js and rewrite it to something like ./asset.svg.js. Consider treating any path with a file extension as already fully specified (e.g. via path.extname() / path.posix.extname()), instead of a hard-coded allowlist.
| const EXTENSION_PATTERN = /\.(js|mjs|cjs|json)$/; | |
| function resolveFullySpecifiedPath(baseDir, specifier) { | |
| if (EXTENSION_PATTERN.test(specifier)) return specifier; | |
| function resolveFullySpecifiedPath(baseDir, specifier) { | |
| const hasExtension = path.posix.extname(specifier) !== ''; | |
| if (hasExtension) return specifier; |
| return (specifier.endsWith('/') ? specifier : specifier + '/') + 'index.js'; | ||
| } | ||
|
|
||
| return specifier + '.js'; |
There was a problem hiding this comment.
resolveFullySpecifiedPath() falls back to returning specifier + '.js' even when neither ${resolvedPath}.js nor ${resolvedPath}/index.js exists. That can silently produce invalid import paths in the output. Consider only rewriting when a target file is found (otherwise leave unchanged or emit a warning/error).
| return specifier + '.js'; | |
| return specifier; |
| newContent = newContent.replace(relativePathRegex, (match) => { | ||
| const pathMatch = match.match(/['"]([^'"]+)['"]/); | ||
| if (!pathMatch || !pathMatch[1].startsWith('.')) return match; | ||
|
|
||
| const normalized = pathMatch[1].replace(/\\/g, '/'); | ||
| const resolved = resolveFullySpecifiedPath(baseDir, normalized); | ||
| if (resolved !== normalized) { | ||
| hasChanges = true; | ||
| return match.replace(pathMatch[1], resolved); |
There was a problem hiding this comment.
The replace callback re-parses the matched substring with match.match(...) to extract the specifier. Since relativePathRegex already captures the specifier, using the callback’s capture-group argument avoids the extra regex pass and clarifies intent.
| newContent = newContent.replace(relativePathRegex, (match) => { | |
| const pathMatch = match.match(/['"]([^'"]+)['"]/); | |
| if (!pathMatch || !pathMatch[1].startsWith('.')) return match; | |
| const normalized = pathMatch[1].replace(/\\/g, '/'); | |
| const resolved = resolveFullySpecifiedPath(baseDir, normalized); | |
| if (resolved !== normalized) { | |
| hasChanges = true; | |
| return match.replace(pathMatch[1], resolved); | |
| newContent = newContent.replace(relativePathRegex, (match, specifier) => { | |
| if (!specifier || !specifier.startsWith('.')) return match; | |
| const normalized = specifier.replace(/\\/g, '/'); | |
| const resolved = resolveFullySpecifiedPath(baseDir, normalized); | |
| if (resolved !== normalized) { | |
| hasChanges = true; | |
| return match.replace(specifier, resolved); |
| "bootstrap": "node ./scripts/bootstrap.mjs", | ||
| "build": "father build", | ||
| "build": "tsup && node scripts/tsup-restructure.mjs && father build", | ||
| "changelog": "node ./scripts/changelogs.mjs", |
There was a problem hiding this comment.
Script paths elsewhere in this file use node ./scripts/<name>.mjs, but build uses node scripts/add-esm-extensions.mjs (missing ./). Aligning this keeps script invocation consistent and avoids surprises in tooling that assumes ./scripts/... patterns.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@package.json`:
- Line 32: The build script in package.json misses invoking
scripts/add-esm-extensions.mjs so ESM outputs won't get .js extensions; update
the "build" pipeline to run the add-esm-extensions script after
tsup-restructure.mjs (and before or after father build) so the ESM files are
post-processed—specifically ensure the current "tsup && node
scripts/tsup-restructure.mjs && father build" sequence includes a step to call
node scripts/add-esm-extensions.mjs (referencing scripts/add-esm-extensions.mjs,
tsup-restructure.mjs, and the build script entry) so ESM relative imports
receive .js extensions.
In `@scripts/add-esm-extensions.mjs`:
- Around line 18-30: The fallback in resolveFullySpecifiedPath blindly appends
".js" even when neither specifier.js nor specifier/index.js exist, which can
produce invalid MODULE_NOT_FOUND paths; update resolveFullySpecifiedPath to,
after checking EXTENSION_PATTERN, .js file and index.js, avoid forcibly
returning specifier + '.js' — instead return the original specifier (or keep it
unchanged) and emit a warning via console.warn or a logger that the specifier
could not be resolved, referencing the resolveFullySpecifiedPath function and
the specifier/resolvedPath variables when constructing the message.
In `@tsup.config.ts`:
- Around line 1-18: ESLint fails because tsup.config.ts (the file exporting
defineConfig from 'tsup') isn't included in the TypeScript project used by the
linter; update your TypeScript config by adding "tsup.config.ts" to the
tsconfig.json "include" array so the TypeScript parser can resolve this file, or
alternatively add an ESLint ignore rule (e.g., add "tsup.config.ts" to eslint's
ignorePatterns) so the linter skips it; modify either the tsconfig.json include
list or the ESLint ignorePatterns accordingly and rerun CI.
🧹 Nitpick comments (5)
scripts/tsup-restructure.mjs (2)
34-44: CJS 回退逻辑可能将非预期文件移入lib/。当
dist-tsup/cjs目录不存在时,回退逻辑会将dist-tsup根目录下除esm/cjs以外的所有文件移入lib/,这可能包括.d.ts、.d.ts.map、sourcemap 等不应出现在 CJS 产出中的文件。建议增加文件过滤条件,只移入.js和.js.map文件。♻️ 建议增加文件后缀过滤
for (const name of fs.readdirSync(root)) { - if (name !== 'esm' && name !== 'cjs') { + if (name !== 'esm' && name !== 'cjs' && (name.endsWith('.js') || name.endsWith('.js.map'))) { fs.renameSync(path.join(root, name), path.join('lib', name)); } }
19-21:rmSync和renameSync缺乏错误处理。如果
renameSync失败(例如跨文件系统),脚本会直接崩溃,且es/目录已被删除,导致构建产物丢失。对于构建关键路径上的脚本,建议增加 try-catch 或使用cpSync+rmSync作为renameSync的降级方案。scripts/add-esm-extensions.mjs (2)
35-35: 正则表达式未覆盖动态import()语法。当前正则
(?:from|import)\s+['"]...可以匹配静态import声明和from子句(包括export ... from),但无法匹配import('./foo')形式的动态导入。鉴于 tsup 配置中splitting: false,动态导入在当前产物中可能不存在,但如果未来启用 code splitting 或有其他使用场景,建议关注此限制。
40-48: 替换回调中重复进行了路径提取。正则
relativePathRegex已经捕获了组 1(相对路径),但replace回调未使用捕获组,而是在第 41 行用第二个正则重新提取路径。可利用replace回调的参数直接获取捕获组,减少冗余解析:♻️ 简化回调
- newContent = newContent.replace(relativePathRegex, (match) => { - const pathMatch = match.match(/['"]([^'"]+)['"]/); - if (!pathMatch || !pathMatch[1].startsWith('.')) return match; - - const normalized = pathMatch[1].replace(/\\/g, '/'); + newContent = newContent.replace(relativePathRegex, (match, captured) => { + if (!captured || !captured.startsWith('.')) return match; + + const normalized = captured.replace(/\\/g, '/'); const resolved = resolveFullySpecifiedPath(baseDir, normalized); if (resolved !== normalized) { hasChanges = true; - return match.replace(pathMatch[1], resolved); + return match.replace(captured, resolved); } return match; });tsup.config.ts (1)
16-16:legacyOutput在 tsup 中仍然有效,不存在弃用。
legacyOutput仍然是 tsup 的有效配置选项,并未被弃用。如果目标是将不同格式的输出分别放在不同的目录中,legacyOutput仍可继续使用。不过,可以考虑的替代方案包括:
- 使用
outExtension在单一目录中使用不同的文件扩展名(如.mjs和.cjs)- 使用多配置模式,为不同格式分别指定
outDir
| "scripts": { | ||
| "bootstrap": "node ./scripts/bootstrap.mjs", | ||
| "build": "father build", | ||
| "build": "tsup && node scripts/tsup-restructure.mjs && father build", |
There was a problem hiding this comment.
add-esm-extensions.mjs 未在构建脚本中调用——PR 的核心功能缺失。
当前构建脚本为 "tsup && node scripts/tsup-restructure.mjs && father build",但 scripts/add-esm-extensions.mjs(为 ESM 相对导入添加 .js 扩展名的脚本)从未被调用。这是本 PR 要解决的核心问题,缺少这一步意味着 ESM 产物中依旧缺少 .js 扩展名。
应在 tsup-restructure.mjs 之后、father build 之前(或之后)添加对该脚本的调用:
🐛 修复建议
- "build": "tsup && node scripts/tsup-restructure.mjs && father build",
+ "build": "tsup && node scripts/tsup-restructure.mjs && node scripts/add-esm-extensions.mjs && father build",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "build": "tsup && node scripts/tsup-restructure.mjs && father build", | |
| "build": "tsup && node scripts/tsup-restructure.mjs && node scripts/add-esm-extensions.mjs && father build", |
🤖 Prompt for AI Agents
In `@package.json` at line 32, The build script in package.json misses invoking
scripts/add-esm-extensions.mjs so ESM outputs won't get .js extensions; update
the "build" pipeline to run the add-esm-extensions script after
tsup-restructure.mjs (and before or after father build) so the ESM files are
post-processed—specifically ensure the current "tsup && node
scripts/tsup-restructure.mjs && father build" sequence includes a step to call
node scripts/add-esm-extensions.mjs (referencing scripts/add-esm-extensions.mjs,
tsup-restructure.mjs, and the build script entry) so ESM relative imports
receive .js extensions.
| function resolveFullySpecifiedPath(baseDir, specifier) { | ||
| if (EXTENSION_PATTERN.test(specifier)) return specifier; | ||
|
|
||
| const resolvedPath = path.resolve(baseDir, specifier); | ||
|
|
||
| if (fs.existsSync(resolvedPath + '.js')) return specifier + '.js'; | ||
|
|
||
| if (fs.existsSync(path.join(resolvedPath, 'index.js'))) { | ||
| return (specifier.endsWith('/') ? specifier : specifier + '/') + 'index.js'; | ||
| } | ||
|
|
||
| return specifier + '.js'; | ||
| } |
There was a problem hiding this comment.
当目标文件不存在时,回退逻辑仍会盲目追加 .js,可能产生无效路径。
第 29 行的最终 fallback 在 specifier.js 和 specifier/index.js 均不存在时,仍然返回 specifier + '.js'。这可能将一个本已正确的裸路径(如指向目录且 tsup 产出结构不同于预期时)改为一个不存在的 .js 路径,导致运行时 MODULE_NOT_FOUND。
建议在 fallback 时保留原始 specifier 不变,或至少输出一条警告:
♻️ 建议:无法解析时保留原路径并打印警告
if (fs.existsSync(path.join(resolvedPath, 'index.js'))) {
return (specifier.endsWith('/') ? specifier : specifier + '/') + 'index.js';
}
- return specifier + '.js';
+ // 无法确认目标文件存在,保留原始路径并警告
+ console.warn(`[warn] Cannot resolve: ${specifier} from ${baseDir}, keeping as-is`);
+ return specifier;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function resolveFullySpecifiedPath(baseDir, specifier) { | |
| if (EXTENSION_PATTERN.test(specifier)) return specifier; | |
| const resolvedPath = path.resolve(baseDir, specifier); | |
| if (fs.existsSync(resolvedPath + '.js')) return specifier + '.js'; | |
| if (fs.existsSync(path.join(resolvedPath, 'index.js'))) { | |
| return (specifier.endsWith('/') ? specifier : specifier + '/') + 'index.js'; | |
| } | |
| return specifier + '.js'; | |
| } | |
| function resolveFullySpecifiedPath(baseDir, specifier) { | |
| if (EXTENSION_PATTERN.test(specifier)) return specifier; | |
| const resolvedPath = path.resolve(baseDir, specifier); | |
| if (fs.existsSync(resolvedPath + '.js')) return specifier + '.js'; | |
| if (fs.existsSync(path.join(resolvedPath, 'index.js'))) { | |
| return (specifier.endsWith('/') ? specifier : specifier + '/') + 'index.js'; | |
| } | |
| // 无法确认目标文件存在,保留原始路径并警告 | |
| console.warn(`[warn] Cannot resolve: ${specifier} from ${baseDir}, keeping as-is`); | |
| return specifier; | |
| } |
🤖 Prompt for AI Agents
In `@scripts/add-esm-extensions.mjs` around lines 18 - 30, The fallback in
resolveFullySpecifiedPath blindly appends ".js" even when neither specifier.js
nor specifier/index.js exist, which can produce invalid MODULE_NOT_FOUND paths;
update resolveFullySpecifiedPath to, after checking EXTENSION_PATTERN, .js file
and index.js, avoid forcibly returning specifier + '.js' — instead return the
original specifier (or keep it unchanged) and emit a warning via console.warn or
a logger that the specifier could not be resolved, referencing the
resolveFullySpecifiedPath function and the specifier/resolvedPath variables when
constructing the message.
| import { defineConfig } from 'tsup'; | ||
|
|
||
| /** | ||
| * tsup 构建 ESM 和 CJS,输出到 es/、lib/ | ||
| * UMD 由 father 单独构建 | ||
| */ | ||
| export default defineConfig({ | ||
| entry: ['src/index.ts'], | ||
| format: ['esm', 'cjs'], | ||
| dts: true, | ||
| splitting: false, | ||
| sourcemap: true, | ||
| clean: true, | ||
| target: 'chrome109', | ||
| keepNames: true, | ||
| legacyOutput: true, | ||
| outDir: 'dist-tsup', | ||
| }); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check current tsconfig include/exclude settings
echo "=== tsconfig.json ==="
cat tsconfig.json 2>/dev/null || echo "Not found"
echo ""
echo "=== ESLint configuration files ==="
for file in .eslintrc .eslintrc.js .eslintrc.json .eslintrc.cjs .eslintrc.yml .eslintrc.yaml; do
if [ -f "$file" ]; then
echo "--- $file ---"
cat "$file"
echo ""
fi
done
echo ""
echo "=== .eslintignore ==="
cat .eslintignore 2>/dev/null || echo "No .eslintignore found"
echo ""
echo "=== tsup.config.ts location ==="
ls -la tsup.config.ts 2>/dev/null || echo "File not found in root"
echo ""
echo "=== package.json (for tsup version) ==="
cat package.json | head -50Repository: ant-design/pro-components
Length of output: 13137
🏁 Script executed:
#!/bin/bash
# Check tsup version
echo "=== Checking tsup version in package.json ==="
grep -A 5 -B 5 '"tsup"' package.json
echo ""
echo "=== package-lock.json or pnpm-lock.yaml for tsup version ==="
if [ -f "pnpm-lock.yaml" ]; then
echo "Found pnpm-lock.yaml, checking tsup..."
grep -A 5 "tsup:" pnpm-lock.yaml | head -20
elif [ -f "package-lock.json" ]; then
echo "Found package-lock.json, checking tsup..."
grep -A 5 '"tsup"' package-lock.json | head -20
fiRepository: ant-design/pro-components
Length of output: 796
🌐 Web query:
tsup 8.5.1 legacyOutput deprecated option
💡 Result:
In tsup v8.5.1, legacyOutput is the flag that puts different formats into separate folders (e.g. dist/cjs/* and dist/esm/*) instead of using different file extensions. Its schema description is: “Output different formats to different folder instead of using different extension”. [1]
If you’re seeing a deprecation warning for legacyOutput, the supported path forward is to stop using the folder-splitting layout and use extension-based output, optionally customized via outExtension (available in the v8.5.1 config types). [2]
Example replacement:
// tsup.config.ts
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
format: ["cjs", "esm"],
// legacyOutput: true, // remove
outExtension({ format }) {
return { js: format === "cjs" ? ".cjs" : ".mjs" };
},
});Sources: [1] (tsup 8.5.1 schema.json), [2] (tsup 8.5.1 dist/index.d.ts).
CI 失败:ESLint 无法解析此文件,因为 tsup.config.ts 未包含在 TypeScript 配置中。
tsup.config.ts 不在 tsconfig.json 的 include 列表中,但 ESLint 配置中指定了 project: './tsconfig.json',导致 TypeScript 解析器无法处理此文件。需要将 tsup.config.ts 加入 tsconfig.json 的 include 列表,或在 ESLint 的 ignorePatterns 中添加此文件的忽略规则。
🧰 Tools
🪛 GitHub Actions: Build CI
[error] 1-1: ESLint parsing error: TS config does not include this file. tsup.config.ts is not included in the configured TS config. This caused 120 problems (1 error, 119 warnings).
🤖 Prompt for AI Agents
In `@tsup.config.ts` around lines 1 - 18, ESLint fails because tsup.config.ts (the
file exporting defineConfig from 'tsup') isn't included in the TypeScript
project used by the linter; update your TypeScript config by adding
"tsup.config.ts" to the tsconfig.json "include" array so the TypeScript parser
can resolve this file, or alternatively add an ESLint ignore rule (e.g., add
"tsup.config.ts" to eslint's ignorePatterns) so the linter skips it; modify
either the tsconfig.json include list or the ESLint ignorePatterns accordingly
and rerun CI.
为 ESM 产物中的相对导入添加
.js扩展名,以兼容严格 ESM 构建工具。此 PR 修复了在使用 Rspack、Vite 或 Webpack 5 + "type": "module" 等严格 ESM 兼容的构建工具时,由于
@ant-design/pro-components/es/index.js中导出语句缺少.js扩展名导致的构建失败。解决方案是保留father构建,并添加一个构建后脚本scripts/add-esm-extensions.mjs来自动补全.js扩展名。Summary by CodeRabbit
版本发布说明