Различия между операторами require и import в JavaScript

В современной веб-разработке мы используем require или import для обозначения зависимостей JavaScript. А иногда мы используем и то, и другое в сочетании и используем то, что подходит для библиотеки.

Но знаете ли вы, почему они оба существуют? Что происходит внизу? И каковы лучшие практики при использовании того или другого?

В этой статье я расскажу об использовании require и import и отвечу на некоторые из этих общих вопросов.

Предпосылки - Типы модулей JavaScript

Прежде чем обсуждать require и import, необходимо иметь представление о модулях JavaScript. Итак, давайте посмотрим, какие типы модулей JavaScript доступны.

1. AMD - определение асинхронного модуля

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

Функция AMD use require используется для загрузки внешних модулей и может выступать в качестве оболочки для модулей CommonJS.

define("exampleModule", [], () => {
   return {
     print: () => console.log("Hello World!");
   }
}
define("main", ["require", "exampleModule"], (require) => {
  const exampleModule= require("exampleModule");
  exampleModule.print(); 
});

Однако с появлением модулей ES использование AMD резко сократилось.

2. Модули CommonJS

CommonJS - это стандарт, используемый NodeJS для инкапсуляции JavaScript в модулях. modules.export используется для экспорта модулей CommonJS, а функция import используется для включения модулей в отдельные файлы.

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

Однако NodeJS начал поддерживать модули ES только начиная с v13. До этого большинство модулей NodeJS, включая библиотеки NPM, разрабатывались с использованием модулей CommonJS.

Поэтому модули CommonJS по-прежнему широко используются разработчиками.

Модули CommonJS не менее важны, чем модули ES, и я расскажу больше в следующих разделах статьи.

3. UMD - универсальное определение модуля

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

UMD используется как резервный модуль в таких сборщиках, как Webpack, и простой пример модуля UMD показан ниже:

(function (root, factory) {
  if (typeof define === "function" && define.amd) {
    define(["jquery"], factory); // AMD
  } else if (typeof exports === "object") {
    modules.export = factory(require("jquery")); //CommonJS
  } else {
    root.returnExports = factory(root.jQuery);
  }
})(this, function ($) {
  function exampleFunction() {}
  return exampleFunction;
});

4. ESM - модули ES

Модули ES (модули ECMAScript) - официальный стандарт, используемый в JavaScript. Модули ES используют операторы import и export для работы с модулями. Он устраняет одно из самых больших ограничений CommonJS - синхронную загрузку.

Модули ES импортируют ведущие модули асинхронно, позволяя проводить статический анализ времени сборки.

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

Поскольку теперь вы знакомы с предысторией модулей JavaScript, давайте перейдем к обсуждению require и import.

«Требовать» встроено в NodeJS.

require обычно используется с NodeJS для чтения и выполнения модулей CommonJS.

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

// built-in moduels
const http= require('http');
// local moduels
const getBlogName = require('./blogDetails.js')

Однако, если вы используете require для получения локальных модулей, сначала вам нужно экспортировать их с помощью modules.export.

Например, предположим, что у вас есть файл с именем blogDetails.js, и вам нужно использовать функцию из этого файла в index.js файле.

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

Примечание. Вместо того, чтобы использовать modules.export в конце, вы также можете добавить export в начале каждой функции. Например: exports.getBlogContent = () => {};

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

«Импорт» был введен с модулями ES6

import - это модуль ES, и с export они известны как ES6 import и export.

Мы не можем использовать import или экспорт вне модулей ES.

Мы видим, что попытка import выйти за пределы модулей ES - распространенная ошибка разработчиков, и на этот счет есть много потоков StackOverflow.

Если я возьму тот же пример, единственное изменение, которое мне нужно сделать, - это изменить modules.export на export default.

Затем мы можем использовать import, чтобы включить этот файл в наш index.js файл.

Примечание. Как и require, вы также можете экспортировать каждую функцию по отдельности, добавив экспорт к каждому определению функции.

Eg: export const = getBlogContent = () => {};

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

Требовать Vs. Импортировать

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

1. Операторы Require можно вызывать в любом месте кода.

Обычно мы вызываем операторы import или require в начале файла.

Но знаете ли вы, что можете свободно использовать операторы require в любом месте вашего кода? Да, ты можешь!

С другой стороны, операторы import могут быть определены только в начале файла. Определение оператора import в другом месте приведет к ошибке или автоматически перейдет к началу файла.

2. Require можно назвать условно

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

Например, вы можете вызвать require внутри функции или условия if, как показано ниже:

if(articleCount>0){
   const getBlogTitle = require(‘./blogDetails.js’);
}

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

Примечание. Вы можете рассматривать это как преимущество require. Но поскольку import statements статичны, вы можете обнаружить любую ошибку до запуска приложения.

3. Операторы импорта асинхронны.

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

если вы используете require, модули будут загружаться и обрабатываться один за другим.

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

4. Модули ES - это будущее

Как мы уже говорили, система модулей ES была введена в качестве стандарта для поддержки клиентских модулей JavaScript. Он также принят TypeScript с дополнениями для определения Type. Поэтому я не думаю, что require снова сможет заменить ES, поскольку он стал широко используемым стандартом среди разработчиков.

Но поскольку существует множество модулей и библиотек NodeJS, написанных с использованием CommonJS, мы не можем полностью игнорировать require. Поэтому мы должны использовать их оба соответственно.

Также мы можем настроить компиляторы для преобразования вывода различных типов модулей.

Если вы используете TypeScript, вы можете настроить таргетинг на разные модульные системы в качестве выходных данных, внеся несколько изменений в tsconfig.json файл. Например, предположим, что нам нужно вывести версию кода, в которой используется CommonJS.

Все, что вам нужно сделать, это создать новый tsconfig файл для вывода CommonJS, расширив исходный tsconfig файл и изменив параметр module в CompilerOptions.

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "CommonJS",
    "outDir": "./lib/cjs"
  },
}

Примечание. Вы также можете использовать инструменты сборки, такие как Webpack, для преобразования модулей ES в модули CommonJS.

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

Создавайте из независимых компонентов для увеличения скорости и масштабирования

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

Инструменты OSS, такие как Bit, предлагают отличные возможности разработчика для создания независимых компонентов и составления приложений. Многие команды начинают с создания своих дизайн-систем или микро-интерфейсов через компоненты. Попробуйте →

Заключение

В этой статье я рассмотрел вопрос, часто задаваемый многими разработчиками: разница между require и import. Хотя ES import и export - это новые стандарты, используемые для включения модулей, функции require широко используются в NodeJS.

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

Спасибо за чтение !!!

Учить больше





« Двойные кавычки против одинарных кавычек против обратных кавычек в JavaScript
Разница между использованием одинарных кавычек , двойных кавычек и обратных кавычек в строках JavaScript . blog.bitsrc.io »