# react18-webpack5-demo **Repository Path**: kayanchan/react18-webpack5-demo ## Basic Information - **Project Name**: react18-webpack5-demo - **Description**: 在node=16.17.0的环境下,实现基于webpack5构建的react18项目框架。 同时也满足vite的构建。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-10-25 - **Last Updated**: 2025-01-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: React, webpack, vite ## README # React18-Webpack5-demo React 项目搭建方式: 1. 浏览器中通过标签直接引入 -- 不符合项目工程化 2. 使用官方脚手架 create-react-app -- webpack 配置默认不暴露 3. 使用 react、webpack 等自行搭建 -- 推荐,配置灵活 4. 使用 Next.js 构建全栈式 -- 官方推荐,需要学习 Next.js 本项目采用从 0 开始自行搭建,对配置过程进行记录。项目需满足在`node=16.17.0`环境下运行。 ## 初始化,基本配置 1. 新建项目文件夹 react18-webpack5-demo ```bash mkdir react18-webpack5-demo cd react18-webpack5-demo ``` 2. git 初始化 ```bash git init touch README.md git add README.md git commit -m '提交 README.md' git remote add origin git@gitee.com:kayanchan/react18-webpack5-demo.git git push -u origin "master" ``` 3. package.js 初始化 `yarn init` 4. 安装 webpack ```bash yarn add webpack webpack-cli -D # webpack 5.95.0 # webpack-cli 5.1.4 ``` 5. 安装 react ``` yarn add react react-dom ``` 6. 搭建项目目录 - config (配置目录) - webpack.config.base.js (webpack 公共配置) - webpack.config.dev.js (webpack 开发配置) - webpack.config.prod.js (webpack 生产配置) - public (静态目录) - index.html - src - components - pages - index.js 7. 安装 HtmlWebpackPlugin ```bash yarn add html-webpack-plugin -D # html-webpack-plugin 5.6.3 yarn add html-loader -D # 当前稳定版本(5.1.0)不兼容node环境 npm view html-loader engines # node: '>= 18.12.0' npm view html-loader@4.2.0 engines # node: '>= 14.15.0' yarn add html-loader@4.2.0 -D # 需要安装指定历史版本 ``` 8. 安装 babel ``` yarn add @babel/core babel-loader @babel/preset-env @babel/preset-react -D ``` 在根目录下建立.babelrc 文件,写入 babel 配置 ``` { "presets": ["@babel/preset-env", "@babel/preset-react"] } ``` 9. 安装 WDS ```bash yarn add webpack-dev-server@4.15.2 -D ``` 10. 编辑 package.json 的 scripts ```json "scripts": { "start": "webpack serve --mode development --config config/webpack.config.base.js --open", "build": "webpack --mode production --config config/webpack.config.base.js" } ``` 11. 编写 webpack 配置 - config/webpack.config.base.js ```javascript const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { entry: { index: "./src/index.js", }, output: { filename: "[name].bundle.js", path: path.resolve(__dirname, "..", "build"), }, plugins: [ new HtmlWebpackPlugin({ title: "react18-webpack5-demo", filename: "index.html", template: "./public/index.html", }), ], module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", }, }, { test: /\.html$/, use: { loader: "html-loader", }, }, ], }, }; ``` 12. 编写 html 模版 - public-index.html ```html Document
``` 13. 编写入口文件 - src/index.js ```javascript import React from "react"; import { createRoot } from "react-dom/client"; const App = () =>
Hello
; const root = createRoot(document.getElementById("app")); root.render(); ``` ## 环境分离 环境分离主要是区分本地和生产两种环境,本地调试需要能实时看到代码变化,而生产环境需要编译成指定的文件。 ### 方法一:开发环境和生产环境共用配置文件,通过参数来区分环境 1. 配置文件分离 package.json **开发环境和生产环境都使用 webpack.config.base.js 文件**,通过 package.json 中设置指令增加 --env 参数来区分 ```javascript "scripts": { "start": "webpack serve --config config/webpack.config.base.js --env development", "build": "webpack --config config/webpack.config.base.js --env production" } ``` 2. 在 webpack.config.base.js 中 module.exports 定义为函数,就可以接收 env 传递的参数 ```javascript module.exports = (env) => { // 赋值后可在 babel.config.js 中获取当前环境 process.env.NODE_ENV = env.production ? "production" : "development"; const config = env.production ? prodConfig : devConfig; }; ``` 3. 通过 webpack-merge 工具来对配置代码进行合并 ```javascript const { merge } = require("webpack-merge"); merge(baseConfig, config); ``` ### 方法二:开发环境和生产环境分别定义配置文件,在 package.json 中定义对应的指令 1. 配置文件分离 package.json ```json "scripts": { "start": "webpack serve --config config/webpack.config.dev.js --env development", "build": "webpack --config config/webpack.config.prod.js --env production" } ``` 2. 添加环境参数 ```javascript process.env.NODE_ENV = "development"; ``` 3. 在指定环境配置文件中,合并公共配置 ```javascript const { merge } = require("webpack-merge"); const baseConfig = require("./webpack.config.base"); const devConfig = {...}; module.exports = merge(baseConfig, devConfig); ``` ## 开发环境配置 1. 设置 mode `mode: 'development'` 2. 配置 devServer ## 生产环境配置 1. 设置 mode `mode: production` 2. 代码压缩、分包、优化 ## 样式资源 1. 安装所需要的包 ```bash # less yarn add less less-loader@11.1.4 # postcss yarn add postcss postcss-loader@4.3.0 postcss-preset-env@9.6.0 # css yarn add css-loader@6.11.0 # 样式处理 yarn add mini-css-extract-plugin style-loader ``` 2. commonStyleLoader: 提取相同的配置 ```javascript // 1. 使用 postcss-loader 进行兼容性处理 // 2. 通过 css-loader 解析 css 语法 const commonStyleLoader = [ isDevelopment && "style-loader", isProduction && MiniCssExtractPlugin.loader, "css-loader", { loader: "postcss-loader", options: { postcssOptions: { plugins: ["postcss-preset-env"], }, }, }, ]; ``` 3. 处理 less 和 css ```javascript { test: /\.css$/, exclude: /node_modules/, use: commonStyleLoader, }, { test: /\.less$/, exclude: /node_modules/, use: [...commonStyleLoader, "less-loader"], } ``` 4. mini-css-extract-plugin: 将 JS 中 import 导入的样式文件代码单独打包成一个 CSS 文件,适用于生产环境,减少 HTML 文件大小,可利用浏览器缓存 ```javascript new MiniCssExtractPlugin({ filename: "style/[name].[contenthash:8].css", }); ``` 5. style-loader‌: 将 JS 中 import 导入的样式文件代码打包到 JS 文件中,运行时将样式自动插入到 style 标签中,适用于开发环境 6. 在 package.json 设置兼容性要求 ```json "browserslist": { "development": [ "last 1 chrome version", "last 1 safari version", "last 1 firefox version" ], "production": [ ">0.2%", "not dead" ] } ``` ## babel 处理 js/jsx 1. 安装 babel 相关资源 - babel-loader 处理 js 和 jsx 文件 - @babel/preset-env 将高版本 js 编译成低版本 js - @babel/preset-react 编译 react 的 jsx 文件 - @babel/plugin-transform-runtime 抽离公共的辅助编译方法,减少构建后包的体积 - @babel/runtime-corejs3 添加 corejs 的配置增加 js 兼容处理 polyfills ```bash yarn add babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/plugin-transform-runtime @babel/runtime-corejs3 -D ``` 2. 在`.babelrc`添加 babel 配置 ``` { "presets": ["@babel/preset-env", "@babel/preset-react"], "plugins": [["@babel/plugin-transform-runtime", { "corejs": "3" }]] } ``` 3. 配置 webpack 的 extension ``` resolve: { extensions: [".jsx", ".js", ".json"], } ``` ## 图片 在 webpack5 之前,处理字体图片等资源需要通过 url-loader(将文件作为 data URI 内联到 bundle 中) 和 file-loader(将文件发送到输出目录 ) webpack5 新增 [asset module type](https://www.webpackjs.com/guides/asset-modules),通过 4 种新的模块类型替代以前的 loader ```javascript { test: /\.(jp(e)g|png|gif)$/, type: "asset", parser: { dataUrlCondition: { maxSize: 8 * 1024, // 8kb }, }, generator: { filename: "img/[name].[contenthash:8].[ext]" }, } ``` ## 开发配置 mode=development 1. 安装 webpack-dev-server `yarn add webpack-dev-server` 2. 在 webpack.config.dev.js 定义开发所需要的配置 3. 使用 webpack-merge 工具来合并 webpack.config.base.js 中的公共配置,将 dev 配置和公共配置合并导出 4. 在 package.json 文件的 script 属性中配置指令 ```json "scripts": { "dev": "webpack serve -c config/webpack.config.dev.js" } ``` 5. HMR 使用 webpack 插件 [react-refresh-webpack-plugin](https://github.com/pmmmwh/react-refresh-webpack-plugin) 实现 ## 生产配置 mode=production 当 mode 定义为 production 时,webpack 会自动给我们做一些代码压缩和 tree shaking 等操作,可以自己再对编译出来的 js 和 css 文件进行压缩 - 使用 css-minimizer-webpack-plugin 压缩 css 资源 - 通过 terser-webpack-plugin 开启多进程并发运行以提高构建速度 - splitChunks 将 node_modules 中使用到的依赖单独打包,利用浏览器缓存策略 - 设置 output.clean 为 true 来自动删除旧的输出文件(webpack4 需要使用插件 clean-webpack-plugin) - 配置 externals 来使用稳定可靠的 cdn 资源,提升页面加载速度,减少打包出来的 bundle 体积, 1. js/css 压缩 ```bash yarn add css-minimizer-webpack-plugin@5.0.1 terser-webpack-plugin ``` ```javascript const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const prodConfig = { optimization: { minimizer: [ new CssMinimizerWebpackPlugin(), new TerserWebpackPlugin({ parallel: true, }), ], }, }; ``` 2. 分包 ```javascript const prodConfig = { optimization: { splitChunks: { chunks: "all", cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, filename: "[name].bundle.js", }, }, }, }, }; ``` 3. externals webpack 配置中定义 externals,告诉 webpack 当遇到 react、react-dom 时,不要将其打包,期望在**全局环境**中找到 React、ReactDOM 的配置 ``` const prodConfig = { externals: { react: "React", "react-dom": "ReactDOM", }, }; ``` 在 index.html 页面引入 react、react-dom ``` ``` ## Tailwind CSS 1. 安装  Tailwind CSS `yarn add tailwindcss` 2. 创建 Tailwind CSS 配置文件 `npx tailwindcss init` 3. 添加 Tailwind CSS 到 PostCSS 配置中 ```javascript { loader: "postcss-loader", options: { postcssOptions: { plugins: ["postcss-preset-env", "tailwindcss"], }, }, } ``` 4. 配置模版路径 ```javascript /** @type {import('tailwindcss').Config} */ module.exports = { content: ["./src/**/*.{jsx,js}"], theme: { extend: {}, }, plugins: [], }; ``` 5. 添加 Tailwind CSS 指令到 CSS 文件 ```CSS /* index.css */ @tailwind base; @tailwind components; @tailwind utilities; ``` - **基础类(Base)**:定义了基本的样式规则,如 margin、padding、color、font-size 等。 - **组件类(Components)**:用于创建可复用的样式块,例如按钮、卡片等。 - **实用工具类(Utilities)**:包含了 Tailwind 的大部分功能,如布局、flex、grid、spacing、colors、typography、borders 等。 ## 优化 ### 开发环境 - [x] HMR 热替换 - [x] webpack-dev-server 本地服务器 - [x] soure-map 调试 - [ ] webpack-bundle-analyzer 打包生成代码块分析视图 - [ ] size-plugin 监控打包资源的体积变量化 - [ ] speed-measure-webpack-plugin 分析 loader 和 plugin 打包的耗时 ### 生产环境 - [x] mini-css-extract-plugin css 提取 - [x] css-minimizer-webpack-plugin css 压缩 - [x] html-webpack-plugin html 压缩 - [ ] externals 排除不需要被打包的第三方 - [x] terser-webpack-plugin js 压缩 - [x] tree-shake production 模式自动开启 - [x] code-split 代码分离 - [ ] import(懒加载,预加载) - [ ] 多线程打包 - [ ] dll 动态链 - [ ] babel 缓存 - [x] include、exclude 排除一些不需要编译的文件 ## vite ### 安装依赖 ```bash # 安装vite yarn add vite@4.3.0 -D # 安装react、react-dom yarn add react react-dom # 安装vite插件 # @vitejs/plugin-react 提供对 React 的支持,包括 JSX 转换、热模块替换(HMR)等功能 yarn add @vitejs/plugin-react -D # 兼容低版本浏览器,生成传统版本的 chunk 及与其相对应 ES 语言特性方面的 polyfill yarn add @vitejs/plugin-legacy@3.0.0-alpha.0 -D ``` ### vite.config.js ```javascript import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; const path = require("path"); export default defineConfig({ plugins: [react()], resolve: { alias: { "@": path.resolve(__dirname, "src"), }, }, }); ``` ### 入口文件 ```html react18-webpack5-demo
``` ### 产出实现 file 协议预览 ```bash node scripts/build.cjs ``` ### Tailwind CSS 1. 安装  Tailwind CSS `yarn add tailwindcss` 2. 创建 Tailwind CSS 配置文件 `npx tailwindcss init` 3. 添加 Tailwind CSS 到 vite 配置中 ```javascript import tailwindcss from "tailwindcss"; css: { postcss: { plugins: [tailwindcss()], }, }, ``` 4. 配置模版路径(tailwind.config.js) ```javascript /** @type {import('tailwindcss').Config} */ module.exports = { content: ["./src/**/*.{jsx,js}"], theme: { extend: {}, }, plugins: [], }; ``` 5. 添加 Tailwind CSS 指令到 CSS 文件 ```CSS /* index.css */ @tailwind base; @tailwind components; @tailwind utilities; ```