28 мая 2020 г.

JavaScript Модули

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

Представьте, что у вас есть функция, которая вычисляет сумму значений в заданном массиве и возвращает резултат. Выглядит она примерно так:

// app.js

function total(numbers) {
    return numbers.reduce((a, b) => a + b, 0)
}

console.log(total([1, 2, 3, 4, 5]))

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

// total.js

function total(numbers) {
    return numbers.reduce((a, b) => a + b, 0)
}

export default total

Пока не обращайте внимания на ключевое слово default. Теперь мы можем импортировать функцию, используя ключевое слово import:

// app.js

import total from './total.js'

console.log(total([1, 2, 3, 4, 5]))

Мы указываем название переменной после ключевого слова import и путь к файлу, который экспортирует его после ключевого слова from. В данном случае, мы использовали переменную total, но могли бы использовать любое произвольное название, потому что мы экспортировали функцию с ключевым словом default. Оно это и означает: когда мы экспортируем что-то с использованием ключевого слова default, мы можем импортировать это используя любое название переменной, которое захотим. Также, обратите внимание как мы указали путь к файлу: он начинается с ./. Если вы хотите импортировать локальные файлы вы ДОЛЖНЫ использовать относительный путь, который должен начинаться с ./ или ../. В другом случае модуль будет импортироваться из папки node_modules. Если вы экспортируете одну переменную, лучше использовать дефолтный импорт. Вот пример импортирования библиотеки axios из node_modules:

import axios from 'axios'

Недефолтный экспорт

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

// functions.js

function total(numbers) {
    return numbers.reduce((a, b) => a + b, 0)
}

function sum(a, b) {
    return a + b
}

export { total, sum }

Но теперь мы не сможем импортировать этот файл, используя любые переменные, которые хотим, мы можем использовать только те, которые экспортировали:

// app.js

import { total, sum } from './functions.js'

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

Альясы

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

import { total as totalQuantity, sum } from './functions.js'

Что вы можете импортировать

Вы можете импортировать любые типы файлов, которые поддерживает ваш сборщик, даже CSS:

import '../sass/app.scss'

Вы также можете импортировать простые JS файлы, которые ничего не экспортируют таким же образом, как показано в примере выше:

Указание пути к файлам

Вы можете опустить расширешие js файлов при импорте. В этом случае будет искаться файл с расширением .js и указанным названием. Если такого файла не существет, то будет искаться папка с указанным названием, внутри которой есть файл с названием index.js, и импортироваться.

Подводные камни

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

if (someCondition) {
    const { total, sum } = require('./functions.js')
}

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

const file = 'functions.js'
const { total, sum } = require('./' + file)

Я думаю вы найдете много случаев, где это может быть очень полезно.

Вы также можете импортировать какую-нибудь дефолтную переменную, используя синтаксис RequireJS:

const total = require('./total.js').default

Я надеюсь это было полезно. До скорых встреч :)