Karma

时间:2018-05-16 15:04:05

标签: typescript webpack karma-runner source-maps karma-webpack

我正在尝试使用Webpack为TypeScript设置构建过程。一切都适用于大多数零件。但是我无法让源映射在Karma测试运行器中正常工作。

问题描述

假设我有一个打字稿文件test.spec.ts(1)。 TypeScript将此文件转换为具有内联源映射的某个ES5源(2)。最后,Web5使用 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有一些见解:我也对任何有助于查明问题的论点感兴趣工具链。

最小测试配置

来自package.json

devDependencies
"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"
        ]
    }
}

1 个答案:

答案 0 :(得分:3)

弄清楚这一点很乏味。这里有两个问题:

  1. webpack-internal://源映射已作为解决方法添加到具有eval类型源映射的未命名Chrome bug。 似乎其他浏览器(如Karma启动器(以及Firefox))仍然无法解释eval类型的源映射,因此会退回到webpack-internal://。为了在这些浏览器中获得适当的源地图支持,您需要使用经典的源地图,例如devtool: inline-source-map。这也完全消除了webpack-internal://源映射。
  2. 在使用karma-webpack编译.ts文件时,仍然不会生成源映射。这是因为默认情况下,karma-webpack会输出带有原始文件名的文件。并且devtool: inline-source-map将过滤器设置为仅为.css.js输出文件构建源映射。可以通过显式配置SourceMapDevToolPlugin并提供包含test文件的.ts正则表达式来解决此问题。
  3. devtool替换SourceMapDevtoolPlugin设置后,只会生成webpack://个源映射,但是在development模式下,它们仍然是错误的。这是因为在此模式下devtool: eval is added automatically进入配置。要禁用此行为,必须显式设置devtool: false
  4. 要使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'
        }
    });
};