背景
我有一组包,我使用类似的结构在整个个人项目中重用它们。
出于生产目的,它们是用TypeScript编写的,并在发布到npm之前通过tsc编译成JavaScript,这样我就可以将它们安装在其他项目中。我还使用Jasmine对它们进行了测试。
在开发中,我使用Webpack及其ts-loader编译TypeScript,使我可以在浏览器中运行的脚本中使用它。我通常也会在我的项目中使用Webpack,在我使用这些包时,虽然它们是在发布之前编译的,但是这些项目将只将它们视为JavaScript,而不需要使用ts-loader。
我在任何地方都使用ES模块语法,这样我就可以在每个上下文中轻松地使用相同的语法,而不用担心在浏览器中切换CommonJS for Node和ES模块语法。为了在茉莉花中允许这样做,我在我的jasmine.json配置文件中设置了"jsLoader": "import"。
关于如何编写import语句,我遇到了一个问题。特别是,如何以一种方式指定文件扩展名,以便在开发这些包时为每个用例工作。
无文件扩展名
打字记录节点模块解析对文件扩展名做了一些有用的假设:
TypeScript将模仿Node.js运行时解析策略,以便在编译时找到模块的定义文件。为此,TypeScript在节点的解析逻辑上覆盖TypeScript源文件扩展名(.ts、.tsx和.d.ts)。
这意味着,如果我使用诸如import { foo } from './foo';之类的代码,那么TypeScript将理解查找一个名为foo.ts的文件。
类似地,配置对象允许在extensions属性中指定一组文件扩展名,告诉Webpack如何尝试解析没有文件扩展名的导入。因此,使用我的extensions: ['.js', '.ts']配置,它将找到与TypeScript相同的foo.ts文件。
但是,当我试图使用没有文件扩展名的import 在茉莉花中运行测试时,它无法解析.。
C:\Users\mark.hanna\Documents\Code Playground\analyser>npm test
> analyser@0.1.0 test C:\Users\mark.hanna\Documents\Code Playground\analyser
> tsc && jasmine
Error: While loading C:/Users/mark.hanna/Documents/Code Playground/analyser/spec/analyser.spec.js: NodeError: Cannot find module 'C:\Users\mark.hanna\Documents\Code Playground\analyser\dist\file-processing' imported from C:\Users\mark.hanna\Documents\Code Playground\analyser\dist\analyser.js
at C:\Users\mark.hanna\Documents\Code Playground\analyser\node_modules\jasmine\lib\loader.js:22:30
at async Jasmine._loadFiles (C:\Users\mark.hanna\Documents\Code Playground\analyser\node_modules\jasmine\lib\jasmine.js:182:5)
at async Jasmine.loadSpecs (C:\Users\mark.hanna\Documents\Code Playground\analyser\node_modules\jasmine\lib\jasmine.js:173:3)
at async Jasmine.execute (C:\Users\mark.hanna\Documents\Code Playground\analyser\node_modules\jasmine\lib\jasmine.js:479:3)
npm ERR! Test failed. See above for more details..js扩展
另一个选项是在导入中指定.js文件扩展名,例如import { foo } from './foo.js。
虽然我还没有找到清晰的文档,但类型记录的模块解析也清楚地理解了./foo.js可能实际上意味着./foo.ts。我发现对此的引用是支持自TypeScript 2
这意味着我可以指定.js文件扩展名,并且仍然可以使用tsc正确地编译代码。然后,我还能够正确地运行茉莉花测试,因为它了解如何在包含文件扩展名时进行模块解析。
然而,Webpack并不明白./foo.js ./foo.ts**. 实际上可能意味着./foo.ts**.。因此,使用这种方法,当将代码导入脚本以在浏览器中显示示例时,我无法在包中构建代码。
ERROR in ./src/file-processing.ts 2:0-49
Module not found: Error: Can't resolve './AnalyserRows.js' in 'C:\Users\mark.hanna\Documents\Code Playground\analyser\src'
resolve './AnalyserRows.js' in 'C:\Users\mark.hanna\Documents\Code Playground\analyser\src'
using description file: C:\Users\mark.hanna\Documents\Code Playground\analyser\package.json (relative path: ./src)
Field 'browser' doesn't contain a valid alias configuration
using description file: C:\Users\mark.hanna\Documents\Code Playground\analyser\package.json (relative path: ./src/AnalyserRows.js)
no extension
Field 'browser' doesn't contain a valid alias configuration
C:\Users\mark.hanna\Documents\Code Playground\analyser\src\AnalyserRows.js doesn't exist
.js
Field 'browser' doesn't contain a valid alias configuration
C:\Users\mark.hanna\Documents\Code Playground\analyser\src\AnalyserRows.js.js doesn't exist
.ts
Field 'browser' doesn't contain a valid alias configuration
C:\Users\mark.hanna\Documents\Code Playground\analyser\src\AnalyserRows.js.ts doesn't exist
as directory
C:\Users\mark.hanna\Documents\Code Playground\analyser\src\AnalyserRows.js doesn't exist
@ ./src/analyser.ts 4:0-48 69:0-50
@ ./docs/assets/js/src/docs-script.ts 2:0-53 7:14-36 34:14-36 43:14-36 48:51-68 49:28-45Webpack别名的.js扩展
到目前为止,我发现的唯一解决方案是我真正不喜欢的解决方案,就是使用Webpack的resolve.alias配置来明确地告诉它,当我说./foo.js时,我指的是./foo.ts。
例如,我目前在我的@cipscis/csv项目中使用了这种方法:
resolve: {
extensions: ['.js', '.ts'],
alias: {
'@cipscis/csv': `${srcPath}/csv.ts`,
'./stringify.js': './stringify.ts',
'./parse.js': './parse.ts',
},
},不过,这感觉很笨重,我必须为导入的每个文件指定这样的别名,这样它就不会有很大的可伸缩性。我觉得肯定有一种“正确”的方法来做这件事?
发布于 2021-09-07 00:11:24
截至2022年的答复
Webpack诉5.74.0是在2022年7月发布的,它包含了一个新的resolve.extensionAlias选项,可以在不需要插件的情况下解决这个问题。
例如:
resolve: {
extensionAlias: {
'.js': ['.ts', '.js'],
},
}截至2021-09-07
多亏了阿莫斯克对我对一个相关问题的回答,我现在有了这个问题的答案。
茉莉花在这里有点像一只红鲱鱼,真正相关的只有ES模块的解析度,它试图做的是我的设置。这个问题的核心是Webpack的模块解决方案无法复制类型记录模块解析规则的功能,在该规则中,它将*.js路径视为指向*.ts文件的潜在指向。
感谢amosq的评论,我能够通过使用Webpack解析器插件:解决-类型记录-插件来解决这个问题。
它的说明只显示了如何在CommonJS语法中使用它,尽管正如我在问题中提到的,我正在尽可能地使用ES模块语法。为了在Webpack配置中使用它,我执行了以下操作:
import resolveTypeScriptPluginModule from 'resolve-typescript-plugin';
const ResolveTypeScriptPlugin = resolveTypeScriptPluginModule.default;
const config = {
// ...
resolve: {
fullySpecified: true,
plugins: [new ResolveTypeScriptPlugin()],
// ...
},
// ...
};这个设置允许我使用Webpack与ts-loader一起编译在导入语句中使用*.js的TypeScript文件,作为我也使用tsc编译这些文件的设置的一部分。我不再需要使用我在问题末尾提到的Webpack化名。
https://stackoverflow.com/questions/69008462
复制相似问题