《模塊化系列》snowpack,提高10倍打包速度「轉」

https://juejin.im/post/5e4c0357f265da570b3f25f2

引言

前幾天聽一個朋友說到 snowpack, 便去去看了下這個包是幹什麼的,看了下官網,發現這個東西還是蠻有意思的。號稱 無需打包工具(Webpack,Parcel)便能將代碼結果實時展現在瀏覽器中。可以先看以下的圖,是不是很誘人?


《模塊化系列》snowpack,提高10倍打包速度「轉」


snowpack 以 ES Modules 為主,如果對 ES Modules 不熟悉的朋友,請先查看我的上一篇文章。

為什麼使用 snowpack


《模塊化系列》snowpack,提高10倍打包速度「轉」


在 ESM 出現之前,JavaScript 的模塊化就有各式各樣的規範,主要有 CommonJS, AMD, CMD, UMD 等規範,最為廣泛的就是 Node.js 的 CommonJS,使用 ​module.exports​ 和 ​require​ 來導出導入模塊,它是 npm 中的模塊最主要提供的格式。由於瀏覽器並不直接支持這些模塊,因此打包工具(Webpack,Browserify,Parcel 等)出現了。

  1. 在開發過程中你是否遇到 webapp 總是需要等待才能看到結果,每次保存後電腦就非常瘋狂。
  2. webpack 之類的打包工具功能非常強大,他們引入配置,插件,依賴成本很低,任意創建一個 react 應用便將要安裝 200M 的依賴包,並且需要寫很多行的webpack配置。
  3. ESM在瀏覽器中使用了大約5年的時間,現在在所有現代瀏覽器中都受支持(可追溯到2018年初)。使用ESM,不再需要打包工具。您可以在沒有 Webpack 的情況下構建一個現代化,高性能,可用於生產的Web應用程序!
  4. 你只需安裝運行一次 snowpack 替換 Webpack,Parcel等繁雜的打包工具,可以獲得更快的開發環境,並減少工具複雜性。

環境支持

由於默認情況下,snowpack將npm依賴項安裝為ES模塊(ESM),那麼 ES 模塊的支持情況怎麼樣了呢?

不用擔心,目前使用的90%的瀏覽器都支持 ESM 語法。自2018年初以來,所有現代瀏覽器(Firefox、Chrome、Edge、Safari)都支持ESM。


《模塊化系列》snowpack,提高10倍打包速度「轉」


示例

需要環境: Node 10 +

基礎

說了這麼多,就是說方便唄。那麼我來實際操作一下。

先以一個 react 項目為例

<code>mkdir snowpack-demo

cd snowpack-demo

npm init -y
複製代碼/<code>

安裝依賴

<code>npm i @babel/cli @babel/core @babel/preset-react servor snowpack -D
npm i react@npm:@pika/react react-dom@npm:@pika/react-dom -S
複製代碼/<code>
<code>// src/index.js
import React, { useState } from "react";
import ReactDOM from "react-dom";

function App() {
return (
hello world

);
}

window.addEventListener("load", () =>
ReactDOM.render(, document.getElementById("app"))
);

複製代碼/<code>
<code>


複製代碼/<code>
<code>npx snowpack

babel src/ --out-dir dist

npx servor --reload
複製代碼/<code>

打開 http://localhost:8080


《模塊化系列》snowpack,提高10倍打包速度「轉」


進階

使用 css

由於瀏覽器不支持直接使用 JS 導入 CSS, 因此以下代碼無法使用。

<code>// ✘ NOT SUPPORTED OUTSIDE OF BUNDLERS
import './style.css';
複製代碼/<code>

如果想要引入css, 需要通過 style 標籤直接引入資源。

官方推薦的使用方式是

  1. 簡單應用,使用內斂 style
  2. 複雜應用推薦使用 CSS-in-JS

因此這裡採用 styled-components

<code>npm i styled-components -S
npx snowpack
複製代碼/<code>

修改 index.js

<code>import React, { useState } from "react";
import ReactDOM from "react-dom";
import styled from 'styled-components';

const UI = styled.div`
color: red
`

function App() {
return (

hello world

);
}

window.addEventListener("load", () =>
ReactDOM.render(, document.getElementById("app"))
);

複製代碼/<code>

修改下 package.json

<code>"start": "babel src/ --out-dir dist --watch & servor --reload"
複製代碼/<code>
<code>npm run start
複製代碼/<code>


《模塊化系列》snowpack,提高10倍打包速度「轉」


使用圖片

<code>// ✘ NOT SUPPORTED OUTSIDE OF BUNDLERS
import './photo.png';
複製代碼/<code>

如今,沒有瀏覽器支持直接從JS導入圖像。 相反,您將要使用以下庫/解決方案之一:

使用TypeScript

<code>npm i @babel/preset-typescript typescript -D
複製代碼/<code>

修改 .babelrc

<code>{
"presets": ["@babel/preset-react", "@babel/preset-typescript"],
"plugins": [
"snowpack/assets/babel-plugin.js"
]
}
複製代碼/<code>

將 src/index 修改成 src/index.tsx 並加入聲明。

<code>import React, { useState } from "react";
import ReactDOM from "react-dom";
import styled, { ThemeProvider } from 'styled-components';

const ThemeColor = {
default: 'red'
}

interface Theme {
themeColor: typeof ThemeColor
}

const UI = ({ children }: { children?: React.ReactNode }) => {
return (
<>
<themeprovider>{children}/<themeprovider>
>
);
};

const AppStyle = styled.div<theme>((props: Theme) => {
console.log(props);
return {
color: props.theme.default
}
})

function App() {
return (

<appstyle>

hello world
/<appstyle>

);
}

window.addEventListener("load", () =>
ReactDOM.render(, document.getElementById("app"))
);

複製代碼/<theme>/<code>

修改 啟動命令,讓 babel 包含對 後綴 tsx 的轉義。

<code>{
"start": "babel src/ --out-dir dist --watch --extensions \".ts,.tsx,.js,.jsx\" & servor --reload"
}
複製代碼/<code>

優化

默認情況下,snowpack會安裝最小化的依賴關係並針對開發進行了優化。 準備好進行生產時,請使用--optimize標誌運行snowpack以啟用某些僅針對生產的優化:

  1. 最小化依賴關係
  2. 轉義低級語法
  3. Tree-Shaking(通過--include啟動自動模式)
  4. 支持舊版瀏覽 --nomodule

如果要構建單頁應用程序(SPA),請使用--nomodule運行snowpack並傳入應用程序入口點。 然後,在你的應用程序中創建第二個腳本標籤,帶有nomodule 標識的入口。

<code>



複製代碼/<code>

完成此操作後,運行snowpack生成一個/web_modules/app.nomodule.js腳本,這個腳本會自動在舊的舊版瀏覽器上運行。

緩存處理

通過傳入 addVersion

<code>/* .babelrc */
"plugins": [
["snowpack/assets/babel-plugin.js", {"addVersion": true}],
]
複製代碼/<code>

可以輸出帶有版本號的腳本

<code>// src/ File Input
import Foo from 'package-name';
// lib/ Babel Output
import Foo from '/web_modules/package-name.js?v=1.2.3';
複製代碼/<code>

結尾

snowpack 優勢

  1. 減少了打包的時間成本,只要一次 snowpack。修改源碼能夠實時反饋在瀏覽器上。
  2. 代碼可移植能力強,相當於純寫 JavaScript 語言。
  3. 模塊和源碼相互獨立,有點類似於 webpack 的 DDL。
  4. 對於簡單應用可以快速搭建,對於一些在線編輯的網站可以使用類似的方案進行構建。

snowpack 劣勢

  1. 對 ES Modules 的依賴性強,在npm 上雖然 ES Modules 的包在逐漸增加,但是短期內需要包都需要做額外的處理。例如我想引入 Antd, 發現其中依賴了很多 CommonJS 的模塊以及樣式未使用 CSS-in-JS, 引入較為繁瑣。


《模塊化系列》snowpack,提高10倍打包速度「轉」


《模塊化系列》snowpack,提高10倍打包速度「轉」


《模塊化系列》snowpack,提高10倍打包速度「轉」


  1. 對於一些 css,images 資源處理不夠友好,需要額外手動處理,並且底層使用 rollup 來進行一次 ES Modules 的導出太過於生硬, 沒有強大的自定義的插件或者配置。
  2. 太多依賴包會造成網絡問題

以上例子: https://github.com/hua1995116/snowpack-demo

對於現階段的 snowpack 來說還是太年輕,但是年輕總是充滿希望和可能。


分享到:


相關文章: