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

  1. Зависимость огромна или установка занимает чрезвычайно много времени.
  2. Это единственный проект NPM (или один из очень немногих тесно связанных проектов NPM) в системе (например, работающий внутри контейнера докеров).

Один из случаев, когда выполняются оба этих критерия, - это создание контейнера докеров для проекта BuckleScript (или ReasonML).

BuckleScript - это прежде всего компилятор, который компилирует код OCaml или ReasonML в JavaScript. Следовательно, может показаться, что bs-platform (зависимость NPM BuckleScript) должна требоваться только как devDependency и использоваться в процессе сборки. Однако bs-platform также содержит некоторый код, который необходимо включить в проект во время выполнения. Следовательно, bs-platform должна быть включена в проект либо как зависимость, либо как peerDependency.

Самый простой вариант включить bs-платформу в проект - это добавить ее в поле dependencies файла package.json и разрешить NPM (или yarn) установить ее локально в каталог node_modules проекта. Этот метод отлично работает на машине разработки, где зависимости npm кэшированы и должны быть установлены снова только в том случае, если пакет удален из локального каталога node_modules. Однако при установке зависимостей npm в контейнер докеров любое изменение файла package.json приведет к полной установке всех пакетов npm. Обычно это не проблема для небольших зависимостей npm, установка которых занимает менее нескольких секунд, но bs-platform устанавливает и компилирует компилятор OCaml с нуля. На моей быстрой машине этот процесс занимает более 6 минут. На моих более медленных машинах этот процесс занимает почти полчаса. Ожидание сборки докер-контейнера более 6 минут всякий раз, когда какие-либо изменения в файле package.json недопустимы. Особенно во время разработки, когда package.json меняется почти все время.

Итак, теперь ситуация такова: у нас есть зависимость, установка которой занимает чрезвычайно много времени, И этот проект является единственным проектом NPM, работающим в системе (то есть контейнером докеров). Похоже, у нас есть идеальный кандидат для того, чтобы отказаться от передовой практики установки зависимости локально и вместо этого установить зависимость глобально заранее. Это позволит нам установить bs-платформу один раз и кэшировать ее как слой докеров. Затем любые изменения в package.json произойдут на следующем уровне докеров без необходимости переустановки bs-platform.

Затем, поскольку нам нужно разрешить глобально установленную зависимость во время выполнения, мы включаем ее как peerDependency в package.json. Это проинформирует наш инструмент сборки (Webpack 4), что для проекта требуется bs-платформа, НО она уже должна быть установлена ​​в системе.

Наконец, мы настраиваем webpack для разрешения bs-platform как глобально установленной зависимости вместо локально установленной зависимости, добавляя следующие строки в webpack.config.js:

  resolve: {
    alias: {
      'bs-platform': path.resolve(
        execSync('npm root -g').toString().trim(),
        'bs-platform'
      )
    }
  },

Когда мы будем готовы построить проект ReasonML, мы запустим:

bsb -make-world
webpack --mode production

который выведет наш окончательный файл JavaScript для отправки в браузер клиента.

Первоначально опубликовано на сайте craigc0de.blogspot.com 25 сентября 2018 г.