我正在重建我的 Gulp 实现,以使用最新版本的 Rollup 将 TypeScript 文件编译、缩小和压缩成一个包。新的实现已经完成并且可以正常工作,我可以从 Task Runner 或使用 Gulp 的文件系统观察器触发它,它完全按照我的需要去做。
我遇到的问题是,为了让 Rollup 看到模块导入,我不得不将“.ts”扩展名附加到导入中:
import { something } from "./Module.ts";
导致 Visual Studio 报错的原因:
TS2691:(TS)导入路径不能以“.ts”扩展名结尾。考虑改为导入“./Module.js”。
TypeScript 编译器似乎忽略了错误,因为当我运行 Gulp 任务时,它会按预期编译 TypeScript 文件。阅读有关“.ts”扩展名的 GitHub 讨论,最新版本的 TypeScript 的推荐解决方案似乎是向
tsconfig.json
文件添加几个属性:
{
"allowImportingTsExtensions": true,
"moduleResolution": "bundler",
"noEmit": true
}
这导致 Visual Studio 给出更多错误:
(TS) 未知的编译器选项“allowImportingTsExtensions”。
(TS) '--moduleResolution' 选项的参数必须是:'node'、'classic'、'node16'、'nodenext'。
所有这些最终导致我根本无法构建项目。现在,我只是在一个实验项目中,在弄清楚新的 Gulp 实现后我将放弃,但如果我将这些更改应用到我的实际项目中,那么我将永远无法编译它们。
我需要做什么来解决这些错误?我尝试在项目属性中抑制 TS2691,但没有效果。我还尝试从 NuGet TypeScript 包切换到 npm TypeScript 包,但也没有效果。作为参考,我使用的是 Visual Studio 2022、TypeScript 4.9.5 和 Rollup 3.17.3.
如果您使用的是现代捆绑器,请删除
allowImportingTsExtensions
,将moduleResolution
设置为"node"
,并将文件扩展名从导入中删除。现代捆绑器了解文件扩展名不存在。
如果您没有使用捆绑器,答案将是(在我看来很奇怪)您必须在您的
.js
语句中使用 import
,即使您的源文件是 .ts
文件。那是因为 TypeScript 不会重写模块说明符(作为 policy decision)。所以如果你有 index.ts
从 mod.ts
导入,你必须写 import { something } from "./mod.js";
这样它就像在编译器生成的 JavaScript 中一样,浏览器可以正确处理它。
TypeScript 5 发布后,我决定尝试一个没有作弊的干净解决方案,现在它按预期工作。我必须在 tsconfig.json 中设置以下内容:
{
"compilerOptions": {
"allowImportingTsExtensions": true,
"moduleResolution": "bundler"
}
}
我还删除了
gulp-replace
并将 gulp 任务减少为:
gulp.task(taskTsRollup, () => rollup.rollup({
input: inputTs,
plugins: [
rollupTypeScript,
rollupTerser()
]
}).then(
_ => _.write({
file: targetJs,
format: "iife",
sourcemap: false
})));
宣布 TypeScript 5.0 帖子中的更多信息。
最后我绕过了它。由于 Rollup 想要扩展而 TypeScript 不想要扩展,我决定给他们两个他们需要的东西。
为此,我首先有一个复制输入文件的 gulp 任务,因此从
Default.ts
到 Default.ts-copy
。然后使用 gulp-replace
我使用正则表达式匹配导入模式并重写值以包含扩展名。然后将复制和修改后的文件传递给 Rollup,它就完成了,最后我删除了复制文件。
这样我就可以让 TypeScript 对没有扩展感到满意,而 Rollup 会得到一个带有扩展的修改后的文件。都很开心。这是最后的 Gulp 任务:
gulp.task(taskTsRollup, gulp.series(
() => gulp
.src(inputTs)
.pipe(gulpRename(`${inputTs}-copy`))
.pipe(gulpReplace(/from\s+\".\/([a-zA-Z0-9_-]+)\"\;/g, "from \".\/$1.ts\";"))
.pipe(gulp.dest(`${rootResources}/Scripts`)),
() => rollup.rollup({
input: `${inputTs}-copy`,
plugins: [
rollupTypeScript,
rollupTerser()
]
}).then(
_ => _.write({
file: targetJs,
format: "iife",
sourcemap: false
})),
() => del([
`${rootResources}/Scripts/${inputTs}-copy`
])
));
也许未来 TypeScript 语言服务会跟随编译器的脚步,支持所有的配置选项。