如何防止karma-webpack创建供应商代码的源映射?

时间:2016-12-21 02:56:18

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

对于Karma测试跑步者来说,我经历了非常缓慢的“启动”时间,并且在对运行进行分析之后,我意识到最大的减速是由源地图的创建引起的。

更具体地说,鉴于我正在使用karma-webpack和webpack作为预处理器,每次测试文件由karma加载时,都会将其提供给webpack,后者会为其生成源地图。

鉴于我没有拆分/分块我的应用和供应商代码,每个测试文件都获得相同的供应商源地图(内联)。

我认为我可以通过简单地阻止node_modules/文件的源映射来解决这个问题,但是我意识到你只能根据最终资产文件而不是输入源/模块来排除获取源映射的文件文件。

所以我找到了this插件来自动将我的应用和供应商代码拆分成单独的块(而不是必须手动列出每个供应商模块)。

但是在运行Karma时我开始遇到这个错误: ReferenceError: Can't find variable: webpackJsonp

我很确定这是因为Karma没有意识到供应商和应用程序代码被拆分成单独的块,因此只包含配置了files选项的代码(即测试文件本身而不是供应商文件)。

似乎在每个测试文件进行预处理之前解析并处理了files配置选项,这意味着我认为不可能在files选项中指定供应商块,因为Karma在尝试寻找它时不会知道它(太早)。

我能看到的唯一解决方案是:

  • 更改实施Karma的方式,以便它可以处理供应商和应用程序块文件的分离。
  • 不是使用karma-webpack和预处理,而是在测试模式下构建应用程序,然后运行测试构建目录的Karma(以便供应商块能够及早存在)。

有没有我错过的解决方案?

我觉得奇怪的是它似乎不是一个常见的问题。

修改1

我找到this,但那里的人建议在webpack配置中使用多个入口点(即一个用于app,一个用于供应商)。我会尝试看看这是否适用于Karma,但它仍然有一个很大的缺点(在我看来)你必须手动跟踪你放在vendor数组中的内容。即每次安装软件包时都必须将其添加到阵列中,反之亦然。

修改2

在配置源映射webpack插件以排除供应商文件之前,使用多个入口点(在webpack配置中)甚至不起作用(而使用webpack-split-by-path插件时)。

我将尝试实施“先构建然后测试”的方法。

1 个答案:

答案 0 :(得分:1)

如果有其他人遇到这个问题,我得到了#34;构建然后休息"接近工作,即我放弃了karma-webpack和Karma预处理,转而使用单独的构建和测试命令(一个接一个地运行)。

这是我的webpack配置,专门用于测试(例如webpack.config.babel.test.js):

import webpack from 'webpack';
import { join, resolve, parse } from 'path';
import SplitByPathPlugin from 'webpack-split-by-path';
import file from 'file';

const plugins = [
  new SplitByPathPlugin([
    {
      name: 'vendor',
      path: resolve(__dirname, 'node_modules')
    }
  ]),

  new webpack.SourceMapDevToolPlugin({
    test: /\.jsx?$/,
    exclude: [/vendor/]
  })
];

const entryPoints = {};
const testFileRegex = new RegExp('\.test\.jsx?$');
const pathPrefixRegex = new RegExp('^src/js/?');

file.walkSync('src/js/', (dirPath, dirs, files) => {
  for (const file of files) {
    if (file.match(testFileRegex)) {
      const parsedPath = parse(file);
      const entryKey = join(
        dirPath.replace(pathPrefixRegex, ''),
        parsedPath.name
      );
      entryPoints[entryKey] = './' + join(dirPath, parsedPath.name);
    }
  }
});

const config = {
  entry: entryPoints,
  output: {
    filename: '/[name]-[chunkhash].js',
    chunkFilename: '/[name]-[chunkhash].js',
    path: resolve(__dirname, 'dist-test'),
    pathinfo: true
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader!eslint-loader',
        exclude: [/node_modules/],
      },
      {
        test: /\.json$/, loader: 'json'
      }
    ],
  },
  bail: true,
  resolve: {
    extensions: ['', '.js', '.jsx', '.json'],
  },
  plugins: plugins,
  stats: {
    assets: false,
    cached: false,
    children: false,
    chunks: false,
    chunkModules: false,
    chunkOrigins: false,
    hash: false,
    modules: false,
    publicPath: false,
    reasons: false,
    source: false,
    timings: false,
    version: false,
    warnings: false
  },
  node: {
    child_process: 'empty',
    fs: 'empty'
  },
  externals: {
    'react/addons': true,
    'react/lib/ExecutionEnvironment': true,
    'react/lib/ReactContext': 'window'
  }
};

export default config;

关键部分是它为每个测试文件创建一个入口点,并在生成块时使用webpack-split-by-path插件自动将应用程序与供应商代码分开。

这是我参加的业力配置:

process.env.BABEL_ENV = 'test';

function karmaConfig(config) {
  config.set({
    basePath: '',
    frameworks: ['mocha'],
    files: [
      {
        pattern: 'dist-test/vendor-*.js',
        watched: false
      },
      'dist-test/**/*.test-*js?(x)'
    ],
    exclude: [],
    reporters: ['progress'],
    port: 9876,
    colors: true,
    browsers: ['Firefox', 'Chrome'],
    singleRun: true,
    logLevel: config.LOG_ERROR
  })
}

export default karmaConfig;

关键部分是供应商文件首先列在files配置选项中,并设置为不被监视,然后是测试文件。这可确保始终为每个测试用例加载/插入供应商代码。

我的问题是否有另一种方式,但这种方法效果很好。表现要好得多。

修改1

这种方法的唯一缺点(我最初没有意识到)是你无法像karma-webpack和预处理那样真正实现测试观看(通过webpack),因为构建和测试步骤的分离。

修改2

每次更改应用程序代码时,此方法都会出现重新编译供应商代码的问题(即使您没有添加/删除任何供应商库)。这样可以减少冗余的速度。​​

您想要解决此问题以及能够再次开始测试的目的是:

  1. 在监视模式下运行Webpack,只要应用程序代码发生变化,就可以构建到dist-test/目录中。
  2. 以监视模式运行Karma,指向dist-test/目录中正在更新的所有测试文件。
  3. 这个解决方案是完美的,除了你可以在一个npm / yarn命令中运行这两个东西的一个缺点。

    注意:Webpack测试版本的输出文件名不应包含任何哈希值(即文件名在其内容更改之间应保持一致)。这样,当您更改测试文件时,您不会运行旧的和新的测试代码(因为Webpack不会删除旧文件)。