Русский
Русский
English
Статистика
Реклама

Контролируем JavaScript импорты с помощью Import maps

Привет. С выходом Chrome 89 (а так же в Deno 1.8) появилась возможность использовать Карты импортов (Import maps) механизма, позволяющего получить контроль над поведением JavaScript-импортов.

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

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

import React from 'react';

Под катом разберём как это всё работает.

Для того, чтобы директива import или выражение import() могли разрешать пути к модулям в новом виде, нужно эти пути где-то описать. Да, оказалось никакой магии с подкапотным разрешением зависимостей как в той же Node.js или webpack тут нет.

Карты импортов задаются с помощью тега script с атрибутом type="importmap" в формате JSON.

А теперь на примере. Запускаем статический сервер (например, с помощью python -m SimpleHTTPServer 9000) и создаём два файла:

index.html

<!DOCTYPE html><html>  <body>    <script type="importmap">      {        "imports": {          "mylib": "./my-lib.mjs"        }      }    </script>    <script type="module">      import { sayHi } from "mylib";      sayHi();    </script>  </body></html>

и my-lib.mjs

export function sayHi() {  console.log("hi!");}

Открываем в браузере страничку, и вуаля: в консоль вывелось "hi!". Далее более подробно разберём, как оно устроено.

Структура

На данный момент, согласно спецификации, описывающий зависимости JSON может содержать два ключа: imports и scopes. Если появится какой-то неизвестный ключ, то должно выводиться предупреждение в консоль (хотя у меня Хром этого не делает).

Imports

Значение ключа imports объект, содержащий в качестве ключей имена модулей (к которым можно обращаться для последующего импорта) и адрес модуля. Адрес должен начинаться с /, ../, ./ или быть абсолютным URL.

"imports": {  "module-name": "address"}

Также есть возможность описывать "пакеты", содержащие несколько модулей. Для этого нужно к названию ключа добавить / в конец.

Создадим директорию "my-pack" добавив в неё index.mjs с содержимым:

export default function mainFunc() {  console.log("text from mainFunc");}

А также в "my-pack" добавим директорию "some-module" с файлом some-helper.mjs с содержимым:

export function someHelper() {  console.log("text from someHelper");}

Перепишем importmap нашего index.html:

  <script type="importmap">    {      "imports": {        "mypack": "./my-pack/index.mjs",        "mypack/": "./my-pack/"      }    }  </script>

Теперь, кроме обычного импорта основного пакета

import mainFunc from "mypack";

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

import { someHelper } from "mypack/some-module/some-helper.mjs";

Scopes

Бывают случаи, когда используя один и тот же импорт (точнее, спецификатор импорта), нам нужно получать разные версии библиотеки в зависимости от того, откуда её импортируют. На этот случай и нужны скоупы. Пример:

<script type="importmap">  {    "imports": {      "mypack": "./my-pack/index.mjs",      "mypack/": "./my-pack/"    },    "scopes": {      "some/other/url/": {        "mypack": "./my-pack/index-v2.jsm"      }    }  }</script>

В данном случае внутри любого модуля, url которого будет начинаться с some/other/url/ импорт "mypack" будет ссылаться на "./my-pack/index-v2.jsm", во всех остальных случаях будет использоваться "./my-pack/index.mjs".

Также есть возможность вложенных скоупов. Например:

<script type="importmap">{  "imports": {    "a": "/a-1.mjs",    "b": "/b-1.mjs",    "c": "/c-1.mjs"  },  "scopes": {    "/scope2/": {      "a": "/a-2.mjs"    },    "/scope2/scope3/": {      "b": "/b-3.mjs"    }  }}</script>

Это даст нам такое разрешение путей:

Specifier

Referrer

Resulting URL

a

/scope1/foo.mjs

/a-1.mjs

b

/scope1/foo.mjs

/b-1.mjs

c

/scope1/foo.mjs

/c-1.mjs

a

/scope2/foo.mjs

/a-2.mjs

b

/scope2/foo.mjs

/b-1.mjs

c

/scope2/foo.mjs

/c-1.mjs

a

/scope2/scope3/foo.mjs

/a-2.mjs

b

/scope2/scope3/foo.mjs

/b-3.mjs

c

/scope2/scope3/foo.mjs

/c-1.mjs

Подключение карт импортов

Как и с остальными ресурсами, подключаемыми через тег script. Можно заполнять содержимое тега:

<script type="importmap">{  "imports": { ... },  "scopes": { ... }}</script>

а можно импортировать карту используя атрибут src:

<script type="importmap" src="some/address/to/import-map.importmap"></script>

Важно, что по этому адресу ответ должен приходить с MIME type application/importmap+json.

Особенности

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

  2. Если добавить карту импорта после использования определения модулей, то это приведёт к ошибке:

    An import map is added after module script load was triggered.

  3. На момент написания этой статьи есть возможность добавить только одну карту импорта. Если добавить вторую, то это приведёт к ошибке. В Хроме выводит следующее:

    Multiple import maps are not yet supported. https://crbug.com/927119

Deno

В Deno карты импортов подключаются помощью флага --import-map:

deno run --import-map=import_map.json index.ts

Где import_map.json - это карта импортов, а index.ts - файл для запуска (компиляции).

Источники

https://wicg.github.io/import-maps

https://github.com/WICG/import-maps

https://deno.land/manual/linking_to_external_code/import_maps

Источник: habr.com
К списку статей
Опубликовано: 15.03.2021 22:22:10
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Javascript

Deno

Ecmascript

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru