能否讓JS作為打開網頁的入口?
- 2019 年 10 月 8 日
- 筆記
最近逛GitHub論壇的時候發現一個很有意思的話題:
Make JavaScript Files a Valid Entry Point to a Web Page
意思是,讓JavaScript文件作為一個合法的網頁入口(而不是html文件)。話題地址在這:
https://github.com/w3c/webcomponents/issues/807
這個話題勾起了我的興趣,因為我一直覺得以html文件作為網頁的唯一入口很麻煩,前後端分離之後寫純靜態html的人越來越少了,前端框架興起之後幾乎所有的網頁和應用都由JavaScript來操作。我們打開用Vue開發的https://element.eleme.cn/官網,檢查一下源代碼會得到這樣一個普遍現象:

整個網頁幾乎只有一行代碼有意義:
<div id="app"></div>
剩下的全是JS。這種現象逐漸讓我們開始質疑html標記語言是否還有存在的必要。
標記語言存在的意義
技術的發展是從自下而上的,新技術出現的順序往往和潛意識相反(在後人看來)。我們都知道JavaScript是用於在前端計算的主要工具,html則是對JavaScript的一種彌補,用來更直觀的表示UI元素的位置關係,這才是js和html正真的主從關係。同理,在Qt中,qml標記語言也是對C++的一種彌補。
然而事實是,前端先有html,再出現了JavaScript。qml倒是後於C++而誕生,主要因為C++本身並不是做UI的。
JS和html誕生順序的顛倒導致了瀏覽器的歷史遺留問題:網頁只能從html來渲染,js必須嵌入到html中。這隻能說,html確實沒啥用了,但是標記語言(或者說描述語言)還是擁有不可動搖的地位。
注意,這裡所說的原生html語言並不包括其他和html長得很像的標記語言,比如前端腳手架中使用的mvvm標記語言,模板引擎等。這些標記語言中的一些特殊語法比如雙花括號 {{ }},php標籤 <?php ?>,很有GraphQL風格的qml,以及JS的模板字符串 `${ }` 這些都是為了解決特定問題而對通用的JavaScript語言進行的一種擴充。當然,即使沒有這些標記語言,通用編程語言也能達到目的,但有了標記語言,效率提升了一個層次。
即時渲染
回到最初的問題,html標記語言目前有一種被孤立的趨勢,但並不代表html就要被淘汰,html至少還支持即時渲染。即時渲染是標記語言的一大優勢,因為標記語言可以拆分成流來傳輸:雖然html中有閉合標籤的語法約束,但是瀏覽器仍然能夠一邊接受html流,一邊渲染UI,當html文件很大的時候,這種網絡的延遲削減是JavaScript不可替代的。上期介紹的ndJSON標記語言也是同樣可以一邊解析一邊傳輸,一個道理。這就是為什麼國內訪問Gmail的時候經常選擇加載基本html:

如果網速很慢,點擊「加載基本HTML」就可以提前享受流式渲染。

以JS作為網頁入口可行嗎?
以上仍然不能解釋為啥網頁的入口一定得是html,現在的問題是,未來有沒有可能支持從JS直接打開網頁,這個問題就是在w3c/webcomponents這個GitHub倉庫下「囂張」質疑w3c標準的issue作者Lonniebiz,從對問題的描述中可以看出他還是個完美主義的杠精,他一再強調以text/html為網頁入口是web標準庫的致命缺陷卻給不出合適的論據,單純從美學的角度要求w3c委員會對標準庫進行修正,於是收穫了網友的一致吐槽:

同時,看戲的小夥伴包括我給他的解決方案基本都是使用<script>標籤將JavaScript代碼包裹起來再以text/html為mime類型傳給瀏覽器作為入口,就像下面這樣:
<!DOCTYPE html><meta charset="utf-8"><script> addEventListener('DOMContentLoaded', function () { document.title = 'Hello index.js'; document.head.appendChild( document.createElement('style') ).textContent = ` html { font-family: sans-serif; font-size: 16px; text-align: center; } `; document.body.appendChild( document.createTextNode('Hello body') ); }, {once: true}) </script>
這種方式已經很常見了,大夥都在用也沒啥意見,可是版主Lonniebiz就是認之為一種hack手段並嗤之以鼻。在翻看了幾十條長篇評論之後終於忍無可忍的我給了他一個「最終」解,希望能結束這場無意義的辯論賽:
我也討厭html醜陋的語法,但瀏覽器的職責是瀏覽不同mime類型的媒體資源,不僅僅是網頁(text/html)!瀏覽器還可以展示圖片,音視頻,pdf,純文本,等等等。所以對於text/JavaScript資源來說,瀏覽器會展示js只讀模式的純文本內容(雖然沒啥實際用途),但不會,不能夠也不應該去執行這個js文件。這裡有三「不」,我來解釋下:
- 「不會」:這是事實,瀏覽器不會直接解析text/JavaScript
- 「不能夠」:text/JavaScript這種媒體資源不會觸發虛擬機和標準庫的加載
- 「不應該」:確實有人希望在瀏覽器中瀏覽js文件內容,而不需要執行
從邏輯上,網頁也屬於一種媒體,它和其他媒體類型是平等對待的,網頁的mime類型就是text/html,沒有其他。所以只有text/html才會讓瀏覽器加載為網頁服務的v8虛擬機以及DOM標準庫。
也許在將來的某一天清晨,網頁擁有了第二個mime叫webpage/javascript或者webpage/wasm!等到那一天,直接從JS或者WebAssembly渲染頁面的美好夙願也就實現了。
(完)