snowpack,提高 10 倍打包速度的神奇工具
引言
前幾天聽一個朋友說到 snowpack, 便去去看了下這個包是幹什麼的,看了下官網,發現這個東西還是蠻有意思的。號稱 無需打包工具(Webpack,Parcel)便能將代碼結果實時展現在瀏覽器中。可以先看以下的圖,是不是很誘人?
snowpack 以 ES Modules 爲主,如果對 ES Modules 不熟悉的朋友,請先查看我的上一篇文章。
爲什麼使用 snowpack
在 ESM 出現之前,JavaScript 的模塊化就有各式各樣的規範,主要有 CommonJS, AMD, CMD, UMD 等規範,最爲廣泛的就是 Node.js 的 CommonJS,使用 module.exports 和 require 來導出導入模塊,它是 npm 中的模塊最主要提供的格式。由於瀏覽器並不直接支持這些模塊,因此打包工具(Webpack,Browserify,Parcel 等)出現了。
- 在開發過程中你是否遇到 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。
示例
需要環境: Node 10 +
基礎
說了這麼多,就是說方便唄。那麼我來實際操作一下。
先以一個 react 項目爲例
mkdir snowpack-demo
cd snowpack-demo
npm init -y
安裝依賴
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
// src/index.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
function App() {
return (
<div>hello world</div>
);
}
window.addEventListener("load", () =>
ReactDOM.render(<App />, document.getElementById("app"))
);
<div></div>
<script type="module" src="/dist/index.js"></script>
npx snowpack
babel src/ --out-dir dist
npx servor --reload
打開 http://localhost:8080
進階
使用 css
由於瀏覽器不支持直接使用 JS 導入 CSS, 因此以下代碼無法使用。
// ✘ NOT SUPPORTED OUTSIDE OF BUNDLERS
import './style.css';
如果想要引入 css, 需要通過 style 標籤直接引入資源。
官方推薦的使用方式是
- 簡單應用,使用內斂 style2. 複雜應用推薦使用 CSS-in-JS
因此這裏採用 styled-components
npm i styled-components -S
npx snowpack
修改 index.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import styled from 'styled-components';
const UI = styled.div`
color: red
`
function App() {
return (
<UI>
hello world
</UI>
);
}
window.addEventListener("load", () =>
ReactDOM.render(<App />, document.getElementById("app"))
);
修改下 package.json
"start": "babel src/ --out-dir dist --watch & servor --reload"
npm run start
使用圖片
// ✘ NOT SUPPORTED OUTSIDE OF BUNDLERS
import './photo.png';
如今,沒有瀏覽器支持直接從 JS 導入圖像。相反,您將要使用以下庫 / 解決方案之一:
<img src="/img/photo.png">
使用 TypeScript
npm i @babel/preset-typescript typescript -D
修改 .babelrc
{
"presets": ["@babel/preset-react", "@babel/preset-typescript"],
"plugins": [
"snowpack/assets/babel-plugin.js"
]
}
將 src/index 修改成 src/index.tsx 並加入聲明。
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 theme={ThemeColor}>{children}</ThemeProvider>
</>
);
};
const AppStyle = styled.div<Theme>((props: Theme) => {
console.log(props);
return {
color: props.theme.default
}
})
function App() {
return (
<UI>
<AppStyle>
hello world
</AppStyle>
</UI>
);
}
window.addEventListener("load", () =>
ReactDOM.render(<App />, document.getElementById("app"))
);
修改 啓動命令,讓 babel 包含對 後綴 tsx 的轉義。
{
"start": "babel src/ --out-dir dist --watch --extensions \".ts,.tsx,.js,.jsx\" & servor --reload"
}
優化
默認情況下,snowpack會安裝最小化的依賴關係並針對開發進行了優化。準備好進行生產時,請使用--optimize標誌運行snowpack以啓用某些僅針對生產的優化:
- 最小化依賴關係 2. 轉義低級語法 3.
Tree-Shaking(通過--include啓動自動模式)4. 支持舊版瀏覽--nomodule
如果要構建單頁應用程序(SPA),請使用--nomodule運行 snowpack 並傳入應用程序入口點。然後,在你的應用程序中創建第二個腳本標籤, 帶有nomodule 標識的入口。
<!-- Ignored by legacy browsers: -->
<script type="module" src="/src/index.js"></script>
<!-- Ignored by modern browsers: -->
<script nomodule src="/web_modules/app.nomodule.js"></script>
完成此操作後,運行 snowpack 生成一個 / web_modules/app.nomodule.js 腳本,這個腳本會自動在舊的舊版瀏覽器上運行。
緩存處理
通過傳入 addVersion
/* .babelrc */
"plugins": [
["snowpack/assets/babel-plugin.js", {"addVersion": true}],
]
可以輸出帶有版本號的腳本
// src/ File Input
import Foo from 'package-name';
// lib/ Babel Output
import Foo from '/web_modules/package-name.js?v=1.2.3';
結尾
snowpack 優勢
- 減少了打包的時間成本,只要一次
snowpack。修改源碼能夠實時反饋在瀏覽器上。2. 代碼可移植能力強,相當於純寫 JavaScript 語言。3. 模塊和源碼相互獨立,有點類似於 webpack 的DDL。4. 對於簡單應用可以快速搭建,對於一些在線編輯的網站可以使用類似的方案進行構建。
snowpack 劣勢
- 對 ES Modules 的依賴性強,在 npm 上雖然 ES Modules 的包在逐漸增加,但是短期內需要包都需要做額外的處理。例如我想引入
Antd, 發現其中依賴了很多CommonJS的模塊以及樣式未使用 CSS-in-JS, 引入較爲繁瑣。
- 對於一些
css,images資源處理不夠友好,需要額外手動處理,並且底層使用rollup來進行一次ES Modules的導出太過於生硬, 沒有強大的自定義的插件或者配置。2. 太多依賴包會造成網絡問題
以上例子:https://github.com/hua1995116/snowpack-demo
對於現階段的 snowpack 來說還是太年輕,但是年輕總是充滿希望和可能。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/pUgbKYmolQS0kYUCLeprng