Как запретить karma-webpack создавать исходные карты кода вендора?

У меня было очень медленное время «загрузки» для запуска тестов Karma, и после профилирования запуска я понял, что самое большое замедление было вызвано созданием исходных карт.

В частности, учитывая, что я использую karma-webpack и веб-пакет в качестве препроцессора, каждый раз, когда тестовый файл загружается кармой, он передается в веб-пакет, который генерирует для него исходную карту.

Учитывая, что я не разделял код приложения и поставщика на части, каждый тестовый файл получал одну и ту же исходную карту поставщика (встроенную).

Я думал, что смогу исправить это, просто предотвратив сопоставление исходного кода для node_modules/ файлов, но понял, что вы можете исключить файлы из сопоставления исходного кода только на основе конечных файлов ресурсов, а не на входных файлах исходного кода/модуля.

Поэтому я нашел этот плагин для автоматического разделения моего кода приложения и кода поставщика на отдельные части. (в отличие от необходимости вручную перечислять каждый модуль поставщика).

Тем не менее, я начал получать эту ошибку при запуске Karma: ReferenceError: Can't find variable: webpackJsonp

Я почти уверен, что это вызвано тем фактом, что Karma не улавливает тот факт, что код поставщика и приложения разбивается на отдельные фрагменты и, следовательно, включает только код, сконфигурированный с опцией files (т. е. сами тестовые файлы и а не файл поставщика).

Кажется, что этот параметр конфигурации files анализируется и обрабатывается до того, как каждый тестовый файл будет предварительно обработан, что означает, что я не думаю, что возможно указать чанк поставщика в параметре files, потому что Карма не будет знать об этом в то время он пытается искать его (слишком рано).

Единственные решения, которые я вижу, это:

  • Измените способ реализации Karma, чтобы он мог обрабатывать разделение файлов поставщиков и приложений.
  • Вместо использования karma-webpack и предварительной обработки создайте приложение в тестовом режиме, а затем запустите Karma из каталога тестовой сборки (чтобы фрагмент поставщика существовал достаточно рано).

Есть ли решение, которое я пропустил?

Мне кажется странным, что это не распространенная проблема.

Изменить 1

Я нашел это, но люди предлагают использовать несколько точек входа в конфигурация веб-пакета (т. е. один для приложения и один для поставщика). Я попытаюсь посмотреть, работает ли это с Karma, но у него все еще есть большой недостаток (на мой взгляд): вам нужно вручную отслеживать то, что вы помещаете в массив vendor. т.е. каждый раз, когда вы устанавливаете пакет, вы должны добавить его в массив и наоборот.

Изменить 2

Использование нескольких точек входа (в конфигурации веб-пакета) не работает даже до того, как я настрою плагин веб-пакета исходной карты для исключения файлов поставщиков (тогда как это было бы с плагином webpack-split-by-path).

Я собираюсь попробовать реализовать подход «сначала построить, а затем протестировать».


person pleasedesktop    schedule 21.12.2016    source источник


Ответы (1)


Если кто-то еще столкнется с этой проблемой, у меня работает подход «сборка, а затем отдых», то есть я отказался от предварительной обработки karma-webpack и Karma в пользу отдельных команд сборки и тестирования (которые запускаются одна за другой).

Вот моя конфигурация веб-пакета, специфичная для тестирования (например, 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 и предварительной обработкой (с помощью веб-пакета), из-за разделения сборки и шаги теста.

Изменить 2

Этот подход страдал от проблемы повторной транспиляции кода поставщика каждый раз, когда вы меняете код приложения (даже если вы не добавляли/не удаляли библиотеки поставщиков). Это чрезмерно замедлило ход событий.

Что вы хотите сделать, чтобы решить эту проблему, а также иметь возможность снова начать тестовый просмотр:

  1. Запускайте Webpack в режиме наблюдения, чтобы встраиваться в каталог dist-test/ всякий раз, когда изменяется код вашего приложения.
  2. Запустите Karma в режиме просмотра, указав на все тестовые файлы, которые обновляются в каталоге dist-test/.

Это решение идеально, за исключением одного недостатка: вы не можете запустить обе эти вещи в одной команде npm/yarn.

Примечание. Имена выходных файлов для тестовой сборки Webpack не должны содержать никаких хэшей (т. е. имена файлов должны оставаться согласованными между изменениями их содержимого). Это сделано для того, чтобы при изменении тестового файла вы не запускали старый и новый тестовый код (поскольку Webpack не удаляет старый файл)..

person pleasedesktop    schedule 21.12.2016