快来跟我一起学 React(Day4)
Posted vv_小虫
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快来跟我一起学 React(Day4)相关的知识,希望对你有一定的参考价值。
简介
上一节我们从 0
开始搭建了一个项目,完成了入口与出口的配置、ts 语法支持、react 基本库的安装、css 样式配置等工作,我们继续上一节的内容。
知识点
- Eslint(代码质量校验)
- eslint-webpack-plugin(Eslint webpack 插件)
- eslint-config-react-app(React 官方 eslint 配置)
- fork-ts-checker-webpack-plugin(ts 语法校验插件)
- Optimization(分包优化等)
准备
上一节所有的内容在 dev 分支:https://gitee.com/vv_bug/cus-react-demo/tree/dev,我们重新切一个新分支 dev-v1.0.0
。
我们安装好依赖,并且用 npm start
命令启动项目:
npm install --registry https://registry.npm.taobao.org && npm start
可以看到,浏览器自动打开了我们项目入口,并且在页面正常显示了 ”hello react111“ ,到这,我们的准备工作算是完成了。
Eslint
ESLint 是在 ECMAScript/javascript 代码中识别和报告模式匹配的工具,它的目标是保证代码的一致性和避免错误。
接下来我们来安装一下 ESLint
相关依赖:
安装 ESLint
Eslint 核心 API。
在工程目录 cus-react-demo
下执行以下命令安装:
npm install -D eslint --registry https://registry.npm.taobao.org
安装 eslint-webpack-plugin
Eslint 在 Webpack
中的插件。
在工程目录 cus-react-demo
下执行以下命令安装:
npm install -D eslint-webpack-plugin --registry https://registry.npm.taobao.org
安装 eslint-config-react-app
React
官方提供的 Eslint
配置。
在工程目录 cus-react-demo
下执行以下命令安装:
npm install -D eslint-config-react-app --registry https://registry.npm.taobao.org
安装 @typescript-eslint/eslint-plugin
ESLint 中的 ts 插件。
在工程目录 cus-react-demo
下执行以下命令安装:
npm install -D @typescript-eslint/eslint-plugin --registry https://registry.npm.taobao.org
安装 @typescript-eslint/parser
ESLint 中的 ts 语法解析器。
在工程目录 cus-react-demo
下执行以下命令安装:
npm install -D @typescript-eslint/parser --registry https://registry.npm.taobao.org
安装 typescript
ts 语法核心库。
在工程目录 cus-react-demo
下执行以下命令安装:
npm install -D typescript --registry https://registry.npm.taobao.org
安装 eslint-plugin-import
Eslint
中对 EsModule
导入导出的规范插件。
在工程目录 cus-react-demo
下执行以下命令安装:
npm install -D eslint-plugin-import --registry https://registry.npm.taobao.org
安装 eslint-plugin-flowtype
Eslint
中对 flow
语法规范插件。
在工程目录 cus-react-demo
下执行以下命令安装:
npm install -D eslint-plugin-flowtype --registry https://registry.npm.taobao.org
安装 eslint-plugin-jsx-a11y
安装 eslint-plugin-react-hooks
安装 eslint-plugin-react
安装 babel-eslint
在工程目录 cus-react-demo
下执行以下命令安装:
npm install -D eslint-plugin-jsx-a11y eslint-plugin-react-hooks eslint-plugin-react babel-eslint --registry https://registry.npm.taobao.org
总算是安装完毕了,其实这些都是 React
官方要求的一些 Eslint
插件,都是在 eslint-config-react-app
中定义要求的,每一个具体什么功能我就不一一分析了,小伙伴自己去官网查看哦,童鞋们平时也不需要刻意去记这些东西,直接 copy 然后安装即可,ESLint 依赖我们是安装完毕了,下面我们来给项目配置一下 ESLint。
首先找到 webpack 配置文件 webpack.config.js
,然后添加 eslint-webpack-plugin
:
const path = require('path');
const config = new (require('webpack-chain'))();
const isDev = process.env.NODE_ENV === 'development'; // 判断是否是开发环境
config
.target('web')
.context(path.resolve(__dirname, '.')) // webpack 上下文目录为项目根目录
.entry('app') // 入口文件名称为 app
.add('./src/main.tsx') // 入口文件为 ./src/main.tsx
.end()
.output
.path(path.join(__dirname, './dist')) // webpack 输出的目录为根目录的 dist 目录
.filename(isDev ? '[name].[hash:8].js' : '[name].[contenthash:8].js') // 打包出来的 bundle 名称为 "[name].[contenthash:8].js"
.publicPath('/') // publicpath 配置为 "/"
.end()
.resolve
.extensions.add('.js').add('.jsx').add('.ts').add('.tsx').end() // 添加后缀自动解析
.end()
.module
.rule('ts') // 配置 typescript
.test(/\\.(js|mjs|jsx|ts|tsx)$/)
.exclude
.add(filepath =>
// Don't transpile node_modules
return /node_modules/.test(filepath)
)
.end()
.use('babel-loader')
.loader('babel-loader')
.end()
.end()
.rule('sass') // sass-loader 相关配置
.test(/\\.(sass|scss)$/) // Sass 和 Scss 文件
.use('extract-loader') // 提取 css 样式到单独 css 文件
.loader(require('mini-css-extract-plugin').loader)
.end()
.use('css-loader') // 加载 css 模块
.loader('css-loader')
.end()
.use('postcss-loader') // 处理 css 样式
.loader('postcss-loader')
.end()
.use('sass-loader') // Sass 语法转 css 语法
.loader('sass-loader')
.end()
.end()
.end()
.plugin('extract-css') // 提取 css 样式到单独 css 文件
.use(require('mini-css-extract-plugin'), [
filename: isDev ? 'css/[name].css': 'css/[name].[contenthash].css',
chunkFilename: isDev ? 'css/[id].css': 'css/[name].[contenthash].css',
,
])
.end()
.plugin('html') // 添加 html-webpack-plugin 插件
.use(require('html-webpack-plugin'), [
template: path.resolve(__dirname, './public/index.html'), // 指定模版文件
chunks: ['app'], // 指定需要加载的 chunk
inject: 'body', // 指定 script 脚本注入的位置为 body
,
])
.end()
.plugin('eslint') // 添加 eslint-webpack-plugin 插件
.use(require('eslint-webpack-plugin'), [
// Plugin options
extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'],
eslintPath: require.resolve('eslint'),
failOnError: !isDev,
context: path.resolve(__dirname, "./src"),
// ESLint class options
cwd: __dirname,
resolvePluginsRelativeTo: __dirname,
])
.end()
.devServer
.host('0.0.0.0') // 服务器外部可访问
.disableHostCheck(true) // 关闭白名单校验
.contentBase(path.resolve(__dirname, './public')) // 设置一个 express 静态目录
.historyApiFallback(
disableDotRule: true, // 禁止在链接中使用 "." 符号
rewrites: [
from: /^\\/$/, to: '/index.html' , // 将所有的 404 响应重定向到 index.html 页面
],
)
.port(8080) // 当前端口号
.hot(true) // 打开页面热载功能
.sockPort('location') // 设置成平台自己的端口
.open(true)
module.exports = config.toConfig();
如果要让 eslint 起作用的话,我们还需要给 eslint 添加一个配置文件 .eslintrc.js
。
我们在工程目录 cus-react-demo
下创建一个 .eslintrc.js
文件:
touch .eslintrc.js
然后写入以下代码到 .eslintrc.js
文件:
module.exports =
env:
node: true, // 添加 node 环境
,
extends: [
"react-app", // 继承 react-app 配置
"react-app/jest" // 继承 react-app/jest 配置
],
rules:
// 自定义规则
semi: [
// 代码结尾必须使用 “;“ 符号
'error',
'always',
],
quotes: [
// 代码中字符串必须使用 ”” 符号
'error',
'double',
],
'no-console': 'error', // 代码中不允许出现 console
,
;
其实我们需要的只是对 src
目录底下的所有文件做代码质量校验,其它的文件是不需要的。所以我们在工程目录 cus-react-demo
下再创建一个 .eslintignore
文件,列出那些不需要校验的文件列表:
touch .eslintignore
然后写入以下内容到 .eslintignore
文件:
node_modules/*
public/*
dist/*
webpack.config.js
.eslintrc.js
ok!万事都已俱备。
然后我们重新运行项目:
npm start
可以看到,终端中报了一些警告,我们尝试修复一下这些警告。
为了方便,我们在 package.json
文件中声明一个 lint
脚本:
"name": "cus-react-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts":
"test": "echo \\"Error: no test specified\\" && exit 1",
"build": "rimraf dist && cross-env NODE_ENV=production webpack --mode=production",
"start": "cross-env NODE_ENV=development webpack serve --mode=development --progress",
"lint": "eslint --ext .js,.mjs,.jsx,.ts,.tsx --fix ./src"
,
"author": "",
"license": "ISC",
"devDependencies":
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"@webpack-cli/serve": "^1.3.0",
"autoprefixer": "^9.8.6",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.2",
"babel-preset-react-app": "^10.0.0",
"cross-env": "^7.0.3",
"css-loader": "^5.1.3",
"cssnano": "^4.1.10",
"eslint": "^7.22.0",
"eslint-config-react-app": "^6.0.0",
"eslint-plugin-flowtype": "^5.4.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-webpack-plugin": "^2.5.2",
"html-webpack-plugin": "^5.3.1",
"mini-css-extract-plugin": "^1.3.9",
"postcss-loader": "^5.2.0",
"sass": "^1.32.8",
"sass-loader": "^11.0.1",
"typescript": "^4.2.3",
"webpack": "^5.26.3",
"webpack-chain": "^6.5.1",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^3.11.2"
,
"dependencies":
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.2",
"react": "^17.0.1",
"react-dom": "^17.0.1"
然后我们在工程目录 cus-react-demo
执行 npm run lint
脚本去修复当前项目代码:
npm run lint
运行过后,ESLint 会自动帮我们修复掉了一些格式方面的问题。
从这里也可以看出,ESLint 不但可以发现我们代码中的一些问题,还能自动帮我们解决大部分语法、格式等问题。但也很多小伙伴是很反感 ESLint 的,因为他们觉得有了 ESLint 后,代码变得难写多了,但我想说的是 “真的代码难写了?还是你写出来的代码本来就问题呢?”。
ok!警告解决完毕后,我们再次执行 npm start
的时候就会发现,没有错误和警告信息了:
npm start
一般我们在平时开发中,为了更好的显示代码规范错误信息,我们直接利用 webpack.devServer
的 overlay
选项将 webpack 的报错跟警告显示到页面中去,所以我们修改一下 webpack.config.js
文件:
...
.devServer
.host("0.0.0.0") // 为了让外部服务访问
.port(8090) // 当前端口号
.hot(true) // 热载
.open(true) // 开启页面
.overlay(
warnings: true,
errors: true
) // webpack 错误和警告信息显示到页面
...
比如我们现在项目中有代码不符合我们的代码规范:
可以看到,页面中提示了 ”编译失败“,IDE
提示了 “语句结尾需要添加分号”,终端中照样提示了 “语句结尾需要添加分号”,这样就很好的保持了项目代码风格的一致性,在团队合作中还是很有必要的。
fork-ts-checker-webpack-plugin
校验 ts 语法,检测 ts 语法中的一些报错并且通过 webpack 在终端中打印出来。
我们首先在工程目录 cus-react-demo
下执行以下命令进行安装:
npm install -D fork-ts-checker-webpack-plugin --registry https://registry.npm.taobao.org
安装完毕后,我们在 webpack.config.js
中将其引入:
.plugin('fork-ts-checker') // 配置 fork-ts-checker
.use(require('fork-ts-checker-webpack-plugin'), [
eslint:
files: './src/**/*.ts,tsx,js,jsx' // required - same as command `eslint ./src/**/*.ts,tsx,js,jsx --ext .ts,.tsx,.js,.jsx`
,
typescript:
extensions:
vue:
enabled: true,
compiler: "vue-template-compiler"
,
])
webpack.config.js
全部配置:
const path = require('path');
const config = new (require('webpack-chain'))();
const isDev = process.env.NODE_ENV === 'development'; // 判断是否是开发环境
config
.target('web')
.context(path.resolve(__dirname, '.')) // webpack 上下文目录为项目根目录
.entry('app') // 入口文件名称为 app
.add('./src/main.tsx') // 入口文件为 ./src/main.tsx
.end()
.output
.path(path.join(__dirname, './dist')) // webpack 输出的目录为根目录的 dist 目录
.filename(isDev ? '[name].[hash:8].js' : '[name].[contenthash:8].js') // 打包出来的 bundle 名称为 "[name].[contenthash:8].js"
.publicPath('/') // publicpath 配置为 "/"
.end()
.resolve
.extensions.add('.js').add('.jsx').add('.ts').add('.tsx').end() // 添加后缀自动解析
.end()
.module
.rule('ts') // 配置 typescript
.test(/\\.(js|mjs|jsx|ts|tsx)$/)
.exclude
.add(filepath =>
// Don't transpile node_modules
return /node_modules/.test(filepath)
)
.end()
.use('babel-loader')
.loader('babel-loader')
.end()
.end()
.rule('sass') // sass-loader 相关配置
.test(/\\.(sass|scss)$/) // Sass 和 Scss 文件
.use('extract-loader') // 提取 css 样式到单独 css 文件
.loader(require('mini-css-extract-plugin').loader)
.end()
.use('css-loader') // 加载 css 模块
.loader('css-loader')
.end()
.use('postcss-loader') // 处理 css 样式
.loader('postcss-loader')
.end()
.use('sass-loader') // Sass 语法转 css 语法
.loader('sass-loader')
.end()
.end()
.end()
.plugin('extract-css') // 提取 css 样式到单独 css 文件
.use(require('mini-css-extract-plugin'), [
filename: isDev ? 'css/[name].css': 'css/[name].[contenthash].css',
chunkFilename: isDev ? 'css/[id].css': 'css/[name].[contenthash].css',
,
])
.end()
.plugin('html') // 添加 html-webpack-plugin 插件
.use(require('html-webpack-plugin'), [
template: path.resolve(__dirname, './public/index.html'), // 指定模版文件
chunks: ['app'], // 指定需要加载的 chunk
inject: 'body', // 指定 script 脚本注入的位置为 body
,
])
.end()
.plugin('eslint') // 添加 eslint-webpack-plugin 插件
.use(require('eslint-webpack-plugin')以上是关于快来跟我一起学 React(Day4)的主要内容,如果未能解决你的问题,请参考以下文章