create react app 项目升级
旧的 cra 项目升级
- 项目介绍
- 关于升级的思考
- 升级实现以及遇到的问题
- 结语
1. 项目介绍
cms 项目,使用 react 开发,状态管理使用 mobx,UI 中使用了 materialui,antd,antd-pro。 项目使用老的create-react-app创建,并且执行过 eject 操作。
2. 关于升级的思考
为什么要升级
项目无法支持 ts 语法,现有的 webpack 构建中对 node 版本有依赖,不能超过 14 版本
如何做
一开始准备直接在项目添加 ts 支持,添加 ts 依赖,eslint 依赖,然后就是提示升级 node 版本,提升了 node 版本后提示 node-sass 不支持。折腾了一顿也没整明白。 因为是 cra 创建的项目尝试以最新版的 cra 创建一个支持 ts 的项目,然后对项目进行相应更改
3. 升级实现以及遇到的问题
- 创建空的 cra 项目,执行 eject
npx create-react-app tmp-app --template typescript cd tmp-app && npm run eject
这一步执行 eject 并不一定是必须得,如果项目中没有特别自定义 webpack 配置,可以考虑不执行 eject,将来项目升级也会方便
- 老的项目已经有 git,将项目中所有文件都放在 tmp 文件夹下,把刚才创建项目都复制过来
安装依赖 yarn
运行 yarn start
- 用老项目的 src 替换新项目的 src(将生成的src删掉,把原有项目的复制过来),cra 的项目项目代码基本都在 src 中,我们可以把这个运行起来就 ok 了。
webapck 配置文件,位置在 config/webpack.config.js。
- 第一步先关闭eslint,放到最后配置,优先将项目运行起来,webpack5中eslint通过eslint-webpack-plugin插件来配置,在配置文件中将eslint开关关闭,找到
disableESLintPlugin
并置为true。也可以在env文件中设置
disableESLintPlugin = true
问题 1. cra 项目不支持装饰器语法,需要进行支持,包括 babel 和 eslint 设置
babel 添加decorator支持 添加插件@babel/plugin-proposal-decorators
yarn add -D @babel/plugin-proposal-decorators
在webpack配置中添加该babel插件,这里应该也可以通过.babelrc文件配置,找到处理src文件出的babel配置,require.resolve加不加无所谓,这个是react-script用来查找依赖的
{
plugins: [
isEnvDevelopment &&
shouldUseReactRefresh &&
require.resolve("react-refresh/babel"),
[
require.resolve("@babel/plugin-proposal-decorators"),
{
legacy: true,
// version: "2018-09",
// decoratorsBeforeExport: true,
},
],
].filter(Boolean),
}
- 再次执行start可以看到babel的decorator提示已经解决,接下来
-
把原有项目的依赖添加到新的项目。cra执行eject后所有的依赖都放在dependencies中了,其中只有react react-dom。
-
添加alias 在配置中添加alias配置
-
安装sass依赖
问题 2. antdcss的引用方式修改 把antd/dist/antd.css 改成 antd/dist/antd.min.css
import 'antd/dist/antd.min.css'
问题 3. 此时start命令在终端已经不报错误了,但是访问页面没有内容,将和proxy代理配置相关的文件移除后可以访问页面 新的代理中使用方法和原来的不一样,新版proxy设置
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
Object.keys(proxyConfig).forEach(function (proxyPath) {
let options = proxyConfig[proxyPath];
app.use(
proxyPath,
createProxyMiddleware({
target: options.target,
changeOrigin: true,
pathRewrite: options.pathRewrite,
})
);
});
};
到目前为止,项目已经能正常运行,还剩下eslint添加和ts文件的测试
- eslint 配置
- 编辑器vscode中有eslint配置,打开index.js有报错,
Using
babel-preset-react-apprequires that you specify
NODE_ENVor
BABEL_ENVenvironment variables.
。配置编辑器eslint运行的参数,在setting.json中添加配置,重新打开编辑器就不报错了
{
"eslint.nodeEnv": "development",
}
- 打开eslint的开关, disableESLintPlugin更改删掉。运行start,eslint报错没有decorators支持 webpack5使用 eslint-webpack-plugin 将配置文件中的除了eslint-webpack-plugin中的配置移到.eslintrc.js文件中,不在配置文件中配置的原因是编辑器无法识别配置文件中的eslint配置
配置文件中,eslint-webpack-plugin的配置,useEslintrc置为true
new ESLintPlugin({
// Plugin options
extensions: ["js", "mjs", "jsx", "ts", "tsx"],
formatter: require.resolve("react-dev-utils/eslintFormatter"),
eslintPath: require.resolve("eslint"),
failOnError: !(isEnvDevelopment && emitErrorsAsWarnings),
context: paths.appSrc,
cache: true,
cacheLocation: path.resolve(
paths.appNodeModules,
".cache/.eslintcache"
),
useEslintrc: true,
}),
还需要添加.prettierrc.js文件
module.exports = {
importOrderParserPlugins: true,
};
- ts文件测试
在原有项目中吧jsx文件改成tsx文件或新建ts文件,看能否执行 新建test.ts
export function baseAdd(num1: number, num2: number): number {
console.log(`num1,num2`, num1, num2);
// const x = num1.split();
return num1 + num2;
}
type Animal = {
age: number;
};
export function getAge (anamial:Animal):number{
return anamial.age;
}
引入
import { baseAdd } from "./utils/test";
console.log(`baseAdd(1,2)`, baseAdd(1, 2));
可以正常使用
将原来的jsx直接修改成tsx文件,终端会有对应的ts编译的错误,也没有问题
4. 结语
老的react项目如果是基于cra创建的在升级时优先考虑直接更新cra的版本,如果已经eject则直接用新版的cra的eject然后将src运行。 最主要的升级工作还是在围绕webpacz做一些配置,优先保证项目运行起来,可以先关掉eslint。最后解决eslint问题。 更好的实践是保持项目与新的技术的更新。
前端的工程化是没有止尽的(因为没有官方支持!!,js语言更多关心的是ecma标准),尽可能选择已有的前端解决方法,ice.js umi.js要比官方的cra好用的多,也会有更多的升级支持。
5. 参考文档
转载自:https://juejin.cn/post/7161235023847227423