从Docker构建失败到CRA被淘汰:一个React项目的ES模块探索记录

news/2025/9/29 16:54:23/文章来源:https://www.cnblogs.com/LexLuc/p/19119088

开头

最近给一个React项目配Docker构建,碰到了一个看起来简单实际很麻烦的错误:

Failed to compile.
The target environment doesn't support dynamic import() syntax so it's not possible to use external type 'module' within a script
Did you mean to build a EcmaScript Module ('output.module: true')?

这个错误让我深入了解了Create React App (CRA)、ES模块、Webpack和CRACO之间的关系。最后还发现了一个消息:CRA已经被官方宣布逐步淘汰了

问题是怎么来的

一开始的错误

项目用的是Create React App构建,在Docker环境里构建失败了。错误信息说动态导入语法不被支持。

项目环境

  • React版本: 18.2.0
  • CRA版本: react-scripts 5.0.1
  • 构建工具: Docker + npm run build
  • 出问题的代码: src/reportWebVitals.js 里的动态导入

我是怎么分析问题的

1. 先找到问题在哪

发现 reportWebVitals.js 里用了动态导入:

// 原来的代码(有问题)
const reportWebVitals = onPerfEntry => {if (onPerfEntry && onPerfEntry instanceof Function) {import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {// 用这些函数});}
};

2. 试了简单修复

一开始想把动态导入改成静态导入:

// 修好的代码
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';const reportWebVitals = onPerfEntry => {if (onPerfEntry && onPerfEntry instanceof Function) {getCLS(onPerfEntry);getFID(onPerfEntry);getFCP(onPerfEntry);getLCP(onPerfEntry);getTTFB(onPerfEntry);}
};

但问题还在,说明不是这个文件的问题。

3. 深入调查

继续查发现:

  • 项目里确实没别的动态导入
  • 问题可能来自依赖包或者webpack配置
  • 需要开启ES模块输出支持

解决方案:用CRACO

CRACO是什么?

CRACO (Create React App Configuration Override) 是个工具,让你能覆盖CRA的webpack配置,不用执行 npm run eject

怎么装和配置

# 装CRACO
npm install --save-dev @craco/craco

创建 craco.config.js

module.exports = {webpack: {configure: (webpackConfig) => {// 关键配置:开启ES模块输出webpackConfig.output = {...webpackConfig.output,module: true,              // 开启模块输出libraryTarget: 'module',   // 设置库目标是模块};// 加webpack实验性功能webpackConfig.experiments = {...webpackConfig.experiments,outputModule: true,        // 开启模块输出实验};// 配置模块解析回退webpackConfig.resolve = {...webpackConfig.resolve,fallback: {...webpackConfig.resolve?.fallback,"fs": false,"path": false,"crypto": false,}};return webpackConfig;},},
};

package.json 脚本:

{"scripts": {"start": "env-cmd -f .env craco start","build": "env-cmd -f .env craco build","test": "craco test"}
}

验证方案

试着去掉CRACO看看是不是真的需要:

  1. 备份配置
  2. 去掉CRACO
  3. 测试构建
  4. 结果:构建失败

结论:CRACO确实是必需的。

技术原理

Webpack、ES模块和CRACO的关系

React项目↓
Create React App (CRA)↓
react-scripts (内置webpack配置)↓
Webpack (模块打包器)↓
处理模块 (CommonJS/ES模块/动态导入)↓
输出打包文件需要自定义时:↓
CRACO (配置覆盖层)↓
修改Webpack配置↓
支持更多模块特性

ES模块 vs CommonJS

// ES模块 (ES6+)
export const value = 42;
import { value } from './module.js';// CommonJS (Node.js)
module.exports = { value: 42 };
const { value } = require('./module.js');

为什么CRA默认不支持ES模块输出?

  1. 兼容性考虑:要支持老浏览器
  2. 生态系统兼容性:很多npm包还是CommonJS格式
  3. 构建复杂度:ES模块输出需要更多配置
  4. 稳定性优先:CRA追求"零配置",避免复杂配置

重大发现:CRA被淘汰了

官方说法

2025年2月14日,React官方宣布逐步淘汰Create React App!

这意味着:

  • CRA不再更新
  • 最新版本停在 react-scripts 5.0.1
  • 不再支持新特性,包括ES模块输出
  • 官方建议迁移到其他现代构建工具

版本对比

// CRA 4.x (2020-2021)
❌ 不支持ES模块输出
❌ 不支持动态导入// CRA 5.x (2022) - 现在最新的
❌ 还是不支持ES模块输出
⚠️ 需要CRACO才能支持// CRA 6.x (没发布)
❌ 被官方取消了
❌ 不会有新版本

现代替代方案

1. Vite - 推荐方案

// vite.config.js
export default {build: {// ✅ 默认支持ES模块输出target: 'esnext',rollupOptions: {output: {format: 'es' // ES模块格式}}}
}

好处:

  • 原生ES模块支持
  • 构建更快
  • 开发体验现代化
  • 社区活跃

2. Next.js

// next.config.js
module.exports = {experimental: {// ✅ 支持ES模块esmExternals: true}
}

3. Parcel

// Parcel 默认支持ES模块
// ✅ 零配置ES模块支持
// ✅ 开箱即用

项目建议

短期方案(继续用CRA + CRACO)

// 现在这个方案还能用
✅ 用 react-scripts 5.0.1 + CRACO
✅ 通过CRACO配置ES模块支持
✅ 项目能正常运行// 但要注意
⚠️ CRA不再维护,安全更新可能停
⚠️ 依赖包可能过时
⚠️ 长期维护有风险

长期方案(迁移到现代工具)

迁移优先级:

  1. Vite - 最接近CRA的体验,迁移成本最低
  2. Next.js - 如果需要服务端渲染
  3. Parcel - 如果喜欢零配置

最终解决方案

Dockerfile修复

顺便修了Dockerfile里的一些问题:

# 修之前
RUN apt-get update && apt-get install -y --no-install-recommends
EXPOSE 3000# 修之后
RUN apt-get update && apt-get install -y --no-install-recommends \curl \&& rm -rf /var/lib/apt/lists/*
EXPOSE 3003  # 匹配.env里的PORT配置

构建结果

# 最终构建成功
✅ 本地构建:npm run build
✅ Docker构建:docker build -t ts-mvp-frontend:latest
✅ 动态导入问题解决
✅ ES模块支持开启

经验总结

学到的东西

  1. 问题往往比表面复杂:看起来简单的动态导入问题,背后涉及整个模块系统
  2. 工具链很重要:现代JavaScript开发需要理解整个工具链
  3. 技术选型的影响:CRA的设计理念虽然简化了配置,但也限制了灵活性
  4. 技术生态变化很快:CRA的淘汰提醒我们技术栈需要持续更新

最佳实践

  1. 深入理解工具:不要只停留在表面使用
  2. 关注官方动态:及时了解技术栈的变化
  3. 准备迁移计划:对于被淘汰的技术要有应急预案
  4. 记录文档:记录解决过程,方便团队分享

结尾

这次探索让我深刻理解了现代JavaScript开发中模块系统的重要性,以及工具链配置的复杂性。CRA的逐步淘汰也提醒我们,在技术快速发展的今天,保持技术栈的现代化和可维护性至关重要。

对于正在用CRA的项目,建议:

  • 短期:继续用CRA + CRACO的方案
  • 中期:制定迁移计划
  • 长期:迁移到Vite等现代工具

技术总是在不断演进,作为开发者,我们需要保持学习的心态,拥抱变化,选择最适合项目的技术栈。


这篇文章记录了一个Docker构建错误到发现CRA被淘汰的完整技术探索过程,希望对遇到类似问题的开发者有帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/922018.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

充气泵PCBA方案中数字传感器和模拟传感器的差异

充气泵的核心需求是实时、准确检测气罐/充气对象(如轮胎、泳圈)的压力,并根据压力值控制电机启停(如达到目标压力后停机),二者的应用差异直接影响产品体验:1.模拟传感器的应用场景低成本入门级充气泵(如家用小…

实用指南:小米17手机的上市公司供应商

实用指南:小米17手机的上市公司供应商pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Mon…

小程序支付遇到:system:access_denied

小程序支付遇到:system:access_denied 原因: 小程序支付,只能用手机微信测试,不能用电脑。 -

cloudfared 内网穿透经过docker方式遇到的问题

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

CDN + WAF + CLB + Higress 架构下的 TLS 加解密详细解析(适用阿里云)

在云环境中,Web 应用常见架构是:用户 → CDN → WAF → CLB → ECS/Higress本文详细解析 WAF 在网络拓扑中的位置、TLS 加解密流程、回源逻辑,以及自定义接入模式下的注意事项,结合阿里云官方推荐实践。1.WAF 在网…

react useMemo Hook详解

什么是 useMemo Hook? useMemo 是一个 React Hook,用于缓存计算结果,避免在每次组件渲染时重复执行昂贵的计算。它通过记忆计算的值,只有在依赖项变化时才会重新计算,从而优化性能。 简单来说,useMemo 让你的计算…

门户网站改版建议wordpress 调用热门 文章

文章目录 1.liunx简介2.liunx的jdk安装2.liunx的tomcat安装3.liunx的mysql安装4.单机项目部署 1.liunx简介 Linux,一般指GNU/Linux(单独的Linux内核并不可直接使用,一般搭配GNU套件,故得此称呼),是一种免费…

vs2012网站开发济南做网站的网络公司

简介: 淘宝的开放技术目前主要有两种形态,第一种是小程序,第二种是今天的主角小部件。它是基于小程序技术体系,面向标准化、轻量化、高性能的开放卡片场景。本文我们将通过技术设计策略、核心技术设施、业务场景接入、技术演进路线…

网站后台系统有哪些佛山优化企业网站排名平台

实验要求 1、R5为ISP,只能进行IP地址配置,其所有地址均配为公有IP地址。 2、(1)R1和R5间使用PPP的PAP认证,R5为主认证方。 (2)R2与R5之间使用ppp的CHAP认证,R5为主认证方。 &#…

完整教程:Python 编辑器:Visual Studio Code(进阶篇)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Python技能大赛-备赛建议

好的,非常理解您希望得到具体、可行的备赛建议。基于您提供的比赛文件,特别是关于“专业能力模块”的详细要求,我为您梳理了一套系统的备赛策略。 [cite_start]该模块分为 理论知识 (权重10%) 和 实践操作 (权重60%…

公司建设网站产生哪些费用毕设做网站些什么比较简单

一、前言 内部培训会有Word版本题库,考核时如果使用Word、Excel、PDF等文档进行关键字查询题目体验不佳。so,撸个软件吧!   20240728更新:支持更多题库类型。 二、Word题库转Excel 1、Word题库格式要求 内容格式要求事例题目…

怎样提高网站收录上海建设厅网站

文章目录 下载树莓派镜像下载烧写软件烧写编辑设置连接树莓派4B重启ssh查看树莓派IPssh远程连接问询、帮助 下载树莓派镜像 https://www.raspberrypi.com/software/operating-systems/#raspberry-pi-os-64-bit 下载烧写软件 https://www.raspberrypi.com/software/ 烧写 编辑…

【软件系统架构】系列七:系统性能——操作系统性能深入解析 - 实践

【软件系统架构】系列七:系统性能——操作系统性能深入解析 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: &quo…

你的下一款定位神器,何必是GPS?Nordic带你解锁Wi-Fi SSID的隐藏潜能

随着 nRF7000 Wi-Fi 协同 IC 的推出,我们现在可以提供具有 Wi-Fi、蜂窝物联网和 GNSS 功能的完整硅到云定位解决方案。nRF7000 针对 Wi-Fi 网络扫描进行了优化,与 nRF91 系列蜂窝物联网模组配合使用,可实现基于 SSI…

CF407E k-d-sequence 题目分析(0929模拟赛最后一题)

首先特判 $d=0$ 的情况。好,对于 $d\geq 1$ 的情况考虑转化。注意到等差序列满足: - 模 $d$ 同余。 - 值两两不同。我们先把 $a$ 变为正数,然后全部除以 $d$,这肯定是正确的,你可以想一想。那么我们就全部转化为了…

vue3踩坑:静态dom无法初始化渲染 - 父组件props与侦听器的交互

vue3踩坑:静态dom无法初始化渲染 -> 父组件props与侦听器的交互今天遇到一个没有渲染dom的问题,原因是父组件如果传递的是未被ref或reactive包裹的静态值,那么传递到子组件中被watch包裹,即使深监听也不会触发响…

Linux 生成随机端口

shuf -i 40000-55535 -n 1作者:Outsrkem原文链接:https://www.cnblogs.com/outsrkem/p/19119039本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法…

门户网站的门户思维有什么特点网站开发软件有哪

上一篇博客链接: 机器学习与建模中 - 判断数据模型拟合效果的三种方法 在上一篇博客中,我们谈到了使用损失函数来判断模型的拟合效果。但是拟合效果比较好的模型不一定是最好的模型,建模的最终目的是为了预测,因此预测最精准的模…

做网站dreamwa怎样做网站优化

西安理工大学2019年硕士研究生拟录取名单考生编号 姓名 备注107009061360689 王帅 101 材料科学与工程学院 080501 材料物理与化学107009061360690 左稼暄 101 材料科学与工程学院 080501 材料物理与化学107009061360735 陈瑶 101 材料科学与工程学院 080501 材料物理与化学107…