Что происходит, когда скрипт загружается как «preload» / «modulepreload»?
На web.dev есть очень интересная статья о модульном работнике https://web.dev/module-workers/ где у нас есть возможность загрузить воркера как предварительно загруженный модуль, что означает, что они могут быть предварительно загружены и даже предварительно проанализированы и предварительно загружены их зависимости (https://web.dev/module-workers/#preload-workers-with-modulepreload).
Если я прав, не только веб-воркеры могут быть загружены как модуль предварительной загрузки, это применимо к любому js-скрипту, шрифту, CSS и т. Д., Например
<link rel="preload" href="fonts/cicle_fina-webfont.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="style.css" as="style">
<link rel="preload" href="main.js" as="script">
В этой статье есть высказывание , которое меня сильно беспокоит:
Предварительно загруженные модули также могут использоваться как основным потоком, так и работниками модуля. Это полезно для модулей, которые импортируются в обоих контекстах, или в тех случаях, когда невозможно заранее узнать, будет ли модуль использоваться в основном потоке или в рабочем.
Означает ли это, что загрузка модуля также кэширует проанализированный код, что означает, что модули, которые используются в основном потоке и в рабочем потоке, не будут анализироваться снова, если мы включили его с помощью оператора импорта сверху?
Однако этого не происходит: всякий раз, когда мы импортируем модули в любую область (основной поток, рабочий поток), они выполняют свой импорт независимо, а затем в дальнейшем они ссылаются на свои проанализированные и кэшированные экземпляры в своих собственных областях.
Я действительно не понимаю, что именно пытается объяснить автор. И как это реализовать.
Статьи по Теме: https://developers.google.com/web/updates/2017/12/modulepreload#does_preloading_modules_help_performance
Ответы
Я не уверен, откуда эта статья взяла эту идею, но, читая спецификации, я не вижу доказательств того, что
Предварительно загруженные модули также могут использоваться как основным потоком, так и работниками модуля.
Если мы проверим спецификации, алгоритм выборки и обработки связанных ресурсов для modulepreloadссылок выполняется на шаге 5.
- Пусть объект настроек будет соответствующим объектом настроек
linkдокумента узла элемента .
Затем этот объект настроек передается на шаге 11 для извлечения алгоритма графа скрипта модуля предварительной загрузки модуля , который сам будет вызывать извлечение скрипта одного модуля и извлекать потомков и ссылку - что в конечном итоге также вызовет выборку скрипта одного модуля - с тем же объект настроек .
Этот объект настройки является где карта модуля будет найдена, и этот модуль карта будет использоваться в выборке одного сценария модуля , чтобы избежать запроса многократно превышающие один и тот же модуля (кэш - памяти).
Пусть moduleMap быть настройки карты модуля объекта «s карты модуля .
Если moduleMap [url] равен
"fetching", дождитесь, пока значение этой записи не изменится, затем поставьте задачу в очередь в источнике сетевой задачи, чтобы продолжить выполнение следующих шагов.Если moduleMap [url] существует, асинхронно завершите этот алгоритм с moduleMap [url] и вернитесь.
Вероятно, следует отметить, что пока этот алгоритм создает скрипт модуля , он еще не выполняет его.
Таким образом, мы можем видеть, что modulepreloadссылки будут извлекать не только связанный ресурс, но и все подресурсы и даже подготовить сценарии модулей для каждого из этих ресурсов, что во многом соответствует тому, что в остальном утверждается в этой статье.
Однако этого недостаточно, чтобы сделать вывод относительно проблемной цитаты.
Мы должны проверить спецификации выделенного конструктора Workers , который вызовет запуск алгоритма worker , передавая тот же параметр объекта документа, который использовался нашей modulepreloadссылкой, на этот раз называемый « внешними настройками ».
На шаге 8 запустите рабочий алгоритм, он просит
- Настройте объект настроек рабочей среды с контекстом выполнения области и внешними настройками , и пусть внутренние настройки будут результатом.
И этот набор до объекта рабочи параметров среды алгоритма будет использовать только документ за пределы настройки , чтобы установить inherited originвнутреннее значение и новые настройки объект «s top-level originсвойства.
Эти новые параметры объекта «s карта модуль является одним из его глобального масштаба , что„ изначально пустой “.
Объект настроек рабочей среды не наследует карту модуля из внешних настроек .
Поэтому , когда работник сам будет называть эти выборки одного сценария модуля и извлечения потомков и ссылок алгоритмов в рамках выборки графа сценария модуль уборщица , то один модуль карта будет проверять это его собственные параметры внутри «ы модуля карты и там, он не найдет скрипты модуля modulepreload, созданные по нашей ссылке.
Итак, прочитав спецификации, я бы сказал, что modulepreloadссылки помогают только рабочим модулям, так как HTTP-кеш уже загрузил все файлы на графике. Если вы собираетесь использовать эти модули только в Worker, то подготовка скриптов модуля на стороне документа на самом деле контрпродуктивна, и простая prefetchссылка может оказаться лучше, за исключением того, что вам придется создавать одну такую ссылку для каждого подресурс.
Кайидо Спасибо за подробный ответ. Это очень полезно.
Я также много искал эту проблемную цитату, а затем я инициировал проблему в web.dev, если они могут обновить контент. Вы можете отслеживать по проблеме
Одна из самых сложных задач для JS Engine - это синтаксический анализ / компиляция ( что такое синтаксический анализ / компиляция ) нашего кода, и он играет важную роль во времени для взаимодействия с веб-страницей, а также есть много способов, с помощью которых мы можем улучшить TTI, например, отправив только код, необходимый пользователю ( разделение кода на веб-пакеты, фрагменты и т. д.), минификация, встряхивание дерева, http-кеширование , рабочие модули и т. д., а также не забывать предварительную загрузку
Фактическое определение предварительной нагрузки:
Основной способ использования предварительной загрузки - это ранняя загрузка поздно обнаруженных ресурсов. Хотя большинство ресурсов на основе разметки обнаруживаются предварительным загрузчиком браузера довольно рано, не все ресурсы основаны на разметке. Некоторые ресурсы скрыты в CSS и JavaScript, и браузер не может знать, что они ему понадобятся, пока не станет уже довольно поздно. Таким образом, во многих случаях эти ресурсы в конечном итоге задерживают первый рендеринг, рендеринг текста или загрузку критических частей страницы.
Коротко:
Загрузите ресурс (предварительная обработка + компиляция), потому что вы знаете, что он вам понадобится, но пока не хотите его запускать.
Раньше, если мы внедряем скрипт в тот момент, когда мы хотим, чтобы он запускался, браузер должен затем загрузить скрипт, прежде чем он сможет быть выполнен (ПРИМЕЧАНИЕ: браузер должен сделать много вещей перед выполнением вашего кода), что может занять в то время как. Но Preload решает эту проблему.
Я считаю, что автор пытается объяснить то же самое, то есть предварительно загруженные и даже предварительно проанализированные модули (не выполнять + скомпилированный байт-код кэшируется), используя тег link rel = "modulepreload" для последующей оценки (повторную компиляцию можно пропустить).
И, наконец, я считаю, что мои вопросы решены. Спасибо огромное!
Пара полезных ссылок:
- https://developers.google.com/web/updates/2017/12/modulepreload
- https://3perf.com/blog/link-rels/