从 0 开始配置 React
本文将使用Webpack5从 0 开始配置React说明相关概念及演示如何集成一系列工具。
版本信息
Webpack5
React18
TypeScript
初始化项目
准备目录webpack-react-ts, 在该文件夹下执行
yarn init -y
在该文件夹下创建目录及文件
├── README.md
├── config
│ ├── webpack.base.js # 公共配置
│ ├── webpack.dev.js # 开发配置
│ └── webpack.prod.js # 生产配置
├── public
│ └── index.html # html模版
└── src
│ └── index.tsx # react入口
├── tsconfig.json # ts配置
├── package.json
安装webpack依赖
yarn add -D webpack webpack-cli
安装react依赖
yarn add -S react react-dom
安装react类型依赖
yarn add -D @types/react @types/react-dom
安装typescript依赖
yarn add -D typescript
配置tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": false,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": ["./src"]
}
添加src/App/App.tsx内容
import React from "react";
function App() {
return <h1>webpack-react-ts</h1>;
}
export default App;
添加src/index.tsx内容
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App/App";
const root = document.getElementById("root");
if (root) {
createRoot(root).render(<App />);
}
格式化&类型检查
安装prettier依赖
yarn add -D prettier
配置prettier 新建.prettierrc.js,内容如下:
module.exports = {
printWidth: 100, // 一行的字符数,如果超过会进行换行
tabWidth: 2, // 一个tab代表几个空格数,默认就是2
useTabs: false, // 是否启用tab取代空格符缩进,.editorconfig设置空格缩进,所以设置为false
semi: false, // 行尾是否使用分号,默认为true
singleQuote: true, // 字符串是否使用单引号
trailingComma: "none", // 对象或数组末尾是否添加逗号 none| es5| all
jsxSingleQuote: true, // 在jsx里是否使用单引号,你看着办
bracketSpacing: true, // 对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
arrowParens: "avoid", // 箭头函数如果只有一个参数则省略括号
};
安装ESLint依赖
yarn add -D eslint
配置eslint 新建.eslintrc.js,内容如下:
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: "latest",
sourceType: "module",
},
plugins: ["react", "@typescript-eslint"],
rules: {
"@typescript-eslint/no-non-null-assertion": "off",
},
settings: {
react: {
version: "detect",
},
},
};
配置Webpack
修改webpack.base.js
- 配置入口文件
const path = require("path");
module.exports = {
// 入口文件
entry: path.join(__dirname, "../src/index.tsx"),
};
- 配置出口文件
const path = require("path");
module.exports = {
// ...
// 打包文件出口
output: {
// js名称
filename: "static/js/[name].js",
// 产物输出路径
path: path.join(__dirname, "../dist"),
// 清理产物文件夹
clean: true,
// 产物的公共路径
publicPath: "/",
},
};
- 配置
loader解析ts和jsx
由于webpack默认只能识别js文件,不能识别jsx语法,需要配置loader的预设预设 @babel/preset-typescript 来先将ts语法转换为 js 语法, 再借助预设 @babel/preset-react 来识别jsx语法。
安装babel核心模块和babel预设
yarn add -D babel-loader @babel/core @babel/preset-react @babel/preset-typescript
const path = require("path");
module.exports = {
// ...
module: {
rules: [
{
// 匹配.ts, tsx文件
test: /.(ts|tsx)$/,
use: {
loader: "babel-loader",
options: {
// 预设执行顺序由右往左,所以先处理ts,再处理jsx
presets: ["@babel/preset-react", "@babel/preset-typescript"],
},
},
},
],
},
};
- 配置
extensions
extensions是webpack的 resolve解析配置下的选项,在引入模块时不带文件后缀时,会来该配置数组里面依次添加后缀查找文件, 因为 ts 不支持引入以 .ts, tsx 为后缀的文件,所以要在 extensions 中配置,而第三方库里面很多引入 js 文件没有带后缀,所以也要配置下 js
module.exports = {
// ...
resolve: {
extensions: [".js", ".tsx", ".ts"],
},
};
这里只配置js, tsx和ts,其他文件引入都要求带后缀,可以提升构建速度。
- 添加
html-webpack-plugin插件
yarn add -D html-webpack-plugin
配置插件(webpack.base.js)
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
// 模版文件路径
template: path.resolve(__dirname, "../public/index.html"),
// 自动注入静态资源
inject: true,
}),
],
};
开发环境
- 安装
dev-server依赖及合并配置依赖
yarn add -D webpack-dev-server webpack-merge
- 修改
webpack.dev.js代码, 合并公共配置,并添加开发模式配置
const path = require("path");
const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.base.js");
// 合并公共配置,并添加开发环境配置
module.exports = merge(baseConfig, {
//开发模式
mode: "development",
// 源码调试模式
devtool: "eval-cheap-module-source-map",
devServer: {
// 服务端口号
port: 3000,
// gzip压缩,开发环境不开启,提升热更新速度
compress: false,
// 开启热更新,后面会讲react模块热替换具体配置
hot: true,
// 解决history路由404问题
historyApiFallback: true,
static: {
// 托管静态资源public文件夹
directory: path.join(__dirname, "../public"),
},
},
});
- 添加开发模式脚本
{
"scripts": {
"start": "webpack serve -c ./config/webpack.dev.js"
}
}
生产环境
- 修改
webpack.prod.js代码
const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.base.js");
module.exports = merge(baseConfig, {
// 生产模式
mode: "production",
});
- 添加生产模式脚本
{
"scripts": {
"build": "webpack serve -c ./config/webpack.dev.js"
}
}
样式配置
- 安装
loader以解析 css
yarn add -D style-loader css-loader
针对scss,额外安装
yarn add -D sass sass-loader
- 修改
webpack.base.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// 将 JS 字符串生成为 style 节点
"style-loader",
// 将 CSS 转化成 CommonJS 模块
"css-loader",
// 将 Sass 编译成 CSS
"sass-loader",
],
},
],
},
};
- 处理
css3前缀兼容
安装postcss-loader
yarn add -D postcss postcss-loader autoprefixer