webpack5项目搭建React-Cli(开发模式)

Posted 天界程序员

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack5项目搭建React-Cli(开发模式)相关的知识,希望对你有一定的参考价值。

step1–新建项目目录

创建一个新的目录,用于搭建React项目。

mkdir react-cli
cd react-cli

step2–初始化项目

初始化项目生成package.json文件。

npm init -y

step3–新建webpack开发模式配置文件

新建config目录文件夹,在创建开发配置文件,并定义好初始配置结构。

文件名:webpack.dev.js

module.exports = 
  // 入口
  entry: '',

  // 输出
  output: '',

  // 存放loader的module
  module: 
    rules: []
  ,

  // 需要加载的插件plugins
  plugins: [],

  // 关于压缩的配置项
  optimization: ,

  // 开发模式mode
  mode: 'development'

step4–详细配置开发模式

1、指定入口文件

entry: './src/main.js'

2、指定输出目录以及文件命名

output: 
    path: undefined, // 开发环境不需要打包,可以设置路径为undefined
    filename: 'static/js/[name].js', // 指定bundle资源的路径以及命名
    chunkFilename: 'static/js/[name].chunk.js', // 一般是动态导入的一些资源
    assetModuleFilename: 'static/media/[hash:10][ext][query]', // 一些静态资源如图片等
,

3、配置loader用于处理为webpack可识别的资源

需要处理的有css资源、图片资源、js资源。

  • 处理css资源

主要的loader有:style-loadercss-loaderless-loadersass-loaderstylus-loader

处理样式的兼容性:postcss-loader

配置兼容的程度:需要在package.json里面配置browserslist属性

1、封装通用样式处理loader函数

由于样式文件有多种(.css|.less|.sass|.scss|.styl),一个个配置会代码冗余,所以使用通用函数来复用代码,减少配置代码的冗余。

// 处理样式loader的通用函数
const getStyleLoader = (pre) => 
  return [
    'style-loader','css-loader',
      // 处理css兼容性
      // 需要配合package.json的browserlist属性来决定兼容性
      loader: 'postcss-loader',
      options: 
        postcssOptions: 
          plugins: ['postcss-preset-env']
        
      
    ,
    pre
  ].filter(Boolean)

2、结合通用函数配置样式loader

  module: 
    rules: [
      
        test: /\\.css$/i, // 以css结尾的文件
        use: getStyleLoader()
      ,
      
        test: /\\.less$/i, // 以less结尾的文件
        use:getStyleLoader('less-loader')
      ,
      
        test: /\\.s[ac]ss$/i, // 以sass/scss结尾的文件
        use:getStyleLoader('sass-loader')
      ,
      
        test: /\\.styl$/i, // 以styl结尾的文件
        use:getStyleLoader('stylus-loader')
      
    ]
  ,

3、配置browserlist

 "browserslist": [
    "last 2 version",
    "> 1%",
    "not dead"
  ]  
  • 处理图片资源
 // 处理图片资源

  test: /\\.(jpe?g|png|webp|svg|gif)$/,
  type: 'asset',
  parser: 
    dataUrlCondition: 
      maxSize: 10 * 1024, // 当图片小于10kb时转为base64
    
  
,
  • 处理其他资源
// 处理其他资源

  test: /\\.(woff2?|ttf|mp3|mp4)$/,
  type: 'asset/resource'

  • babel处理js|jsx资源
// webpack.dev.js
const path = require('path')

//...省略


  test: /\\.(jsx|js)$/,
  include: path.resolve(__dirname, "../src"),
  loader: "babel-loader",
  options: 
    cacheDirectory: true,
    cacheCompression: false,
    plugins: [
      // "@babel/plugin-transform-runtime", // presets中包含了
      "react-refresh/babel", // 开启js的HMR功能
    ],
  ,
,
  • 编写babel配置文件
// babel.config.js
module.exports = 
  // 使用react官方规则
  presets: ["react-app"],
;
  • ESlint监测语法插件
// webpack.dev.js
const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");

//...省略

plugins: [
    new ESLintWebpackPlugin(
      context: path.resolve(__dirname, "../src"),
      exclude: "node_modules", // 排除的目录
      cache: true, // 开启缓存
      cacheLocation: path.resolve(
        __dirname,
        "../node_modules/.cache/.eslintcache"
      ),
    ),
]
  • 编写ESlint配置文件
// .eslintrc.js
module.exports = 
  extends: ["react-app"], // 继承 react 官方规则
  parserOptions: 
    babelOptions: 
      presets: [
        // 解决页面报错问题
        ["babel-preset-react-app", false],
        "babel-preset-react-app/prod",
      ],
    ,
  ,
;
  • 处理HTML资源
// webpack.dev.js
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
//...省略
 plugins: [
    new ESLintWebpackPlugin(
      context: path.resolve(__dirname, "../src"),
      exclude: "node_modules",
      cache: true,
      cacheLocation: path.resolve(
        __dirname,
        "../node_modules/.cache/.eslintcache"
      ),
    ),
    new HtmlWebpackPlugin(
      template: path.resolve(__dirname, "../public/index.html"),
    ),
]
  • 设定开发模式
// webpack.dev.js
// 开发模式mode
mode: 'development'
  • 配置sourceMap
// webpack.dev.js
devtool: "cheap-module-source-map"
  • 配置代码分割
 optimization: 
    splitChunks: 
      chunks: "all",
    ,
    runtimeChunk: 
      name: (entrypoint) => `runtime~$entrypoint.name`,
    ,
  ,
  • 开发模式自动化服务器配置
devServer: 
    open: true,
    host: "localhost",
    port: 3000,
    hot: true,
    compress: true,
    historyApiFallback: true, // 解决react-router刷新404问题
,

step5–编写react文件

  • src/main.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";


const root = ReactDOM.createRoot(document.getElementById("app"));
root.render(
    <App />
);
  • src/App.jsx
import React from "react";
function App() 
  return (
    <div>
      <h1>App</h1>
    </div>
  );


export default App;
  • public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>React</title>
</head>
<body>
  <div id="app"></div>
</body>
</html>

step6–安装所需依赖

  • webpack相关依赖
npm i webpack webpack-cli webpack-dev-server -D
  • 资源处理相关
npm i eslint-webpack-plugin -D
npm i html-webpack-plugin -D
npm i style-loader css-loader less-loader sass-loader sass stylus-loader -D
npm i postcss-loader postcss-preset-env -D

npm i babel-loader @babel/core babel-preset-react-app eslint-config-react-app -D
  • react相关
npm i react react-dom 

step7–启动项目

  • 编写启动命令
  "scripts": 
    "start": "npm run dev",
    "dev": "webpack serve --config ./config/webpack.dev.js"
  ,
  • 运行项目
npm start
  • 报错
Error: [BABEL] D:\\MyWorkSpace\\VUE3_WORKSPACE\\react-cli\\node_modules\\webpack-dev-server\\client\\index.js: Using `babel-preset-react-app` requires that you specify `NODE_ENV` or `BABEL_ENV` environment variables. Valid values are "development", "test", and "production". Instead, received: undefined.
  • 解决方案

1、安装cross-env

npm i cross-env -D

2、修改启动命令

 "scripts": 
    "start": "npm run dev",
    "dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.dev.js"
  ,

将开发环境变量传给配置

  • 再次启动
npm start
  • 遇到新的错误
ERROR in ./src/main.js 4:0-24
Module not found: Error: Can't resolve './App' in 'D:\\MyWorkSpace\\VUE3_WORKSPACE\\react-cli\\src'
resolve './App' in 'D:\\MyWorkSpace\\VUE3_WORKSPACE\\react-cli\\src'

原因是后缀为jsx的文件,webpack无法识别。

  • 解决方案-修改配置增加扩展名
 resolve: 
    extensions: [".jsx", ".js", ".json"], // 自动补全文件扩展名,让jsx可以使用
 ,

再次启动就可以正常运行了。


step8–激活HMR功能

css默认在style-loader里面就已经激活了HMR功能,我们只需要激活js的HMR功能就好。

  • 安装依赖
npm install -D @pmmmwh/react-refresh-webpack-plugin react-refresh
  • 配置

1、配置babel-loader


        test: /\\.(js|jsx)$/,
        loader: 'babel-loader',
        options: 
          cacheDirectory: true,
          cacheCompression: false,
          plugins: [
            // "@babel/plugin-transform-runtime", // presets中包含了
            require.resolve('react-refresh/babel'), // 开启js的HMR功能
          ],
        ,
      

2、开启插件

plugins: [
    // ...省略
    new ReactRefreshWebpackPlugin(), // 解决js的HMR功能运行时全局变量的问题
]

step9–解决react-router刷新404问题

  • 修改文件

1、src/main.js

import React from 'react'
import ReactDOM from 'react-dom/client'
import BrowserRouter from 'react-router-dom'
import App from './App'
 //..
const root = ReactDOM.createRoot(document.getElementById('app'))
root.render(<div>
  <BrowserRouter>
  <App />
  </BrowserRouter>
  
</div>)

2、src/App.jsx

import React from "react";
import Link, Route, Routes from "react-router-dom"

import Home from "./pages/home"
import About from "./pages/about"

function App() 
  return (
    <div>
      <h1>App1</h1>

      <ul>
        <li><Link to="/home">Home</Link></li>
        <li><Link to="/about">About</Link></li>
      </ul>

      <Routes>
          <Route path="/home" element=<Home /> />
          <Route path="/about" element=<About /> />
      </Routes>
    </div>
  );


export default App;

3、src/pages/home/index.jsx

import React from "react";

export default function Home() 
  return <h1>Home~~~</h1>;


4、src/pages/about/index.jsx

import React from "react";

export default function Home() 
  return <h1 >about~~~</h1>;


  • 安装依赖
npm i react-router-dom
  • 启动项目
npm run dev

在浏览器可以切换路由,但是在路由下刷新页面会出现404错误。

GET http://localhost:3000/home 404 (Not Found)
  • 解决方案
devServer: 
    //...
    historyApiFallback: true, // 解决react-router刷新404问题

重新启动项目即可。


step10–关于react的路由懒加载

  • 修改文件

1、src/App.jsx

import React,  Suspense, lazy  from 'react'
import  Link, Route, Routes  from 'react-router-dom'

// import Home from './pages/home'
// import About from './pages/about'

const Home = lazy(()=>import(/*webpackChunkName: 'Home'*/"./pages/home"))
const About = lazy(()=>import(/*webpackChunkName: 'About'*/"./pages/about"))

function App() 
  return (
    <div>
      <h1>App1</h1>

      <ul>
        <li>
          <Link to="/home">Home</Link>
        </li>
        <li>
          <Link to="/about">About</Link>
        </li>
      </ul>

      <Suspense fallback=<div>loading...</div>>
        <Routes>
          <Route path="/home" element=<Home /> />
          <Route path="/about" element=<About /> />
        </Routes>
      </Suspense>
    </div>
  )


export default App

  • 启动项目
npm run dev

开启懒加载后,其路由代码会被单独打包到一个chunk里面,实现按需加载。


step11–现阶段的详细开发模式配置

const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
// 处理样式loader的通用函数
const getStyleLoader = (pre) => 
  return [
    'style-loader','css-loader',
      // 处理css兼容性
      // 需要配合package.json的browserlist属性来决定兼容性
      loader: 'postcss-loader',
      options: 
        postcssOptions: 
          plugins: ['postcss-preset-env']
        
      
    ,
    pre
  ].filter(Boolean)



module.exports = 
  // 入口
  entry: './src/main.js',

  // 输出
  output: 
    path: undefined, // 开发环境不需要打包,可以设置路径为undefined
    filename: 'static/js/[name].js'

以上是关于webpack5项目搭建React-Cli(开发模式)的主要内容,如果未能解决你的问题,请参考以下文章

webpack5项目搭建React-Cli(配置合并)

webpack5项目搭建React-Cli(配置优化)

webpack5项目搭建Vue-Cli(生产环境)

webpack5项目搭建Vue-Cli(开发模式)

webpack5项目搭建Vue-Cli(合并配置)

Webpack5 搭建一个简易的 React+TS 开发环境