咱們能夠簡單的認爲 JavaScript 這門語言目前有兩個主要的 runtime,一個是 Node.js,另外一個就是瀏覽器環境。咱們日常所謂的 JavaScript 是單線程的,實際上指的是 JavaScript 運行在 Render process 的 Main thread,什麼是 Render process,看完你就明白了。web
先來扯一些背景知識,什麼是進程,什麼是線程(JavaScript 其實還有個協程的概念,不扯),這個對咱們後面的講解很重要。面試
好比下面的代碼,理論上來講經過多線程處理要比單線程要快,緣由是由於多線程容許並行處理chrome
const a = 1 + 2;
const b = 20 / 5;
const c = 7 * 8;
console.log(a, b, c);
複製代碼
下圖展現同一個進程的內存是如何共享的瀏覽器
不扯之前的舊的瀏覽器架構,Chrome 瀏覽器的架構以下圖所示(不必定最新)。須要注意的是,像 UI process, Network process 等等這些進程都有可能會被「降級」爲 Browser process 的線程(UI thread, Network thread)。安全
When Chrome is running on powerful hardware, it may split each service into different processes giving more stability, but if it is on a resource-constraint device, Chrome consolidates services into one process saving memory footprint.網絡
因此當你僅僅打開一個 tab 頁的時候的進程信息多是這樣的多線程
就是插件運行的進程,每一個插件一個進程,單獨隔離出是爲了防止插件掛了影響用戶架構
主要負責 UI 渲染app
Handles GPU tasks in isolation from other processes. It is separated into different process because GPUs handles requests from multiple apps and draw them in the same surface.dom
負責網絡資源加載
負責界面展現,用戶交互,子進程管理,文件存取等
Controls anything inside of the tab where a website is displayed.
主要負責將 HTML, CSS, JavaScript 轉換爲用戶可交互的網頁,排版引擎 Blink 和 JavaScript 引擎 V8 就運行在渲染進程,默認每一個 tab 一個渲染進程(特殊狀況下面的進程模式會講)
Chromium 提供了四種進程模式,不一樣的進程模式會對 tab 進程作不一樣的處理,好比採用某個模式況會給 tab 分配新進程,而採用另一個模式則不會,下面是四種模式的介紹,Chrome 默認採用第一個模式
這裏須要給出 site 和 site-instance 的定義
<a target="_blank">
這種方式點擊打開的新頁面window.open
)理解了這兩個關鍵字就能夠仔細說下上面的四種進程模式
Single process 和 Process-per-tab 就不用說了,意如其名。 若是使用 Process-per-site 模式,當你打開了一個 tab 訪問 a.baidu.com,而後再打開一個 tab 訪問 b.baidu.com,這兩個 tab 其實用的是同一個進程,由於這兩個 tab 被分在同一個 group。這就意味着,你在其中一個 tab 寫一個死循環,這兩個 tab 都會 hang
Process-per-site-instance 是最重要的,由於這個是 Chrome 默認使用的模式,也就是幾乎全部的用戶都在用的模式。當你打開一個 tab 訪問 a.baidu.com,而後再打開一個 tab 訪問 b.baidu.com,這兩個 tab 會使用兩個進程。若是 b.baidu.com 是經過 a.baidu.com 頁面的 JavaScript 代碼打開的,這兩個 tab 會使用同一個進程,好比下圖的例子,能夠看到兩個 tab 的 processId 是相同的
由於這種模型兼顧了性能與易用性,是一個比較中庸通用的模式
同時這麼作也知足了 different subdomains or ports of a site to access each other via Javascript 這種需求。
咱們一開始的時候說過,同一個進程的多個線程是共享內存的。因此當兩個 tab 使用同一個進程的時候,這兩個 tab 就是「通的」。好比 A 頁面使用 JavaScript 打開 B 頁面,那麼 B 頁面能夠經過 window.opener
訪問 A 頁面的 window
對象。
這個問題大概是面試出現機率最高的題目之一了,這整個流程其實有個名字叫 Navigation,咱們從進程線程的角度來梳理一下。
首先,在輸入框輸入 www.mysite.com
而後輸入 Enter
這些都是由瀏覽器進程的 UI thread 來負責處理的,其中還有個額外的處理就是判斷輸入是一個 URL 仍是個 Query,不管是哪一個都要經過 IPC 通知網絡進程發送請求,只不過請求的目標不同(輸入的 URL / 搜索引擎)。
通知網絡進程後,UI thread 展現 Spinner,Network process 會負責後續網絡相關的處理好比 DNS lookup 和 establishing TLS Connection。Network process 有可能會收到 redirect response 好比 HTTP 301,這種狀況 Network 會通知 UI thread 對輸入框的 URL 作修改。
網絡進程會根據 Content-Type(HTTP Header) 和文件的 MIME type 來對不一樣的返回作不一樣的處理。好比,若是是 HTML 會交給 Renderer process, 若是是 zip 會交給 Download manager。
同時這裏會作一些安全檢查,好比 SafeBrowsing 和 Cross Origin Read Blocking (CORB)
Network process 完成解析文件類型和安全檢查後,會通知 Browser process,而後 browser process 經過 IPC 通知指定的渲染進程提交導航(commit the navigation),同時將網絡進程的 data stream 傳給渲染進程 so the renderer process can keep receiving HTML data。渲染進程在開始接收 HTML 後,會返回確認信息(confirm message),而後瀏覽器進程這邊就會對 UI 作一些修改,好比 HTTPS 的小鎖頭,前進後退按鈕等等
就像上面說的,Renderer process 收到 commit navigation 的信息後會返回 confirm message 給瀏覽器主進程,同時接收 HTML 並渲染的過程就開始了,具體細節不講太複雜,咱們只關心進程間通信。渲染進程結束後而且全部 onload 事件觸發後,會發送 IPC 給瀏覽器進程,而後 tab 頁的 spinner 會中止,頁面加載完成。