【react学习笔记】项目配置(typeScript)

益阳平
2023-12-01

 
 

使用cra创建项目

在项目中使用ts
npx create-react-app 项目名 --template typescript
为什么使用cra呢?因为它会自动安装并配置ts相关的包,以及jest测试包等常用的包,以及一些常用的webpack配置,比如热重载、优化后的打包配置等,还直接配置好了对es6+的各自新特性的支持。而且,如果将来cra增加了新功能,我们可以只修改package.json中react-scripts的版本号,然后运行npm i或者yarn i来更新react-scripts,之后我们就可以直接在项目里使用新版本的功能了!
更多细节可以阅读CreateReactApp中文文档,如果你使用cra创建项目,那这就是必读的。

 

配置路径别名

我希望可以像使用vue那样,通过@/component直接访问到src/component,而不是在某个层级比较深的文件内写一堆../../../src/component
 

路径代码提示

这步操作是为了让编辑器可以在我们输入@的时候能识别它并且可以给出代码提示。
首先在项目根目录下创建一个名为tsconfig.path.json的文件,然后复制下列内容:

{
    "compilerOptions": {
        "baseUrl": "src",
        "paths": {
            "@/*": [
                "*"
            ],
        }
    }
}

之后,在根目录下的tsconfig.json文件中新增一行配置信息,目的是将tsconfig.path.json文件内的配置合并进来。

{
  "extends": "./tsconfig.path.json",
  "compilerOptions": {...略},
  "include": [...略]
}

为什么不直接将路径配置写在tsconfig.json中呢?因为我的项目是使用cra创建的,每次运行项目的时候tsconfig.json内的paths字段都会被移除掉,于是只好使用extend字段继承额外的配置文件。两个文件里面的配置加载顺序是这样的:在原文件里的配置先被加载,然后被来至继承文件里的配置重写。 如果发现循环引用,则会报错。
 

webpack识别别名

现在编辑器做静态分析的过程中可以识别别名了,我们输入@可以给出提示了。但是webpack在打包的时候仍然不认识这个别名,不信你可以试试运行项目,看看报错信息。我们还需要对webpack做一些配置。不过cra创建的项目默认是没有webpack.config等配置文件的,需要在控制台执行yarn run eject来将CRA 中的配置全部反编译到当前项目中,但如果我们使用了eject命令,就再也享受不到CRA 升级带来的好处了,因为react-scripts已经是以文件的形式存在于你的项目,而不是以包的形式,所以无法对其升级。
基于上面的原因,我选择使用react-app-rewired来重写部分webpack配置,这样可以做到不弹出webpack配置的前提下,重写webpack配置。
首先命令行执行npm install react-app-rewired --save-dev或者yarn add react-app-rewired --dev来安装这个包,之后在项目根目录下创建名为config-overrides.js的文件,文件内容一会儿再说,最后修改package.json的scripts字段,修改后如下:

"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test --env=jsdom",
    "eject": "react-scripts eject"
  },

接下来就可以编写config-overrides.js文件了,不过我们其实没必要编写原生的webpack配置,我选择借助customize-cra这个包的一些工具函数自动生成配置项。
首先安装它yarn add customize-cra -D,之后开始编写config-overrides.js,内容如下:

const path = require('path');
const {override, addWebpackAlias } = require("customize-cra");

module.exports=override(
    addWebpackAlias({
        "@": path.resolve(__dirname, 'src')
    })
)

保存之后重新执行yarn start,发现webpack可以找到文件了,项目通过编译。

 

css预处理器

配置sass

本以为使用sass需要在config-overrides.js里面配置下sass-loader,可根据cra官方文档的说法,我只需要安装node-sass即可,猜测cra默认已经安装了sass-loader并且已经配置完成。于是创建了一个新项目然后执行npm run eject弹出webpack.config.js看了下,确实已经对拓展名为.sass.scss的文件使用了sass-loader来加载。
于是如果我想在cra创建的项目中使用sass就简化为只安装node-sass即可。
因为众所周知的原因,我们需要使用镜像源来安装。
npm:npm i node-sass --sass_binary_site=https://npm.taobao.org/mirrors/node-sass/ --save-dev
yarn:yarn config set registry https://registry.npm.taobao.org -gyarn add node-sass
祝你好运

配置less

安装: yarn add less less-loader -Dnpm i less less-loader -D
修改config-overrides.js,如下:

const {override,addLessLoader} = require("customize-cra");

module.exports = override(
    addLessLoader({
        javascriptEnabled: true,
        localIdentName: '[local]--[hash:base64:5]' 
    })
)

 

配置sass文件自动导入

配置好sass之后,根据我的习惯,我喜欢创建两个文件: src/styles/mixin.scsssrc/styles/variables.scss。然后使用sass-resources-loader将这两个文件自动引入到其他.scss文件内,这样我就可以在任何一个.scss文件内使用这些变量和mixin了。十分方便。
首先,安装sass-resources-loader,yarn add sass-resources-loader --devnpm i sass-resources-loader --save-dev。之后我本打算继续使用reactAppRewrite和customizeCra做配置,但是麻烦事来了。
首先,阅读下cra的webpack默认配置模板可以知道,scss文件要经历四个loader的加载才能最终放置到页面内,按照先后顺序分别是:
sass-loader:用于将scss语法转为css。
postcss-loader:为css添加特定厂商的前缀,就是-moz--webkit-等等这些。
css-loader:分析@import和url,推导各个css文件之间的关系,把各个css文件合并成一段css。
style-loader:将css添加到index.html的style标签内。
因为sass-resources-loader这个loader是用来处理scss文件的,所以一定是要放在saa-loader之前使用,可我翻遍了customize-cra的文档,也没找到哪个api可以在loader调用链中插入新的loader,于是只好完全重新配置所有css相关loader,并在尾部添加我自己需要的这个sass-resources-loader(loader的调用是从loader列表尾部开始的)。config-overrides.js内容如下:

const path = require('path');
const { override, addWebpackAlias, addWebpackModuleRule } = require("customize-cra");

module.exports = override(
    addWebpackAlias({
        "@": path.resolve(__dirname, 'src')
    }),
    addWebpackModuleRule(
        {
            test: /\.scss$/, use: [
                { loader: 'style-loader' },
                { loader: 'css-loader', options: { sourceMap: true } },
                { loader: 'sass-loader', options: { sourceMap: true } },
                {
                    loader: 'sass-resources-loader',
                    options: {
                        sourceMap: true,
                        resources: ['./src/styles/variables.scss']
                    }
                }]
        }
    )
)

然而这样太麻烦了,不仅手动把cra配置过的loader重新配了一遍,而且还完全放弃了cra给我们做好的各个loader的options,这样绝对不行,于是我换了种方式,如下:

const path = require('path');
const { override, addWebpackAlias, addWebpackModuleRule } = require("customize-cra");

function overwriteScssLoader(config) {
    config.module.rules[2].oneOf[5].use.push({
        loader: 'sass-resources-loader',
        options: {
            sourceMap: true,
            resources: ['./src/styles/variables.scss']
        }
    })
    return config
}

module.exports = override(
    addWebpackAlias({
        "@": path.resolve(__dirname, 'src')
    }),
    overwriteScssLoader
)


customizeCra会为overwriteScssLoader函数传入webpack的配置(config参数),我选择直接修改它。但其实这种方式也不行,大家可以看到我是直接使用了下标的方式操作数组,如果将来react把webpack的配置改动了,那我这种写法就失效了。可这已经是我倒腾2个多小时的结果了。当然,大家可以选择在overwriteScssLoader函数里面加上各种各样的判断语句来增加健壮性,但是!最终我建议,如果需要对webpack做精细的配置还是eject吧!一分钟搞定的事情花十几分钟甚至个把小时去弄实在得不偿失。

 

配置Mobx

  1. 安装 mobx: yarn add mobx mobx-reactnpm i mobx mobx-react --save

  2. 然后配置装饰器:
    首先,安装 yarn add @babel/plugin-proposal-decorators -Dnpm i --save-dev @babel/plugin-proposal-decorators
    然后,修改override-config.js文件如下:

const path = require('path');
const {addDecoratorsLegacy, override } = require("customize-cra");

module.exports = override(
    addDecoratorsLegacy()
)

如果是非ts项目的话,做到这一步即可,否则还需要修改tsconfig.json。如果不这样做的话,ts会给出警告说装饰器是不稳定的语法balabala什么的,但其实这个语法很多库源码都在用,而且js最终支持不支持无所谓,反正babel是支持的,这就够了。废话有点多了,我们只需在tsconfig.json中添加一条选项即可

{
  "compilerOptions": {
    "experimentalDecorators": true,
	}
}

 

配置react-router

安装:npm install react-router-dom --saveyarn add react-router-dom
我们不需要安装react-router这个包,因为 react-router 为了支持 Web 和 React Native 出了两个包—— react-router-domreact-router-native ,我们只关心 Web,所以只需要安装 react-router-dom 。这个 react-router-dom 依赖于 react-router ,所以 react-router 也会被自动安装上。并且react-router-dom也会导出(动词)react-router的那些导出(名词)。

如果是非ts项目的话,到这一步安装就结束了,不过对ts项目来说,还需要安装相应的类型声明的包,因为react-router-dom并没有提供.d.ts文件。至于第三方的类型声明仓库,一般是使用DefinitelyTyped。

DefinitelyTyped 是一个庞大的声明仓库,为没有声明文件的 JavaScript 库提供类型定义。这些类型定义通过众包的方式完成,并由微软和开源贡献者一起管理。—— React官方文档

这是它的官网,你可以直接搜索包名。如果存在其对应的类型声明文件的话,页面会自动跳转到npm中相应包的主页。
react-rouer-dom对应的包为@types/react-router-dom。所以直接安装:npm install --save @types/react-router-domyarn add @types/react-router-dom。至此react-router就安装完毕了。

 

配置antd

安装:yarn add antd或者npm i antd --save
配置按需引入还需安装babel-plugin-import:npm i --save-dev babel-plugin-importyarn add babel-plugin-import -D
此外还需要修改config-overrides.js,如下:

const {override,fixBabelImports } = require("customize-cra");

module.exports = override(
    fixBabelImports('import', {
        libraryName: 'antd',
        libraryDirectory: 'es',
        style: true,
    })
)

注意style选项是true,官方文档给出的style值是’css’,之所以写成true是因为antd源码中样式全部是使用less编写的,当style为true时引入的就是less源文件,而style为’css’的时候引入的是等效的css文件。虽然less文件的体积要比css小很多算是个优点,但其实体积大小不重要,因为最终less文件仍然会被less-loader编译成css,也就是说引入到index.html里面的就是编译出来的css。而我选择引入less而非css的原因是cra配置了对less的优化策略,比起我直接引入css要好一些。
另外,安装less是不会增加打包后的体积的,因为less和sass都是开发环境的工具,它们只在打包过程中发挥作用。它们不会被打包到最终的输出目录中,大家放心大胆的装两个是完全OK的,我自己的项目是less和sass都安装了。

antd自定义主题

刚刚也说过了,antd的样式是用less写的,其中使用了大量的变量来做到风格的一致性。如果我们想修改less中的变量的话,有两种方案:
第一个方案是配置 less 变量文件,它的优点是配置简单。但这种方式我不推荐,因为这么做会强制导入全部样式,那么之前配置的按需导入样式就失效了。

第二个方案是修改less-loader的配置,让webpack在打包的过程中修改使用到的那些less变量的值,这种方式不会影响到按需导入,推荐!
只需一步,修改config-overrides.js。在addLessLoader的选项中新增modifyVars属性,然后在其中以键值对方式制定变量和它的新值即可。如下:

const {override,addLessLoader} = require("customize-cra");

module.exports = override(
    addLessLoader({
        javascriptEnabled: true,
        modifyVars: {
            '@primary-color': '#1DA57A' //注意这里
        },
        localIdentName: '[local]--[hash:base64:5]' 
    })
)

 

参考

react + typescript 集成mobx和设置别名alias最新解决方案
ts官方文档
CreateReactApp中文文档
Create React App无eject配置(react-app-rewired 和 customize-cra)
babel-plugin-import
less中文文档

 类似资料: