Browser 上的 ESmodule & 現代化的前端構建工具 Snowpack / Vite

瀏覽器看得懂 import / export 耶!支援程度如何?對資深前端打工仔 aka 網頁開發者來說又有什麼改變?未來的打包趨勢跟當今的 solution 又有何不同呢?

大致上談幾件事

  • Support 程度
  • 對前端工程化影響
  • 適用 ESM 之打包工具——Snowpack / Vite

寫在前面

適合閱讀的受眾:

  • 已經了解前端工程化
  • 了解當代打包工具功能的前端打工仔。

不適合閱讀本文:

  • (Tune 模板)只有在 HTML 嵌入過 Bootstrap/jQuery
  • (前端新人)沒有 build 過 npm package 到瀏覽器上
  • (來自 2008 年的時空穿越者)以為前端只能寫幾個按鈕給 User submit

Browser 上的 import / export

註:開發者都是傾向於寫 ESModule 的語法,再透過 Babel 這類的工具把它轉成 Node 可以看懂的 CommonJS (require / module.exports = {})。

啊怎麼用?

首先 HTML 上,這段要用 ESModule 的 script 必須要長這樣:

<script type="module" src="js/index.js">

你的 JS 裡頭就可以用 import / export 了

import helloworld from './helloworld.js'
helloworld()

而 helloworld.js 就是:

export default ()=> {
console.log("hello world");
}

你的 static folder 大概長這樣

├── index.html
└── js
├── helloworld.js
└── index.js

不相信嗎?我 Code 都寫好了,直接來 Verify 吧,沒混直接發。

啊不是,是沒 bundle 直接發。

ESModule 的 支援度如何?

IE 就不用想了,不過號稱當代手機界的IE—Safari是支持的呢。

這個支援度…好像滿猛的耶?如果不考慮 IE 這個爛東西,似乎可以朝著 ESModule 的路筆直向前了!

ESModule 跟以往的體驗差異

  • 所有的模組都是 static 的 js file
  • 瀏覽器會 Handle relative /absolution URL 並加載模組的過程

這意味著幾件事情:

  • Code splitting
  • Decrease file size
  • Network concurrent fetch

ESmodule 對前端工程化的影響

註:儘管可以透過宣告方式做 Code Splitting 、 lazy loading,但無論是前者可以被 ESModule 的分拆解決,或是後者可以透過原生的 import() 解決。

這也意味著當你選擇了 ESmodule 作為開發,你對於 build time 需要去處理的 Effort 大大降低,再也不需要雜亂的 Bundler 配置、設定 Entry file 等等的,只要透過 <script type=module> 就可以進入具 module dependency 的 JS code。

但實際上有這麼理想嗎? node_modules 的 packages / CSS的預處理 / babel transform / typescript …工程化還有這麼多件事,難道只能繼續捆綁在 Webpack 了?

我們仍然需要有 build tool 在 build time 時幫我們:

  • 把 package dependency 放到對應的 static folder裡頭
  • 做一些預處理的動作(包括 .ts/.jsx /.scss /.sass / …)

Snowpack — modern bundler

Snowpack leverages JavaScript’s native module system (known as ESM) to create a first-of-its-kind build system that never builds the same file twice. Snowpack pushes changes instantly to the browser, saving you hours of development time traditionally spent waiting around for your bundler.

以上在 Build time 需要完成的事情 Snowpack 都可以透過其原始的功能或者對應的 Plugin (你也可以想象成 Loader)去做掉。

有趣的是他們解決 node_modules 的方法,如果你試著透過 snowpack 來 build 你的 index.js 如下:

// src/index.js// The below three is from node_modules
import rQUI from 'rQUI';
import carousel from 'rQUI.carousel';
import animation from 'rQUI.animation';
// The below one is what you create and import
import elements from './elements.js';

最終 build 出來的 _dist_/index.js 會是

// _dist_/index.js
import rQUI from '/web_modules/rQUI/index.js';
import carousel from '/web_modules/rQUI.carousle/index.js';
import animation from '/web_modules/rQUI.animation/index.js';

你的 public folder 會是這樣的 file structure:

├── _dist_
│ └── js
│ ├── elements.js
│ └── index.js
├── index.html
└── web_modules
├── rQUI
│ └── index.js
├── rQUI.carousel
│ └── index.js
└── rQUI.a
└── index.js

屆時這些東西會一路從 public folder server 到 web 上,而 Browser 在吃到 ESModule 後會自動發起網路請求,並且把這些東西 collect 回來 as module。

另外一個一樣風格的 build tool —Vite

後記

If any interest, 👉 https://realdennis.me.

If any interest, 👉 https://realdennis.me.