【手寫簡易瀏覽器】思路綜述篇

其實有這個想法很久了,只是一直沒開始寫,正好趕上掘金的日更活動,就想着把它實現一遍吧,然後把實現過程記錄下來。

想法的來源

前段時間在研究 babel,寫了一本小冊,裏面有一個 基於 babel parser 實現 js 解釋器的案例,寫那個案例的時候我就在想,js 的解釋執行都實現了,是不是再進一步,加上渲染的部分,寫一個簡易的瀏覽器呢。

最近在看 postcss 的源碼,把 css parser 的實現也理清了,能夠自己實現從 css 到 ast 的 parse。

之前寫過 html parser,寫了很多次類似的東西,比如 vue template parser、wxml parser 等,html 到 ast 的轉換也能實現。

最近還寫了一篇 event loop 與 js 引擎、渲染引擎關係的文章,和一篇跨端引擎原理的文章,講述瞭如何用 event loop 把 js 的解釋執行與 css 的渲染綜合起來,共用一個線程完成渲染和邏輯,以及如何基於容器的思路實現跨端引擎。

這些東西湊到一塊,其實就是一個簡易瀏覽器的實現思路,所以我想趁着這次更文活動,把它給實現了。一個是對這段時間輸出的東西的一個綜合,另一個也能加深對前端代碼運行環境的理解。也希望給大家一些啓發。

實現思路概述

這篇文章會講一下實現思路,具體實現從下一篇開始。

html parser

我們會實現一個 html parser,把 html 字符串 parse 成 dom tree,使用一趟遍歷的方式來實現,和 vue template compiler 的 parser 思路一致。

css parser

我們會實現一個 css parser,把 css 字符串 parse 成 css tree,實現思路和 postcss 的 parser 類似。

佈局引擎

有了 html parser 和 css parser 之後把兩者合併成 render tree,之後實現佈局引擎,把樣式計算爲具體的座標。

渲染引擎

js 解釋器

js 字符串的解釋執行,首先需要一個 js parser,這個就不自己實現了,用 acron 就行,之後自己做解釋執行。會實現 scope 和函數的執行,注入幾個綁定事件、操作 dom 的 api 的實現。

event loop

渲染和邏輯執行都實現了,但是兩者要跑在同一個線程,那麼就需要通過 event loop 來調度。js 按照 一個宏任務、所有微任務的方式的方式執行,每次 loop 結束 check 一下是否需要渲染,渲染按照每幀 16 ms 的速率來刷新。

我們會通過不斷的 setTimeout 來實現 event loop 不斷取事件的邏輯,因爲死循環會卡死主線程(在 c++ 裏面可以用死循環實現 event loop,因爲有其他線程來往隊列裏放事件對象)。

這樣就能實現渲染的按幀率刷新和 js 邏輯的執行。

網絡資源下載

上面實現了 html、css、js 的渲染和執行,而且實現了 event loop 的調度。這些資源是從網絡上下載的,所以還要實現一個下載模塊,這個模塊要能從一個 url 下載 html,然後還會解析出其中的鏈接來下載。

靜態服務器

html、css、js 等資源是從 web 服務器下載的,通過 http 協議,這個服務器也需要實現,可以是一個簡單的靜態服務器,也可以是有一些邏輯的動態服務器。

瀏覽器的界面

既然是瀏覽器,那麼肯定要有一個輸入 url 的地方和顯示內容的地方,所以我們會做一個界面,上面是地址欄,用於輸入 url,下面是內容區,用於顯示渲染的內容。

整體架構圖如下:

總結

首先是 html parser、css parser、js parser,除了 js 的會用 acorn 其餘都會自己實現,然後會實現佈局引擎和渲染引擎,實現 js ast 的解釋執行,通過 event loop 綜合兩者,實現渲染和邏輯的調度。之後加上網絡資源的下載、瀏覽器的界面,就是一個簡易的瀏覽器了,思路是可行的。

後續每一部分會用一篇文章來講清楚,並且會把源碼放在 github,敬請期待。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/szlB_K2yOG32DhaSSDRNAA