本篇承接 使用Webpack5搭建项目 

 

开发模式:

配置webpack.dev.js

新建项目,生成package.json文件,创建config文件夹,创建webpack.dev.js文件

配置webpack.dev.js

const path = require("path")

const EslintWebpackPlugin = require("eslint-webpack-plugin")

//返回处理样式的loader函数

getStyleLoaders=function(pre){

return[

"style-loader", "css-loader", {

//处理兼容性问题,配合package.json中的browserslist来指定兼容性做到什么程度

loader: "postcss-loader",

options: {

postcssOptions: {

plugins: ["postcss-preset-env"]

}

}

},

pre

].filter(Boolean)

}

module.exports = {

entry: "./src/main.js",

output: {

path: undefined,

filename: "static/js/[name].js",

chunkFilename: "static/js/[name].chunk.js",

assetModuleFilename: "static/media/[hash:10][ext][query]"

},

module: {

rules: [

// 处理css

{

test: /\.css$/,

use: getStyleLoaders(),

},

{

test: /\.less$/,

use: getStyleLoaders('less-loader'),

},

{

test: /\.s[ac]ss$/,

use: getStyleLoaders('sass-loader'),

},

{

test: /\.styl$/,

use: getStyleLoaders('stylus-loader'),

},

//处理图片

{

test:/\.(jpe?g|png|gif|webp|svg)/,

type:"asset",

parser:{

dataCondition:{

maxSize:10*1024, //小于10kb以下可以转为base64,减少请求数量

}

}

},

// 处理其他资源

{

test:/\.(woff2?|ttf)/,

type:"asset/resource",

},

//处理js

]

},

plugins:[

new EslintWebpackPlugin({

context:path.resolve(__dirname,'../src'),

exclude:'node_modules',

cache:true,

cacheLocation:path.resolve(__dirname,'../node_modules/.cache/.eslintcache')

})

]

}

配置package.json,browserslist

{

"name": "webpack-react",

"version": "1.0.0",

"description": "",

"main": "index.js",

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1"

},

"keywords": [],

"author": "",

"license": "ISC",

"browserslist":[

"last 2 version",

"> 1%",

"not dead"

]

}

创建并配置.eslintrc.js

module.exports={

extends:["react-app"], //继承官方react规则

parserOptions:{

babelOptions:{

presets:[

//解决页面报错的问题

["babel-preset-react-app",false],

"babel-preset-react-app/prod"

]

}

}

}

继续配置处理js文件

//处理js

{

test:/\.jsx?$/,

include:path.resolve(__dirname,'../src'),

loader:"babel-loader",

options:{

cacheDirectory:true,

cacheCompression:false

}

}

同时配置babel.config.js文件

module.exports={

presets:["react-app"] //内置了corejs,runtime插件,具体详情可以去github上查看。

}

添加HtmlWebpackPlugin,配置mode,以及devtool:

const path = require("path")

const EslintWebpackPlugin = require("eslint-webpack-plugin")

const HtmlWebpackPlugin = require("html-webpack-plugin")

//返回处理样式的loader函数

getStyleLoaders=function(pre){

return[

"style-loader", "css-loader", {

//处理兼容性问题,配合package.json中的browserslist来指定兼容性做到什么程度

loader: "postcss-loader",

options: {

postcssOptions: {

plugins: ["postcss-preset-env"]

}

}

},

pre

].filter(Boolean)

}

module.exports = {

entry: "./src/main.js",

output: {

path: undefined,

filename: "static/js/[name].js",

chunkFilename: "static/js/[name].chunk.js",

assetModuleFilename: "static/media/[hash:10][ext][query]"

},

module: {

...

plugins:[

...

new HtmlWebpackPlugin({

template:path.resolve(__dirname,"../public/index.html")

})

],

mode:"development",

devtool:"cheap-module-source-map"

}

配置代码分割:

optimization:{

splitChunks:{

chunks:"all" //代码分割

},

runtimeChunk:{

name:entrypoint=>`runtime~${entrypoint.name}.js` //单独储存引用的chunk的打包地址,main.js不会随着其他模块的变化导致地址变化而打包变化

}

}

配置devServer:

devServer:{

host:"localhost",

port:3000,

open:true,

hot:true

}

这就是目前的基本配置:

const path = require("path")

const EslintWebpackPlugin = require("eslint-webpack-plugin")

const HtmlWebpackPlugin = require("html-webpack-plugin")

//返回处理样式的loader函数

getStyleLoaders=function(pre){

return[

"style-loader", "css-loader", {

//处理兼容性问题,配合package.json中的browserslist来指定兼容性做到什么程度

loader: "postcss-loader",

options: {

postcssOptions: {

plugins: ["postcss-preset-env"]

}

}

},

pre

].filter(Boolean)

}

module.exports = {

entry: "./src/main.js",

output: {

path: undefined,

filename: "static/js/[name].js",

chunkFilename: "static/js/[name].chunk.js",

assetModuleFilename: "static/media/[hash:10][ext][query]"

},

module: {

rules: [

// 处理css

{

test: /\.css$/,

use: getStyleLoaders(),

},

{

test: /\.less$/,

use: getStyleLoaders('less-loader'),

},

{

test: /\.s[ac]ss$/,

use: getStyleLoaders('sass-loader'),

},

{

test: /\.styl$/,

use: getStyleLoaders('stylus-loader'),

},

//处理图片

{

test:/\.(jpe?g|png|gif|webp|svg)$/,

type:"asset",

parser:{

dataCondition:{

maxSize:10*1024, //小于10kb以下可以转为base64,减少请求数量

}

}

},

// 处理其他资源

{

test:/\.(woff2?|ttf)$/,

type:"asset/resource",

},

//处理js

{

test:/\.jsx?$/,

include:path.resolve(__dirname,'../src'),

loader:"babel-loader",

options:{

cacheDirectory:true,

cacheCompression:false

}

}

]

},

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")

})

],

mode:"development",

devtool:"cheap-module-source-map",

optimization:{

splitChunks:{

chunks:"all" //代码分割

},

runtimeChunk:{

name:entrypoint=>`runtime~${entrypoint.name}.js` //单独储存引用的chunk的打包地址,main.js不会随着其他模块的变化导致地址变化而打包变化

}

},

devServer:{

host:"localhost",

port:3000,

open:true,

hot:true

}

}

创建并配置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.jsx

import React from "react";

function App(){

return

App

}

export default App

创建并配置public/index.html文件

React Cli

开始下载依赖:

npm i eslint-webpack-plugin html-webpack-plugin style-loader css-loader postcss-loader postcss-preset-env less-loader sass-loader sass stylus-loader -D

npm i babel-loader @babel/core babel-preset-react-app eslint-config-react-app -D

npm i webpack-dev-server webpack webpack-cli -D

npm i react react-dom

 下载完成后,配置package.jason

"scripts": {

"start":"npm run dev",

"dev":"webpack serve --config ./config/webpack.dev.js"

},

输入指令:npm start ,页面报错了:

 这里需要babel-preset-app要求我们制定一个NODE_ENV或者BABEL_ENV的环境变量,我们下载cross-env的库设置环境变量:

npm install --save-dev cross-env

修改package.json:

"scripts": {

"start": "npm run dev",

"dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.dev.js"

},

输入npm start ,继续报错:

在引入的时候我们没有这里是对js文件有自动补全的功能,但这里是jsx文件,所以继续配置webpack.dev.js 

optimization:{

splitChunks:{

chunks:"all" //代码分割

},

runtimeChunk:{

name:entrypoint=>`runtime~${entrypoint.name}.js` //单独储存引用的chunk的打包地址,main.js不会随着其他模块的变化导致地址变化而打包变化

}

},

//webpack解析块加载选项

resolve:{

//自动补全文件拓展名

extensions:[".jsx",".js",".json"]

},

再次编译就没有问题了。

检测HMR热更新,样式文件是可以触发,但是js文件依旧不行,所以引用插件,react-refresh-webpack-plugin

npm install -D @pmmmwh/react-refresh-webpack-plugin react-refresh

配置webpack.dev.js

const path = require("path")

const EslintWebpackPlugin = require("eslint-webpack-plugin")

const HtmlWebpackPlugin = require("html-webpack-plugin")

const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');

...

module.exports = {

entry: "./src/main.js",

output: {

path: undefined,

filename: "static/js/[name].js",

chunkFilename: "static/js/[name].chunk.js",

assetModuleFilename: "static/media/[hash:10][ext][query]"

},

module: {

rules: [

...

//处理js

{

test:/\.jsx?$/,

include:path.resolve(__dirname,'../src'),

loader:"babel-loader",

options:{

cacheDirectory:true,

cacheCompression:false,

plugins:["react-refresh/babel"]//激活js文件HMR功能

}

}

]

},

plugins:[

...

new ReactRefreshWebpackPlugin()

],

...

}

 接下来是路由设置:App.jsx

import React from "react";

import Home from "../src/pages/Home/Home"

import {Link, Routes,Route} from "react-router-dom"

import About from './pages/About/About'

function App() {

return (

App

  • Home
  • About

}/>

}/>

)

}

export default App

import React from 'react'

export default function About() {

return (

About

)

}

import React from 'react'

import "./Home.less"

export default function Home() {

return (

Home

)

}

页面重新启动即可,但是刷新页面会有404的问题,解决方案:historyApiFallback,配置webapck.dev.js

devServer:{

host:"localhost",

port:3000,

open:true,

hot:true,

historyApiFallback:true//解决前端路由刷新404的问题

}

希望路由单独打包,需要配置路由懒加载:

import React, { Suspense, lazy } from "react";

// import Home from "../src/pages/Home/Home"

import { Link, Routes, Route } from "react-router-dom"

// import About from './pages/About/About'

const Home = lazy(() => import("./pages/Home/Home.jsx"))

const About = lazy(() => import("./pages/About/About.jsx"))

function App() {

return (

App

  • Home
  • About

loading...

}>

} />

} />