原文链接:https://devtails.xyz/how-to-replace-webpack-in-create-react-app-with-esbuild[1]
作者:Adam[2]
正文从这开始~
今年是2022年,你所有搞web开发的朋友都告诉你要学习React
。为了让事情变得简单,他们告诉你有一个神器叫做create-react-app[3]。你会看到,在三个命令行的帮助下,你可以拥有一个完整配置的React应用程序运行,并为此感到高兴。
npx create-react-app my-app
cd my-app
npm start
在大约一分钟的依赖包安装和几秒钟的npm
启动后,你就可以开始了。
现在你拥有了一个基础的React
应用程序,你添加了几个额外的组件和页面来建立你梦寐以求的React
应用程序。到目前为止,一切都很顺利,你所做的更改神奇地展示在localhost
上。
最后,是时候将这个应用程序部署到网络上,并分享你的创造。为了使事情变得简单,你只需运行npm run build
,并添加一个命令将文件scp
到你的服务器上。
这是你第一次运行npm run build
,你发现运行该命令需要花费20秒。"这是我唯一一次部署",你告诉自己,并忽略了构建所需的时间。
你加载很炫酷的新网站,却发现上面有一个错别字。你快速的修改完并重新部署。在你的改动生效之前,又要花费漫长的20秒时间。
"嗯,也许我应该更新这里的padding
。" "如果这是不同的颜色呢?" "我应该添加谷歌网站分析。" 各种各样的新想法涌入你的脑海。它们中的每一个都只需要更新一行代码。然而,要让这些代码被部署起来,却要花上20-30秒。
当你意识到在刚刚部署成功后,却有一个严重bug需要被修复时,问题变得糟糕起来。问题修复起来很简单,但是我们又要花费半分钟才能上线。
这不是一个编造的故事。这是我目前在Kaizen做的一个音乐应用程序的情况。
在其他项目中,我看到生产环境构建时间已经膨胀到超过一分钟。在一个较慢的构建机器上运行时,有时需要两倍的时间。
以前,我曾写过快速迭代的重要性,三行代码不应花费一整天[4]。这个原则同样适用于部署代码。在生产环境被充分验证之前,不能声称事情已经搞定。这个过程越慢,就必须等待更长的时间才能看到代码是否按预期工作。
这篇文章演示了如何用速度更快的esbuild
打包器替换create-react-app
中安装的webpack
打包器。
安装esbuild
代码语言:javascript复制npm i -D esbuild
在package.json中更新构建脚本
代码语言:javascript复制// package.json
"scripts": {
"start": "react-scripts start",
"build": "esbuild src/index.js --bundle --outfile=public/js/app.js --loader:.js=jsx",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
重新运行构建
代码语言:javascript复制npm run build
在默认的create-react-app
应用程序中,你应该会看到以下错误:
esbuild-errors.png
启用JS文件的JSX语法
前两个错误建议在构建命令中加入 --loader:.js=jsx
。esbuild
对扩展名为jsx
的文件默认会进行处理,但要处理扩展名为.js
的文件则需要添加上述命令。
// package.json
"build": "esbuild src/index.js --bundle --outfile=build/js/app.js --loader:.js=jsx"
添加SVG Loader
默认的应用程序使用import
语法来包含一个svg
图像。esbuild
默认不处理这种类型的文件。为了支持这些类型的文件,esbuild
提供了插件支持。你可以在这里[5]找到社区esbuild
插件的列表。此时,我们将使用esbuild-plugin-inline-image
来内联我们的svg
图片。额外的,该插件也可以处理未来有关img
的需求。
npm i -D esbuild-plugin-inline-image
为了加载新的插件,我们需要改变我们的构建命令,来使用esbuild
的JavaScript API。
// build.js
const esbuild = require("esbuild");
const inlineImage = require("esbuild-plugin-inline-image");
esbuild.build({
entryPoints: ["./src/index.js"],
outfile: "./public/js/app.js",
minify: true,
bundle: true,
loader: {
".js": "jsx",
},
plugins: [inlineImage()],
}).catch(() => process.exit(1));
代码语言:javascript复制// package.json
"build": "node build.js"
更改完之后,当运行npm run build
时,将会看到构建成功。
esbuild-success.png
在我的电脑上,这个构建命令现在大概需要60毫秒。比起6秒的webpack
构建,快了整整100倍。但是还没结束,我们仍需要真正的看到并运行这些改动。
更新index.html
Create React App
创建了一个public
文件夹,里面预置了几个文件。包含在其中的index.html
更像是一个模板,在运行react-scripts build
时,会被处理并输出到build
文件夹。
在我们新的esbuild
构建中,index.html
不需要成为模板。删除对%PUBLIC_URL%
的引用,并添加一个script
标签,指向我们新构建的app.js
和app.css
包。
// public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="/logo192.png" />
<link rel="manifest" href="/manifest.json" />
<title>React App</title>
<script src="/assets/app.js" async defer></script>
<link rel="stylesheet" href="/assets/app.css"/>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
你可能想把public/js
添加到你的.gitignore
中,因为你可能不想在生产构建的时候进行检查。
添加serve.js来自动重新构建
代码语言:javascript复制// serve.js
const esbuild = require("esbuild");
const inlineImage = require("esbuild-plugin-inline-image");
esbuild
.serve(
{
servedir: "public",
port: 8000,
},
{
entryPoints: ["./src/index.js"],
outfile: "./public/js/app.js",
bundle: true,
loader: {
".js": "jsx",
},
plugins: [inlineImage()],
}
)
.catch(() => process.exit());
替换npm start
代码语言:javascript复制// package.json
"start": "node serve.js"
运行npm start
会在8000端口启动一个本地开发服务器,这样你就可以通过http://localhost:8000[6]进行访问。有了esbuild
,你将看到应用程序会如期运行,而且初始构建和后续构建都快如闪电。
总结
只需仅仅几步,我们就将一个6秒的构建转换为60毫秒的构建。有一些地方还可以再调整一下,但这应该给你留下了一个良好的开端,也就是如何将基于webpack
的React
构建转换为esbuild
。如前所述,我将在Kaizen的前端代码中进一步探索这种转换,并将写下我在一个更大的项目中遇到的任何问题。
参考资料
[1]
https://devtails.xyz/how-to-replace-webpack-in-create-react-app-with-esbuild: https://devtails.xyz/how-to-replace-webpack-in-create-react-app-with-esbuild
[2]
Adam: https://devtails.xyz/about/
[3]
create-react-app: https://github.com/facebook/create-react-app
[4]
三行代码不应花费一整天: https://devtails.xyz/3-lines-of-code-shouldnt-take-all-day
[5]
这里: https://github.com/esbuild/community-plugins
[6]
http://localhost:8000: http://localhost:8000