Karma 中的源映射 TypeScript
Sourcemapping TypeScript in Karma
我正在尝试使用 Webpack 为 TypeScript 设置构建过程。大多数部分一切正常。但是我无法让源映射在 Karma 测试运行器中正常工作。
问题描述
假设我有一个打字稿文件 test.spec.ts
(1)。该文件由 TypeScript 转译为带有内联源映射 (2) 的某些 ES5 源。最后,Webpack 4 使用 eval-source-maps (3) 将 ES5 源代码打包,并由 Karma 测试运行器提供给 Chrome。
通过检查 Chrome 中 Karma Debug Runner 中的源代码,我可以看到浏览器实际上可以使用所有三个转译阶段:
- (1) 源映射为
webpack://test.spec.ts?c161
- (2) 源映射为
webpack-internal://test.spec.ts
- (3) 可用作
localhost:9876/base/test.spec.ts
在 Chrome 控制台中,我还获得了测试执行期间抛出的所有错误的正确堆栈跟踪。正如我所料,这些包括源映射到 (1) 的行号。例如:
Error: Oh no!
at Function.MyClass.myBadMethod (test.spec.ts?c161:9)
at UserContext.eval (test.spec.ts?c161:21)
at <Jasmine>
然而,Karma 本身记录错误,行号仅源映射到 (2)。例如:
Error: Oh no!
at Function.MyClass.myBadMethod (webpack-internal:///./src/test.spec.ts:8:15)
at UserContext.eval (webpack-internal:///./src/test.spec.ts:17:17)
at <Jasmine>
这完全没有用,因为 (2) 只是一些中间源,甚至从未写入磁盘。事实上,我不需要 (2) 的源映射,也不明白为什么首先要包含它们。如果可能的话,我想尝试禁用它们(当然,同时为 (1) 保留适当的源映射)。
无论如何,重要的是让 Karma 报告堆栈跟踪,其中包含与原始文件相关的行号,就像在 Chrome 控制台中所做的那样。如果有必要,我也愿意用执行速度换取
如果你想不出一个完整的解决方案,但对 TypeScript / TS-Loader / Webpack / Karma-Webpack / Karma 有一些见解:我也对任何有助于查明问题的论据感兴趣沿着那个工具链。
最小测试配置
devDependencies 来自 package.json
"devDependencies": {
"@types/jasmine": "~2.8.7",
"jasmine": "~3.1.0",
"karma": "~2.0.2",
"karma-chrome-launcher": "~2.2.0",
"karma-jasmine": "~1.1.2",
"karma-webpack": "~3.0.0",
"ts-loader": "~4.3.0",
"typescript": "~2.8.3",
"webpack": "~4.8.3"
}
karma.conf.js
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
browsers: ['Chrome'],
files: [
'./test.spec.ts'
],
mime: {
'text/x-typescript': ['ts']
},
preprocessors: {
'**/*.ts': ['webpack']
},
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-webpack'
],
webpack: {
devtool: 'eval-source-map',
mode: 'development',
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader',
}
]
},
resolve: {
extensions: [ '.ts' ]
}
},
webpackMiddleware: {
logLevel: 'error'
}
});
};
tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"module": "es2015",
"moduleResolution": "node",
"sourceMap": true,
"target": "es5",
"types": [
"jasmine"
]
}
}
解决这个问题相当乏味。这里有几个问题:
webpack-internal://
源映射已作为一种变通方法添加到具有 eval 类型源映射的未命名 Chrome bug。
似乎其他浏览器如 Karma 启动器(以及 Firefox)仍然无法解释 eval 类型的源映射,因此退回到 webpack-internal://
。为了在这些浏览器中获得适当的源映射支持,您需要使用像 devtool: inline-source-map
这样的经典源映射。这也完全消除了 webpack-internal://
源映射。
- 当使用 karma-webpack 转译
.ts
文件时,仍然不会生成源映射。这是因为 karma-webpack 默认情况下会输出带有原始文件名的文件。 devtool: inline-source-map
设置了一个过滤器,只为 .css
和 .js
输出文件构建源映射。这可以通过显式配置 SourceMapDevToolPlugin 并提供包含 .ts
文件的 test
正则表达式来挽救。
- 一旦用
SourceMapDevtoolPlugin
替换了 devtool
设置,只会生成 webpack://
源映射,但在 development
模式下这些仍然是错误的。那是因为在这种模式下 devtool: eval
is added automatically 到配置。要禁用此行为,您必须显式设置 devtool: false
.
- 为了让 Karma 加载内联源地图,您需要应用 karma-sourcemap-loader.
将所有这些放在一起,问题的配置可以修复如下:
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
browsers: ['Chrome'],
files: [
'./test.spec.ts'
],
mime: {
'text/x-typescript': ['ts']
},
preprocessors: {
'**/*.ts': ['webpack', 'sourcemap']
},
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-sourcemap-loader',
'karma-webpack'
],
webpack: {
devtool: false,
mode: 'development',
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader',
}
]
},
plugins: [
new webpack.SourceMapDevToolPlugin({
test: /\.(ts|js|css)($|\?)/i
})
],
resolve: {
extensions: [ '.ts' ]
}
},
webpackMiddleware: {
logLevel: 'error'
}
});
};
我正在尝试使用 Webpack 为 TypeScript 设置构建过程。大多数部分一切正常。但是我无法让源映射在 Karma 测试运行器中正常工作。
问题描述
假设我有一个打字稿文件 test.spec.ts
(1)。该文件由 TypeScript 转译为带有内联源映射 (2) 的某些 ES5 源。最后,Webpack 4 使用 eval-source-maps (3) 将 ES5 源代码打包,并由 Karma 测试运行器提供给 Chrome。
通过检查 Chrome 中 Karma Debug Runner 中的源代码,我可以看到浏览器实际上可以使用所有三个转译阶段:
- (1) 源映射为
webpack://test.spec.ts?c161
- (2) 源映射为
webpack-internal://test.spec.ts
- (3) 可用作
localhost:9876/base/test.spec.ts
在 Chrome 控制台中,我还获得了测试执行期间抛出的所有错误的正确堆栈跟踪。正如我所料,这些包括源映射到 (1) 的行号。例如:
Error: Oh no!
at Function.MyClass.myBadMethod (test.spec.ts?c161:9)
at UserContext.eval (test.spec.ts?c161:21)
at <Jasmine>
然而,Karma 本身记录错误,行号仅源映射到 (2)。例如:
Error: Oh no!
at Function.MyClass.myBadMethod (webpack-internal:///./src/test.spec.ts:8:15)
at UserContext.eval (webpack-internal:///./src/test.spec.ts:17:17)
at <Jasmine>
这完全没有用,因为 (2) 只是一些中间源,甚至从未写入磁盘。事实上,我不需要 (2) 的源映射,也不明白为什么首先要包含它们。如果可能的话,我想尝试禁用它们(当然,同时为 (1) 保留适当的源映射)。
无论如何,重要的是让 Karma 报告堆栈跟踪,其中包含与原始文件相关的行号,就像在 Chrome 控制台中所做的那样。如果有必要,我也愿意用执行速度换取
如果你想不出一个完整的解决方案,但对 TypeScript / TS-Loader / Webpack / Karma-Webpack / Karma 有一些见解:我也对任何有助于查明问题的论据感兴趣沿着那个工具链。
最小测试配置
devDependencies 来自 package.json
"devDependencies": {
"@types/jasmine": "~2.8.7",
"jasmine": "~3.1.0",
"karma": "~2.0.2",
"karma-chrome-launcher": "~2.2.0",
"karma-jasmine": "~1.1.2",
"karma-webpack": "~3.0.0",
"ts-loader": "~4.3.0",
"typescript": "~2.8.3",
"webpack": "~4.8.3"
}
karma.conf.js
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
browsers: ['Chrome'],
files: [
'./test.spec.ts'
],
mime: {
'text/x-typescript': ['ts']
},
preprocessors: {
'**/*.ts': ['webpack']
},
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-webpack'
],
webpack: {
devtool: 'eval-source-map',
mode: 'development',
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader',
}
]
},
resolve: {
extensions: [ '.ts' ]
}
},
webpackMiddleware: {
logLevel: 'error'
}
});
};
tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"module": "es2015",
"moduleResolution": "node",
"sourceMap": true,
"target": "es5",
"types": [
"jasmine"
]
}
}
解决这个问题相当乏味。这里有几个问题:
webpack-internal://
源映射已作为一种变通方法添加到具有 eval 类型源映射的未命名 Chrome bug。 似乎其他浏览器如 Karma 启动器(以及 Firefox)仍然无法解释 eval 类型的源映射,因此退回到webpack-internal://
。为了在这些浏览器中获得适当的源映射支持,您需要使用像devtool: inline-source-map
这样的经典源映射。这也完全消除了webpack-internal://
源映射。- 当使用 karma-webpack 转译
.ts
文件时,仍然不会生成源映射。这是因为 karma-webpack 默认情况下会输出带有原始文件名的文件。devtool: inline-source-map
设置了一个过滤器,只为.css
和.js
输出文件构建源映射。这可以通过显式配置 SourceMapDevToolPlugin 并提供包含.ts
文件的test
正则表达式来挽救。 - 一旦用
SourceMapDevtoolPlugin
替换了devtool
设置,只会生成webpack://
源映射,但在development
模式下这些仍然是错误的。那是因为在这种模式下devtool: eval
is added automatically 到配置。要禁用此行为,您必须显式设置devtool: false
. - 为了让 Karma 加载内联源地图,您需要应用 karma-sourcemap-loader.
将所有这些放在一起,问题的配置可以修复如下:
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
browsers: ['Chrome'],
files: [
'./test.spec.ts'
],
mime: {
'text/x-typescript': ['ts']
},
preprocessors: {
'**/*.ts': ['webpack', 'sourcemap']
},
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-sourcemap-loader',
'karma-webpack'
],
webpack: {
devtool: false,
mode: 'development',
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader',
}
]
},
plugins: [
new webpack.SourceMapDevToolPlugin({
test: /\.(ts|js|css)($|\?)/i
})
],
resolve: {
extensions: [ '.ts' ]
}
},
webpackMiddleware: {
logLevel: 'error'
}
});
};