React + TypeScript + Webpack项目构建(简版)
一、项目初始化
1. 创建项目文件夹
bash
mkdir react-webpack-demo
cd react-webpack-demo
2. 初始化 package.json
npm init -y
二、安装基础依赖
① React 相关依赖
npm install react react-dom
② Webpack 相关依赖
vbscript
npm install -D webpack webpack-cli webpack-dev-server
③ Babel(转译 JSX 和现代 JS)
bash
npm install -D @babel/core @babel/preset-env @babel/preset-react babel-loader
④ HTML 模板插件
css
npm install -D html-webpack-plugin
⑤ CSS 支持
npm install -D style-loader css-loader
⑥ 安装 TypeScript 相关依赖
bash
npm install -D typescript @babel/preset-typescript ts-loader
npm install -D @types/react @types/react-dom
三、目录结构
pgsql
react-demo/
├── package.json
└── /webpack
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js
├── tsconfig.json
├── .babelrc
├── /public
│ └── index.html
└── /src
├── index.tsx
├── App.tsx
└── style.css
四、Babel 配置(支持 ts / tsx)
修改 .babelrc
perl
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript"
]
}
这样 Babel 就可以转译 .ts
和 .tsx
文件了。
五、添加 tsconfig.json
在根目录创建 tsconfig.json
json
{
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"]
}
六、配置 Webpack
我们可以把 webpack 配置拆分为三份:
- 公共配置(common) :入口、输出、模块解析、Babel、HTML 插件等通用设置
- 开发配置(development) :css、devServer、sourceMap、热更新等
- 生产配置(production) :压缩、代码分割、提取 CSS、环境变量等
然后用 webpack-merge
来组合。
1️⃣ 安装依赖
sql
npm install -D webpack-merge cross-env mini-css-extract-plugin css-minimizer-webpack-plugin terser-webpack-plugin
2️⃣ 目录结构示意
webpack/
├── webpack.common.js
├── webpack.dev.js
├── webpack.prod.js
3️⃣ 公共配置(webpack.common.js)
js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.tsx",
output: {
path: path.resolve(__dirname, "../dist"),//`__dirname` 表示当前 webpack 配置文件所在的目录。`../dist` 回到项目根目录再生成
filename: "js/[name].js",
assetModuleFilename: "assets/[hash][ext][query]",
clean: true,
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"],
alias: {
"@": path.resolve(__dirname, "src"),
},
},
module: {
rules: [
// JS/TS 文件由 babel-loader 处理
{
test: /\.[jt]sx?$/,
exclude: /node_modules/,
use: "babel-loader",
},
// 图片等资源
{
test: /\.(png|jpg|jpeg|svg|gif)$/i,
type: "asset/resource",
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
],
};
4️⃣ 开发环境配置(webpack.dev.js)
js
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "development",
devtool: "eval-cheap-module-source-map",
module: {
rules: [
{
test: /\.css$/,
use: [
"style-loader", // 将 CSS 注入 <head>
"css-loader", // 解析 CSS
],
},
],
},
devServer: {
static: "./public",
port: 3000,
open: true,
hot: true,
historyApiFallback: true,
},
});
5️⃣ 生产环境配置(webpack.prod.js)
js
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const { DefinePlugin } = require("webpack");
module.exports = merge(common, {
mode: "production",
devtool: "source-map",
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, // 提取 CSS 到单独文件
"css-loader",
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash:8].css",
}),
new DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production"),
}),
],
optimization: {
minimize: true,
minimizer: [new TerserPlugin(), new CssMinimizerPlugin()],
splitChunks: {
chunks: "all",
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all",
},
},
},
},
});
七、HTML 模板
js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React + Webpack</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
八、React 入口文件
src/index.tsx
javascript
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import "./style.css";
const container = document.getElementById("root");
const root = createRoot(container!);
root.render(<App />);
src/App.tsx
javascript
import React from "react";
const App: React.FC = () => {
return (
<div>
<h1>React + TypeScript + Webpack ⚙️</h1>
<p>现在支持 TS / JSX 转译!</p>
</div>
);
};
export default App;
九、添加启动命令
修改 package.json
js
{
"scripts": {
"start": "cross-env NODE_ENV=development webpack serve",
"build": "cross-env NODE_ENV=production webpack"
},
"devDependencies": {
"cross-env": "^7.0.3"
}
}
安装 cross-env
:
sql
npm install -D cross-env
十、启动项目
开发模式
sql
npm start
生产构建
arduino
npm run build
输出到 /dist
文件夹,包含压缩后的 JS/CSS。
十一、 其他说明

