最近在補一些 HTML 的書籍,偶爾讀到這本書,雖然這本書已是10年之前的書籍了,不過其中有些有趣的知識點與觀點被我提取了出來。css
做者在開始就提出了 Mozilla 開發人員關於標準與實現之間的衝突的一個觀點:html
一份技術規範和他的具體實現必需要作到步調一致。實現先於規範完成不是什麼好事情,由於人們會開始依賴這些已實現的細節,這樣會對規範形成制約。然而,你也不但願在規範已經完成時尚未任何相關的具體實現與實踐經驗,由於這樣規範就得不到任何反饋。這裏面若是存在着沒法避免的衝突,而咱們也須要硬着頭皮去克服了。
事實上,對於前端開發而言,具體實現早於技術規範的制定已是一種常態了。但與其餘領域不一樣的是:前端的新標準非必要條件下是不能夠破壞以前的實現。前端
在這裏,我能夠舉幾個兼容性的例子:vue
你們可能都使用過 String.prototype.includes 來判斷一個字符串是否包含在另外一個字符串中。可是實際上,在 Firefox 18 - 39中,這個方法的名稱叫 contains()
。因爲在Firefox 17上,一些使用 MooTools 1.2的網站會崩潰掉。當年因爲各個框架爲了可以更簡單的使用函數,在各自的代碼庫中修改內置對象的 prototype,同時框架也考慮到了將來標準可能會實現,爲了兼容之後的標準,他們對 prototype 進行判斷,而後若是對象當前 prototype 上沒有函數實現,就使用當前本身定製的函數,若是有函數實現的話,就使用瀏覽器所提供的函數。雖然他們考慮到了兼容標準,可是他們卻沒能考慮到標準是會發生改變的。可能在若干年後,標準實現後,函數已經與當前截然不同。所使用的代碼就會發生錯誤。因此,無奈之下,該函數被重命名爲 includes()
。事實上咱們能夠看出,contains 命名要比 includes 好得多。 webpack
在最新的提案之一就是在類中添加私有變量方法,標準將使用 #
符號來表示類的私有變量。css3
class Count { #a = 1; getCount() { return this.#a } } const count1 = new Count() count1.getCount() // 1 console.log(count1) // Uncaught SyntaxError: Private field '#a' must be declared in an enclosing class
emmm...,美醜你們自行鑑別。也正是由於前端以前沒有所謂的私有變量,因此你們都會「約定」 _
就是私有變量,可是事實上,任何約定都只會防君子不防小人。必定會有大量的代碼直接進行調用。一旦瀏覽器支持後,必然會影響大量網頁。 因此咱們也只能硬着頭皮去克服了。git
受到影響的不只僅是 JavaScript,同時也有 Css。 Css 變量爲了可以在 Sass(變量用了 $ ) 和 Less(變量用了 @) 中使用,也是不得不去使用 --。能夠看到這樣進行 Css 變量定義也是不那麼美觀的。github
:root { --main-bg-color: brown; }
該書也討論了爲何會存在 <img> 這個元素標籤。爲何它是 img,而不是 include,image(事實上,貌似 image 元素標籤也是存在在瀏覽器中的,能夠看這一篇 blog Having fun with <image>)?web
答案以 93 年一羣大佬的精彩的對話爲主線,其中能夠看到一些真知灼見,也有一些前瞻性很強的言論。衆口難調是必然的。不少時候,協議的制定自己就不是一個技術問題,很難有對錯而言。可是爲何必定是 <img>,答案很簡單,由於提議者馬克·安德里森在對話後直接發佈了代碼來處理這個元素。vue-cli
這並非說給出代碼實現的就必定是贏家,可是這是贏家的必要條件,不是嗎?討論固然重要,是一種思想的交流,可是當咱們不能從道理上說服別人的時候,就只能用其餘的方案來代表本身的態度。
該書也討論了當年 WHAT 小組和 W3C HTML 小組之間對於 HTML 發展的不一樣思考和看法,開始時候,兩個小組之間各自爲政,無視對方存在。WHAT 小組針對 Web 表單和新的特性進行工做,而另外一組忙於制定 XHTML 2.0 版本,但惋惜的事情是: 沒有瀏覽器爲之提供實現。
XHTML 是和 HTML 不兼容的,這意味者不但瀏覽器開發者要作大量的工做,還須要讓前端開發者一會兒切換到 XML,徹底書寫良好的規範 — 這是行不通的。而 WHAT 小組採用寬容的錯誤處理,把重點放在新特性上。
不管從觀念仍是互聯網產品,過於超前的結局其實都不是太好。固然,這從側面也印證了一個道理,選擇比努力更重要的不是一句空話。
最後,咱們來聊一下技術吧。
新的功能已經到來,可是咱們要等到何時才能夠採用它?這個問題不但出如今 10 年前,同時也會在如今。優秀的開發者老是但願使用最新的特性來提高用戶體驗。固然了,咱們如今能夠依賴 Can I use 來判斷瀏覽器支持狀況。
很早以前,咱們用 <noscript> 來處理不使用腳本的網頁。
再而後,咱們經過瀏覽器特性檢測來進行兼容處理。例如 Modernizr 庫來檢查瀏覽器是否支持 HTML5 以及 css3。利用 polyfill 來升級不支持特性的瀏覽器。
即便在今天,這些問題依然沒有被解決。固然咱們利用更加先進的技術來支持罷了。
若是進行過前端開發,就不可能沒有使用過 polyfill。polyfill你能夠理解爲「膩子」,就是裝修的時候,能夠把缺損的地方填充抹平。針對於各個瀏覽器的把差別化抹平。因爲各個瀏覽器版本不一樣,所須要的 polyfill 也不一樣,
Polyfill.io是一項服務,可經過選擇性地填充瀏覽器所需的內容來減小 Web 開發的煩惱。Polyfill.io讀取每一個請求的User-Agent 標頭,並返回適合於請求瀏覽器的polyfill。
若是是最新的瀏覽器且具備 Array.prototype.filter
https://polyfill.io/v3/polyfill.min.js?features=Array.prototype.filter /* Disable minification (remove `.min` from URL path) for more info */
可是若是當前瀏覽器沒有此函數,就會在 正文下面添加有關的 polyfill。
國內的阿里巴巴也搭建了一個服務,能夠考慮使用,網址爲 polyfill.alicdn.com/polyfill.mi…
使用新的 DOM API,能夠有條件地加載 polyfill,由於能夠在運行時檢測。可是,使用新的 JavaScript 語法,這會很是棘手,由於任何未知的語法都會致使解析錯誤,而後全部代碼都不會運行。
該問題的解決方法是
<script type="module">。
早在 2017 年,我便知道 type=module 能夠直接在瀏覽器原生支持模塊的功能。具體能夠參考 JavaScript modules 模塊 以及 ECMAScript modules in browsers。可是當時感受只是這個功能很強大,並無對這個功能產生什麼解讀。可是卻沒有想到能夠利用該功能識別你的瀏覽器是否支持 ES2015。
每一個支持 type="module" 的瀏覽器都支持你所熟知的大部分 ES2015+ 語法!!!!!
例如
所以,利用該特性,徹底能夠去作優雅降級。在支持 type=module 提供所屬的 js,而在 不支持的狀況下 提供另外一個js。具體能夠參考 Phillip Walton 精彩的博文,這裏也有翻譯版本 【譯】如何在生產環境中部署ES2015+。
若是當前項目已經開始從 webpack 陣營轉到 Vue CLI 陣營的話,那麼恭喜你,上述解決方案已經被內置到 Vue CLI 當中去了。只須要使用以下指令,項目便會產生兩個版本的包。
vue-cli-service build --modern
具體能夠參考 Vue CLI 現代模式。
不得不說的是: 目前也有開發者把 ESM module 已經做爲主流瀏覽器的功能來思考。還提供了 10 倍打包速度的 Snowpack。雖然目前距離生產環境還有必定差距,不過若是下次須要開發小型我的項目,我會嘗試使用該工具。
若是你以爲這篇文章不錯,但願能夠給與我一些鼓勵,在個人 github 博客下幫忙 star 一下。