在沒有構(gòu)建系統(tǒng)的情況下編寫 Javascript
嗨!這周我一直在寫一些 Javascript,和往常一樣,當(dāng)我開始一個新的前端項目時,我面臨的問題是:我是否應(yīng)該使用構(gòu)建系統(tǒng)?
我想談?wù)剺?gòu)建系統(tǒng)對我有什么吸引力,為什么我(通常)仍然不使用它們,以及一些前端 Javascript 庫要求你使用構(gòu)建系統(tǒng)時,為什么我覺得這讓我感到沮喪。
我寫這篇文章是因為我看到的大多數(shù)關(guān)于 JS 的文章都假定你正在使用構(gòu)建系統(tǒng),而對于像我這樣的人來說,編寫非常簡單的、不需要構(gòu)建系統(tǒng)的小型 Javascript 項目時,構(gòu)建系統(tǒng)可能反而添加了很多麻煩。
什么是構(gòu)建系統(tǒng)?
構(gòu)建系統(tǒng)的思路是,你有一堆 Javascript 或 Typescript 代碼,你想在把它放到你的網(wǎng)站上之前把它翻譯成不同的 Javascript 代碼。
構(gòu)建系統(tǒng)可以做很多有用的事情,比如:
- (出于效率的考慮)將 100 多個 JS 文件合并成一個大的捆綁文件
- 將 Typescript 翻譯成 Javascript
- 對 Typescript 進(jìn)行類型檢查
- 精簡化
- 添加 Polyfills 以支持舊的瀏覽器
- 編譯 JSX
- 搖樹優(yōu)化Tree Shaking(刪除不使用的 JS 代碼以減少文件大?。?/li>
- 構(gòu)建 CSS(像 ??tailwind?? 那樣)
- 可能還有很多其他重要的事情
正因為如此,如果你今天正在構(gòu)建一個復(fù)雜的前端項目,你可能會使用 Webpack、Rollup、Esbuild、Parcel 或 Vite 等構(gòu)建系統(tǒng)。
很多這些功能對我很有吸引力,我過去使用構(gòu)建系統(tǒng)也是出于這樣一些原因: 例如,??Mess With DNS?? 使用 Esbuild 來翻譯 Typescript,并將許多文件合并成一個大文件。
目標(biāo):輕松地對舊的小網(wǎng)站進(jìn)行修改
我做了很多簡單的小網(wǎng)站(??之一??、??之二??、??之三??、??之四??),我對它們的維護(hù)精力大約為 0,而且我改變它們的頻率很低。
我的目標(biāo)是,如果我有一個 3、5 年前做的網(wǎng)站,我希望能在 20 分鐘內(nèi),
- 在一臺新的電腦上從 GitHub 獲取源代碼
- 做一些修改
- 把它放到互聯(lián)網(wǎng)上
但我對構(gòu)建系統(tǒng)(不僅僅是 Javascript 構(gòu)建系統(tǒng)?。┑慕?jīng)驗是,如果你有一個 5 年歷史的網(wǎng)站,要重新構(gòu)建這個網(wǎng)站會非常痛苦。
因為我的大多數(shù)網(wǎng)站都很小,所以使用構(gòu)建系統(tǒng)的 優(yōu)勢 很小 —— 我并不真的需要 Typescript 或 JSX。我只要有一個 400 行的 ??script.js?
? 文件就可以了。
示例:嘗試構(gòu)建 SQL 實驗場
我的一個網(wǎng)站(??SQL 試驗場??)使用了一個構(gòu)建系統(tǒng)(它使用 Vue)。我最后一次編輯該項目是在 2 年前,是在另一臺機(jī)器上。
讓我們看看我今天是否還能在我的機(jī)器上輕松地構(gòu)建它。首先,我們要運(yùn)行 ??npm install?
?。下面是我得到的輸出:
在構(gòu)建 ??grpc?
? 時出現(xiàn)了某種錯誤。沒問題。反正我也不需要這個依賴關(guān)系,所以我可以花 5 分鐘把它拆下來重建。現(xiàn)在我可以 ??npm install?
? 了,一切正常。
現(xiàn)在讓我們試著構(gòu)建這個項目:
??這個 Stack Overflow 的答案?? 建議運(yùn)行 ??export NODE_OPTIONS=--openssl-legacy-provider?
? 來解決這個錯誤。
這很有效,最后我得以 ??npm run build?
? 來構(gòu)建這個項目。
這其實并不壞(我只需要刪除一個依賴關(guān)系和傳遞一個略顯神秘的 Node 選項?。?,但我寧愿不被那些構(gòu)建錯誤破壞。
對我來說,對于小項目來說,構(gòu)建系統(tǒng)并不值得
對我來說,一個復(fù)雜的 Javascript 構(gòu)建系統(tǒng)對于 500 行的小項目來說似乎并不值得 —— 它意味著放棄了在未來能夠輕松更新項目的能力,以換取一些相當(dāng)微小的好處。
Esbuild 似乎更穩(wěn)定一些
我想為 Esbuild 大聲叫好: 我 ??在 2021 年了解到 Esbuild??,并用于一個項目,到目前為止,它確實是一種更可靠的構(gòu)建 JS 項目的方式。
我剛剛嘗試在一臺新電腦上構(gòu)建一個我最后一次改動在 8 個月前的 Esbuild 項目,結(jié)果成功了。但我不能肯定的說,兩年后我是否還能輕松的建立那個項目。也許會的,我希望如此!
不使用構(gòu)建系統(tǒng)通常是很容易的
下面是 ??Nginx 實驗場?? 代碼中導(dǎo)入所有庫的部分的樣子:
這個項目也在使用 Vue,但它只是用 ??<script src?
? 來加載 Vue —— 前端沒有構(gòu)建過程。
一個使用 Vue 的無構(gòu)建系統(tǒng)模板
有幾個人問如何在沒有構(gòu)建系統(tǒng)的情況下開始編寫 Javascript。當(dāng)然,如果你想的話,你可以寫原味的 JS,但我常用的框架是 Vue 3。
??這是我做的一個小模板??,用于啟動一個沒有構(gòu)建系統(tǒng)的 Vue 3 項目。它只有 2 個文件和大約 30 行的 HTML/JS。
有些庫需要你使用構(gòu)建系統(tǒng)
構(gòu)建系統(tǒng)這些事情最近盤旋在我的腦海里,因為這周我正在用 CodeMirror 5 做一個新項目,我看到有一個新版本,CodeMirror 6。
所以我想 —— 很酷,也許我應(yīng)該使用 CodeMirror 6 而不是 CodeMirror 5。但是 —— 似乎沒有構(gòu)建系統(tǒng)你就不能使用 CodeMirror 6(根據(jù) ??遷移指南??),所以我打算堅持使用 CodeMirror 5。
同樣地,你以前可以把 Tailwind 作為一個巨大的 CSS 文件下載,但是 ??Tailwind 3?? 似乎根本不能作為一個大的 CSS 文件使用,你需要運(yùn)行 Javascript 來構(gòu)建它。所以我現(xiàn)在要繼續(xù)使用 Tailwind 2。(我知道,我知道,你不應(yīng)該使用大的 CSS 文件,但是它驗收只有 300KB,而且我真的不希望有構(gòu)建步驟)
(更正:看起來 Tailwind 在 2021 年發(fā)布了一個 ??獨(dú)立的命令行工具??,這似乎是一個不錯的選擇)
我不完全確定為什么有些庫不提供無構(gòu)建系統(tǒng)版本 —— 也許發(fā)布無構(gòu)建系統(tǒng)版本會給庫增加很多額外的復(fù)雜性,而維護(hù)者認(rèn)為這不值得?;蛘撸瑤斓脑O(shè)計意味著由于某種原因,不可能發(fā)布無構(gòu)建系統(tǒng)版本。
我希望有更多的無構(gòu)建系統(tǒng)的 Javascript 技巧
到目前為止,我的主要策略是:
- 在某個庫的網(wǎng)站上搜索 “CDN”,找到一個單獨(dú)的 Javascript 文件
- 使用 ??https://unpkg.com?? 來查看該庫是否有一個我可以使用的內(nèi)置版本
- 托管我自己的庫的版本,而不是依賴可能崩潰的 CDN
- 編寫我自己的簡單集成方案,而不是拉入另一個依賴關(guān)系(例如,前幾天我為 Vue 編寫了自己的 CodeMirror 組件)。
- 如果我想要一個構(gòu)建系統(tǒng),就使用 Esbuild
還有一些看起來很有趣但我還沒有研究過的東西:
- 這個 ??關(guān)于 Javascript 注釋中類型語法的 Typescript 建議??
- 一般來說,ES 模塊