水族馆

用最轻的方式从头创建一个 React APP

使用 esbuild 替换 creat-react-app,npm 依赖仅 17M,毫秒级构建速度。

阅读时间 2 分钟


咱第一次接触 React 和 JavaScript 生态搞前端开发的时候,按照 React 官网教程 使用 create-react-app 创建了一个 Hello, World! 项目,npm 依赖大小达到恐怖的 200M。

一部分原因是 react 作为库而不是框架,本身不提供打包、转译等开发和调试功能。create-react-app (简称 CRA)做的工作是帮助用户创建 src public 等目录结构,设置好 webpack 打包器、babel 转译器、webvital 测试之类的辅助工具。正是这些与 react 无关的依赖占了大部分空间。

而这些开发工具配置又复杂难懂,尤其是 webpack 不仅配置难写难看,打包性能还低。正好有个超快的打包器 esbuild,官网贴了打包 three.js 的速度,可以说是秒天秒地。正如其名,esbuild 适合在支持 es6 语法的浏览器上使用。用在大生产环境不合适,但用在自己的玩具上还是没问题的,不会有开发者还在跑 Chrome 51 吧(

create-react-app

整个 CRA 框架可以看作一个黑盒子,输入 src 目录中的 js 文件和 public 中的静态文件,然后

test image

esbuild

相比之下 esbuild 做的事情简单很多。esbuild 读入 JavaScript 和他的依赖并打包出 index.js。简单,我喜欢。

loading-ag-264

动手

安装依赖

首先创建空目录,初始化 npm 包。

mkdir test
cd test
mkdir -p src build
npm init -y

接着安装必要的依赖,安装后大小只有 17M,相比于 CRA 的 200M 算是非常小了。react-router-dom 是可选的。

npm install react react-dom react-router-dom esbuild

编写代码

创建 src/index.jsx 文件,这是我们 react 应用的入口,它负责在 id="root" 的节点上渲染出 react 应用。

import React from "react";
import ReactDOM from "react-dom/client";

const App = () => {
  return <h1>Hello, World!</h1>;
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);

接着创建 build/index.html 文件,它负责载入 打包好的 js 文件。

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <div id="root"></div>
    <script type="module" src="./index.js"></script>
  </body>
</html>

开始打包

最后一步,使用 esbuild 打包。修改 package.json 类似如下

{
  "script": {
    "build": "esbuild src/index.jsx --bundle --minify --sourcemap --outfile=build/index.js"
  }
}

运行 npm run build 即可瞬间打包好啦。

  build/index.js      138.3kb
  build/index.js.map  339.8kb
⚡ Done in 55ms

浏览器直接打开 index.html,一切正常 👍

使用 preact 替代 react

首先安装 preact 的兼容层 preact/compat

npm install @preact/compat

在 esbuild 中替换 react 模块为 preact

esbuild src/index.jsx --bundle --minify --sourcemap --alias:react=preact/compat --alias:react-dom=preact/compat --outfile=build/index.js

进一步缩小构建产物大小

  build/index.js       21.3kb
  build/index.js.map  144.8kb
⚡ Done in 15ms

写在最后

我自己的玩具 msw-open-music 目前就是使用这种方式构建。大大减小 npm 依赖后咱自己架在国内的 CI/CD 机器因为 npm install 超时而失败的情况基本不存在了。目前一切都工作很好。