前言
esbuild 的大名相信大家也有耳闻,它是一个非常快的 Javascript 打包工具,用 GO 语言编写,是 figma 的 cto Evan Wallace 著作的,一个 30 min 的 webpack 项目用 esbuild 可以分钟级运行。本文将记录使用 esbuild 来打包一个 React 库。
需求
这里我打算开发一个 react-checkbox 为例
<input type="checkbox" checked={true}/><input type="checkbox" checked={false}/>复制代码
复制代码
因为 checkbox 只有两种值:选中(checked)或未选中(unchecked),在视觉上 checkbox 有三种状态:checked、unchecked、indeterminate(不确定的),在实现全选效果时,你可能会用到 indeterminate 属性, 对于indeterminate 这个状态无法在 HTML 中设置 checkbox 的状态为 indeterminate。因为 HTML 中没有indeterminate这个属性,你可以通过 Javascript 脚本来设置
const checkbox = document.getElementById("checkbox");checkbox.indeterminate = true;复制代码
复制代码
效果如下:
所以我们的需求是需要给 checkbox 增加一个 indeterminate 属性
项目初始化
首先我们来创建一个文件夹并且初始化 npm.
mkdir react-checkbox && cd react-checkbox && npm init --yes复制代码
复制代码
我们使用 typescript,当然也要安装 react 和 react-dom
npm i esbuild typescript @types/react @types/react-dom --save-dev复制代码
复制代码
然后我们在根目录下创建文件 ./tsconfig.json
{ "compilerOptions": { "outDir": "./lib", "target": "es6", "module": "commonjs", "noImplicitAny": true, "strictNullChecks": true, "declaration": true, "sourceMap": true, "esModuleInterop": true, "jsx": "react-jsx", "typeRoots": ["node_modules/@types"] }, "include": ["./src/**/*.tsx", "./src/**/*.ts", "example/index.tsx"], "exclude": ["node_modules"]}
复制代码
复制代码
代码实现
接下来我们创建 src/checkbox.tsx,下面是实现代码
import { ReactElement, CSSProperties, ChangeEvent } from "react";
export interface CheckboxProps { checked?: boolean; indeterminate?: boolean; className?: string; style?: CSSProperties; disabled?: boolean; onChange?: (e: ChangeEvent<HTMLInputElement>) => void;}
const Checkbox = ({ checked = false, indeterminate = false, className = "", style = {}, disabled = false, onChange,}: CheckboxProps): ReactElement => { return ( <input type="checkbox" className={className} style={style} ref={(input) => { if (input) { input.checked = checked; input.indeterminate = indeterminate as boolean; input.disabled = disabled as boolean; } }} onChange={(e) => { if (onChange) { onChange(e); } }} /> );};
export default Checkbox;
复制代码
复制代码
很简单,直接使用 ref 设置 dom 属性就可以了。
代码打包
接着我们在项目根目录下建立./esbuild.js文件
写入打包配置
const esbuild = require('esbuild');
esbuild .build({ entryPoints: ['src/checkbox.tsx'], outdir: 'lib', bundle: true, sourcemap: true, minify: true, splitting: true, format: 'esm', target: ['esnext'] }) .catch(() => process.exit(1));复制代码
复制代码
entryPoints 和 ourdir 指定需要将哪些文件输入和打包输出目录
bundle 代表是否递归引用打包文件。
sourcemap 代表是否生成 sourcemap 源映射文件
minify 代表是否压缩代码
splitting 代表
多入口的是否提取公共代码
是否将 import() 异步文件单独打包
target 定义了我们想要输出的 javascript 类型
format 是设置生成的 javascript 文件的输出格式, 有 3 个值可选,cjs、esm、iife
iife 格式代表“立即调用函数表达式”,可以在浏览器中运行。
cjs 格式代表“CommonJS”,在 node 中运行。
esm 格式代表“ECMAScript 模块”,既可以在浏览器中使用,也可以在 node 中使用
然后使用node ./esbuild.js 就可以打包成功了,但是一个typescript项目最终要提供d.ts出来给外部用,但是esbuild最终 build 出来的内容中并没有d.ts,因此我们要单独运行tsc,稍微修改一下上面的代码。
我们在 package.json 中加入如下代码
"scripts": { "ts-types": " tsc --emitDeclarationOnly --outDir lib", "build": "rm -rf lib && node ./esbuild.js && npm run ts-types" },复制代码
复制代码
还是使用 tsc 的 emitDeclarationOnly 来生成 d.ts
然后我们在 package.json 中指定入口文件
"main": "lib/checkbox.js","module": "lib/checkbox.js","types": "lib/checkbox.d.ts","files": [ "lib" ]复制代码
复制代码
至此打包完成,如果需要发包,我们要还需要添加测试。
本地预览
当然我们的项目需要预览,建立一个 example/index.tsx 文件
import React, { ReactElement } from "react";import { render } from "react-dom";
import Checkbox from "../src/checkbox";
function App(): ReactElement { return ( <div> <Checkbox></Checkbox> <Checkbox checked={true}></Checkbox> <Checkbox indeterminate={true}></Checkbox> </div> );}
render(<App />, document.querySelector("#root"));
复制代码
复制代码
这个文件作为预览 js 的打包入口;
然后建立一个./example/index.html
<!DOCTYPE html><html> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>checkbox</title> </head> <body> <div id="root"></div> <script src="./bandle.js"></script> </body></html>复制代码
复制代码
这个 html 就引用了 bandle.js,接下来,我们需要打包出一个 bandle.js
建立一个./example/esbuild.js 文件,代码如下:
const esbuild = require("esbuild");const path = require("path");
esbuild .build({ entryPoints: [path.resolve(__dirname, "./index.tsx")], outfile: path.resolve(__dirname, "./bandle.js"), bundle: true, minify: true, target: ["esnext"], watch: { onRebuild(error, result) { if (error) console.error("watch build failed:", error); else console.log("watch build succeeded:", result); }, }, format: "esm", }) .then((result) => { console.log("watching..."); });复制代码
复制代码
这个 esbuild.js 是打包预览文件的配置,这里开启了监听模式,这样修改 js 就会自动打包了。
然后在 package.json 的 scripts 中添加 :
"start": " node ./example/esbuild.js"复制代码
复制代码
接着修改 js 就会自动打包了,我们一起来看下效果,唯一的缺点是没有热更新,我们需要手动刷新。
小结
本文结合 react 对 esbuid 这个打包工具进行了简单使用;
esbuid 的缺点
esbuild 的优点
esbuild 除了打包速度飞快,对于 ts、css 文件的处理也是非常友好,不需要设置各种 loader,配置简单。如果你的项目不需要兼容 es5、完全可以将一些 Monorepo 的 js 库迁移到 esbuild。
最后
如果你觉得此文对你有一丁点帮助,点个赞。或者可以加入我的开发交流群:1025263163 相互学习,我们会有专业的技术答疑解惑
如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点 star: https://gitee.com/ZhongBangKeJi不胜感激 !
PHP 学习手册:https://doc.crmeb.com技术交流论坛:https://q.crmeb.com
评论