Как координировать поиск модулей между Webpack, Jest и TypeScript

В JavaScript у нас есть два типа ссылок на модули: относительные и абсолютные («неотносительные» в некоторых онлайн-материалах). Для абсолютных ссылок на модули модули обычно ищутся в каталоге node_modules.

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

Проблема: сложные относительные пути импорта

Скажем, у вас есть такая структура каталогов:

src/
  views/
    Menu/
      Menu.ts
      Menu.css
    List/
      List.ts
      List.css
  util/
    assign-path.ts
  service/
    xhr.ts

Теперь предположим, что вы находитесь в Menu.ts и хотите импортировать List.ts, assign-path.ts и xhr.ts. Обычно это выглядело бы примерно так:

import List from "../List/List";
import assignPath from "../../util/assign-path";
import XHR from "../service/xhr";

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

Это раздражает. Даже если ваша система сборки и редактор способны вовремя отловить эти проблемы с импортом, исправить их все равно не так уж и удобно.

Решение: конфигурация разрешения модуля

Что, если бы мы могли сделать импорт следующим образом:

import List from "views/List/List";
import assignPath from "util/assign-path";
import XHR from "service/xhr";

Что это дает нам, так это то, что нам больше не нужно помнить, на сколько уровней нам нужно подняться, прежде чем мы сможем вернуться к каталогам, таким как views, util или service, и, таким образом, освобождает нас от ада с двумя точками. По сути, мы преобразовали кучу ссылок на локальные модули в абсолютные ссылки на модули — как если бы они были установлены через NPM.

Чтобы получить это, нам нужно настроить все движущиеся части, которые имеют дело с модулями. Это может быть, например, Webpack, компилятор TypeScript или Jest. Если мы настроим только один из них, остальные части системы сборки будут работать некорректно, поэтому важно, чтобы все они были на одной странице.

В следующем тексте я покажу вам, как обращаться с этими тремя компонентами.

Конфигурация веб-пакета

Webpack поддерживает опцию конфигурации resolve.modules. Это массив путей, который будет использоваться в качестве базового каталога для разрешения модулей при использовании абсолютных ссылок на модули.

В нашем случае это будет выглядеть примерно так:

// webpack.config.js
module.exports = {
  // ....
  resolve: {
    modules: [path.join(__dirname, "src"), "node_modules"],
  }
};

Конфигурация в примере предписывает Webpack найти абсолютные ссылки на модули в каталоге src и вернуться к node_modules, если они не найдены в src.

Обратите внимание, что это означает, что абсолютные ссылки на модули будут скрывать модули в node_modules — те, которые установлены через NPM.

Конфигурация TypeScript

TypeScript немного лучше, так как он всегда будет смотреть на node_modules независимо от конфигурации. Все, что нам нужно сделать, это добавить параметр baseUrl, который задокументирован в разделе документации Параметры компилятора, а также в разделе Разрешение модуля.

В нашем случае конфигурация baseUrl достаточно проста. tsconfig.json должно выглядеть так:

{
  "compilerOptions": {
    ...
    "baseUrl": "src"
  },
  ...
}

Как и в конфигурации Webpack, модули в node_modules затенены модулями в src.

Конфигурация шутки

Jest настраивается аналогично Webpack. Мы предоставляем список путей поиска, используя modulePaths опций конфигурации, задокументированных здесь.

В наш package.json мы добавим что-то вроде этого:

{
  ...
  "jest": {
    ...
    "modulePaths": [
      "<rootDir>/src/", 
      "<rootDir>/node_modules/"
    ]
  }
}

Вывод

Подводя итог тому, что мы сделали:

  • Преобразование относительных ссылок на модули в нашем исходном дереве в абсолютные ссылки
  • Убедитесь, что все программы в нашей системе сборки разрешают ссылки на модули одинаково.
  • Имейте в виду, что абсолютные ссылки на модули в нашем коде затеняют абсолютные ссылки на модули в node_modules

Я надеюсь, что это было полезно для вас. Если да, то не забудьте порекомендовать. :)