Утверждения, применяемые при импортировании в JavaScript

Количество имеющихся в мире данных с течением времени продолжает бурно расти. Этот огромный объем существует во многих различных типах данных: текстовых файлах, изображениях, видео, аудио и т. д. К тому же эти данные хранятся в нескольких файловых форматах. Файловый формат  —  это стандартный способ кодирования данных для сохранения в файловой системе хранения. Существует много разных форматов файлов (HTML, JSON, XML, JPEG, PNG, MP3, MP4 и т.д.). Хотя форматы отличаются друг от друга, в основе всех их  —  данные. Для использования этих существующих в нескольких файловых форматах данных нужен способ безопасно импортировать их в приложения на JavaScript. Утверждения, применяемые при импортировании,  —  это то предложение разработчиков, которое мы обсудим сегодня.

Что такое “утверждения, применяемые при импортировании”?

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

JavaMentor
JavaMentor

В веб-разработке была необходимость импортировать в код JavaScript существующие в различных формах данные. Особенно необходим был импорт с типами данных JSON, поскольку этот файловый формат был очень распространен среди современных веб-разработчиков, использовавших его как замену XML в приложениях на AJAX.

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

import json from "./foo.json" assert { type: "json" };
import("foo.json", { assert: { type: "json" } });

Вы спросите: «А почему нельзя просто импортировать модули JSON?». Вот так:

import json from "./data.json";

И действительно этот подход был многими поддержан и быстро получил признание, а позже был реализован в движке V8 для Chromium. Но в вопросе, на который обратили внимание инженеры из Apple и Mozilla, была обозначена проблема безопасности. Она связана с существующей реализацией, в которой задействованы MIME-типы.

У некоторых разработчиков сложилось такое понимание, что для определения типа модуля надо использовать расширения файла, так же как и во многих существующих нестандартных системах модулей. Однако в веб-разработке существует принцип, согласно которому суффикс URL (расширение файла загружаемых данных) не определяет то, как он интерпретируется веб-браузером. Это определяет MIME-тип. Кроме того, в вебе также обнаруживается несоответствие между расширениями файлов и HTTP-заголовком Content-Type.

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

А как это делалось раньше?

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

require(['json!someData.json'], function(data){
  ...
})

Этот синтаксис напоминал '«specifier-of-plugin-module»!«specifier-of-artifact»'.

После успеха RequireJS тот же синтаксис был использован в webpack при реализации загрузчика модулей, не относящихся к JS. Было использовано несколько типов файлов, в том числе стили, фреймворки, шаблоны и т. д.

Предлагаемый синтаксис утверждений импорта

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

Для обозначения типа модулей в синтаксисе с использованием пар «ключ  —  значение» будет задействовано свойство type.

Статические операторы импорта

Пример синтаксиса статического импорта мы уже видели. Вот он:

import json from "./foo.json" assert { type: "json" };

Этот синтаксис допускает любые произвольные утверждения после ключевого слова assert. Разработчики JS хорошо знакомы с объектными литералами, так что этот синтаксис будет для них довольно удобным. В приведенном выше примере для утверждения использован тип (type) JSON.

Кроме того, задействован стандартный функционал объектных литералов:

  • Ключи объекта либо закавычены, либо оставлены без кавычек.
  • Значениями должны быть строки.

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

Операторы реэкспорта

Как и в случае со статическими операторами импорта, утверждения здесь добавляются с помощью ключевого слова assert:

export { default as foo } from './foo.json' assert { type: 'json' };

Динамические операторы импорта

Для работы с утверждениями в операторах динамического импорта у функции import() будет дополнительный параметр, для которого требуется множество опций. Это объект со свойством assert, значение которого и будет утверждением импорта. Необходимо отметить, что этот объект в настоящее время поддерживает только свойство assert, но он создан с учетом совместимости с теми, что появятся после.

import("foo.json", { assert: { type: "json" } })

Интеграция в другие среды

Сейчас планируется интегрировать утверждения и в другие среды.

Реализация с веб-воркером

Хотя применение утверждений здесь все еще обсуждается, реализации их будет выглядеть следующим образом:

new Worker("foo.wasm", { type: "module", assert: { type: "webassembly" } });

HTML

Комитет TC39 не будет указывать ​изменения в HTML. Но есть возможность включать утверждения в качестве атрибута в теги скриптов при импортировании модулей:

<script src="foo.wasm" type="module" asserttype="webassembly"></script>

Модули JSON

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

Возможные случаи использования, не связанные с JSON

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

  • Импортирование таблиц стилей для стилевого оформления  —  CSS, LESS, SASS, SCSS и т. д.
  • Компоненты фреймворков для интеграции  —  компоненты React, Vue, Angular.
  • Шаблоны  —  HTML-документы, разметки и т. д.
  • Raw-файлы (необработанные файлы).

Спасибо за внимание, а теперь практиковаться!

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Mahdhi Rezvi: Import Assertions in JavaScript

Предыдущая статьяЧто такое HTTP/3 и зачем он нужен?
Следующая статьяКлассификация текстов отзывов о фильмах с помощью Scikit-learn