The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

網站如何開始使用 ES6 / ES2015 模組化技術進行前端開發

在 2019 的今天,還有多少人在使用傳統前端技術在開發 Web 應用程式?撇除市面上知名的 SPA 框架不說,就算你公司內部還在使用 jQuery 開發網頁,你依然可以將自己升級到使用現代化前端技術的前端工程師。今天這篇文章,將分享如何將現有傳統網站逐步升級,改用如 ES6 / ES2015 等語法,以及透過好用的模組打包工具(module bundler)將全新的 JS 語法轉譯為舊版瀏覽器也能執行的 JS 語法。

開始使用 ES6 Modules 組織程式碼

知名的練習專案 TodoMVC 有提供一個 Vanilla ES6 版本,我擷取這個專案的 HTML、CSS 與 JavaScript 部分,然後將所有工具移除,弄了一個相當純粹的 Vanilla ES6 版本。

https://github.com/doggy8088/todomvc-vanilla-es6-modules

由於從 Chrome 61 開始 (2017/9/5 Released) 就從瀏覽器原生支援 ES Module (ESM) 模組化技術,所以你完全可以在不使用 module bundler 工具的輔助下,直接使用 ESM 進行開發,而且可以使用大部分 ES6 語法。

從我這份 TodoMVC Vanilla ES6 範例的 index.html 第 42 行可以看見,你只要在 <script> 標籤中加入 type="module" 屬性 (Attribute),就可以啟用 ESM 機制。

一般來說,當你使用了 ESM 模組化技術,我們會將所有 JavaScript 檔案集中一個進入點,其他需要的模組,只要透過 import 語法就可以匯入使用,如此一來便可依所需載入必要的程式碼,也能限制 JS 全域變數的使用。

image

我重新整理過後的這個範例程式,如果要能順利在瀏覽器中執行,可以參考以下步驟,透過 lite-server 這個輕量的開發伺服器,就可以快速啟動網站進行測試:

  1. 透過 npm 安裝 lite-server

    npm install -g lite-server
    
  2. 啟動本地開發伺服器

    lite-server
    
  3. 此時瀏覽器會自動開啟 http://localhost:3000/ 網頁

只要你可以開始使用 ESM 模組化技術,你的 JavaScript 視野就此打開,正式進入現代化的前端世界!

使用 Parcel 將新式語法轉為舊版瀏覽器相容語法

市面上知名的 module bundler 非常多,比較知名的有 webpack module bundlerrollup.jsParcelGoogle Closure Compiler 等等。其中最熱門的應該是非 webpack 莫屬,這套同時也是 Angular 目前預設的模組打包工具。

這篇文章我將推薦使用 Parcel 當做新手入門的模組打包工具,因為這套 module bundler 的最主要特色,就是「完全零設定」,一個設定檔都不用寫,全自動幫你的網頁所用到的 JavaScript 或 CSS 進行自動封裝。相較於 webpack 來說,這套 Parcel 可說是既親民又強大,而且 bundle (打包) 的速度一點也不慢!

以下就是在目前的專案使用 Parcel 進行封裝的步驟說明:

  1. 安裝 parcel-bundler 套件

    npm install -g parcel-bundler
    
    yarn global add parcel-bundler
    
  2. 執行 Parcel 並啟動 Parcel 開發伺服器

    parcel index.html --open
    

    使用 --open 參數會自動開啟預設瀏覽器進入測試網站。

此時你就可以連到 http://localhost:1234 測試網站功能,且所有從 src/app.js 匯入進來的檔案,以及所有相依的檔案,都會自動透過 Parcel 自動封裝 (bundle),最後濃縮成一支 *.js 檔案。不僅如此,他還會自動幫你修正 index.html 檔案的內容,將載入的 JS 與其相依的模組,全部自動綑綁在一起。除了 JS 支援,頁面中的 CSS 也會被視為可以自動打包的資產(Assets),也會全自動 bundle 完成。

請注意:使用 module bundler 之後,原本一個頁面中如果載入多支 JS 檔或 CSS 檔,通常都會修改成只載入一支「主要 JS 檔案」,其他相依的檔案就會透過 ES6/ES2015 的 import 匯入進來。

由於 Parcel 預設採用 Babel 對專案內的 JavaScript 檔案進行轉譯,而目前最新版的 Babel 7 在轉譯 JS 的時候,預設是採用 ES2015 以上版本。也就是說,當你在專案中用到了 ES2016 或 ES2017 的 JS 語法,都會全自動轉換為 ES2015/ES6 的語法。

如果你走到這一步都非常順利,那我在此恭喜你,您已經成為一位使用現代化前端技術現代化前端攻城獅了!

使用 Parcel 產生連 IE9 也能運行的網站

Internet Explorer 已經漸漸成為時代的眼淚,不過在企業尚未全面升級至現代化瀏覽器之前,總還是需要面對 IE 的荼毒。

目前 Babel 預設採用 @babel/preset-env,基本上你不用做任何設定,就會自動判斷市佔率高於 0.25% 的各個瀏覽器版本。

但如果你真的想讓 IE9+ 也能支援 ES2015 各種語言特性的話,還是必須對這個範例專案做出些許調整,步驟如下:

  1. 修正 index.htmltype="module" 移除

    <script src="src/app.js"></script>
    
  2. 加入 npm 設定檔:package.json

    你可以透過 npm init -y 快速建立預設 package.json 檔案。

    {
      "name": "todomvc-vanilla-es6-modules",
      "version": "1.0.0",
      "dependencies": {},
      "devDependencies": {},
      "scripts": {}
    }
    
  3. 安裝 js-polyfills 套件 (此套件就是讓 IE9 支援 ES2015 APIs 的利器)

    npm install -D js-polyfills
    

    雖然 Babel 內建支援 @babel/polyfill 套件,但是對 IE 的支援度完全不足,我想應該是 Babel 社群沒多少人想認真支援 IE 吧! XD

  4. 修正 src/app.js 檔案,匯入 js-polyfills 套件

    import 'js-polyfills';
    
  5. 執行 Parcel 並啟動開發伺服器

    parcel index.html
    

    ※ 各位有沒有發現,我們在使用 Parcel 的過程中,完全不用設定這套工具!所有的 bundle 行為都已經預設內建,直接執行就能用!

完成上述步驟之後,就可以讓 IE9+ 安心的瀏覽網站,所有 ES6/ES2015 全新的 API 也可以順利的在網站中使用。

如果你有用 Git 版控的話,建議加入 .gitignore 版控忽略檔,避免不必要的檔案被加入到版控之中:

# Dependency directories
node_modules/

# Yarn Integrity file
.yarn-integrity

# parcel-bundler cache (https://parceljs.org/)
.cache

# distribution files
dist/

# package-lock.json file
package-lock.json

使用 Parcel 自動編譯 TypeScript 原始碼的網站

JavaScript 是個弱型別的程式語言,你無法在開發時期判斷型別,所有型別的問題都只能在執行時期才有機會被發現,你必須執行到那一行有問題的程式碼,才會知道是否發生錯誤。這個狀況會導致當你程式碼變多時,有許多問題是很難第一時間發現的。

此時 TypeScript 的出現,無疑是一種救贖。他讓你在開發時期,透過 TypeScript 編譯器,就能提早得知 JavaScript 程式碼可能出現的問題,並在第一時間修正他。不過,學習 TypeScript 是有點門檻的,你過往寫 JS 那種自由奔放的靈魂,到了 TypeScript 的世界,可能就會覺得礙手礙腳。你必須靜下心來,認真研讀 TypeScript 如何宣告型別,並且認真面對加入型別後的種種限制。

我將用以下步驟,示範如何將目前這個專案升級到使用 TypeScript 進行開發:

  1. 將所有 *.js 檔案批次更名為 *.ts 檔案

    cd src
    rename *.js *.ts
    
  2. 將所有 *.js 檔案中 import 語法的 .js 部分移除

    例如以下 import 語法:

    import Controller from './controller.js';
    import {$on} from './helpers.js';
    import Template from './template.js';
    import Store from './store.js';
    import View from './view.js';
    

    請全部改成如下:

    import Controller from './controller';
    import {$on} from './helpers';
    import Template from './template';
    import Store from './store';
    import View from './view';
    

    如果你用 VSCode 的話,可以用全部取代的方式,搭配正規表示式就可以一次取代完成:

    • 搜尋:import (.*).js';
    • 取代:import $1';
  3. 修正 TypeScript 型別問題

    請參考此版本的變更紀錄。

  4. 修正 index.htmlsrc/app.js 修改為 src/app.ts

    <script src="src/app.js"></script>
    

    改為

    <script src="src/app.ts"></script>
    
  5. 執行 Parcel 並啟動開發伺服器

    parcel index.html
    

各位有沒有再次發現,我們在使用 Parcel 的過程中,即便原始碼全部變成 TypeScript 也完全不用進行設定,連需要的 typescript 套件也會自動安裝,完全是佛心來著!

結語

本篇文章以一個 ES6 專案開始,讓大家了解原來 Google Chrome 瀏覽器已經原生支援 ESM 模組化技術,在不用 module bundler 的幫助下,你已經可以開始進行開發與測試。當寫到一定程度後,搭配著現成好用的 module bundler 工具,即可讓舊版瀏覽器也能順利瀏覽網站,你幾乎沒有理由不用現代化的前端工具,來優化目前程式的品質。

當然,要寫好 JS 沒那麼簡單,有些真正基礎又重要的觀念,必須紮紮實實的建立,我在 我要成為前端工程師!給 JavaScript 新手的建議與學習資源整理 這篇文章中已經明確的點出,大部分的 JavaScript 開發者都是靠自己腦補出來寫 code 的,要培養出好的、正確的觀念,確實相當不容易。

我這幾年所開設的 JavaScript 開發實戰:核心概念篇 課程,目前已經影響上千名學員打好 JavaScript 的堅實基礎,你很難想像花這一天的時間,可以對你未來的 JavaScript 開發生涯帶來多大幫助,如果你還沒有親身體驗過這堂課程,強烈建議你真的可以來上課,感受不一樣的學習體驗。

相關連結

留言評論