[TOC]
# ===babel 编译===
## 借助 CRA:
```
yarn create react-app react-project --template typescript
```
## 手动安装
```
npm init
npm i react react-dom react-router-dom core-js regenerator-runtime
npm i -D webpack webpack-cli webpack-merge html-webpack-plugin webpack-dev-server clean-webpack-plugin @babel/core @babel/preset-react @babel/preset-env babel-loader
```
## 依赖包
| 包名 | 释义 |
| --- | --- |
| @babel/core | babel 核心依赖包,将 js 代码分析成 ast,方便各个插件分析语法进行相应的处理 |
| @babel/preset-env | 解析 ES 的包,取代了`preset-es20**`系列的babel 预设,会根据配置`.babelrc`的 `env` 只编译那些当前运行环境还不支持的特性。|
| @babel/preset-react | 专门为了 react 的包,解析 jsx 的包 |
| @babel/plugin-proposal-class-properties | 支持类属性的转化 |
| @babel/plugin-proposal-object-rest-spread | 支持对象使用解构,Babel 默认只转换语法,而不转换新的 API,如需使用新的 API,还需要使用对应的转换插件或者 polyfill。更多查看官网 |
| @babel/plugin-syntax-dynamic-import | 支持动态导入文件 |
| @babel/plugin-proposal-decorators | 装饰器插件 |
| @babel/plugin-transform-runtime | 使用 `async/await` 或其他一些功能时,会需要 |
| @babel/runtime | `@babel-plugin-transform-runtime`插件所需要的,需要将其作为**依赖项**安装。 |
| core-js、regenerator-runtime | 作为 polyfill,供`@babel/preset-env`使用(适当的配置,可以把这2个库的代码,按需打入bundle) |
| webpack | webpack 核心包 |
| webpack-cli | webpack cli 工具包 |
| babel-loader | 和 webpack 结合,用于编译打包 js 文件 |
| html-webpack-plugin | webpack 插件,用于将打包后的文件添加到指定的 html |
| webpack-dev-server | webpack 开发环境工具 |
## 配置文件
### `.babelrc`:
```
{
presets: [
[
'@babel/preset-env',
{
"corejs": "3", // 指定core-js的版本,2或者3,这里我们用最新版3
"useBuiltIns": "usage", // usage是最佳实践,会按需把core-js和regenerator引入(所谓按需就是按下面的target和编译的js用到的es6语法来判断
"targets": '> 2% in CN and not ie <= 8 and not dead',
// 选择目标环境为:中国区统计数据为2%以上的浏览器,不包括版本号小于8的IE浏览,不包括官方已经不维护的浏览器
},
],
'@babel/preset-react',
'@babel/preset-typescript',
],
"exclude": [/node_modules/], // 不要编译node_modules,不然会出一些奇奇怪怪的问题
"plugins": ["@babel/plugin-transform-runtime", "@babel/plugin-proposal-object-rest-spread", "@babel/plugin-proposal-class-properties"],
"comments": false
}
```
### `webpack.config.js`:
```
const webpack = require('webpack');
...
module.exports = {
...
resolve: {
extensions: ['.js', '.jsx'],
alias: {
'@': path.resolve(__dirname, '../src'),
},
},
module: {
rules: [
...
{
test: /\.js(x?)$/,
exclude: /[\\/]node_modules[\\/]/,
loader: 'babel-loader?cacheDirectory=true',
},
],
},
plugins: [
...
new webpack.ProvidePlugin({
React: 'react',
// 不用在每个组件文件中都使用一次`import React from 'react'`
}),
],
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
},
},
},
},
}
```
## 参考
> [纯手动搭建React项目](https://juejin.im/post/5e7b16b0f265da57187c77a3)
# ===Typescript 编译===
Typescript本身具有编译器,可以根据`tsconfig.json`来进行编译。当我们使用 Webpack 进行打包编译的时候,我们需要相应的 loader,Webpack 官网推荐了 ts-loader。而社区也有 awesome-typescript-loader,它针对 ts-loader 做了一些优化,将类型检查和代码生成分离到单独进程中,另外,它还可以直接集成 babel。最后祭出大杀器,Babel 本身是非常强大的语法转换工具,在 babel7 之后开始支持 typescript。
综上,目前转换 Typescript 有三种常用的方式:
* 经典的 ts-loader
* awesome-typescript-loader
* babel7 之后已经支持的 `@babel/preset-typescript
` (目前推荐的)
————————————————
## 借助 CRA:
```
$ npx create-react-app my-app --typescript $
# 或者
$ yarn create react-app my-app --typescript
npm start / yarn start
```
# 手动安装
```shell
mkdir ts-react && cd ts-react
npm init -y && tsc --init
npm i react react-dom react-router-dom @types/react @types/react-dom @types/react-router-dom
npm i -D typescript babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript
npm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin
npm i -D css-loader sass-loader node-sass mini-css-extract-plugin
npm i -D url-loader file-loader
npm i -D eslint eslint-loader eslint-plugin-react eslint-plugin-react-hooks @typescript-eslint/parser @typescript-eslint/eslint-plugin
```
## 依赖包
| 包名 | 释义 |
| --- | --- |
| @babel/preset-react | 专门为了 react 的包,解析 jsx 的包 |
| @babel/preset-typescript | babel 的 preset,用于处理 TypeScript,没有类型检查的能力 |
| @babel/preset-env | 解析过 JSX 和 TypeScript 之后得到的 JavaScript 可能依然无法在某些浏览器上正常运行,所以需要使用[@babel/preset-env](https://babeljs.io/docs/en/next/babel-preset-env.html) |
| @babel/plugin-transform-typescript | 增加了对 TypeScript 编程语言使用的语法的支持。但是,这个插件没有添加类型检查的能力 |
| @typescript-eslint | 配置 ESLint 来达到 TypeScript 类型检查 |
| tsx-control-statements | babel 的 preset,用于处理 TypeScript |
| awsome-typescript-loader | babel 的 preset,用于处理 TypeScript |
| fork-ts-checker-webpack-plugin | 启用 TypeScript 类型检测 |
| eslint-plugin-react | 检测和规范 React 代码的书写 |
| @typescript-eslint/parser | ESLint 的解析器,用于解析 typescript,从而检查和规范 Typescript 代码 |
| @typescript-eslint/eslint-plugin | ESLint 插件,包含了各类定义好的检测 Typescript 代码的规范 |
## `.babelrc`
```
// presets 是自下而上执行的,和 webpack 的 loader 一样
{
presets: [
[
'@babel/preset-env',
{
"targets": '> 2% in CN and not ie <= 8 and not dead',
// 选择目标环境为:中国区统计数据为2%以上的浏览器,不包括版本号小于8的IE浏览,不包括官方已经不维护的浏览器
},
],
'@babel/preset-react',
'@babel/preset-typescript',
]
}
```
## `.eslintrc.js`
~~~js
module.exports = {
parser: '@typescript-eslint/parser',
extends: [
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended'
], //使用推荐的React代码检测规范
plugins: ['@typescript-eslint'],
env:{
browser: true,
node: true,
},
settings: { //自动发现React的版本,从而进行规范react代码
"react": {
"pragma": "React",
"version": "detect"
}
},
parserOptions: { //指定ESLint可以解析JSX语法
"ecmaVersion": 2019,
"sourceType": 'module',
"ecmaFeatures":{
jsx:true
}
},
rules: {
//自定义React代码编码规范
}
}
~~~
## `tsconfig.json`
~~~json
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"jsx": "react",
"lib": ["es6", "dom"],
"module": "esnext",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"allowSyntheticDefaultImports": true, // 允许使用 ES2015 默认的 import 风格
"esModuleInterop": true, // 可调用的CommonJS模块必须被做为默认导入,在已有的“老式”模块模式之间保证最佳的互通性
"moduleResolution": "node",
"noImplicitAny": true,
"rootDir": "src",
"sourceMap": true,
"strict": true,
"target": "es5"
},
"exclude": [
"node_modules",
"build"
]
}
~~~
## 目录结构
~~~
├── build # 构建结果目录
├── styles # 样式
└── main.css
├── bundle.ssr.js # SSR应用文件
├── bundle.web.js # Web应用文件
├── index.html # Web应用入口HTML
├── public
└── index.html # 模板页面
├── src # 应用源码
├── components # 组件
└── Header
└── Header.js
├── home # 首页
└── index.scss # 首页 scss
└── index.tsx # 首页
├── signin # 登录页
└── index.scss # 登录页 scss
└── index.tsx # 登录页
├── App.tsx # 应用路由设置
├── main.ssr.tsx # SSR入口文件
├── index.web.tsx # Web 入口文件
├── index.js # express服务器入口
├── package.json
├── tsconfig.json # TypeScript配置文件
├── webpack.config.js # Web应用webpack配置
├── webconfig.ssr.config.js # SSR应用Webpack配置
~~~
## 参考
> [Microsoft/TypeScript-Babel-Starter](https://github.com/microsoft/TypeScript-Babel-Starter)
> [使用Webpack等搭建一个适用于React项目的脚手架(1 - React、TypeScript)](https://juejin.im/post/5e8b3e626fb9a03c546c2e60#heading-6)
> [webpack从0开始手动搭建react + typeScript项目(二)](https://www.jianshu.com/p/34af24231d2a)
# create-react-app
eject 和 不 eject(使用react-app-rewired) 这2种情况下的 antd 组件按需引入配置:
* 不 eject(使用 [react-app-rewired](https://github.com/timarney/react-app-rewired))配置:
1. **react-app-rewired2.x 以后,不再支持 injectBabelPlugin 的方式,需要安装 [customize-cra](https://github.com/arackaf/customize-cra)。**
替代项目和分支:
[Rescripts](https://github.com/rescripts/rescripts),用于扩展 CRA 配置的替代框架(支持 2.0+)
[react-scripts-rewired](https://github.com/marcopeg/create-react-app/blob/master/packages/react-scripts/README.md) 为该项目的一个分支,旨在支持 CRA 2.0
[craco](https://github.com/sharegate/craco)
2. 项目的根目录下,新建名为 `config-overrides.js` 文件,然后进行 webpack 的相关配置。
3. 修改 package.json 文件
```
/* package.json */
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
}
```
ant.design 说明:https://ant.design/docs/react/use-with-create-react-app-cn
[使用 react-app-rewired2.x 添加 webpack 配置](https://www.cnblogs.com/zyl-Tara/p/10635033.html)
* eject 后,配置:
按需引入 antd 的2种方式:
出处:https://blog.csdn.net/well2049/article/details/78801228
推荐使用第2种方式:在`package.json`里面直接添加代码,这种方式简单。
---------------------
# 参考
[ How to set up React with Webpack and Babel](https://www.robinwieruch.de/minimal-react-webpack-babel-setup)
[webpack手动搭建React项目](https://juejin.im/post/5cfb8c0051882541b24c3ed3)