这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
关于esbuild
这是截自官网的一张图,可以看到esbuild相比其他构建工具速度有着夸张的差异,目前vue3 + vite搭建的项目在开发模式下也是使用到了esbuild。接下来就介绍下如何使用esbuild搭建一个基于typescript的开发库。
开始
新建一个叫做mylib的文件夹
mkdir mylib && cd mylib && npm init --yes
安装下依赖:
npm i esbuild typescript rimraf --save-dev
在根目录下,增加tsconfig.json文件,可以根据自己的需求添加内容,以下为示例内容:
{
"compilerOptions": {
"declaration": true, // 生成声明文件,开启后会自动生成声明文件
"target": "esnext", // 最新的ES标准
"lib": ["esnext", "dom"], // TS需要引用的库,即声明文件,es5 默认引用dom、es5、scripthost,如需要使用es的高级版本特性,通常都需要配置,如es8的数组新特性需要引入"ES2019.Array"
"strict": true, // 开启所有严格的类型检查
"noImplicitAny": false, // 不允许隐式的any类型
"esModuleInterop": true, // 允许export=导出,由import from 导入
"moduleResolution": "node", // 模块解析策略,ts默认用node的解析策略,即相对的方式导入
"outDir": "lib" // 指定输出目录
}
}
这里要注意,esbuild并不会生成声明文件,方法是通过tsc命令生成。修改package.json文件,添加module字段,并添加脚本
{
"name": "mylib",
"version": "1.0.0",
"description": "",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"module": "lib/index.js",
"scripts": {
"ts-types": " tsc --emitDeclarationOnly --outDir lib",
"build": "rimraf lib && node ./esbuild.js && npm run ts-types"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"esbuild": "^0.12.1",
"typescript": "^4.2.4"
}
}
新建src目录,里面添加index.ts文件,示例内容如:
export const add = (a: number, b: number): number => a + b;
在根目录添加esbuild.js文件,编写esbuild相关代码(详细配置文档请查阅官网)。
const esbuild = require("esbuild");
esbuild
.build({
entryPoints: ["src/index.ts"],
outdir: "lib",
bundle: true,
sourcemap: true,
minify: true, // 压缩代码
splitting: true,
format: "esm",
target: ["esnext"],
})
.catch(() => process.exit(1));
运行npm run build,可以看到成功生成lib目录,并且里面包含了声明文件
额外内容
将script内容写入到html文件:在src目录下先新建一个html文件
const esbuild = require("esbuild");
const { readFile, writeFile, mkdir } = require("fs").promises;
(async () => {
await mkdir("./lib");
const script = esbuild.buildSync({
entryPoints: ["src/index.ts"],
bundle: true,
minify: true,
format: "esm",
target: ["esnext"],
write: false,
});
const html = await readFile("src/index.html", "utf8");
const content = html.replace(
"<body>",
`<body><script type="module">${script.outputFiles[0].text}</script>`
);// 将script插入到body标签内
await writeFile("lib/index.html", content);
})();
对html内容进行压缩处理,安装压缩包:
npm i html-minifier-terser --save-dev
const esbuild = require("esbuild");
const { readFile, writeFile, mkdir } = require("fs").promises;
const minify = require("html-minifier-terser").minify;
(async () => {
await mkdir("./lib");
const script = esbuild.buildSync({
entryPoints: ["src/index.ts"],
bundle: true,
minify: true,
format: "esm",
target: ["esnext"],
write: false,
});
const html = await readFile("src/index.html", "utf8");
const content = html.replace(
"<body>",
`<body><script type="module">${script.outputFiles[0].text}</script>`
); // 将script插入到body标签内
const minifyOptions = {
collapseWhitespace: true,
keepClosingSlash: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
useShortDoctype: true,
minifyCSS: true,
}; //压缩配置
const fileContent = minify(content, minifyOptions);
await writeFile("lib/index.html", fileContent);
})();