xây dựng là một gói nhanh có thể tối ưu hóa mã JavaScript, TypeScript, JSX và CSS. Bài viết này sẽ giúp bạn bắt kịp tốc độ với esbuild và chỉ cho bạn cách tạo hệ thống xây dựng của riêng mình mà không cần các phụ thuộc khác.
ESbuild hoạt động như thế nào?
Các khuôn khổ như Sống đã áp dụng esbuild, nhưng bạn có thể sử dụng esbuild như một công cụ độc lập trong các dự án của riêng mình.
-
esbuild gói mã JavaScript vào một tệp duy nhất theo cách tương tự như các gói như Tập hợp. Đây là chức năng chính của esbuild và nó giải quyết các mô-đun, báo cáo các sự cố cú pháp, "lắc cây" để xóa các chức năng không sử dụng, xóa các câu lệnh ghi nhật ký và trình gỡ lỗi, thu nhỏ mã và cung cấp bản đồ nguồn.
-
esbuild bó mã CSS thành một tập tin duy nhất. Nó không phải là sự thay thế hoàn toàn cho các bộ xử lý trước như Sass or đăngCSS, nhưng esbuild có thể xử lý các phần, vấn đề cú pháp, lồng, mã hóa nội dung nội tuyến, bản đồ nguồn, tự động thêm tiền tố và thu nhỏ. Đó có thể là tất cả những gì bạn cần.
-
esbuild cũng cung cấp một máy chủ phát triển cục bộ với gói tự động và tải lại nóng, do đó không cần phải làm mới. Nó không có tất cả các tính năng được cung cấp bởi Đồng bộ hóa trình duyệt, nhưng nó đủ tốt cho hầu hết các trường hợp.
Đoạn mã dưới đây sẽ giúp bạn hiểu các khái niệm esbuild để bạn có thể điều tra thêm các cơ hội cấu hình cho các dự án của mình.
Tại sao gói?
Gói mã vào một tệp duy nhất mang lại nhiều lợi ích khác nhau. Dưới đây là một số trong số họ:
- bạn có thể phát triển các tệp nguồn nhỏ hơn, độc lập, dễ bảo trì hơn
- bạn có thể lint, làm đẹp và kiểm tra cú pháp mã trong quá trình đóng gói
- gói có thể loại bỏ các chức năng không sử dụng - được gọi là rung cây
- bạn có thể gói các phiên bản thay thế của cùng một mã và tạo mục tiêu cho các trình duyệt cũ hơn, Node.js, Deno, v.v.
- các tệp đơn lẻ tải nhanh hơn nhiều tệp và trình duyệt không yêu cầu hỗ trợ mô-đun ES
- gói cấp độ sản xuất có thể cải thiện hiệu suất bằng cách giảm thiểu mã và xóa các câu lệnh ghi nhật ký và gỡ lỗi
Tại sao nên sử dụng esbuild?
Không giống như các gói JavaScript, esbuild là một tệp thực thi Go được biên dịch, thực hiện xử lý song song nặng. Nó nhanh và nhanh hơn hàng trăm lần so với Rollup, Parcel hoặc Webpack. Nó có thể tiết kiệm hàng tuần thời gian phát triển trong suốt vòng đời của một dự án.
Ngoài ra, esbuild còn cung cấp:
- gói và biên dịch tích hợp cho JavaScript, TypeScript, JSX và CSS
- API cấu hình dòng lệnh, JavaScript và Go
- hỗ trợ cho các mô-đun ES và CommonJS
- một máy chủ phát triển cục bộ với chế độ xem và tải lại trực tiếp
- bổ sung để thêm chức năng
- tài liệu toàn diện và một công cụ thí nghiệm trực tuyến
Tại sao Tránh esbuild?
Tại thời điểm viết bài này, esbuild đã đạt đến phiên bản 0.18. Nó đáng tin cậy nhưng vẫn là một sản phẩm beta.
esbuild được cập nhật thường xuyên và các tùy chọn có thể thay đổi giữa các phiên bản. Các tài liệu hướng dẫn khuyên bạn nên gắn bó với một phiên bản cụ thể. Bạn có thể cập nhật nó, nhưng bạn có thể cần di chuyển các tệp cấu hình của mình và tìm hiểu kỹ tài liệu mới để khám phá những thay đổi đột phá.
Cũng lưu ý rằng esbuild không thực hiện kiểm tra kiểu TypeScript, vì vậy bạn vẫn cần chạy tsc -noEmit
.
Bắt đầu siêu nhanh
Nếu cần, hãy tạo một dự án Node.js mới với npm init
, sau đó cài đặt esbuild cục bộ dưới dạng phụ thuộc phát triển:
npm install esbuild --save-dev --save-exact
Việc cài đặt yêu cầu khoảng 9 MB. Kiểm tra nó hoạt động bằng cách chạy lệnh này để xem phiên bản đã cài đặt:
./node_modules/.bin/esbuild --version
Hoặc chạy lệnh này để xem trợ giúp CLI:
./node_modules/.bin/esbuild --help
Sử dụng API CLI để đóng gói tập lệnh nhập cảnh (myapp.js
) và tất cả các mô-đun đã nhập của nó vào một tệp duy nhất có tên bundle.js
. esbuild sẽ xuất một tệp bằng định dạng biểu thức hàm (IIFE) mặc định, được nhắm mục tiêu theo trình duyệt, được gọi ngay lập tức:
./node_modules/.bin/esbuild myapp.js --bundle --outfile=bundle.js
Bạn có thể cài đặt esbuild theo những cách khác nếu bạn không sử dụng Node.js.
Dự án mẫu
Tải xuống các tệp ví dụ và một cấu hình esbuild từ Github. Đó là một dự án Node.js, vì vậy hãy cài đặt phần phụ thuộc esbuild duy nhất với:
npm install
Xây dựng các tập tin nguồn trong src
đến một build
thư mục và bắt đầu một máy chủ phát triển với:
npm start
Bây giờ điều hướng đến localhost:8000
trong trình duyệt của bạn để xem trang web hiển thị đồng hồ thời gian thực. Khi bạn cập nhật bất kỳ tệp CSS nào trong src/css/
or src/css/partials
, esbuild sẽ nhóm lại mã và tải lại trực tiếp các kiểu.
Ấn Bản Ctrl|Cmd + Ctrl|Cmd để dừng máy chủ.
Tạo bản dựng sản xuất để triển khai bằng cách sử dụng:
npm run build
Kiểm tra các tệp CSS và JavaScript trong build
thư mục để xem các phiên bản rút gọn mà không có bản đồ nguồn.
Tổng Quan Dự Án
Trang đồng hồ thời gian thực được xây dựng trong một build
thư mục sử dụng các tập tin nguồn từ src
.
Sản phẩm package.json
tập tin xác định năm npm
kịch bản. Việc đầu tiên xóa các build
danh mục:
"clean": "rm -rf ./build",
Trước khi bất kỳ gói nào xảy ra, một init
script chạy clean
, tạo một cái mới build
thư mục và bản sao:
- một tệp HTML tĩnh từ
src/html/index.html
đếnbuild/index.html
- hình ảnh tĩnh từ
src/images/
đếnbuild/images/
"init": "npm run clean && mkdir ./build && cp ./src/html/* ./build/ && cp -r ./src/images ./build",
An esbuild.config.js
tệp kiểm soát quy trình đóng gói esbuild bằng API JavaScript. Điều này dễ quản lý hơn là chuyển các tùy chọn tới API CLI, điều này có thể trở nên khó sử dụng. MỘT npm
bundle
script chạy init
tiếp theo node ./esbuild.config.js
:
"bundle": "npm run init && node ./esbuild.config.js",
Hai cái cuối cùng npm
tập lệnh chạy bundle
với một trong hai production
or development
tham số được truyền cho ./esbuild.config.js
để kiểm soát việc xây dựng:
"build": "npm run bundle -- production",
"start": "npm run bundle -- development"
Thời Gian ./esbuild.config.js
chạy, nó sẽ xác định xem nó có nên tạo các bản rút gọn hay không production
tệp (mặc định) hoặc development
các tệp có cập nhật tự động, bản đồ nguồn và máy chủ tải lại trực tiếp. Trong cả hai trường hợp, gói esbuild:
- tệp CSS mục nhập
src/css/main.css
đếnbuild/css/main.css
- tệp JavaScript mục nhập
scr/js/main.js
đếnbuild/js/main.js
Cấu hình esbuild
package.json
có một "type"
of "module"
vì vậy tất cả .js
các tệp có thể sử dụng Mô-đun ES. Các esbuild.config.js
nhập tập lệnh esbuild
và bộ productionMode
đến true
khi đóng gói để sản xuất hoặc false
khi đóng gói để phát triển:
import { argv } from 'node:process';
import * as esbuild from 'esbuild'; const productionMode = ('development' !== (argv[2] || process.env.NODE_ENV)), target = 'chrome100,firefox100,safari15'.split(','); console.log(`${ productionMode ? 'production' : 'development' } build`);
mục tiêu gói
Lưu ý rằng biến mục tiêu định nghĩa một mảng các trình duyệt và số phiên bản sẽ sử dụng trong cấu hình. Điều này ảnh hưởng đến đầu ra đi kèm và thay đổi cú pháp để hỗ trợ các nền tảng cụ thể. Ví dụ: esbuild có thể:
- mở rộng làm tổ CSS gốc vào bộ chọn đầy đủ (lồng nhau sẽ vẫn còn nếu
"Chrome115"
là mục tiêu duy nhất) - thêm các thuộc tính tiền tố nhà cung cấp CSS khi cần thiết
- điền vào
??
nhà điều hành liên kết nullish - tẩy
#
từ các trường lớp riêng
Cũng như các trình duyệt, bạn cũng có thể nhắm mục tiêu node
và es
các phiên bản như es2020
và esnext
(các tính năng JS và CSS mới nhất).
Gói JavaScript
API đơn giản nhất để tạo một gói:
await esbuild.build({ entryPoints: ['myapp.js'], bundle: true outfile: 'bundle.js'
});
Điều này sao chép lệnh CLI được sử dụng ở trên:
./node_modules/.bin/esbuild myapp.js --bundle --outfile=bundle.js
Dự án ví dụ sử dụng các tùy chọn nâng cao hơn như xem tệp. Điều này đòi hỏi một quá trình xây dựng lâu dài bối cảnh trong đó thiết lập cấu hình:
const buildJS = await esbuild.context({ entryPoints: [ './src/js/main.js' ], format: 'esm', bundle: true, target, drop: productionMode ? ['debugger', 'console'] : [], logLevel: productionMode ? 'error' : 'info', minify: productionMode, sourcemap: !productionMode && 'linked', outdir: './build/js' });
cung cấp esbuild hàng chục tùy chọn cấu hình. Dưới đây là danh sách những cái được sử dụng ở đây:
-
entryPoints
xác định một mảng các điểm nhập tệp để đóng gói. Dự án ví dụ có một tập lệnh tại./src/js/main.js
. -
format
đặt định dạng đầu ra. ví dụ sử dụngesm
, nhưng bạn có thể tùy ý đặtiife
cho các trình duyệt cũ hơn hoặccommonjs
cho Node.js. -
bundle
đặt thànhtrue
nội tuyến các mô-đun đã nhập vào tệp đầu ra. -
target
là mảng các trình duyệt mục tiêu được xác định ở trên. -
drop
là một mảng củaconsole
và / hoặcdebugger
tuyên bố để loại bỏ. Trong trường hợp này, các bản dựng sản xuất loại bỏ cả hai và các bản dựng phát triển giữ lại chúng. -
logLevel
xác định mức độ chi tiết của nhật ký. Ví dụ trên cho thấy các lỗi trong quá trình xây dựng sản xuất và nhiều thông báo dài dòng hơn trong quá trình xây dựng phát triển. -
minify
giảm kích thước mã bằng cách xóa các nhận xét và khoảng trắng cũng như đổi tên các biến và hàm nếu có thể. Dự án ví dụ thu nhỏ trong quá trình xây dựng sản xuất nhưng làm đẹp mã trong quá trình xây dựng phát triển. -
sourcemap
đặt thànhlinked
(chỉ trong chế độ phát triển) tạo bản đồ nguồn được liên kết trong một.map
tệp để tệp nguồn gốc và dòng có sẵn trong các công cụ dành cho nhà phát triển trình duyệt. Bạn cũng có thể thiết lậpinline
để bao gồm bản đồ nguồn bên trong tệp được đóng gói,both
để tạo cả hai, hoặcexternal
để tạo ra một.map
tệp không có liên kết từ JavaScript đi kèm. -
outdir
xác định thư mục đầu ra của tệp đi kèm.
Gọi đối tượng bối cảnh của rebuild()
phương pháp để chạy bản dựng một lần — thường dành cho bản dựng sản xuất:
await buildJS.rebuild();
buildJS.dispose();
Gọi đối tượng bối cảnh của watch()
phương pháp để tiếp tục chạy và tự động xây dựng lại khi tệp đã xem thay đổi:
await buildJS.watch();
Đối tượng bối cảnh đảm bảo các bản dựng tiếp theo được xử lý tăng dần và chúng sử dụng lại công việc từ các bản dựng trước đó để cải thiện hiệu suất.
Tệp đầu vào và đầu ra JavaScript
Mục nhập src/js/main.js
nhập tệp dom.js
và time.js
mô-đun từ lib
thư mục con. Nó tìm thấy tất cả các phần tử với một lớp clock
và đặt nội dung văn bản của chúng thành thời điểm hiện tại mỗi giây:
import * as dom from './lib/dom.js';
import { formatHMS } from './lib/time.js'; const clock = dom.getAll('.clock'); if (clock.length) { console.log('initializing clock'); setInterval(() => { clock.forEach(c => c.textContent = formatHMS()); }, 1000); }
dom.js
xuất khẩu hai chức năng. main.js
nhập cả hai nhưng chỉ sử dụng getAll()
:
export function get(selector, doc = document) { return doc.querySelector(selector);
} export function getAll(selector, doc = document) { return Array.from(doc.querySelectorAll(selector));
}
time.js
xuất khẩu hai chức năng. main.js
nhập khẩu formatHMS()
, nhưng điều đó sử dụng các chức năng khác trong mô-đun:
function timePad(n) { return String(n).padStart(2, '0');
} export function formatHM(d = new Date()) { return timePad(d.getHours()) + ':' + timePad(d.getMinutes());
} export function formatHMS(d = new Date()) { return formatHM(d) + ':' + timePad(d.getSeconds());
}
Gói phát triển kết quả loại bỏ (lắc cây) get()
từ dom.js
nhưng bao gồm tất cả các time.js
chức năng. Một bản đồ nguồn cũng được tạo ra:
function getAll(selector, doc = document) { return Array.from(doc.querySelectorAll(selector));
} function timePad(n) { return String(n).padStart(2, "0");
} function formatHM(d = new Date()) { return timePad(d.getHours()) + ":" + timePad(d.getMinutes());
} function formatHMS(d = new Date()) { return formatHM(d) + ":" + timePad(d.getSeconds());
} var clock = getAll(".clock");
if (clock.length) { console.log("initializing clock"); setInterval(() => { clock.forEach((c) => c.textContent = formatHMS()); }, 1e3);
}
(Lưu ý rằng esbuild có thể viết lại let
và const
đến var
cho chính xác và tốc độ.)
Gói sản xuất kết quả thu nhỏ mã thành 322 ký tự:
function o(t,c=document){return Array.from(c.querySelectorAll(t))}function e(t){return String(t).padStart(2,"0")}function l(t=new Date){return e(t.getHours())+":"+e(t.getMinutes())}function r(t=new Date){return l(t)+":"+e(t.getSeconds())}var n=o(".clock");n.length&&setInterval(()=>{n.forEach(t=>t.textContent=r())},1e3);
gói CSS
Gói CSS trong dự án ví dụ sử dụng một đối tượng ngữ cảnh tương tự như JavaScript ở trên:
const buildCSS = await esbuild.context({ entryPoints: [ './src/css/main.css' ], bundle: true, target, external: ['/images/*'], loader: { '.png': 'file', '.jpg': 'file', '.svg': 'dataurl' }, logLevel: productionMode ? 'error' : 'info', minify: productionMode, sourcemap: !productionMode && 'linked', outdir: './build/css' });
Nó định nghĩa một external
tùy chọn dưới dạng một mảng các tệp và đường dẫn đến loại trừ từ bản dựng. Trong dự án ví dụ, các tập tin trong src/images/
thư mục được sao chép vào build
thư mục để HTML, CSS hoặc JavaScript có thể tham chiếu trực tiếp đến chúng. Nếu điều này không được đặt, esbuild sẽ sao chép tệp vào đầu ra build/css/
thư mục khi sử dụng chúng trong background-image
hoặc các thuộc tính tương tự.
Sản phẩm loader
tùy chọn thay đổi cách esbuild xử lý tệp đã nhập không được tham chiếu dưới dạng tệp external
tài sản. Trong ví dụ này:
- Hình ảnh SVG trở thành nội tuyến dưới dạng URI dữ liệu
- Hình ảnh PNG và JPG được sao chép vào
build/css/
thư mục và được tham chiếu dưới dạng tệp
Tệp đầu vào và đầu ra CSS
Mục nhập src/css/main.css
nhập tệp variables.css
và elements.css
từ partials
thư mục con:
@import './partials/variables.css';
@import './partials/elements.css';
variables.css
xác định các thuộc tính tùy chỉnh mặc định:
:root { --font-body: sans-serif; --color-fore: #fff; --color-back: #112;
}
elements.css
xác định tất cả các phong cách. Ghi chú:
- các
body
có hình nền được tải từ bên ngoàiimages
thư mục - các
h1
được lồng bên trongheader
- các
h1
có một SVG nền sẽ được nội tuyến - các trình duyệt mục tiêu không yêu cầu tiền tố nhà cung cấp
*, *::before, ::after { box-sizing: border-box; font-weight: normal; padding: 0; margin: 0;
} body { font-family: var(--font-body); color: var(--color-fore); background: var(--color-back) url(/images/web.png) repeat; margin: 1em;
} header { & h1 { font-size: 2em; padding-left: 1.5em; margin: 0.5em 0; background: url(../../icons/clock.svg) no-repeat; } } .clock { display: block; font-size: 5em; text-align: center; font-variant-numeric: tabular-nums;
}
Gói phát triển kết quả mở rộng cú pháp lồng nhau, nội tuyến SVG và tạo bản đồ nguồn:
:root { --font-body: sans-serif; --color-fore: #fff; --color-back: #112;
} *,
*::before,
::after { box-sizing: border-box; font-weight: normal; padding: 0; margin: 0;
}
body { font-family: var(--font-body); color: var(--color-fore); background: var(--color-back) url(/images/web.png) repeat; margin: 1em;
}
header h1 { font-size: 2em; padding-left: 1.5em; margin: 0.5em 0; background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>*{fill:none;stroke:%23fff;stroke-width:1.5;stroke-miterlimit:10}</style></defs><circle cx="12" cy="12" r="10.5"></circle><circle cx="12" cy="12" r="0.95"></circle><polyline points="12 4.36 12 12 16.77 16.77"></polyline></svg>') no-repeat;
}
.clock { display: block; font-size: 5em; text-align: center; font-variant-numeric: tabular-nums;
}
Gói sản xuất kết quả thu nhỏ mã thành 764 ký tự (SVG được bỏ qua ở đây):
:root{--font-body: sans-serif;--color-fore: #fff;--color-back: #112}*,*:before,:after{box-sizing:border-box;font-weight:400;padding:0;margin:0}body{font-family:var(--font-body);color:var(--color-fore);background:var(--color-back) url(/images/web.png) repeat;margin:1em}header h1{font-size:2em;padding-left:1.5em;margin:.5em 0;background:url('data:image/svg+xml,<svg...></svg>') no-repeat}.clock{display:block;font-size:5em;text-align:center;font-variant-numeric:tabular-nums}
Quan sát, xây dựng lại và phục vụ
Phần còn lại của esbuild.config.js
gói tập lệnh một lần cho các bản dựng sản xuất trước khi chấm dứt:
if (productionMode) { await buildCSS.rebuild(); buildCSS.dispose(); await buildJS.rebuild(); buildJS.dispose(); }
Trong quá trình xây dựng phát triển, tập lệnh tiếp tục chạy, theo dõi các thay đổi của tệp và tự động nhóm lại. Các buildCSS
bối cảnh khởi chạy một máy chủ web phát triển với build/
như thư mục gốc:
else { await buildCSS.watch(); await buildJS.watch(); await buildCSS.serve({ servedir: './build' }); }
Bắt đầu xây dựng phát triển với:
npm start
Sau đó điều hướng tới localhost:8000
để xem trang.
Không giống như Browsersync, bạn sẽ cần thêm mã của riêng mình vào các trang phát triển để tải lại trực tiếp. Khi thay đổi xảy ra, esbuild sẽ gửi thông tin về bản cập nhật qua sự kiện do máy chủ gửi. Tùy chọn đơn giản nhất là tải lại toàn bộ trang khi có bất kỳ thay đổi nào xảy ra:
new EventSource('/esbuild').addEventListener('change', () => location.reload());
Dự án ví dụ sử dụng đối tượng ngữ cảnh CSS để tạo máy chủ. Đó là vì tôi muốn làm mới các thay đổi JavaScript theo cách thủ công — và vì tôi không tìm được cách để esbuild gửi sự kiện cho cả bản cập nhật CSS và JS! Trang HTML bao gồm tập lệnh sau để thay thế các tệp CSS đã cập nhật mà không cần làm mới toàn bộ trang (tải lại nóng):
<script type="module">
// esbuild server-sent event - live reload CSS
new EventSource('/esbuild').addEventListener('change', e => { const { added, removed, updated } = JSON.parse(e.data); // reload when CSS files are added or removed if (added.length || removed.length) { location.reload(); return; } // replace updated CSS files Array.from(document.getElementsByTagName('link')).forEach(link => { const url = new URL(link.href), path = url.pathname; if (updated.includes(path) && url.host === location.host) { const css = link.cloneNode(); css.onload = () => link.remove(); css.href = `${ path }?${ +new Date() }`; link.after(css); } }) });
Lưu ý rằng esbuild hiện không hỗ trợ tải lại nóng JavaScript — không phải là tôi sẽ tin tưởng nó anyway!
Tổng kết
Với một chút cấu hình, esbuild có thể đủ để xử lý tất cả các yêu cầu xây dựng sản xuất và phát triển dự án của bạn.
Có một bộ toàn diện của bổ sung nếu bạn yêu cầu chức năng nâng cao hơn. Xin lưu ý rằng những công cụ này thường bao gồm Sass, PostCSS hoặc các công cụ xây dựng tương tự, vì vậy chúng sử dụng hiệu quả esbuild làm trình chạy tác vụ. Bạn luôn luôn có thể mà tạo plugin của riêng bạn nếu bạn cần các tùy chọn tùy chỉnh, nhẹ hơn.
Tôi đã sử dụng esbuild được một năm. Tốc độ đáng kinh ngạc so với các gói tương tự và các tính năng mới xuất hiện thường xuyên. Nhược điểm nhỏ duy nhất là phá vỡ những thay đổi phát sinh bảo trì.
esbuild không tuyên bố là một công cụ xây dựng hợp nhất, tất cả trong một, nhưng có lẽ nó gần với mục tiêu đó hơn là Roma.
- Phân phối nội dung và PR được hỗ trợ bởi SEO. Được khuếch đại ngay hôm nay.
- PlatoData.Network Vertical Generative Ai. Trao quyền cho chính mình. Truy cập Tại đây.
- PlatoAiStream. Thông minh Web3. Kiến thức khuếch đại. Truy cập Tại đây.
- Trung tâmESG. Ô tô / Xe điện, Than đá, công nghệ sạch, Năng lượng, Môi trường Hệ mặt trời, Quản lý chất thải. Truy cập Tại đây.
- BlockOffsets. Hiện đại hóa quyền sở hữu bù đắp môi trường. Truy cập Tại đây.
- nguồn: https://www.sitepoint.com/esbuild-introduction/?utm_source=rss