精讀《snowpack》

1 引言

基於 webpack 構建的大型項目開發速度已經很是慢了,前端開發者已經逐漸習慣忍受超過 100 秒的啓動時間,超過 30 秒的 reload 時間。即使被寄予厚望的 webpack5 內置了緩存機制也不會獲得質的提高。但放到十年前,等待時間是幾百毫秒。css

好在瀏覽器支持了 ESM import 模塊化加載方案,終於原生支持了文件模塊化,這使得本地構建再也不須要處理模塊化關係並聚合文件,這甚至能夠將構建時間從 30 秒下降到 300 毫秒。前端

固然基於 ESM import 的構建框架不止 snowpack 一個,還有好比基於 vue 的 vite,由於瀏覽器支持模塊化是一個標準,而不與任何框架綁定,將來任何構建工具都會基於此特性開發,這意味着在將來的五年,前端構建必定會回到十年前的速度,這個趨勢是明顯、肯定的。vue

ESM import 帶來的最直觀的改變有下面三點:node

  1. node_modules 徹底不須要參與到構建過程,僅這一點就足以讓構建效率提高至少 10 倍。
  2. 模塊化交給瀏覽器管理,修改任何組件都只需作單文件編譯,時間複雜度永遠是 O(1),reload 時間與項目大小無關。
  3. 瀏覽器徹底模塊化加載文件,不存在資源重複加載問題,這種原生的 TreeShaking 還能夠作到訪問文件時再編譯,作到單文件級別的按需構建。

因此能夠說 ESM import 模式下的開發效率,能作到與十年前修改 HTML 單文件的零構建效率幾乎至關。react

2 簡介 & 精讀

snowpack 核心特徵:webpack

  • 開發模式啓動僅需 50ms 甚至更少。
  • 熱更新速度很是快。
  • 構建時能夠結合任何 bundler,好比 webpack。
  • 內置支持 TS、JSX、CSS Modules 等。
  • 支持自定義構建腳本以及三方插件。

安裝

yarn add --dev snowpack
複製代碼

經過 snowpack.config.json 文件配置,並能自動讀取 babel.config.json 生效 babel 插件。git

開發調試

調試 snowpack dev,編譯 snowpack build,會自動以 src/index 做爲應用入口進行編譯。github

snowpack dev 命令幾乎是零耗時的,由於文件僅會在被瀏覽器訪問時進行按需編譯,所以構建速度是理想的最快速。web

當瀏覽器訪問文件時,snowpack 會將文件作以下轉換:npm

// Your Code:
import * as React from "react";
import * as ReactDOM from "react-dom";

// Build Output:
import * as React from "/web_modules/react.js";
import * as ReactDOM from "/web_modules/react-dom.js";
複製代碼

目的就是生成一個相對路徑,並啓動本地服務讓瀏覽器能夠訪問到這些被 import 的文件。其中 web_modules 是 snowpack 對 node_modules 構建的結果。

在這以前也會對 Typescript 文件作 tsc 編譯,或者 babel 編譯。

編譯

編譯命令 snowpack build 默認方式與 snowpack dev 相同:

也能夠指定以 webpack 做爲構建器:

// snowpack.config.json
{
  // Optimize your production builds with Webpack
  "plugins": [
    [
      "@snowpack/plugin-webpack",
      {
        /* ... */
      }
    ]
  ]
}
複製代碼

除了默認構建方式以外,還支持自定義文件處理,經過 snowpack.config.json 配置 scripts 指定:

{
  "extends": "@snowpack/app-scripts-react",
  "scripts": {
    "build:scss": "sass $FILE"
  },
  "plugins": []
}
複製代碼

好比上述語法支持了對 scss 文件編譯的拓展。

"build:*": "..."

對文件後綴進行編譯,好比:"build:js,jsx": "babel --filename $FILE" 指定了對 js,jsx 後綴的文件進行 babel 構建。

"run:*": "..."

僅執行一次,能夠用來作 lint,也能夠用來配合批量文件處理命令,好比 tsc: "run:tsc": "tsc"

"mount:*": "mount DIR [--to /PATH]"

將文件部署到某個 URL 地址,好比 "mount:public": "mount public --to /" 意味着將 public 文件夾下的文件部署到 / 這個 URL 地址。

還有 proxy 等 API 就不一一列舉了,詳細能夠見 官方文檔

咱們能夠從構建命令體會到 snowpack 的理念,將源碼以流式方式編譯後,直接部署到本地 server 提供的 URL 地址,瀏覽器經過一個 main 入口以 ESM import 的方式加載這些文件。

因此全部加載與構建邏輯都是按需的,snowpack 要作的只是將本地文件逐個構建好並啓動本地服務給瀏覽器調用。

前端開發離不開 node_modules,snowpack 經過 snowpack install 的方式支持了這一點。

snowpack install

這個命令已經被 snowpack dev 內置了,因此 snowpack install 僅用來理解原理。

如下是 snowpack install 執行的結果:

✔ snowpack install complete. [0.88s]

  ⦿ web_modules/                 size       gzip       brotli
    ├─ react-dom.js              128.93 KB  39.89 KB   34.93 KB
    └─ react.js                  0.54 KB    0.32 KB    0.28 KB
  ⦿ web_modules/common/ (Shared)
    └─ index-8961bd84.js         10.83 KB   3.96 KB    3.51 KB
複製代碼

能夠看到,snowpack 遍歷項目源碼對 node_modules 的訪問,並對 node_modules 進行了 Web 版 install,能夠認爲 npm install 是將 npm 包安裝到了本地,而 snowpack install 是將 node_modules 安裝到了 Web API,因此這個命令只需構建一次,node_modules 就變成了能夠按需被瀏覽器加載的靜態資源文件。

同時源碼中對 npm 包的引用都會轉換爲對 web_modules 這個靜態資源地址的引用:

import * as ReactDOM from "react-dom";

// 轉換
import * as React from "/web_modules/react.js";
複製代碼

但同時能夠看到 snowpack 對前端生態的高要求,若是某些包經過 webpack 別名設置了一些 magic 映射,就沒法經過文件路徑直接映射,因此 snowpack 生態成熟須要一段時間,但模塊標準化必定是趨勢,不規範的包在將來幾年內會逐步被淘汰。

2020 年適合使用 snowpack 嗎

答案是還不適合用在生產環境。

固然用在開發環境仍是能夠的,但須要承擔三個風險:

  1. 開發與生產環境構建結果不一致的風險。
  2. 項目生態存在非 ESM import 模塊化包而致使大量適配成本的風險。
  3. 項目存在大量 webpack 插件的 magic 魔法,致使標準化後丟失定製打包邏輯的風險。

但能夠看到,這些風險的緣由都是非標準化形成的。咱們站在 2020 年看之前瀏覽器非標準化 API 適配與兼容工做,可能會以爲難以想象,爲何要與那些陳舊非標準化的語法作鬥爭;相應的,2030 年看 2020 年的今天可能也以爲難以想象,爲何不少項目存在大量 magic 自定義構建邏輯,明明標準化構建邏輯已經徹底夠用了 :P。

因此咱們要看到將來的趨勢,也要理解當下存在的問題,不要在生態還沒有成熟的時候貿然使用,但也要跟進前端規範化的步伐,在合適的時機跟上節奏,畢竟 bundleless 模式帶來的開發效率提高是很是明顯的。

3 總結

前端發展到 2020 年這個時間點,代碼規範已經基本穩定,工程化要作的事情已經重新增功能逐漸轉移到研發提效上了,所以提高開發時熱更新速度、構建速度是當下前端工程化的重中之重。

snowpack 表明的 bundleless 方案確定是光明的將來,帶來的構建提效很是明顯,人力充足的前端團隊與不須要考慮瀏覽器兼容性的敏捷小團隊都已經開始實踐 bundleless 方案了。

但對於業務須要兼容各瀏覽器的大團隊來講,目前 bundleless 方案僅可用於開發環境,生產環境仍是須要 webpack 打包,所以 webpack 生態還能夠繼續繁榮幾年,直到大的前端團隊也拋棄它爲止。

若是看將來十年,可能前端工程化構建腳本都不須要了,瀏覽器能夠直接運行源碼。在這一點上,以 snowpack 爲表明的 bundleless 模式着實跨越了一大步。

討論地址是:精讀《snowpack》· Issue #252 · dt-fe/weekly

若是你想參與討論,請 點擊這裏,每週都有新的主題,週末或週一發佈。前端精讀 - 幫你篩選靠譜的內容。

關注 前端精讀微信公衆號

版權聲明:自由轉載-非商用-非衍生-保持署名(創意共享 3.0 許可證

相關文章
相關標籤/搜索