Импорт и требование в приложении Nodejs

Недавно, когда я рефакторил одно из своих приложений, построенных на стеке MERN, я решил разбить одну из своих больших схем на нечто более управляемое и масштабируемое. У меня была игра, которую я создавал, в которой использовалась единая схема для создания персонажа. Он включал всю их основную информацию, такую ​​как имя, раса и класс, но также включал все оружие, атаки, статистику и другой инвентарь, что делало его очень большим файлом.

Поскольку за последние несколько лет я понял, что идеально использовать принцип единой ответственности, когда это возможно, я решил разбить схему на более мелкие, более управляемые фрагменты, которые облегчили бы обращение к моей программе, особенно если я хотел только для доступа к небольшой части сведений о персонаже (т. е. только имени и классу) при вызове данных. Поэтому я сделал еще несколько схем и сгруппировал похожие вещи. Например, базовые характеристики, используемые персонажем в DND (Сила, Мудрость, Ловкость, Интеллект, Телосложение и Харизма), были сгруппированы вместе в одной схеме. Это вещи, к которым программе и, соответственно, пользователю обычно требуется доступ только в определенное время, и ей не нужны остальные данные, чтобы пометить их при простом вызове, чтобы получить мудрость персонажа.

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

const characterModel = require(“./characterModel”);

Однако, когда я недавно работал с другим разработчиком, и они просматривали мой код, они предложили просто использовать оператор импорта, например:

импортировать модель персонажа из «./модель персонажа»;

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

SyntaxError: Cannot use import statement outside a module

Это сбивало меня с толку. Поскольку я никогда раньше не работал с оператором импорта и никогда не имел проблем с требованием, мне пришлось поискать его, потому что я понятия не имел, что это значит. После некоторых поисков я узнал, что для того, чтобы исправить это, мне нужно было специально указать моему файлу package.json, что тип был модулем, чтобы использовать импорт. Так что я покорно добавил его, думая, что это решит мою проблему, и на минуту это так и произошло. Затем я заметил, что мое приложение разбилось при попытке загрузить все другие модули, которые все еще использовали оператор require. Как будто они не могли сосуществовать или что-то в этом роде.

Итак, я пришел к выводу, что моя проблема заключалась в том, что вы можете использовать только одно или другое по всем направлениям, и это приводило к сбою моей программы. Это казалось очевидным! Поэтому я вернул все обратно на require, удалил новую запись из моего package.json и зафиксировал свои изменения, уверенный в своих новых знаниях. Однако позже мне стало любопытно, будет ли использование одного метода лучше другого для моей программы. Итак, я вернулся в Интернет, на этот раз, чтобы узнать фактические различия между ними.

Оказывается, оператор import немного более привередлив, чем require. Он используется только для загрузки модулей ES и ни для чего другого и может использоваться только в начале модуля. Require, с другой стороны, немного более надежен и может использоваться для импорта нескольких вещей. Я пошел в MDN, чтобы проверить эту информацию, и вот что я нашел:

Объявления import могут присутствовать только в модулях и только на верхнем уровне (т. е. не внутри блоков, функций и т. д.). Если объявление import встречается в немодульных контекстах (например, теги <script> без type="module", eval, new Function, которые все имеют сценарий или тело функции в качестве целей синтаксического анализа), выдается SyntaxError. Чтобы загружать модули в контекстах, отличных от модулей, вместо этого используйте синтаксис динамического импорта.

Интересный! Так что да, это более жестко, но, очевидно, если вы просто используете оператор динамического импорта, такой как «import()», то, возможно, вы не столкнетесь с таким количеством проблем? Тем не менее, узнав больше о require, я решил использовать его в своем проекте. Как оказалось, операторы require можно использовать в любом месте внутри модуля, а не только в его начале. Его тоже можно назвать условно!

Операторы require обладают такой гибкостью, потому что они обрабатываются как функции. Они вызываются во время выполнения, и нет никакой возможности узнать что-либо до этого. Но операторы import являются статическими, и мы не можем использовать их условно или динамически.

-Из blog.bitsrc.io

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