Defront — про фронтенд-разработку и не только
12.8K subscribers
21 photos
1.09K links
Ламповый канал про фронтенд и не только. Всё самое полезное для опытных web-разработчиков

Обсуждение постов @defrontchat

Также советую канал @webnya
Download Telegram
Сегодня столкнулся с циклическими зависимостями в своём проекте. Захотелось посмотреть, как эту проблему решают другие. Нашёл статью Мишеля Вестстрате (автор mobx) — "How to fix nasty circular dependency issues once and for all in JavaScript & TypeScript".

Суть подхода заключается в использовании двух файлов internal.js и index.js. Файл internal.js реэкспортит все локальные модули. Файл index.js (входная точка в библиотеку) реэкспортит содержимое internal.jsexport * from "./internal.js";. Локальные зависимости должны импортировать нужные сущности только из internal.js. В internal.js все реэкспорты размещаются в таком порядке, в котором все зависимости будут корректно разрешены. Благодаря такому подходу можно управлять порядком загрузки модулей.

В итоге пофиксил циклические зависимости по-другому, но взял на заметку подход Мишеля.

#js #esm #trick

https://medium.com/visual-development/how-to-fix-nasty-circular-dependency-issues-once-and-for-all-in-javascript-typescript-a04c987cf0de
25 апреля npm немного поштормило. Ошибка в пакете is-promise, привела к поломке трёх миллионов зависимых проектов. Форбс Линдсей — автор библиотеки — написал постмортем.

После добавления поддержки ESM новый файл index.mjs не был добавлен в секцию files в package.json. Также в секции exports идентификатор модуля был без префикса ./. Из-за опубликованного кода перестал работать require вида require('is-promise/index'), require('is-promise/index.js'), require('is-promise/package.json').

С момента публикации сломанной библиотеки до её полного фикса прошло четыре часа. Для предотвращения проблем в будущем был удалён .npmignore и добавлен прогон тестов для Node.js 12 и 14, также были добавлены тесты, использующие npm pack для проверки публикуемого API и настроена публикация пакетов из CI. Разработчики Node.js в свою очередь обновили документацию, уточнив, что package.exports должен явно включать в себя все необходимые точки входа.

#npm #postmortem #esm #nodejs

https://medium.com/@forbeslindesay/is-promise-post-mortem-cab807f18dcc
Микаэль Роджерс написал пост про организацию совместимости Node.js-модулей, использующих ESM, и require — "Native ESM in Node.js with require() fallbacks".

Последние версии Node.js поддерживают нативную модульную систему и позволяют импортировать CommonJS-модули внутри ESM-файлов. Но может возникнуть ситуация, когда нужно обеспечить импорт ESM-файлов в CommonJS. Node.js не поддерживает такое направление импорта. Для обхода этого ограничения можно использовать export maps в package.json. В нём каждому файлу сопоставляются соответствующие CommonJS- и ESM-версии:

"exports": {
".": {
"import": "./index.js",
"require": "./dist/index.cjs"
},
"./basics.js": {
"import": "./basics.js",
"require": "./dist/basics.cjs"
},
...
}


Для автоматического создания cjs-файлов из esm-файлов Микаэль воспользовался Rollup и небольшим конфигом.

Статья будет полезна тем, кто хотел использовать в своих пакетах ESM, но не делал этого из-за отсутствия совместимости с CommonJS.

#nodejs #esm

https://dev.to/mikeal_2/native-esm-in-node-js-w-require-fallbacks-and-support-for-all-front-end-compilers-2ded
Лия Веру написала небольшую статью про то как подружить между собой ESM и библиотеки, использующие другие подходы, — "Import non-ESM libraries in ES Modules, with client-side vanilla JS".

Все популярные браузеры поддерживают нативную модульную систему (ESM). Проблема в том, что есть очень много CommonJS-библиотек, которые были написаны давно и которые просто так нельзя взять и подключить к себе с помощью import. Для обхода этой проблемы Лия предлагает использовать небольшой трюк, суть которого заключается в использовании динамического импорта с предварительно застабленной переменной module:

async function require(path) {
let _module = window.module;
window.module = {};
await import(path);
let exports = module.exports;
window.module = _module;
return exports;
}


У такого подхода много ограничений, но он может пригодиться, если надо по-быстрому поэкспериментировать с библиотеками, которые распространяются как CommonJS/AMD-модули (для AMD надо стабить define).

#esm #trick #js

https://lea.verou.me/2020/07/import-non-esm-libraries-in-es-modules-with-client-side-vanilla-js/
Тим Ван Дер Лип из команды разработки Chrome написал статью о миграции кодовой базы девтулзов на ECMAScript Modules — "DevTools architecture refresh: Migrating to JavaScript modules".

Chrome DevTools — это большое приложение, написанное на стандартных web-технологиях: HTML, CSS, JS. Оно было спроектировано более 10 лет назад до массового распространения модульных систем. Для организации модульности до 2020 года в Dev Tools использовался паттерн Externally Defined Dependencies. В этом паттерне весь граф зависимостей описывается в независимом файле или файлах. Специальная утилита (в случае Dev Tools, написанная на python) считывает этот файл и собирает из большого количества js-файлов один бандл.

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

Чтобы избавиться от этих проблем, ребята решили перенести всю кодовую базу на ESM. Начальная оценка была 2-4 недели, но весь процесс миграции занял 7 месяцев, так как по ходу дела возникло много проблем, например, с интеграцией со старой системой и с тестами, которые работали в sloppy режиме (то есть без "use strict"; ). Миграция включала в себя два этапа: в первом были добавлены новые export'ы, во втором — import'ы с удалением устаревшего кода.

Очень интересная статья. Советую почитать, если хотите узнать больше технических подробностей.

#esm #migration

https://developers.google.com/web/updates/2020/09/migrating-to-js-modules
Якуб Джейерлюк поделился шпаргалкой со всеми способами загрузки JavaScript-кода, их преимуществами и недостатками.

Примеры использования:

— "script src" — самый распространённый вариант загрузки, используется для загрузки кода стандарта ES5 и ниже
— "script src defer" — для отложенного выполнения кода с сохранением порядка выполнения скриптов
— "script src async" — для отложенного выполнения кода без сохранения порядка выполнения
— "script src async defer" — тоже самое, что и предыдущий вариант, но с поддержкой IE9
— "script inline" — для внедрения на страницу небольших сниппетов кода, которые нужно выполнить как можно быстрее
— "script src module" — для загрузки кода в современных браузерах
— "script src module async" — для загрузки кода для прогрессивного улучшения страницы в современных браузерах
— "script inline module" — небольшой сниппет кода, который не нужно кэшировать
— "script inline module async" — небольшой сниппет кода для прогрессивного улучшения страницы, который не нужно кэшировать
— "script nomodule" — фоллбек для старых браузеров, не поддерживающих модульную систему ECMAScript 2015

#js #esm

https://gist.github.com/jakub-g/385ee6b41085303a53ad92c7c8afd7a6
Синдре Сорхус — автор большого количества npm-пакетов — поделился своими планами миграции на нативную модульную систему — "Get Ready For ESM".

В конце апреля 2021 года будет прекращена поддержка Node.js 10. Это означает, что майнтейнеры пакетов могут начать использовать все фичи Node.js 12 в том числе и ECMAScript Modules. ESM решает проблему интероперабельности модулей между Node.js и web, включает strict-режим по умолчанию и поддерживает три-шейкинг.

Синдре планирует в этом году перевести все свои npm-пакеты (более тысячи) на ESM и планирует полностью отказаться от CommonJS. Также он призывает всех майнтейнеров npm-пакетов присоединиться к этой инициативе, чтобы ускорить процесс миграции всей JavaScript-экосистемы.

#esm #nodejs

https://blog.sindresorhus.com/get-ready-for-esm-aa53530b3f77
В Chrome 89 была добавлена поддержка import maps. Гай Бедфорд рассказал, какие преимущества несёт эта фича с точки зрения производительности — "Import Maps Release & Module CDN Launch".

Благодаря поддержке import maps можно использовать bare specifiers в импортах. То есть не import something from './path/to/something.js', а import something from 'something'. По сути это есть не что иное, как соответствие спецификаторов и соответствующих им путей до модулей:

<script type="importmap">
{
"imports": {
"something": "./path/to/something.js"
}
}
</script>


Благодаря import maps можно обеспечить кэширование кусков JS-приложения без каскадной инвалидации кода при обновлении нижележащих зависимостей. То есть они открывают возможность эффективного кэширования при инкрементальном обновлении web-приложений.

На данный момент поддержка import maps есть только в Chrome 89. Для других браузеров доступен полифилл.

#js #esm #performance

https://jspm.org/import-map-cdn
Полифил для предзагрузки JavaScript-модулей с проверкой целостности

Гай Бедфорд — автор jspm и SystemJS — рассказал о своих опытах реализации кроссбраузерной предзагрузки JavaScript-модулей с проверкой целостности — "ES Module Preloading & Integrity".

В нативной модульной системе модули загружаются после загрузки их родителей. Чтобы ускорить загрузку нижележащих модулей, можно использовать предзагрузку с помощью <link rel="modulepreload">. Ещё можно включить проверку целостности с помощью атрибута integrity. Проблема в том, что modulepreload и integrity поддерживаются только в Chrome.

Гай в своей статье предлагает использовать полифил для поддержки modulepreload и integrity во всех браузерах и рассуждает о том, как ещё может быть реализована проверка целостности JavaScript-модулей.

#esm #performance #security

https://guybedford.com/es-module-preloading-integrity
Использование внешних ресурсов в JavaScript без сборки

Ингвар Степанян рассказал о способе подключения ресурсов приложения без сборки — "Bundling non-JavaScript resources".

Современные бандлеры позволяют импортировать стили, wasm-модули, изображения и т.п. После сборки такие импорты превращаются в набор URL, которые без проблем загружаются браузером. С внедрением нативной поддержки esm в браузеры такой подход вызывает проблемы, так как JavaScript-код с импортом внешних ресурсов нельзя использовать без сборки.

В статье предлагается использовать альтернативный паттерн, который распознаётся всеми браузерами — new URL('./relative-path', import.meta.url). Такой подход формирует в рантайме корректный URL ресурса для дальнейшего использования. import.meta.url нужно использовать, чтобы пути резолвились относительно текущего JavaScript-файла, а не относительно HTML-документа. Выражение new URL('...', import.meta.url) также распознаётся современными сборщиками при создании чанков с кодом.

В будущем new URL('...', import.meta.url) может быть заменён методом import.meta.resolve('...') (на данный момент в спецификации не решены некоторые вопросы). Также в браузеры потихоньку начинает проникать поддержка import assertions, но она не покрывает все возможные виды ресурсов.

#bundle #esm

https://web.dev/bundling-non-js-resources/
Абсолютные импорты в JavaScript

Евгений Карагодин написал статью про настройку абсолютных импортов — "Абсолютные импорты в JavaScript".

Относительные пути в спецификаторах импортов могут быть неудобны в проектах с глубокой вложенностью директорий. Поэтому были придуманы разные способы для импорта файлов от корня проекта. В статье рассказывается про основные способы упрощения работы с импортами. Про сложность настройки абсолютных импортов в Node.js-проектах c TypeScript и тест-раннерами.

Процесс настройки абсолютных импортов должен стать проще после имплементации спецификация import maps, с помощью которой можно управлять резолвингом модулей. На данный момент import maps поддерживаются только в Deno.

#js #esm

https://blog.ekaragodin.com/TH2jgliMXOO
🔥264👍3
Cовременные возможности для работы с JavaScript-модулями

Аксель Раушмайер написал статью про современные возможности для работы с JavaScript-модулями — "Publishing and consuming ECMAScript modules via packages – the big picture".

Последние версии Node.js поддерживают package exports и package imports. Package exports используются авторами библиотек для настройки путей, по которым будет доступен импорт модулей. Package imports позволяют создавать альясы на пакеты или модули. Их можно использовать для подмены реализации модуля в зависимости от окружения. Package exports и package imports настраиваются в package.json.

В браузерах скоро появится поддержка import maps. С их помощью можно создавать альясы, относительно которых будут резолвиться спецификаторы модулей в браузере. Это полезно при доставке кода пользователям в чистом ESM, когда в названии файлов модулей есть хеши. Import maps уже используют в проде авторы почтового клиента hey.

#js #esm #nodejs #npm

https://2ality.com/2022/01/esm-specifiers.html
🔥7👍5