Всегда помните о своей среде выполнения и о том, какой стандарт модулей реализован в ней.

Если вы работаете в веб-разработке, вы, вероятно, видели это в какой-то момент. Это происходит, когда вы пытаетесь require(...) открыть модуль в браузере.

Вы искали решение и обнаружили, что проблема в том, что вы не можете использовать require(...); в браузере. Браузер этого не понимает и жалуется.

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

Среда выполнения

Каждый язык программирования имеет по крайней мере одну среду выполнения, которую также можно назвать системой выполнения. Это набор программ, которые управляют выполнением языка.

Среда выполнения может иметь разные обязанности в зависимости от языка программирования; таких как управление памятью, взаимодействие с операционной системой, сборка мусора или многопоточность.

Например, в C система времени выполнения представляет собой определенный набор инструкций, вставляемых компилятором в исполняемый файл. Эти инструкции управляют стеком, создают пространство для локальных переменных и настраивают стек с параметрами при вызове новой функции.

Среда выполнения Javascript

В мире Javascript есть два популярных типа сред выполнения. С одной стороны, у нас есть браузерные среды с Chrome, Firefox, Safari и т. д. С другой стороны, node.js.

В обоих случаях среда предоставляет разработчику набор инструментов, помогающих в выполнении кода:

  • Стандартная библиотека со встроенными функциями, такими как «карта» в Array.
  • API, которые расширяют функциональность самого языка, например. «document.getElementById» в браузере.
  • Движок JS, выполняющий код, например V8 в Chrome.

Javascript-модули

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

Вот основные стандарты на данный момент: модули CommonJS, AMD и ES6.

CommonJS

CommonJS был запущен в 2009 году инженером Mozilla Кевином Дангуром. Я нахожу его цитату, раскрывающую стандарты JS Modules:

"То, что я здесь описываю, не является технической проблемой. Люди собираются вместе и принимают решение сделать шаг вперед и начать вместе создавать что-то большее и крутое».
 – Кевин Дангур, 2009 г.

В этом стандарте способ указать, что экспортируется в файл, осуществляется с помощью module.exports, а импорт выполняется с помощью функции require:

const lodash = require(‘lodash’);

Определение асинхронного модуля или (AMD)

AMD был разработан как способ асинхронной загрузки модулей, поскольку стандарт CommonJS плохо подходил для среды браузера. Поэтому некоторые люди собрались вместе, чтобы придумать новый стандарт.

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

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
  exports.verb = function() {
    return beta.verb();
    //Or:
    return require("beta").verb();
  }
});

Модули ES6

Модули ES6 — это новейший способ использования модулей. Он использует ключевые слова import и export, чтобы указать, что предоставляет модуль и как использовать модуль в другом файле.

import { useState } from ‘react’;

Реализации стандартов модулей Javascript

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

Существуют различные способы внедрения стандартов. Например, NodeJS реализует стандарт CommonJS, тогда как библиотека RequireJS реализует AMD для браузеров.

Новый стандарт модулей ES6 уже реализован в самых современных браузерах и последних версиях NodeJS.

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

Когда мы начинаем проект и хотим использовать модули, наш первый шаг — спросить, какая у меня система времени выполнения? Какой стандарт он реализует?

Несколько сред выполнения

Текущая разработка интерфейса немного сложна. Иногда трудно понять, в какой среде выполнения выполняется код. Например, если мы используем create-react-app, мы импортируем модули с модулями ES6; тем не менее, код можно запустить в браузере, который не поддерживает модули ES6.

С create-react-app мы одновременно используем несколько систем выполнения — каждая для разных целей. Например, NodeJS используется для создания файла (или файлов), выполняемых в браузере. Это создание файлов также известно как этап сборки.

Файл (или файлы), созданный на этапе сборки, уже имеет все свои зависимости. Поэтому, когда этот файл выполняется на веб-сайте, ему не нужно использовать какие-либо модули.

Вы можете использовать модули ES6, даже если используете версию Node, которая их не поддерживает. Приложение Create-React использует библиотеку под названием Babel, которая реализует стандарт модулей ES6. В этом случае, хотя мы и используем NodeJS, мы не полагаемся на реализацию JS-модулей, предлагаемых NodeJS. Вместо этого мы полагаемся на библиотеку для реализации стандарта, который хотим использовать.

Знайте свою среду выполнения и стандарт модуля

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

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

Браузер + CommonJS → НЕ ПОДДЕРЖИВАЕТСЯ

Эта другая ошибка возникает, когда мы пытаемся использовать модули ES6 в Node версии 12, которая не поддерживает модули ES6.

Модули Node v12 + ES6 → НЕ ПОДДЕРЖИВАЮТСЯ

Всегда помните о вашей среде выполнения и о том, какой стандарт модулей реализован в ней.