从0到1:React项目中的Webpack配置实战

2024-08-26 06:52

本文主要是介绍从0到1:React项目中的Webpack配置实战,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

公司项目一般都是使用集团封装好的脚手架,脚手架内部实现咱看不到也摸不着,好不容易组内推行新的UI框架,需要自行定义 webpack 配置,这可是个绝佳的好机会,我对配置过程进行了梳理,把商业项目的成熟配置小跑着送上。

初始化

首先新建一个空文件夹,执行 npm init初始化生成 package.json 文件。

创建 src 文件夹,项目的业务代码都放在这里,再创建 index.js,这是项目的入口文件,待会使用 webpack 来打包项目,就从 index.js 文件开始。

大家都知道,webpack 在开发和生产时部分配置是不同的,比如在开发时,我们希望代码能够即改即生效,能够立马在页面中看到效果,需要 devServer 来帮助我们实现,而在开发中,我们希望能对 node_modules 资源进行分包,需要借助 splitChunks 属性,而还有一些属性是开发和生产共用的,比如 js 、css 资源的处理。

创建 webpack-config 文件夹,里面包含 webpack.dev.js,webpack.prod.js,webpack.base.js,分别定义 webpack 的开发环境、生产环境、公共的配置。

公共配置

开发和生产的配置都需要依赖公共配置,所以我们首先来定义 webpack.base.js。

项目入口/出口

执行 npm install webpack webpack-cli安装 webpack 基础依赖,再定义 webpack 配置文件的基础框架,entry 定义项目入口文件,output 定义编译后的出口,我们把编译后文件放在项目根目录的 dist 文件夹下。

const path = require("path");
module.exports = {entry: "./src/index.js",output: {path: path.join(__dirname, "../dist"),filename: "[name].[contenthash:8].js",},module: {},plugins: [],
};
样式资源

module 中放置各种文件的 loader 处理规则,首先处理样式资源,我们项目中通常使用 scss 来作为项目的预处理器,所以这里指定 css 及 scss 处理方式(less 或其他预处理器同理)。

执行 npm install sass sass-loader postcss postcss-loader postcss-preset-env css-loader mini-css-extract-plugin --save指令,安装所需要的 loader 和 plugin。

css 和 scss 文件的区别仅在于 scss 需要先通过 sass-loader 处理为 css 资源,其他的配置是一致的,这里提取到 commonStyleLoader。

const MiniCssExtractPlugin = require("mini-css-extract-plugin");module.exports = {module: {rules: [{test: /\.css$/,exclude: /node_modules/,use: commonStyleLoader,},{test: /\.scss$/,exclude: /node_modules/,use: [...commonStyleLoader, "sass-loader"],},],},plugins: [new MiniCssExtractPlugin({filename: "style/[name].[contenthash:8].css",}),],
};

再来看处理 sass 和 css 资源的公共 loader,首先使用 postcss-loader 进行兼容性处理,然后通过 css-loader 解析 css 语法,最后通过 mini-css-extract-plugin 的将 css 从 js 中分离出来并生成新的 css 文件,也就是下面代码的 MiniCssExtractPlugin.loader 和上面代码的 new MiniCssExtractPlugin 操作 。

const commonStyleLoader = [MiniCssExtractPlugin.loader,"css-loader",{loader: "postcss-loader",options: {postcssOptions: {plugins: ["postcss-preset-env"],},},},
];

另外,postcss-loader 在进行兼容性处理的时候,需要配置 browserslist 来告知兼容的要求,可以直接定义在 package.json中,开发环境兼容要求为近一个版本的chrome/safari/firefox浏览器,生产环境兼容市场份额大于 0.2% 且活跃的浏览器。

"browserslist": {"development": ["last 1 chrome version","last 1 safari version","last 1 firefox version"],"production": [">0.2%","not dead"]}
js/jsx

js 和 react 需要使用的 jsx 资源的处理方式相同,都使用 babel-loader,所以可以一起来定义 loader 匹配规则。

执行 npm install babel @babel/core babel-loader @babel/preset-env core-js@3 @babel/preset-react --save指令来安装相关资源。

module.exports = {module: {resolve: {extensions: [".jsx", ".js", ".json"],},rules: [{test: /\.(js|jsx)$/,exclude: /node_modules/,use: ["babel-loader"],},],},
};

extensions 中配置上常用文件后缀名,这样引入jsx文件时,就可省略后缀。

babel-loader 使用 babel 工具 来处理资源,需要配置处理规则,babel 中有很多 pluginspresets,presets 包括很多 plugins,所以直接配置 presets 会方便很多。

新增 babel.config.js 文件,使用 @babel/preset-react 处理 react 资源,通过 @babel/preset-env 处理 js 资源,再添加 corejs 的配置增加 js 兼容处理 polyfills

module.exports = {presets: [["@babel/preset-env",{useBuiltIns: "usage",corejs: 3,},],"@babel/preset-react",],
};
图片

在 webpack5 之前,处理字体图片等资源需要通过 url-loaderfile-loader,webpack5 新增 asset module type,通过4种新的模块类型替代以前的loader。

module.exports = {module: {rules: [{test: /\.(jp(e)g|png|gif)$/,type: "asset",parser: {dataUrlCondition: {maxSize: 8 * 1024,},},generator: {filename: "img/[name].[contenthash:8].[ext]",},},],},
};

其中模块类型 asset 替代 url-loader,可以自行定义根据图片大小导出资源为 Data URI 内联到 js 文件中,还是生成一个单独的文件,这里定义以资源大小 8kb 为分界线。

html

html 文件处理非常的简单,通过 html-webpack-plugin 生成 HTML 文件并注入 webpack 输出的 javaScript 文件和 css 文件即可。

const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {plugins: [new HtmlWebpackPlugin({template: "./public/index.html",inject: "body",minify: {collapseWhitespace: true,},}),],
};

可以在 plugin 中配置模板、引入 webpack 输出 js 资源的地址、压缩方式。

运行测试

以上就完成了公共配置部分,现在我们来测试一下配置是否生效。

在 public 目录下创建 index.html 文件,初始化之后在 body 标签中增加 react 需要的挂载容器。

<div id="container"></div>

再执行 npm install react react-dom --save指令,在 src/index.js 文件中定义渲染逻辑

import React from 'react';
import ReactDom from 'react-dom';
import App from './App';
ReactDom.render(<App/>, document.getElementById('container'))

然后在 src 目录下新建 App.js,里面随意编写 jsx 代码。

再通过命令行工具执行 npx webpack -c webpack-config/webpack.base.js,运行结果没有报错就代表配置正确啦~ 有 warning ⚠ The ‘mode’ option has not been set 是没关系的,后续结合开发环境和生产环境的配置一起执行时,mode 属性会被配置上。

开发环境配置

开发环境的配置很简单,只要使用 webpack-dev-server 开启本地服务就行。

执行 npm install webpack-dev-server webpack-merge -D指令安装依赖,在 config.dev.js 中定义开发时所需要的配置。

使用 webpack-merge 工具来合并 webpack.base.js 中的公共配置,将 dev 配置和公共配置合并导出。

const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.base");const devConfig = {mode: "development",devServer: {open: true,port: 8001,compress: true,hot: true},
};
module.exports = merge(devConfig, baseConfig);

运行命令 npx webpack serve -c ./webpack-config/webpack.dev.js,如果能在浏览器自动打开 http://localhost:8001 页面就表示开发环境配置成功。

我们通常会把指令配置到 package.json 文件的 script 属性中,执行起来更为方便。

"scripts": {"dev": "webpack serve -c ./webpack-config/webpack.dev.js"
}

这样,在命令行工具中,我们只需要执行 npm run dev即可。

生产环境配置

生产环境配置的框架和开发环境类似,都是使用 webpack-merge 合并公共配置

const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.base");const prodConfig = {mode: "production",
};
module.exports = merge(prodConfig, baseConfig);

当 mode 定义为 production 时,webpack 会自动给我们做一些代码压缩和 tree shaking 等操作,我们可以自己再对编译出来的 js 和 css 文件进行压缩。

js/css压缩

执行 npm install css-minimizer-webpack-plugin terser-webpack-plugin clean-webpack-plugin --save指令安装依赖。

使用 css-minimizer-webpack-plugin 压缩 css 资源,通过 terser-webpack-plugin 开启多进程并发运行以提高构建速度。

const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin");
const TerserWebpackPlugin = require("terser-webpack-plugin");const prodConfig = {optimization: {minimizer: [new CssMinimizerWebpackPlugin(),new TerserWebpackPlugin({parallel: true,}),],},
};
splitChunks

目前除了异步加载引入的模块,其他的内容都打包在了一个入口文件中,其中包含 node_modules 中使用到的依赖,如 React、RecatDom 等,这些依赖通常是不会变化的,打包到一个公共的文件中,可以利用浏览器的缓存策略,不需要每次都重新拉取资源。

const prodConfig = {optimization: {splitChunks: {chunks: "all",cacheGroups: {vendor: {test: /[\\/]node_modules[\\/]/,filename: '[name].bundle.js'},},},},
};

这样 node_modules中使用到的资源文件会被打包成一个以 bundle.js 结尾的文件

clean-webpack-plugin

当我们执行 npm run build后,编译后文件会放到 dist 文件夹下,为了避免 dist 文件夹内容越来越来多不便查看,每次我们都要手动删除文件夹,非常不方便。clean-webpack-plugin 可以帮助我们解决这个问题。

const { CleanWebpackPlugin } = require('clean-webpack-plugin')const prodConfig = {plugins: [new CleanWebpackPlugin()]
};
externals

有些资源,我们会使用稳定可靠的 cdn 资源,提升页面加载速度,减少打包出来的 bundle 体积,这时候就要配合 externals 使用。

如在 index.html 页面引入 react、react-dom

    <script src="https://cdn.bootcdn.net/ajax/libs/react/18.0.0/umd/react.production.min.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/react-dom/18.0.0/umd/react-dom.production.min.js"></script>

在 webpack.prod.js 中定义 externals,告诉 webpack 当遇到 react、react-dom 时,不要将其打包,期望在全局环境中找到 React、ReactDOM 的配置。

const prodConfig = {externals: {react: "React","react-dom": "ReactDOM",},
};

同样,将生产环境的编译指令配置到 package.json 文件的 script 属性中。

"scripts": {"build": "webpack -c ./webpack-config/webpack.prod.js"
}

这样,在命令行工具中,我们只需要执行 npm run build即可查看编译产物。

总结

在真实的开发场景,还有生产模式使用 CopyWebpackPlugin 在构建过程复制文件到输出目录,不经过 webpack 打包的情况,也有根据项目部署域名来定义 publicPath 的情况。这些都比较定制化,不同项目使用的配置也不相同。

另外还有前端工程化的配置大家也可以加上,如 eslint、prettier、stylelint、git hooks,为react项目添加开发/提交规范中有详细的讲述,可点击查看。

以上就是开发和生产环境的基础配置,大家可以在这个基础上增加自己项目的不同配置。更多有关 前端工程化的内容可以参考我其它的博文,持续更新中~

附上完整配置代码。

webpack.base.js 文件

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const commonStyleLoader = [MiniCssExtractPlugin.loader,"css-loader",{loader: "postcss-loader",options: {postcssOptions: {plugins: ["postcss-preset-env"],},},},
];
module.exports = {entry: "./src/index.js",output: {path: path.join(__dirname, "../dist"),filename: "[name].[contenthash:8].js",},resolve: {extensions: [".jsx", ".js", ".json"],},module: {rules: [{test: /\.css$/,exclude: /node_modules/,use: commonStyleLoader,},{test: /\.scss$/,exclude: /node_modules/,use: [...commonStyleLoader, "sass-loader"],},{test: /\.(js|jsx)$/,exclude: /node_modules/,use: ["babel-loader"],},{test: /\.(jp(e)g|png|gif)$/,type: "asset",parser: {dataUrlCondition: {maxSize: 8 * 1024,},},generator: {filename: "img/[name].[contenthash:8].[ext]",},},],},plugins: [new MiniCssExtractPlugin({filename: "style/[name].[contenthash:8].css",}),new HtmlWebpackPlugin({template: "./public/index.html",inject: 'body',minify: {collapseWhitespace: true,}}),],
};

webpack.dev.js 文件

const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.base");
const devConfig = {mode: "development",devServer: {open: true,port: 8001,compress: true,hot: true},
};
module.exports = merge(devConfig, baseConfig);

webpack.prod.js 文件

const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.base");
const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin");
const TerserWebpackPlugin = require("terser-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const prodConfig = {mode: "production",optimization: {minimizer: [new CssMinimizerWebpackPlugin(),new TerserWebpackPlugin({parallel: true,}),],splitChunks: {chunks: "all",cacheGroups: {vendor: {test: /[\\/]node_modules[\\/]/,filename: "[name].bundle.js",},},},},externals: {react: "React","react-dom": "ReactDOM",},plugins: [new CleanWebpackPlugin()],
};
module.exports = merge(prodConfig, baseConfig);

这篇关于从0到1:React项目中的Webpack配置实战的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1107861

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

CentOS7安装配置mysql5.7 tar免安装版

一、CentOS7.4系统自带mariadb # 查看系统自带的Mariadb[root@localhost~]# rpm -qa|grep mariadbmariadb-libs-5.5.44-2.el7.centos.x86_64# 卸载系统自带的Mariadb[root@localhost ~]# rpm -e --nodeps mariadb-libs-5.5.44-2.el7

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

hadoop开启回收站配置

开启回收站功能,可以将删除的文件在不超时的情况下,恢复原数据,起到防止误删除、备份等作用。 开启回收站功能参数说明 (1)默认值fs.trash.interval = 0,0表示禁用回收站;其他值表示设置文件的存活时间。 (2)默认值fs.trash.checkpoint.interval = 0,检查回收站的间隔时间。如果该值为0,则该值设置和fs.trash.interval的参数值相等。

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p