Напишите более элегантный импорт, используя локальные модули NodeJS.

При создании проектов NodeJS мы неизбежно разбиваем наши проекты на модули в поисках лучшего разделения задач на практике. Существует множество онлайн-предложений по использованию макетов проектов, которые, по-видимому, делают структуру ваших папок лучше и элегантнее организованной. Тем не менее, несмотря на используемую вами структуру папок, это почти никогда не позволяет избежать уродливых операторов импорта, разбросанных по всему коду, которые выглядят следующим образом:

const db = require('../../lib/db')

const { userRepository } = require('../../lib/repositories')

const fancyUtilsFunction = require('../../../utils')

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

Проблема с этими операторами import заключается в том, что они тесно связаны с конкретной структурой каталога. Любые изменения экспортируемых функций или структуры папок, составляющих модуль, могут повлиять на весь клиентский код, использующий такой модуль. Более того, уровень вложенности и количество «…» в операторе import могут повлиять на наши решения по организации кода.

Локальные модули

NodeJS позволяет ссылаться на модули, принадлежащие одному и тому же проекту (локальные модули), по псевдониму. Это быстрое и простое решение вышеупомянутой проблемы.

Допустим, у нас есть следующая структура каталогов:

/db
/src
--/domain
----/user.js
--/repositories
----/userRepository.js
package.json

И userRepository.js запускает некоторый оператор импорта, как показано ниже:

const { User } = require('../domain');
const { query } = require('../../db')

module.exports = {
    findOne: async (id) => {
        const [data] = await query('user', { id })
        return new User(data.id, data.name)
    }
}

Из папки /db мы можем создать файл package.json со следующими строками:

{
    "name": "@project/db"
}

Затем из корневой папки мы можем запустить следующую команду в CLI:

npm install -S .\db

Эта команда создаст запись в нашем корневом package.json файле под ключом dependencies, она будет выглядеть следующим образом:

{
// ...
"dependencies": {
    "@project/db": "file:db",
    "@project/domain": "file:src/domain",
    "@project/repositories": "file:src/repositories"
  }
}

Так что, как вы можете догадаться, это то же самое, что вручную объявлять каждую локальную зависимость непосредственно в package.json и затем запускать npm install.. Локальные файлы package.json можно безопасно удален в настоящее время, хотя я не рекомендую делать это.

Теперь, сочная часть! Вернувшись в наш файл userRepository.js, мы можем просто ссылаться на наши локальные пакеты по их псевдонимам:

const { User } = require('@project/domain');
const { query } = require('@project/db')

module.exports = {
    findOne: async (id) => {
        const [data] = await query('user', { id })
        return new User(data.id, data.name)
    }
}

Отлично сделано! Теперь наши операторы import не связаны со структурой папок, которую мы выбрали для нашего проекта. Наши определения модулей теперь сильно централизованы, поэтому мы получили гораздо больший контроль над изменениями, которые мы вносим в макет проекта, и наш код не связан с ним.