前言
在本文中,我們從使用原生 JavaScript 改寫 jQuery 網頁程式的觀點,來看需要那些工具。如果是要寫新的網頁程式,重點則會放在如何使用原生網頁 API 上,但本文介紹的工具仍可繼續沿用。
選擇目標瀏覽器
對於網頁程式來說,瀏覽器就是運行環境和發佈平台。選擇目標瀏覽器,可以了解目標平台所支援的網頁 API。
從西元 2001 年發佈的 Internet Explorer (IE) 6 到現代瀏覽器,市面上的瀏覽器種類繁多。但我們容易掉入支援度的思考誤區。並不是市面上所有的瀏覽器都得支援,要看專案的需求而定。
為了支援舊瀏覽器,得受到一些功能限制,會使得專案的難度上升。對於不支援的瀏覽器,我們可以用一些提示訊息提醒使用者更換瀏覽器。
以桌面瀏覽器來說,應支援以下四種瀏覽器的最新兩個版本:
- Chrome
- Safari
- Firefox
- Edge
至於 IE 則視專案需求來決定是否要支援。
若要支援行動瀏覽器,應支援以下兩種瀏覽器的最新兩個版本:
- Chrome
- Safari
至於行動版 Firefox 和行動版 Edge 則視專案決定是否要支援。
讀者可能會懷疑要如何取得這麼多種瀏覽器?總不能為了測 Safari 相容性特地去買台 Mac 電腦來用吧。
市面上有許多雲端瀏覽器測試 (browser testing) 環境,利用虛擬機器的技術,可以在許多瀏覽器間快速切換。比起購買實體機器,使用這類雲端軟體會便宜得多。
用 Babel 或 TypeScript 轉譯現代 JavaScript 程式碼
即使我們要支援舊瀏覽器,我們也不必受限於舊瀏覽器的 JavaScript 語法和 API。我們可以透過 JavaScript 轉譯器,撰寫現代 JavaScript (ES6+) 程式碼,再將其轉為等效的 ES5 版本程式碼。
目前來說,JavaScript 轉譯器中最建議的是 Babel 和 TypeScript,因為這兩個軟體所使用的語言皆相容於現有的 JavaScript,可以套用在現有的 JavaScript 專案上,再慢慢重構到新式 JavaScript 語法。
相較於這兩個專案,其他 JavaScript 轉譯器採用其他語言,無法直接套用在現有 JavaScript 程式碼上,只能移植或重寫。
Babel 和 TypeScript 的差別在於所採用的語言。Babel 是直接用新的 JavaScript 語法轉回舊的 JavaScript 語法。TypeScript 則是將 JavaScript 加入型別檢查和以類別 (class) 為主體的物件系統。
目前 TypeScript 較 Babel 受到觀迎。喜歡原生 JavaScript 的話,可以使用 Babel;喜歡 Java 或 C# 的類別系統的話,則可用 TypeScript。
在改寫 jQuery 時,搭配 Babel 或 TypeScript,可以直接用新式 JavaScript 語法或 API 來重構程式碼。轉譯器會自動將其轉為 ES5 程式碼,會比直接寫 ES5 程式碼來得輕鬆。
用 Polyfill 補足缺乏的 JavaScript API
雖然我們用 Babel 將 ES6+ 代碼轉為 ES5 代碼了,但仍有一些舊瀏覽器無法完全支援 ES5 語法,這時候我們會用 polyfill 來補足網頁 API 的不足。
Polyfill 本身是 JavaScript 函式庫,其原理為用舊網頁 API 重新實作新網頁 API 的功能。雖然用 JavaScript 重新實作會比直接使用瀏覽器提供的 API 來得慢,有模擬 API 可用總比完全沒 API 可用來得好。
對於已有 API 的新瀏覽器來說,polyfill 會透過條件判斷把該段 API 實作跳過,所以不會顯著影響瀏覽器的效能。
市面上有許多 polyfill 的實作品,一個知名的函式庫是 polyfill.io,這套函式庫可支援到 IE 8,應該算是夠舊了。在網路程式中引入 polyfill 的語法如下:
<script src="https://polyfill.io/v3/polyfill.min.js"></script>
引入 polyfill 的位置應該要在所有的 JavaScript 程式碼和命令稿之前,這樣其他的 JavaScript 程式才能完整吃到 polyfill 修正過的網頁 API。
(選擇性) 使用客製的 jQuery
如果一時半刻無法完全移除 jQuery,其實可以透過自行編譯 jQuery 減少 jQuery 的容量。因為編譯 jQuery 的時候,我們只會編譯所需的模組 (module),編譯出來的 jQuery 就會比標準 jQuery 來得小。也有熱心的程式人寫出 jquery-builder 這個命令列工具,簡化編譯 jQuery 的任務。
要編譯 jQuery,得熟悉專案程式碼,因為要知道會專案用到那些 jQuery 模組。如果接手別人的專案,可能無法馬上熟悉專案有用到那些 jQuery API,就不適合用這個方法。
(選擇性) 使用 Zepto.js 取代 jQuery
除了使用客製的 jQuery 外,也可以用 Zepto.js 取代 jQuery。Zepto.js 並不是 jQuery,但在 API 上刻意和 jQuery 相容,藉以減少網路程式所消耗的頻寬。不過,API 相容不代表程式的行為也一定相容,還是得測試一下程式。
不論使用客製版 jQuery 或是 Zepto.js,這都只是權宜之計,長期的目標還是要放在完全去除 jQuery。我們在撰寫新的程式碼時,應該刻意避開 jQuery 的 API,改用原生 JavaScript 或其他函式庫來寫功能。
使用小型函式庫來替代 jQuery 的部分功能
我們在改寫 JavaScript 程式碼時,不一定每行 jQuery 程式碼都可以用一兩行原生 JavaScript 程式碼代換掉,有時候要寫多行 JavaScript 程式碼才能獲得等效的功能。
當無法用很簡短的原生 JavaScript 程式碼取代 jQuery 程式碼時,可以用小型函式庫來代換掉該段程式碼,整體上來說程式碼會比較簡潔。像是用在動畫的 animate.css 或是用在 Ajax 呼叫的 superagent 等。
使用外部函式庫時,同樣要注意瀏覽器相容性的問題。此外,學習新函式庫也要一定的時間成本。在搜尋和評估函式庫時要有一些耐心。
移除 Bootstrap 的 jQuery 依賴
有時候我們並沒有要用 jQuery,但是要用 Bootstrap,結果就多掛上 jQuery 了。Bootstrap 團隊也發現這個議題,新的版本已經移除 jQuery 了。
對於 Bootstrap 3 和 Bootstrap 4 來說,也有一些開發者做出不需要 jQuery 的 Bootstrap。像是用原生 JavaScript 的 Bootstrap.Native、使用 React 的 React Bootstrap 或是改用 Vue.js 的 BootstrapVue 等。
由於這些 Bootstrap 發行版是非官方版本,可能會和官方版 Bootstrap 有一些小落差。還是得親身嘗試看看,才知道是否符合自己的需求。
結語
移除 jQuery 是一個漸進的過程,在這個過程中,每個專案所需要的工具或函式庫可能略有不同。希望本文的內容,能對讀者有一些啟發,讓移除 jQuery 的旅程更加平順。