相关阅读:webpack5高级配置
案例代码仓库:Github地址
一、基本概念
1、概念
webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容
2、核心概念
(1)entry:入口配置
(2)output:输出配置
(3)module(loader):加载器配置
(4)plugin:插件配置
(5)mode:模式配置 ,分为开发模式(development),生产模式(production)
二、初始化项目
1、初始化项目,创建基本项目结构
(1)初始化项目
由于web是运行在node环境中的,因此我们需要先使用npm init -y命令初始化一个项目,然后创建最基本的目录结构如下:
(2)项目结构分析
config/webpack.dev.js:配置开发环境的配置文件
config/webpack.prod.js:配置生产环境的配置文件
public/index.html:项目代码运行的页面
src/index.js:打包的入口文件
package.json:包管理文件
2、安装运行webpack
(1)安装webpack
npm i webpack webpack-cli --save-dev
(2)运行webpack
当我们在项目中局部安装webpack后,运行webpack需要使用npx来运行webpack,npx可以自动帮我们找到webpack可运行的文件夹运行webpack,此时我们还未配置webpack的配置文件,我们使用命令启动打包程序,在根目录下运行以下代码,其中mode是指定开发环境还是生产环境
npx webpack ./src/index.js --mode=development
此时运行成功后根目录下会出现一个dist文件夹,里面有一个main.js文件,此时代表实现了第一步,webpack正常运行,第一次打包成功。
3、使用配置文件打包
(1)使用配置文件打包命令
如果执行npx webpack进行打包,webpack默认识别的配置文件是根目录下的webpack.config.js,如果我们想指定配置文件打包,需要使用以下命令,其中配置文件的相对路径是相对于当前项目的根目录
npx webpack --config 配置文件的相对路径
例如,我们当前项目的代码结构已经建好两个配置文件,在config文件夹中,所以如果我们想要根据配置文件打包,我们可以执行以下代码,当然我们现在配置文件中还没有任何内容,执行此命令会报错,后续我们会继续介绍配置文件具体配置内容。
// 打包开发环境
npx webpack --config ./config/webpack.dev.js
// 打包生产环境
npx webpack --config ./config/webpack.prod.js
(2)配置打包命令的快捷命令
通过配置package.json中的script属性可以简化打包命令,简化后我们运行npm run serve就可以打包开发环境代码,运行npm run build就可以打包生产环境代码
{
"name": "webpack_001",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"serve": "npx webpack --config ./config/webpack.dev.js",
"build": "npx webpack --config ./config/webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.88.1",
"webpack-cli": "^5.1.4"
}
}
三、常用基础配置
1、入口(entry)、出口(output),模式(mode)配置
(1)入口配置
入口配置开发环境和生产环境配置相同,分为单入口打包和多入口打包
单入口打包
module.exports = {
// 入口配置
entry: './src/index.js'
}
多入口打包
module.exports = {
// 多入口入口配置,index和app是自定义的名称
entry: {
index: './src/index.js',
app: './src/app.js'
}
}
(2)出口配置
出口配置开发环境和生产环境略有不同,开发环境后续我们会使用webpack-dev-server进行运行,因此不会产生具体文件,不用配置输出路径和清空打包文件夹,只需要指定文件名即可(注:[name]是webpack的命名方式,默认是main,当入口为多文件入口时,可用于区分打包后文件,此时打包后的文件名就是多入口时配置的自定义名称)
开发环境
module.exports = {
// 入口配置
entry: './src/index.js',
// 出口配置
output: {
// 输出路径
path: undefined,
// 输出文件名
filename: 'js/[name].js',
}
}
生产环境,clean: true的配置,可以使每次打包前清空上次打包内容
const path = require('path')
module.exports = {
// 单入口配置
entry: './src/index.js',
// 出口配置
output: {
// 输出路径
path: path.resolve(__dirname, '../dist'),
// 输出文件名
filename: 'js/[name].js',
// 清空输出目录
clean: true
}
}
(3)模式配置
模式配置就是生产环境和开发环境的配置,只需要在module.exports添加mode属性就好
开发模式
module.exports = {
// 入口配置
entry: './src/index.js',
// 出口配置
output: {
// 输出路径
path: undefined,
// 输出文件名
filename: 'js/[name].js',
},
// 模式
mode: 'development'
}
生产模式
const path = require('path')
module.exports = {
// 单入口配置
entry: './src/index.js',
// 出口配置
output: {
// 输出路径
path: path.resolve(__dirname, '../dist'),
// 输出文件名
filename: 'js/[name].js',
// 清空输出目录
clean: true
},
// 模式
mode: 'production'
}
以上这些就是最基本的配置,如果是单入口配置,运行npm run build之后,将在根目录下输出dist/js文件夹,内部输出main.js。如果是多入口配置,则在dist/js文件夹下输出index.js和app.js。
2、加载器(loader)配置
加载器配置是在module.exports中配置module属性,下面我们都以单入口为例
(1)webpack5资源处理介绍
资源模块(asset module)是webpack5新增的一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。加载器的配置无法绕过对项目中资源文件的处理,因此也无法绕过对该模块的了解,下面我们介绍以下资源模块的具体模块类型,一共分成四种。
- asset/resource:发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
- asset/inline:导出一个资源的 data URI。之前通过使用 url-loader 实现。
- asset/source:导出资源的源代码。之前通过使用 raw-loader 实现。
- asset:在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。
(2)处理样式文件加载器
webpack无法处理css,less,sass,scss这样的样式文件,因此想要打包处理这些文件就需要配置其他的loader去处理,这里我们已处理css,less文件为例,配置相关loader。首先我们要安装对应loader,需要安装的包有less,less-loader,css-loader,style-loader。(注:这样处理的样式文件将会被输出为html中的style标签中,要想生成单独文件还需要配置css插件,详情见插件配置)
安装包
npm i less less-loader css-loader style-loader --save-dev
配置
module.exports = {
// 模块配置
module: {
// 规则
rules: [
// 处理css,less文件
{
// 匹配文件
test: /\.(css|less)$/,
// 使用的loader
use: [
// 将js的样式内容插入到style标签中
'style-loader',
// 将css转换为js
'css-loader',
// 将less转换为css
'less-loader'
]
}
]
}
}
(3)处理图片加载器
配置图片加载器,我们将用到asset模块的默认模块类型,即asset类型,并且我们配置当图片大小小于8kb时,将图片转为base64格式。图片文件将输出在dist/image文件夹中,生成的文件名将已配置格式输出,其中[name]是原文件名,[hash:8]是随机生成的8位哈希值,[ext]是文件扩展名,保持原文件不变
module.exports = {
// 模块配置
module: {
// 规则
rules: [
// 处理图片,小于8kb的图片转为base64格式
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024
}
},
// 生成文件名
generator: {
filename: 'image/[name].[hash:8][ext]'
}
}
]
}
}
(4)处理字体文件及其他媒体文件
配置字体文件及其他媒体文件时,我们将用到asset模块的asset/resource模块类型
module.exports = {
// 模块配置
module: {
// 规则
rules: [
// 处理字体文件及其他媒体文件
{
test: /\.(woff2?|eot|ttf|otf|mp3|mp4|avi)$/,
type: 'asset/resource',
// 生成文件名
generator: {
filename: 'media/[name].[hash:8][ext]'
}
}
]
}
}
(5)处理js兼容性问题
一些低版本浏览器不兼容es6语法,因此需要配置将es6转成es5的加载器,不过当前加载器只能转一般的es6语法,像promise,await、asyn,这些高级语法无法转换,需要额外配置(详情见另一篇文章:《webpack5高级配置》)。
安装babel-loader @babel/core @babel/preset-env
npm i babel-loader @babel/core @babel/preset-env --save-dev
配置babel-loader
module.exports = {
// 模块配置
module: {
// 规则
rules: [
// 配置babel,将ES6+转换为ES5
{
test: /\.js$/,
// 排除node_modules目录下的文件
exclude: /node_modules/,
use: [
{
// 使用babel-loader
loader: 'babel-loader',
// 配置babel
options: {
// 预设
presets: [
// 预设包含了ES6、7、8的语法转换规则
'@babel/preset-env'
]
}
}
]
}
]
}
}
(6)配置html-loader
html-loader可以对html中引用的资源进行打包
安装
npm install html-loader --save-dev
配置
module.exports = {
// 模块配置
module: {
// 规则
rules: [
// 处理html中的资源引用
{
test: /\.html$/,
// 使用html-loader
loader: 'html-loader'
}
]
}
}
3、插件(plugin)配置
Webpack 拥有丰富的插件接口。webpack 自身的大部分功能都使用这些插件接口,这使得 webpack 很灵活。插件配置需要配置module.exports中的plugin属性
(1)配置html插件
html-webpack-plugin插件将为你生成一个 HTML5 文件, 在 body 中使用 script 标签引入你所有 webpack 生成的js文件,如果你有多个 webpack 入口,他们都会在已生成 HTML 文件中的
npm install html-webpack-plugin --save-dev
配置插件
// 引入html-webpack-plugin插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// 配置插件
plugins: [
// 生成html文件插件
new HtmlWebpackPlugin({
// 模板文件
template: './public/index.html',
// 输出文件名
filename: 'index.html',
})
]
}
(2)配置css插件
之前配置css加载器之后,会将样式直接以style的方式放入html中,现在我们需要将css文件生成一个单独的文件并用link的方式引入,则需要配置mini-css-extract-plugin插件。我们当前的许多css3的新样式属性,一些老的浏览器并不支持,因此我们需要使用postcss-preset-env插件将其转成可兼容的样式
安装相应的包
npm i postcss-loader postcss postcss-preset-env mini-css-extract-plugin --save-dev
配置mini-css-extract-plugin插件
// 引入mini-css-extract-plugin插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
// 配置插件
plugins: [
// 提取css文件插件
new MiniCssExtractPlugin({
// 输出文件名
filename: 'style/[name].css'
})
]
}
修改less,css加载器
module.exports = {
// 模块配置
module: {
// 规则
rules: [
// 处理css,less文件
{
// 匹配文件
test: /\.(css|less)$/,
// 使用的loader
use: [
// 将css提取为单独的文件
MiniCssExtractPlugin.loader,
// 将css转换为js
'css-loader',
// 使用postcss-loader
{
loader: 'postcss-loader',
// 配置postcss
options: {
// 使用插件
postcssOptions: {
// 使用预设包
plugins: ['postcss-preset-env']
}
}
},
// 将less转换为css
'less-loader'
]
}
]
}
}
(3)配置eslint插件
该插件使用 eslint 来查找和修复 JavaScript 代码中的问题,配置该插件后我们需要在项目根目录中新建.eslintrc.js和.eslintignore两个文件,.eslintrc.js用于配置eslint规则,.eslintignore用于忽略eslint需要检查的文件,eslint具体配置请参考eslint中文官网 安装插件
npm install eslint eslint-webpack-plugin --save-dev
配置插件
// 引入eslint-webpack-plugin插件
const EslintWebpackPlugin = require('eslint-webpack-plugin')
module.exports = {
// 配置插件
plugins: [
// eslint插件
new EslintWebpackPlugin({
// eslint检查的文件, 只检查src目录下的文件
context: path.resolve(__dirname, '../src')
})
]
}
4、开发环境,webpack-dev-server配置
webpack-dev-server 是一个用于开发环境的轻量级服务器,使用webpack-dev-server可以在本地启动一个本地服务,当我们修改代码时不需要重新打包,便可以自动更新修改内容,并展示在页面上。
(1)devServer基础配置
安装webpack-dev-server包
npm i webpack-dev-server --save-dev
配置webpack.dev.js
module.exports = {
// 开发服务器配置
devServer: {
// 服务器启动域名
host: '127.0.0.1',
// 端口号
port: 3000
}
}
修改package.json启动开发环境的命令
"scripts": {
"serve": "npx webpack server --config ./config/webpack.dev.js",
"build": "npx webpack --config ./config/webpack.prod.js"
}
(2)devServer高级配置
配置服务器根目录
module.exports = {
// 开发服务器配置
devServer: {
// 服务器根目录
static: {
directory: path.join(__dirname, '../dist'),
}
}
}
配置是否开启压缩,开启后可使资源传输更快
module.exports = {
// 开发服务器配置
devServer: {
// 开启gzip压缩
compress: true
}
}
将host配置成0.0.0.0,此时同局域网内的其他用户可以通过你的ip地址+端口号访问你的服务
module.exports = {
// 开发服务器配置
devServer: {
// 服务器启动域名,配置为0,0,0,0
// 相同局域网内所有人都可以通过你的当前ip访问你的服务
host: '0.0.0.0'
}
}
开启HMR功能,作用是当我们修改代码时会局部更新,不会刷新整个页面,提升开发效率
module.exports = {
// 开发服务器配置
devServer: {
// 开启HMR功能, 作用是局部更新,不会刷新整个页面,提升开发效率
hot: true
}
}
开启historyApiFallback,true表示任意的404响应都可能需要被替代为index.html
module.exports = {
// 开发服务器配置
devServer: {
// historyApiFallback: true表示任意的404响应都可能需要被替代为index.html
historyApiFallback: true
}
}
配置头部信息headers,给响应头配置一些自定义配置例如
module.exports = {
// 开发服务器配置
devServer: {
// 配置headers
headers: {
'X-Access-Token': 'harbour-bro2'
}
}
}
配置proxy代理,解决跨域请求问题,例如:
module.exports = {
// 开发服务器配置
devServer: {
// 配置代理
proxy: {
// 当请求路径以/api开头时,开发服务器会代理转发请求到目标服务器
'/api': {
// 目标服务器地址
target: 'http://localhost:3000',
// 开启代理服务器
changeOrigin: true,
// 重写路径
pathRewrite: {
'^/api': '/app'
},
// 禁用对目标服务器的安全验证
secure: false
}
}
}
}
配置自动打开浏览器
module.exports = {
// 开发服务器配置
devServer: {
// 配置是否自动打开浏览器
open: false
}
}
(3)devServer完整配置
// 引入path模块
const path = require('path')
module.exports = {
// 开发服务器配置
devServer: {
// 服务器根目录
static: {
directory: path.join(__dirname, '../dist'),
},
// historyApiFallback: true表示任意的404响应都可能需要被替代为index.html
historyApiFallback: true,
// 开启gzip压缩
compress: true,
// 服务器启动域名,配置为0,0,0,0相同局域网内所有人都可以通过你的当前ip访问你的服务
host: '0.0.0.0',
// 端口号
port: 8000,
// 开启HMR功能, 作用是局部更新,不会刷新整个页面,提升开发效率
hot: true,
// 配置headers
headers: {
'X-Access-Token': 'harbour-bro2'
},
// 配置代理
proxy: {
// 当请求路径以/api开头时,开发服务器会代理转发请求到目标服务器
'/api': {
// 目标服务器地址
target: 'http://localhost:3000',
// 开启代理服务器
changeOrigin: true,
// 重写路径
pathRewrite: {
'^/api': '/app'
},
// 禁用对目标服务器的安全验证
secure: false
}
},
// 配置是否自动打开浏览器
open: false
}
}
四、总结
本篇文章介绍了webpack5的基础常用配置,如需常用优化相关配置,请查阅《webpack5高级配置》一文。