iT邦幫忙

2023 iThome 鐵人賽

DAY 25
0
Modern Web

網頁的另一個大腦:從基礎到進階掌握 Web Worker 技術系列 第 25

使用 modulepreload 優先下載 module worker 檔案

  • 分享至 

  • xImage
  •  

使用 preload 優先下載資源

不知道大家有沒有使用過 preloadpreload 用來明確告知瀏覽器,某一份資源是很重要的,所以請優先下載它,使用方式如下:

<head>
  <link
    rel="preload"
    as="style"
    href="important-style.css"
  </link>
</head>

使用 modulepreload 優先下載 module worker 檔案

module worker 也有一個類似的用法,使用 modulepreload 使得 worker 的載入速度變快

<!DOCTYPE html>
<html>
  <head>
    <!-- 預先加載重要的 worker.mjs 檔案 -->
    <link rel="modulepreload" href="worker.mjs" />
    <script src="./src/index.mjs" type="module"></script>
  </head>

  <body>
    <div id="app"></div>
  </body>
</html>

如何確認 modulepreload 有優先加載到檔案?

因為 modulepreload 是比較新的用法,不一定各大瀏覽器都有支援,而驗證的方法可以開啟 devtoolnetwork 選項,查看 worker.mjs 是否會在 index.mjs 前被載入,這裡有個 範例 Demo 可以驗證,當使用兩種不同的寫法,在 network 中瀏覽器載入檔案的順序會不同,加了 <link rel="modulepreload" href="worker.mjs" /> 這一行後,worker.mjs 會提早在 src/index.mjs 之前載入。

worker.mjsindex.mjs 之前載入:
https://ithelp.ithome.com.tw/upload/images/20231009/201626878hx9YdnSU7.png

自動加載所有依賴項

MDNmodulepreload 的部分提到了:

A browser may additionally also choose to automatically fetch any dependencies of the module resource.

瀏覽器可以額外選擇自動的加載模塊中用到的所有依賴模塊。

關於這點這個 範例 Demo 中也有進行測試,可以看到 add.mjsworker.js 依賴,但沒有寫在 modulepreload 裡,如果瀏覽器會自動加載所有依賴模塊的話,add.mjs 應該也會提前加載,但我實測 Chrome 116 瀏覽器,add.mjs 會在最後才被加載,代表瀏覽器目前應該沒有實作此功能。

modulepreload 不僅預加載,而且也解析、編譯了 Javascript 模塊

Links with rel="modulepreload" are similar to those with rel="preload". The main difference is that preload just downloads the file and stores it in the cache, while modulepreload gets the module, parses and compiles it, and puts the results into the module map so that it is ready to execute.

基本上 modulepreloadpreload 是很相似的,但有一個主要的不同點在於,preload 只預先下載檔案並把它快取在瀏覽器中,然而 modulepreload 做到的更多,它更進一步的 解析 (parse) 而且 編譯 (compile) Javascript 模塊。

一開始看到這段想說 modulepreloadpreload其實沒什麼差別,不過就是多進行了 解析 (parse)編譯 (compile) 而已,但深入瞭解後發現這其中是一段非常複雜的過程,關於這過程的解釋會放在最後的 補充小知識 2. Javascript 的 解析(parse) 與 編譯(compile)

結論

module worker 可以使用 rel="modulepreload" 的方式告知瀏覽器將重要的 worker 檔案優先下載,優化資源下載的流程

補充小知識

1. preload 是什麼?
preload 指令用來明確的告知瀏覽器,這份資源檔案很重要,請優先加載這份資料!通常會用到這個指令的場景是希望優先加載一些被寫在很深層的內嵌 css 或字型檔等,像以下的狀況,important-font.woff2 這個字型檔可能被嵌套在很深的 css

index.html
main.js
styles/
    main.css
        ...
            ...
            font.css
            important-font.woff2

那麼在 index.html 中就可以使用 preload 告知瀏覽器先行下載 important-font.woff2 這個字型檔

<head>
  <meta charset="utf-8">
  <title>Preload example</title>

  <!-- 明確告知瀏覽器,優先加載某個很深路徑的字型檔 -->
  <link
    rel="preload"
    href="styles/very/deep/path/important-font.woff2"
    as="font"
    type="font/woff2"
    crossorigin
  </link>
  
  <link href="styles/main.css" rel="stylesheet" />
</head>

在不加 preload 的一般狀況下,瀏覽器會優先讀取到 styles/main.css,然後再往下讀取 styles/main.css 中用到了哪些其他的 css 或是字型檔,等到瀏覽器解析到 important-font.woff2 這份檔案時,已經過去一段時間了,而這時瀏覽器才會開始去抓這份重要的字型檔,而使用 preload 後可以明確告知瀏覽器這是重要的資源,請幫我優先下載它

想了解更多的推薦以下文章:
[教學] Preload, Prefetch 和 Preconnect 的差異
HTTP/2 服务器推送(Server Push)教程

2. Javascript 的 解析(parse) 與 編譯(compile)
相信大家一定都有聽過 Chrome 用來處理 JavascriptV8 引擎,那什麼是 V8 引擎呢?它實際上就包含了對 Javascript 解析(parse)編譯(compile) 的處理
https://ithelp.ithome.com.tw/upload/images/20231009/20162687Ave8jIthZk.jpg
圖片來源:https://dev.to/edisonpappi/how-javascript-engines-chrome-v8-works-50if

JS 檔案 (source code),雖然人類看得懂但對於電腦來說就像是天書一樣,所以 JS 檔案 需要轉換為機器看得懂的機器碼,而這個轉換的過程就是中間這一塊 Javasciprt 引擎 處理的範疇,而引擎處理的事情大致上來說可以分成三個步驟:
Step 1. 解析(parse) 原始碼結構
Step 2. 轉換為 AST
Step 3. 交由 解釋器(Interpreter) 及 編譯器(Compiler),最終變為可執行的機器碼

我想這裡面每個步驟都牽涉到蠻複雜的知識,所以我找到一些不錯的網站希望分享給大家:

概略說明各個步驟的作用,初步暸解 V8 引擎 - 深入研究 JavaScript 引擎 - (Chrome V8)
解釋 parse => AST 這段的過程 - How JavaScript works: Optimizing for parsing efficiency
用簡單易懂的方式講解什麼是 AST - 淺談 AST 及 ESlint Rule:AST 是殺毀?(上)
清楚易懂的實例,講解 Interpreter 到 Compiler 這段過程的原理 - JavaScript 编译 - JIT (just-in-time) compiler 是怎么工作的


上一篇
將 Web worker 內嵌於 HTML 中 - Embedded worker
下一篇
小故事 - modulepreload 的來源
系列文
網頁的另一個大腦:從基礎到進階掌握 Web Worker 技術30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言