最近用vite 构建项目的时候发现 vite 加入了 <link rel="modulepreload" >
参考文章Preloading modules
虽然文章上说的已经很明白了, 但鉴于这是2017年的文档, 所以还需要翻译翻译
浏览器最近已经原生的支持JS modules
, 包括静态和动态的 import
, 这意味着现在们可以在浏览器内直接基于模块编写JS不用编译和打包
但是, 模块依赖项会带来加载问题, 因为浏览器需要先等待模块加载, 然后才能找到其依赖项. 解决此问题的一种方法是预加载依赖项, 以便浏览器提前知道所有文件并可以保持连接
Chrome 64
附带 ‘实验性Web平台功能’ 标志后的<link rel ='modulepreload'>
<link rel ='modulepreload'>
是 <link rel =' preload'>
特定于模块的版本, 它解决了后者的许多问题
Chrome在50
版中添加了对<link rel ='preload'>
的支持, 这是一种在浏览器需要资源之前以声明方式提前请求资源的方法
<head>
<link rel="preload" as="style" href="critical-styles.css">
<link rel="preload" as="font" crossorigin type="font/woff2" href="myfont.woff2">
</head>
为什么 <link rel ='preload'>
对module不生效?
源有多种凭证模式, 为了获得高速缓存命中, 它们必须匹配, 否则最终将获取资源两次. 双重获取是不好的, 因为它浪费用户的带宽并使他们等待更长的时间, 这没有充分的理由
对于 <script>
和 <link>
标签, 可以使用 crossorigin
属性设置凭据模式. 事实证明, 没有crossorigin
属性的 <script type ='module'>
不具有凭据模式
此外, 获取文件只是实际运行代码的第一步. 首先, 浏览器必须解析和编译它. 理想情况下, 这也应该提前发生, 以便在需要模块时, 代码就可以运行了. 但是 V8
解析和编译模块的方式与其他JavaScript
不同.<link rel ='preload'>
没有提供任何方式表明正在加载的文件是模块, 因此浏览器所能做的就是加载文件并将其放入缓存. 使用<script type ='module'>
标记加载脚本(或由其他模块加载)后, 浏览器将代码解析并编译为JavaScript
模块
那么对于模块来说, <link rel ='modulepreload'>
只是 <link rel ='preload'>
吗?
是的 通过为预加载模块使用特定的链接类型, 我们可以编写简单的HTML, 而不必担心我们使用的是哪种凭据模式.
<head>
<link rel="modulepreload" href="super-critical-stuff.mjs">
</head>
[...]
<script type="module" src="super-critical-stuff.mjs">
而且由于Chrome现在知道您要预加载的是模块, 因此它可以很聪明地在完成获取操作后立即解析并编译该模块, 而不必等到它尝试运行为止
预加载模块是否有助于提高性能
通过向浏览器告知需要获取的内容, 预加载可以帮助最大程度地利用带宽, 从而避免在长途往返期间无所事事