Как я оптимизировал время запуска проекта vue с 70 до 7 с?

Webpack
Как я оптимизировал время запуска проекта vue с 70 до 7 с?

Ужасное время запуска

Продукт компании представляет собой относительно большую систему фонового управления, в которой используется шаблонный проект vue из webpack 3. Время запуска одного проекта достигает около 70 с.

image.png

Для запуска проекта достаточно съесть тарелку тофу-мозгов, а если нет тофу-мозгов, то оптимизируйте время запуска!

Учитывая, что риск обновления версии веб-пакета все еще относительно высок, я должен прийти ко мне, если возникнут какие-либо проблемы.Я думаю, что лучше сначала не рисковать, а быть в безопасности, поэтому я решил оптимизировать время сборки через плагины.

Консультируясь с информацией, есть следующие направления для улучшения времени сборки веб-пакета:

  • Обрабатывать файлы в нескольких процессах, обрабатывать несколько файлов одновременно
  • Предварительно компилируемые ресурсные модули, такие как извлечение долгосрочных неизменных библиотек для предварительной компиляции, и просто принять результаты компиляции напрямую при строительстве
  • Кэши, немодифицированный модуль напрямую получают результаты, без компиляции
  • Уменьшите количество файлов, которые ищет и обрабатывает сборка.

Для указанных выше направлений оптимизации даны следующие схемы оптимизации.

многопроцессная сборка

happypack

Роль happypack состоит в том, чтобы разбить задачу анализа файла на несколько подпроцессов для одновременного выполнения.

Дочерний процесс обрабатывает задачу, а затем отправляет результат основному процессу. Таким образом, скорость компонента проекта Webpack может быть значительно улучшена.

Глядя на github happypack, я обнаружил, что автор больше не поддерживает плагин, и автор рекомендует использовать официальный загрузчик потоков многопроцессорного плагина webpack, поэтому я отказался от happypacy и выбрал thread-loader.

thread-loader

thread-loaderЭто официально поддерживаемый многопроцессорный загрузчик, его функция аналогична happypack, но он также параллельно парсит файлы, открывая подзадачи, тем самым повышая скорость сборки.

Поместите этот загрузчик перед другими загрузчиками. Однако загрузчик ограничен. Пример:

  • Загрузчик не смог передать файл.
  • Загрузчики не могут использовать пользовательский API загрузчика.
  • Загрузчик не может получить доступ к опции webpack.

Каждый рабочий процесс — это отдельный процесс node.js с накладными расходами около 600 мс. Существуют также накладные расходы на межпроцессное взаимодействие. Использование в небольших проектахthread-loaderЭто может не оптимизировать скорость строительства проекта, но замедлит скорость строительства, поэтому при использовании данного загрузчика необходимо уточнить реальный трудоемкий процесс в строительстве проекта.

В моем проекте я в основном использую этот загрузчик для разбора файлов vue и js, воздействуя наvue-loaderиbabel-loader, следующий код:

const threadLoader = {
  loader: 'thread-loader',
  options: {
    workers: require('os').cpus().length - 1,
  }
}

module.exports = {
  module:{
  rules: [
      {
        test: /\.vue$/,
        use: [
          threadLoader, // vue-loader前使用该loader
          {
            loader: 'vue-loader',
            options: vueLoaderConfig
          }
        ],
      },
      {
        test: /\.js$/,
        use: [
          threadLoader, // babel-loader前使用该loader
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true
            }
          }
        ]
      }
    ]
  }
}

настроенthread-loaderПосле этого попробуйте пересобрать, как показано на рисунке ниже, время сборки сократилось примерно на 10 секунд, что неплохо.

image.png

Используйте кеш для повышения скорости вторичного строительства

Хотя многопроцессный проект сборки сократил время сборки на 10 секунд, время сборки в одну минуту по-прежнему неприемлемо.Такой метод оптимизации, как выдавливание зубной пасты, несколько неприятен.Есть ли классный способ еще больше сократить его? время сборки?

Ответ - да, используйте кеш.

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

cache-loader

Когда дело доходит до кэширования, конечно же, когда Baidu проверяет, первое, что появляется, этоcache-loader, github просмотрел официальную документацию и получил следующие результаты:

Загрузчик будет кешировать результаты обработки других загрузчиков и ставить загрузчик перед другими загрузчиками, при этом загрузчик будет иметь накладные расходы на сохранение и чтение файлов кеша, поэтому рекомендуется использовать этот загрузчик перед загрузчиком с большие накладные расходы.

Документация проста, учитываяvue-loader,babel-loader,css-loaderБудет относительно большой оверхед, поэтому добавьте к этим загрузчикам кеш, потом ставьтеcache-loaderДобавьте его в проект:

const cacheLoader = {
  loader: 'cache-loader'
}

const threadLoader = {
  loader: 'thread-loader',
  options: {
    workers: require('os').cpus().length - 1,
  }
}

module.exports = {
  module:{
  rules: [
      {
        test: /\.vue$/,
        use: [
          cacheLoader,
          threadLoader, // vue-loader前使用该loader
          {
            loader: 'vue-loader',
            options: vueLoaderConfig
          }
        ],
      },
      {
        test: /\.js$/,
        use: [
          cacheLoader,
          threadLoader, // babel-loader前使用该loader
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true
            }
          }
        ]
      }
    ]
  }
}

существуетutil.jsВ файле этот файл в основном генерирует конфигурацию веб-пакета, связанную с CSS, найдитеgenerateLoadersфункция, модифицированная следующим образом:

  const cacheLoader = {
    loader: 'cache-loader'
  }
  
  function generateLoaders(loader, loaderOptions) {
  // 在css-loader前增加cache-loader
    const loaders = options.usePostCSS ? [cacheLoader, cssLoader, postcssLoader] : [cacheLoader, cssLoader]

    if (loader) {
      loaders.push({
        loader: loader + '-loader',
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader',
        // 添加这句配置解决element-ui的图标路径问题
        publicPath: '../../'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }
  }

После того, как вышеуказанная конфигурация завершена, снова запустите проект, вы можете обнаружить, что текущее время запуска не изменилось, а затем мы запустим проект во второй раз, мы можем обнаружить, что текущее время запуска достигло примерно 30 с, так как мы сказал раньше,cache-loaderКэш вступит в силу только при второй загрузке.

image.png

Хотя время запуска проекта было оптимизировано более чем наполовину, наше желание безгранично, и 30-секундное время все еще немного далеко от наших ожиданий.Продолжайте оптимизировать!

hard-source-webpack-plugin

HardSourceWebpackPlugin— это подключаемый модуль веб-пакета, который обеспечивает промежуточный этап кэширования модулей. Чтобы увидеть результаты, вам нужно дважды запустить webpack с этим плагином: первая сборка займет обычное время. Второе строительство будет значительно ускорено.

Без лишних слов настройте его прямо в проекте:

const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
module.exports = {
    //...
    plugins: [
        new HardSourceWebpackPlugin()
    ]
}

image.png

Во второй сборке мы обнаружим, что время сборки выражается однозначными цифрами, всего 7 секунд.

Во втором билде я обнаружил такое явление, что прогресс билда подскочит с 10% до 80%, и даже промежуточный процесс билда завершится в одно мгновение. Это подтверждает утверждение о том, что плагин предоставляет промежуточный кеш для модулей.

Чтобы обеспечить промежуточный кеш для модулей, насколько я понимаю, cache-loader кэширует результаты обработки соответствующего загрузчика, и этот плагин может даже кэшировать все результаты обработки всего проекта, напрямую ссылаясь на конечный выходной файл кеша, тем самым значительно улучшая скорость сборки.

Другие методы оптимизации

babel-loader включает кеширование

babel-loaderВстроенная функция кеша, включитьcacheDirectoryПункта конфигурации достаточно, на официальном сайте написано, что включение кеша увеличит время конвертации примерно в два раза.

module.exports = {
  module: {
  rules: [
      {
        test: /\.js$/,
        use: [
          ...
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true // 开启缓存
            }
          }
        ]
      }
    ]
  }
}

uglifyjs-webpack-plugin обеспечивает многопроцессорное сжатие

uglifyjs-webpack-pluginИли другие инструменты сжатия кода предоставляют функцию многопроцессорного сжатия кода, которая может ускорить сжатие кода.

Динамический полифилл

Рекомендуется просмотреть эту статью

Одна статья, чтобы разобраться с интерфейсным полифиллом

Суммировать

На данный момент мы завершили процесс оптимизации времени строительства проекта с 70 до 7. В статье в основном используются:

инструмент эффект Эффект оптимизации
thread-loader Многопроцессорный разбор файлов 70s -> 60s
cache-loader Кешируйте некоторые дорогие загрузчики 60s -> 30s
hard-source-webpack-plugin Промежуточный процесс модуля кэширования 30s -> 7s

Шаг за шагом оптимизировать проект, чтобы начать практически сразу, эй, кажется, что времени на рыбалку стало меньше, давай, работай!