O que acontece quando um script é carregado como “preload” / “modulepreload”?
Há um artigo muito interessante no web.dev sobre módulo trabalhador https://web.dev/module-workers/ onde temos a capacidade de carregar o worker's como módulo pré-carregado, o que significa que eles podem ser pré-carregados e até mesmo pré-analisados e pré-buscar suas dependências (https://web.dev/module-workers/#preload-workers-with-modulepreload)
Se eu estiver correto, não apenas Web-Workers podem ser carregados como módulo de pré-carregamento, isso se aplica a qualquer script js, fonte, css etc. como
<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">
Há um ditado neste artigo que me incomoda muito:
Módulos pré-carregados também podem ser usados pelo thread principal e pelos trabalhadores do módulo. Isso é útil para módulos que são importados em ambos os contextos, ou nos casos em que não é possível saber com antecedência se um módulo será usado no thread principal ou em um trabalhador.
Isso significa que o carregamento do módulo também armazena em cache o código analisado, o que significa que os módulos que são usados no thread principal e em um trabalhador não serão analisados novamente, se o tivermos incluído usando a instrução import no topo?
No entanto, isso não acontece, sempre que importamos módulos em qualquer reino (thread principal, thread de trabalho), eles executam suas importações independentemente e, no futuro, eles se referem a suas instâncias em cache analisadas em seus próprios reinos.
Estou muito confuso, o que exatamente o autor está tentando explicar. E como podemos implementá-lo.
Artigos relacionados: https://developers.google.com/web/updates/2017/12/modulepreload#does_preloading_modules_help_performance
Respostas
Não tenho certeza de onde este artigo tirou essa ideia, mas lendo as especificações, não vejo evidências de que
Módulos pré-carregados também podem ser usados pelo thread principal e pelos trabalhadores do módulo.
Se verificarmos as especificações, a busca e o processamento do algoritmo de recurso vinculado para algoritmo de modulepreloadlinks o faz na etapa 5
- Deixe que o objeto de configurações seja o objeto de configurações relevante
linkdo documento do nó do elemento .
Este objeto de configurações é, então, passado na etapa 11 para o algoritmo de gráfico de script de módulo de pré-carregamento de módulo , que por si próprio chamará a busca de um script de módulo único e buscará os descendentes de e link - que por fim também chamará a busca de um script de módulo único - com o mesmo objeto de configurações .
Este objeto de configurações é onde o mapa do módulo será encontrado, e este mapa do módulo será usado na busca de um único script de módulo para evitar a solicitação de várias vezes o mesmo módulo (um cache).
Vamos moduleMap ser definições do mapa módulo de objeto do mapa módulo .
Se moduleMap [url] for
"fetching", espere em paralelo até que o valor dessa entrada mude e, em seguida, enfileire uma tarefa na fonte de tarefa de rede para continuar executando as etapas a seguir.Se moduleMap [url] existir, conclua de forma assíncrona este algoritmo com moduleMap [url] e retorne.
Deve-se notar que, embora esse algoritmo crie um script de módulo , ele ainda não o executa.
Portanto, podemos ver que os modulepreloadlinks não apenas buscarão o recurso vinculado, mas todos os sub-recursos e até mesmo prepararão scripts de módulo para cada um desses recursos, o que corresponde muito ao que este artigo afirma.
No entanto, isso não é suficiente para concluir nada sobre a citação problemática.
Temos que verificar as especificações sobre o construtor Workers dedicado , que chamará a execução de um algoritmo de trabalho passando a mesma configuração de objeto do documento que nosso modulepreloadlink estava usando, desta vez chamado de " configurações externas ".
At step 8 of this run a worker algorithm, it asks to
- Set up a worker environment settings object with realm execution context and outside settings, and let inside settings be the result.
And this set up a worker environment settings object algorithm will only use the document's outside settings to set the inherited origin internal value and the new settings object's top-level origin property.
This new settings object's module map is the one of its global scope, which is "initially empty".
The worker's environment settings object doesn't inherit its module map from outside settings.
So when the worker will itself call these fetch a single module script and fetch the descendants of and link algorithms as part of fetch a module worker script graph, the one module map it will check is its own inside settings's module map and there, it won't find the module scripts our modulepreload link has created.
So by my reading of the specs, I'd say that modulepreload links only help for module Workers is that the HTTP cache will already have downloaded all the files in the graph. If you are going to use these modules only in the Worker, then having it prepare the module scripts on the document's side is actually counter-productive, and a simple prefetch link might do better, except that you'd have to create one such link per sub-resource.
Kaiido Thank you for the detailed response. It is very helpful.
I also searched a lot on this problematic quote and then I initiated an issue on web.dev if they could update the content. You can track on Issue
One of heaviest job for JS Engine is to parse/compile(What is Parse/Compile) our code and it plays an important role in time to interact of a web page and also there are many ways where we can improve TTI like only sending the code a user needs(code-splitting by webpack, chunks etc..), minification, tree shaking, http-caching, module-workers etc.... and also not to forget preload
Actual Definition of Preload:
The basic way you could use preload is to load late-discovered resources early. While most markup-based resources are discovered fairly early by the browser’s preloader, not all resources are markup-based. Some of the resources are hidden in CSS and in JavaScript, and the browser cannot know that it is going to need them until it is already fairly late. So in many cases, these resources end up delaying the first render, the rendering of text, or loading of critical parts of the page.
In short:
Download a resource(preparse + compile) because you know you’d need it, but you don’t yet want to execute it.
Earlier, If we inject the script at the point we want it to run, the browser will have to then download the script before it can be executed(NOTE: Browser has to do lot of stuff before executing your code), which can take a while. But Preload resolve this.
I believe the author is trying to explain the same i.e preloaded and even pre-parsed modules(Not to execute + compiled bytecode is cached) using link rel="modulepreload" Tag for later evaluation(re-compilation can be skipped).
And Finally I believe my queries are resolved. Thank you so much!
Couple of Helpful Links:
- https://developers.google.com/web/updates/2017/12/modulepreload
- https://3perf.com/blog/link-rels/