【问题标题】:How to prevent karma-webpack from creating source maps of vendor code?如何防止 karma-webpack 创建供应商代码的源映射?
【发布时间】:2017-05-06 09:09:42
【问题描述】:

我遇到了 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 配置中使用多个入口点(即一个用于应用程序,一个用于供应商)。我会尝试看看这是否适用于 Karma,但它仍然有一个很大的缺点(在我看来),您必须手动跟踪您在 vendor 数组中放入的内容。 IE。每次安装软件包时,都必须将其添加到数组中,反之亦然。

编辑 2

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

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

【问题讨论】:

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


    【解决方案1】:

    如果其他人遇到这个问题,我得到了“构建然后休息”的方法,即我放弃了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/ 目录中正在更新的所有测试文件。

    这个解决方案是完美的,除了你不能在一个 npm/yarn 命令中运行这两个东西的一个缺点。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-27
      • 1970-01-01
      • 2017-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-30
      相关资源
      最近更新 更多