第一章、React + TypeScript + Webpack项目构建
React + TypeScript + Webpack项目构建(简版)
一、项目初始化
1. 创建项目文件夹
mkdir react-webpack-demo
cd react-webpack-demo
2. 初始化 package.json
npm init -y
二、安装基础依赖
① React 相关依赖
npm install react react-dom
② Webpack 相关依赖
npm install -D webpack webpack-cli webpack-dev-server
③ Babel(转译 JSX 和现代 JS)
npm install -D @babel/core @babel/preset-env @babel/preset-react babel-loader
④ HTML 模板插件
npm install -D html-webpack-plugin
⑤ CSS 支持
npm install -D style-loader css-loader
⑥ 安装 TypeScript 相关依赖
npm install -D typescript @babel/preset-typescript ts-loader
npm install -D @types/react @types/react-dom
三、目录结构
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
{"presets": ["@babel/preset-env","@babel/preset-react","@babel/preset-typescript"]
}
这样 Babel 就可以转译 .ts 和 .tsx 文件了。
五、添加 tsconfig.json
在根目录创建 tsconfig.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️⃣ 安装依赖
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)
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)
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)
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 模板
<!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
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
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
{"scripts": {"start": "cross-env NODE_ENV=development webpack serve","build": "cross-env NODE_ENV=production webpack"},"devDependencies": {"cross-env": "^7.0.3"}
}
安装 cross-env:
npm install -D cross-env
十、启动项目
开发模式
npm start
访问 http://localhost:3000
生产构建
npm run build
输出到 /dist 文件夹,包含压缩后的 JS/CSS。
十一、 其他说明


