Параметры для ES6-импорта
Недавно я спросил себя, действительно ли возможно использовать операторы импорта системы ES6-модулей в Javascript не только обычным способом (импортируя только локальный модуль через относительный путь или имя пакета), но и с параметрами.
Мой вариант использования будет примерно таким: предоставить какие-то параметры во время импорта, чтобы импортированный модуль мог сам обрабатывать эти параметры как флаг для условного импорта или специальной обработки кода.
Как оказалось, это вполне возможно!
Импорт ES6 - это просто URL-адреса
Прежде чем мы посмотрим на код, важно помнить, что операторы импорта в Node.js - это практически просто URL-адреса. Node.js по умолчанию использует алгоритм для определения того, как на самом деле выглядят URL-адреса после полного разрешения. Например, если вы указываете только относительный путь в качестве спецификатора импорта, Node.js по-прежнему преобразует строку в абсолютный URL-адрес для скрытого импорта.
Использование параметров URL-запроса для импорта
И поскольку импорт разрешается в URL-адрес, мы можем использовать общие параметры поиска URL-адресов, а также URL-фрагменты в нашем импорте.
Во-первых, убедитесь, что ES6-модули поддерживаются для тестирования этой функции. Это требует небольшого изменения в нашем package.json, где в поле «type» должно быть установлено значение «module». Обратите внимание, что вам необходимо использовать Node.js версии 12 или выше.
{
"name": "es6-import-params",
"version": "1.0.0",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": ""
}
Затем определите два минимальных модуля для простой демонстрации.
//
// index.js
//
import {greet} from "./lib.js?name=Tom";
// This will print "Hello Tom".
greet();
//
// lib.js
//
// We're using Node's native 'URL'-module
// to transform the provided string into
// a usable representation.
//
// Note that 'import' here isn't part of
// an acutal import, but rather resolved
// to a global variable.
const url = new URL(import.meta.url);
// A simple greeter for demo purposes.
// We just access the map 'searchParams'
// from our usable 'url'-object and use
// a fallback if no params are provided.
export function greet() {
console.log(`Hello ${url.searchParams.get("name") || "World"}`);
}
Множественный импорт с разными параметрами
Как написано в документации Node.js, каждый импорт кэшируется во время выполнения для более быстрого последующего импорта в другие модули. Поэтому важно знать, что импорт из одного и того же модуля, но с разными параметрами, кэшируется отдельно. Конечно, импорт с соответствующей подписью все равно будет считываться из кеша.
//
// index.js
//
// A small adaptation for the index.js
// file, this time importing the same
// module twice w/ different params. Each
// module gets cached twice, too.
import * as tomLib from "./lib.js?name=Tom";
import * as lukeLib from "./lib.js?name=Luke";
// 'Hello Tom'.
tomLib.greet();
// 'Hello Luke'.
lukeLib.greet();
// Still 'Hello Tom', as it's
// its own module.
tomLib.greet();
Сценарии использования
Примеры в этой статье намеренно очень короткие, но вы уловили идею. В зависимости от ваших требований использование параметров запроса с импортом может быть довольно элегантным вариантом для установки «глобальных» переменных для каждого модуля. Это избавляет от необходимости использовать геттеры и сеттеры провайдера для достижения одной и той же цели.