You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React不eject如何通过.env区分构建内置/在线引用字体版本

CRA项目无eject实现公网/离线局域网双模式字体构建方案

不需要拆分webpack配置,不需要多html入口,不需要运行时动态插DOM,完全基于CRA原生能力+环境变量就能实现,代码零侵入,两种构建产物功能完全一致。


具体实现步骤

1. 准备两份字体样式文件

  • 先把你当前SASS中引入的Google Fonts链接在浏览器里打开,把返回的所有@font-face规则复制下来,对应规则里引用的woff2/woff字体文件全部下载到项目src/assets/fonts/目录下(放在src目录下才能被webpack处理,不要放public)。
  • 新建本地字体样式文件src/styles/fonts-local.scss,把刚才复制的@font-face规则粘进去,只把规则里的远程字体url替换成本地字体文件的相对路径即可,字体名、font-weight、font-display等所有属性保持和原来完全一致,保证样式效果不偏差。
  • 新建CDN字体样式文件src/styles/fonts-cdn.scss,内容就是你原来写的Google Fonts引入语句即可。

2. 配置环境变量做构建时切换

CRA原生支持自定义环境变量,不需要改任何构建配置:

  • 根目录新建默认公网构建的配置文件.env.production,写入REACT_APP_FONT_SOURCE=cdn,平时执行普通build命令时默认读这个配置。
  • 根目录新建离线局域网构建的配置文件.env.lan,写入REACT_APP_FONT_SOURCE=local,专门给离线构建用。
  • 删掉你原来在全局样式里硬编码的Google Fonts引入,改成在项目入口文件src/index.js里做静态条件引入:
// 其他import逻辑之前加
if (process.env.REACT_APP_FONT_SOURCE === 'local') {
  import './styles/fonts-local.scss';
} else {
  import './styles/fonts-cdn.scss';
}

这里的判断是构建时生效的:react-scripts打包时会直接把process.env.REACT_APP_FONT_SOURCE替换成当前环境的常量值,没用到的那份样式和对应资源会被Tree Shaking完全剔除,不会出现在最终产物里。如果选local模式,所有本地字体文件会被webpack自动加上hash指纹,打包到build目录的static/media下,引用路径自动处理为相对路径,不需要手动改任何public下的资源配置。

3. 新增离线构建命令

先安装一个零配置的环境变量读取工具当开发依赖:npm i env-cmd -D,不需要做任何额外配置。
然后在package.json的scripts块里加一行:

"build:lan": "env-cmd -f .env.lan react-scripts build"

后续使用逻辑非常简单:

  • 公网部署就跑原来的npm run build,产物和你现在的版本完全一致,走Google Fonts CDN,不会把字体打进包,包体积不变。
  • 离线局域网部署就跑npm run build:lan,产物自动内置所有字体资源,不需要外网就能正常加载字体,渲染效果和CDN版完全一致。

为什么不推荐其他方案

  • 运行时动态插入link/样式的方案:不管选哪种模式,两份逻辑都会被打进bundle,冗余代码多;放在public目录的字体不会被webpack做hash缓存处理,后续更新容易出缓存问题,还可能出现字体加载闪烁。
  • 多HTML入口的方案:两份入口文件维护成本高,后续改meta、公共脚本等内容需要同步改两份,容易出现版本不一致。
  • 上述方案全程不需要eject,不需要修改webpack配置,业务代码里的字体相关写法完全不用改,两种构建模式的逻辑在编译阶段完全分离,没有多余运行时开销。

内容的提问来源于stack exchange,提问作者Alex Kogan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 11:30:48