这篇主要介绍《webpack详细配置》。(demo代码github地址)
知识点包括:
- webpack详细配置之entry
- webpack详细配置之output
- webpack详细配置之module
- webpack详细配置之resolve
- webpack详细配置之devserver
- webpack详细配置之optimization
- webpack4至webpack5详细变化
一、webpack详细配置之entry
1、新建工程文件目录如下
![](https://i-blog.csdnimg.cn/blog_migrate/1e5403adec256f26e6859c42c956772c.png)
2、config.js中代码
const { resolve } = require('path');
const HtmlwebpackPlugin = require('html-webpack-plugin')
/**
* entry : 入口起点有三种值
* 1. string
* 2. array
* 3. object
*/
module.exports = {
entry: './src/index.js ',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build')
},
plugins: [
new HtmlwebpackPlugin()
],
mode: 'development'
};
3、index.js代码
import add from './add';
import count from './count'
console.log('index.js文件被加载了');
console.log(add(1, 2));
console.log(count(2, 3));
4、add.js
function add(x, y) {
return x + y;
}
export default add;
5、count.js
function count(x, y) {
return x - y;
}
export default count;
6、然后在终端命令依次输入:
npm init
webpack_entry
npm i webpack webpack-cli -D
npm i html-webpack-plugin -D
然后此时工程目录如下
![](https://i-blog.csdnimg.cn/blog_migrate/1f652d77605a1481ee5e21c1cd2f0333.png)
7、修改package.json
{
"name": "webpack_entry",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^5.5.0",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1"
}
}
8、然后终端命令输入npm run dev
。build文件夹下生成了两个文件。
![](https://i-blog.csdnimg.cn/blog_migrate/8ebe4b87f961faaf835ccfb6f22ff816.png)
所以说,entry入口起点,使用string形式,输入一个单文件,则会打包形成一个built.js文件,之前自己写的add.js,count.js全杂糅进来了。
entry: './src/index.js', //string写法
修改config.js文件,改为数组形式的多入口文件配置,则最终只会形成一个built.js文件,之前自己写的add.js,count.js全杂糅进来了。
在HMR功能中使用该方法。
entry: ['./src/index.js', './src/add.js'] //array写法
修改config.js文件,改为对象形式(key:value)写法,有几个入口文件,就打包成几个文件,打包后文件的名称,为key的名称。
entry: {
index: './src/index.js',
add: './src/add.js'
},//对象object形式写法
object形式还有个特殊用法:
// object有个特殊用法
{
//index数组中的所有入口文件最终只会形成一个chunk,打包输出出去只有一个bundle文件。
index: [ './src/index.js', './src/count.js'],
//add中的入口文件形成一个chunk,打包输出一个bundle文件。
add: './src/add.js'
}
!!!entry的object形式的两种写法,我在测试的时候执行失败,用不了,不知道是什么原因~~~~
二、webpack详细配置之output
1、复制entry工程文件。并重命名。修改config.js代码,增添一些对打包输出文件的相关配置。
const { resolve } = require('path');
const HtmlwebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
//文件名称(指定名称+目录)
filename: 'built.js',
//输出文件目录(将来所有资源输出的公共目录)
path: resolve(__dirname, 'build'),
// 所有资源引入公共路径的前缀,比如imgs/a.jpg' 变成 '/imgs/a.jpg'
publicPath: '/',
chunkFilename: 'js/[name]_chunk.js',// 非入口chunk的名称,entry指定的文件就叫入口chunk
library: '[name]',// 整个库向外暴露的变量名
// libraryTarget: 'window'//变量名添加到哪个上 browser上
libraryTarget: 'global' //变量名添加到哪个上 nodejs上
},
plugins: [
new HtmlwebpackPlugin()
],
mode: 'development'
};
2、修改index.js代码
import count from './count'
console.log('index.js文件被加载了');
import('./add').then(({ default: add }) => {
console.log(add(1, 2));
});
console.log(add(1, 2));
console.log(count(2, 3));
3、输入npm run build
查看打包生成的文件,非入口文件add,被单独打包了,且在js文件夹下,名为add_js_chunk.js。index.html中引入的built.js前也加上了“/”。
三、webpack详细配置之module
1、复制上一节工程,并重命名。修改其中的config.js。一些常用的配置已在代码注释说明中。
const { resolve } = require('path');
const HtmlwebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
//文件名称(指定名称+目录)
filename: 'built.js',
//输出文件目录(将来所有资源输出的公共目录)
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
//loder的配置
test: /\.css$/,
//多个loader用use
use: ['style-loader ', 'css-loader']
},
{
test: /\.js$/,
// exclude排除检查node_modules下的js文件
exclude: /node_modules/,
// 只检查src下的js文件
include: resolve(__dirname, 'src'),
// 优先执行
enforce: 'pre',
//单个loader用loader
loader: 'eslint-loader',
},
{
// 以下loader配置只会生效一个
oneOf: []
}
]
},
plugins: [
new HtmlwebpackPlugin()
],
mode: 'development'
};
2、输入npm i eslint-loader -D
下载eslint插件,然后输入npm run dev
进行打包。注意的是。
在webpack5中推荐使用eslint-webpack-plugin
代替eslint-loader
进行使用。
打包后生成的文件如下
四、webpack详细配置之resolve
1、复制上一节工程文件,并重命名。resolve表示是解析模块的规则。
2、先下载相关包。终端输入npm i css-loader style-loader -D
。工程文件目录修改如下
3、然后修改config.js代码
const { resolve } = require('path');
const HtmlwebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/js/index.js',
output: {
//文件名称(指定名称+目录)
filename: 'built.js',
//输出文件目录(将来所有资源输出的公共目录)
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
//loder的配置
test: /\.css$/,
//多个loader用use
use: ['style-loader', 'css-loader']
},
]
},
plugins: [
new HtmlwebpackPlugin()
],
mode: 'development',
// 解析模块的规则
resolve: {
//配置解析模块路径别名.优点:可以简写路径,缺点:没有路径提示了
// 在index.js中引入css文件时,只需写$css/index.css,即自动定位到src/css文件夹,在寻找index.css
alias: {
$css: resolve(__dirname, 'src/css')
},
//省略文件路径的后缀名,比如引入index.css时,可以只写到index即可。
extensions: ['.js', '.json', '.css'],
// 告诉webpack 解析模块是去找哪个目录
// 默认是node_modules
modules: ['node_modules']
}
};
4、修改index.js代码
import '$css/index.css'
5、index.css代码
html,
body {
height: 100%;
background-color: blue;
}
6、最后输入npm run dev
运行打包。
五、webpack详细配置之devserver
1、复制上一节工程文件,并重命名。注意devserver一定用于开发环境development。
2、先下载相关包,输入npm install -D webpack-dev-server
。
注意的是:
// 开发时可直接访问到 ./build 下的静态资源,这些资源在开发中不必打包
// contentBase: resolve(__dirname, 'build'),在webpack5中不需要配置这个contentBase
3、修改config.js代码
const { resolve } = require('path');
const HtmlwebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
]
},
plugins: [
new HtmlwebpackPlugin()
],
mode: 'development',
resolve: {
alias: {
$css: resolve(__dirname, 'src/css')
},
extensions: ['.js', '.json', '.css'],
modules: ['node_modules']
},
devServer: {
// 开发时可直接访问到 ./build 下的静态资源,这些资源在开发中不必打包
// contentBase: resolve(__dirname, 'build'),在webpack5中不需要配置这个contentBase
//启动gzip压缩
compress: true,
//端口号
port: 5000,
//域名
host: 'localhost',
//自动打开浏览器
open: true,
//开启hmr功能
hot: true,
// 如果出错了,不要全屏提示
client: {
overlay: false,
},
// 服务器代理,解决开发环境的跨域问题
proxy: {
//一旦devServer(5000)服务器接受到/api/xxx的请求,就会把请求转发到另外一个服务器
'/api': {
target: 'http://localhost:3000',
// 发送请求时,请求路径重写,将/api/xxx -->/xxx(去掉/api)
pathRewrite: {
'^/api': ''
}
}
}
}
};
然后输入npm run dev
先打包一下,在输入npx webpack serve
启动服务器。启动成功会自动弹出一个页面。
(!!!原博主使用npx webpack serve启动成功了,我本地测试的时候启动失败,不知道什么原因~~~)
![](https://i-blog.csdnimg.cn/blog_migrate/130960cb341175ce29c3cbd4c33885dc.png)
六、webpack详细配置之optimization
1、将详细配置resolve的工程文件复制并重命名。修改一些文件夹如下所示
![](https://i-blog.csdnimg.cn/blog_migrate/010ca9009ee7119657f02e9f63e837ed.png)
2、其中index.js代码,写成了import动态引入的方式,所以打包后,会生成两个.js文件。
import('./a.js').then(({ add }) => {
console.log(add(1, 2));
});
3、a.js代码
export function add(x, y) {
return x + y;
}
4、config.js代码
const { resolve } = require('path');
const HtmlwebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
]
},
plugins: [
new HtmlwebpackPlugin()
],
mode: 'production',
resolve: {
alias: {
$css: resolve(__dirname, 'src/css')
},
extensions: ['.js', '.json', '.css'],
modules: ['node_modules']
},
// 代码分割的配置,可以将node_modules中代码单独打包一个chunk输出
// 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk输出
optimization: {
splitChunks: {
chunks: 'all',
// 如果使用默认值,下边内容可以不写
// minsize: 30 * 1024,// 分割的chunk最小为30kb,低于30kb就不分割
// maxSize: 0,//最大没有限制
// minChunks: 1,//要提取的chunk最少被引用1次
// maxAsyncRequests: 5,// 按需加载时,并行加载的文件最大数量为5
// maxInitialRequests: 3,//入口js文件最大并行请求数量
// automaticNameDelimiter: '~',
// name: true,// 可以使用命名规则
// cacheGroups: {// 分割chunk的组
// // node_modules文件会被打包到 vendors 组的chunk中。--> vendors~xxx.js
// //满足上面的公共规则,如:大小超过3okb,至少被引用一次。
// defaultvendors: {
// test: /[\\/]node_modules[\\/]/,
// // 优先级为-10
// priority: -10
// },
// default: {
// //要提取的chunk最少被引用2次,会覆盖掉前边代码规定的公共的引用规则设定
// minChunks: 2,
// //优先级
// priority: -20,
// //如果当前要打包的模块,和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块
// reuseExistingChunk: true
// }
// }
}
}
};
5、输入npm run build
打包结果如下
![](https://i-blog.csdnimg.cn/blog_migrate/a2bf39f94434578e4039f8b400044202.png)
6、但是此时,因为文件中都带了哈希值,我们生成的main.js(对应index.js)要通过715.js(对应a.js)对应的hash值来引入里边的函数。所以当我改动a.js代码时,在打包,会发生a.js和index.js都重新打包的问题。此时需要在optimization中增加一个属性runtimeChunk。
修改config.js代码:
const { resolve } = require('path');
const HtmlwebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
]
},
plugins: [
new HtmlwebpackPlugin()
],
mode: 'production',
resolve: {
alias: {
$css: resolve(__dirname, 'src/css')
},
extensions: ['.js', '.json', '.css'],
modules: ['node_modules']
},
// 代码分割的配置,可以将node_modules中代码单独打包一个chunk输出
// 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk输出
optimization: {
splitChunks: {
chunks: 'all',
// 如果使用默认值,下边内容可以不写
// minsize: 30 * 1024,// 分割的chunk最小为30kb,低于30kb就不分割
// maxSize: 0,//最大没有限制
// minChunks: 1,//要提取的chunk最少被引用1次
// maxAsyncRequests: 5,// 按需加载时,并行加载的文件最大数量为5
// maxInitialRequests: 3,//入口js文件最大并行请求数量
// automaticNameDelimiter: '~',
// name: true,// 可以使用命名规则
// cacheGroups: {// 分割chunk的组
// // node_modules文件会被打包到 vendors 组的chunk中。--> vendors~xxx.js
// //满足上面的公共规则,如:大小超过3okb,至少被引用一次。
// defaultvendors: {
// test: /[\\/]node_modules[\\/]/,
// // 优先级为-10
// priority: -10
// },
// default: {
// //要提取的chunk最少被引用2次,会覆盖掉前边代码规定的公共的引用规则设定
// minChunks: 2,
// //优先级
// priority: -20,
// //如果当前要打包的模块,和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块
// reuseExistingChunk: true
// }
// }
},
// 将当前模块中,记录其他模块的hash值单独打包为一个文件runtime
// 解决问题:修改a文件导致b文件的contenthash变化
runtimeChunk: {
name: (entrypoint) => `runtime~${entrypoint.name}`,
},
}
};
7、输入npm run build
打包
8、此时改动a.js文件
export function add(x, y) {
return x - y;
}
9、再重新打包。发现变化的只有我们的715.js文件和存放哈希值的文件。
10、最后还有一个对js和css文件修改压缩方案的功能,修改config.js
const { resolve } = require('path');
const HtmlwebpackPlugin = require('html-webpack-plugin');
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
]
},
plugins: [
new HtmlwebpackPlugin()
],
mode: 'production',
resolve: {
alias: {
$css: resolve(__dirname, 'src/css')
},
extensions: ['.js', '.json', '.css'],
modules: ['node_modules']
},
// 代码分割的配置,可以将node_modules中代码单独打包一个chunk输出
// 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk输出
optimization: {
splitChunks: {
chunks: 'all',
// 如果使用默认值,下边内容可以不写
// minsize: 30 * 1024,// 分割的chunk最小为30kb,低于30kb就不分割
// maxSize: 0,//最大没有限制
// minChunks: 1,//要提取的chunk最少被引用1次
// maxAsyncRequests: 5,// 按需加载时,并行加载的文件最大数量为5
// maxInitialRequests: 3,//入口js文件最大并行请求数量
// automaticNameDelimiter: '~',
// name: true,// 可以使用命名规则
// cacheGroups: {// 分割chunk的组
// // node_modules文件会被打包到 vendors 组的chunk中。--> vendors~xxx.js
// //满足上面的公共规则,如:大小超过3okb,至少被引用一次。
// defaultvendors: {
// test: /[\\/]node_modules[\\/]/,
// // 优先级为-10
// priority: -10
// },
// default: {
// //要提取的chunk最少被引用2次,会覆盖掉前边代码规定的公共的引用规则设定
// minChunks: 2,
// //优先级
// priority: -20,
// //如果当前要打包的模块,和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块
// reuseExistingChunk: true
// }
// }
},
// 将当前模块中,记录其他模块的hash值单独打包为一个文件runtime
// 解决问题:修改a文件导致b文件的contenthash变化
runtimeChunk: {
name: (entrypoint) => `runtime~${entrypoint.name}`,
},
minimizer: [
//配置生产环境的压缩方案:js和css
// 需要下载插件terser-webpack-plugin
// webpack v5 开箱即带有最新版本的 terser-webpack-plugin
new TerserPlugin({
// 开启多进程打包
parallel: true,
})
]
}
};
七、webpack4至webpack5详细变化
请见此处。
注:笔记转载自疯子的梦想@博客,课程来自尚硅谷b站Webpack5实战课程