webpack工具打包的使用
先用npm init -y,快速生成package.json文件,package-lock.json文件是用来固化依赖包的版本的,导入包后会自行生成,提交给他人项目时,只需要给这两个配置文件,然后输入npm i,即可自动下载依赖。
新建一个webpack.config.js配置文件,以下是配置文件的信息,之后输入自定义的命令npm run build(以下代码自定义名字用的就是build)即可。
--mode=production为生产模式,特点是会进行压缩,体积更小,更轻量化
--mode=development为开发模式,特点是易读,方便插件进行热加载
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --mode=production", //webpack打包的命令
"dev": "webpack serve --open --mode=development" //热加载插件的启动命令
},
中途需要导入依赖包
--save-dev:在开发模式中应用,生产环境中不应用
npm i webpack webpack-cli --save-dev //webpack基础依赖包,默认只打包js文件
npm i npm i html-webpack-plugin --save-dev //需要打包html文件时的依赖包
npm i style-loader css-loader --save-dev //需要打包css文件时的依赖包
npm i mini-css-extract-plugin --save-dev //想将css文件另外导入,而不是打包后直接和js文件合并,则用该依赖代替style-loader依赖
npm i css-minimizer-webpack-plugin --save-dev //将css文件另外导入的话,还需要压缩css文件
npm i less less-loader --save-dev //解析less文件
npm i webpack-dev-server --save-dev //热加载,无需每次更改代码后执行编译命令,项目会被打包到内存上
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); // 用于访问内置插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
mode: 'development', //想使用webpack-dev-server插件进行热加载,需要设为开发模式,也可以在上述代码块处设置命令行参数
entry: path.resolve(__dirname,'src/login/index.js'),//打算打包的js文件位置
output: {
path: path.resolve(__dirname, 'dist'),//想把js文件打包到哪个路径下
filename: './login/index.js',//js文件具体文件名
clean:true //设置后可以将path下的文件全部清空再重新打包
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/login.html'),//打算打包的html文件位置
filename: "login.html" //html文件在dist文件夹下的相对路径,也可以向上面使用绝对路径设置
}),
new MiniCssExtractPlugin({ //想将css独立打包的依赖的配置
filename:'./login/index.css'//更改css文件的位置。注意:filename后的属性只能设置相对路径,不能设置绝对路径
})
],
module: {
rules: [
{
test: /\.css$/i,//i代表无论大小写
// use: ['style-loader','css-loader'] //注意,此处两个配置的顺序不能反,否则会报错
use: [MiniCssExtractPlugin.loader,'css-loader']//如果不想将js和css文件凑一起,就用这个,而不用上面被注释的配置
},
{//解析less文件
test: /\.less$/i,
use: [
// compiles Less to CSS
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
],
},
{//webpack5中,内置了图片打包的loader,只需要进行以下配置即可
test: /\.(png|jpg|gif)$/i,
type:'asset'//自动配置,当图片大于8kb,则利用url引入,小于8kb时,打包进js里
generator: {
filename: 'assets/[hash][ext][query]'//assets为打包目录下的文件夹名字,hash可对重复图片进行去重压缩,ext表示图片使用原来的后缀,query表示保留图片链接的?id=12类型的参数
}
},
],
},
optimization: {
minimizer: [//自定义压缩
// 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
// `...`,
`...`,
new CssMinimizerPlugin(),//压缩css文件
],
},
};
npm i cross-env --save-dev //使切换开发环境和生产环境变得简易
package.json的自定义命令中,修改为
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "cross-env NODE_ENV=production webpack --mode=production",
"dev": "cross-env NODE_ENV=development webpack serve --open --mode=development"
},
之后即可在webpack.config.js中修改代码,来自动选择
module: {
rules: [
{
test: /\.css$/i,
// use: ['style-loader','css-loader']
use: [
process.env.NODE_ENV === 'development'?'style-loader' : MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /\.less$/i,
use: [
// compiles Less to CSS
process.env.NODE_ENV === 'development'?'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
],
},
],
},
而在页面js中的代码,若想快速进行环境的切换,可利用webpack的内置插件,只需设置
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),//也可以直接将process.env.NODE_ENV的值注入,使webpack.config.js和网页js文件一同修改
'变量名':JSON.stringify('变量值')//必须用JSON.stringify()进行转换,否则不会看成一个字符串
})
],
打包后的js语句若报错,浏览器就无法精确定位到报错位置了,这时我们可以在webpack.config.js设置
module.exports ={
devtool = 'inline-source-map'
}
当然,该语句如果在生产环境配置会有一定的安全隐患,所以我们可以结合上述切换环境的插件,更改为
const config={}
if (process.env.NODE_ENV === 'development'){
config.devtool = 'inline-source-map'
}
module.exports=config
在前面,我们引入的代码使用相对路径可能会过长,或者不安全,所以可以在webpack.config.js中使用以下配置来设置绝对路径
const config = {
resolve:{
alias:{
'@':path.resolve(__dirname,'src')
}
},
}
module.exports=config
//之后js文件内这样使用
import myAxios from '@/utils/request.js'
//表示__dirname/src/utils/requset.js
为了减轻服务器压力,我们有时不会将第三方库一同打包进项目,而是利用CDN来使用网络路径,就近向其他服务器请求获取第三方库,在webpack.config.js中进行如下配置,使生产模式下,屏蔽js文件中的两个第三方包的导入。
const config = {
plugins: [
new HtmlWebpackPlugin({
useCdn: process.env.NODE_ENV === 'production'
}),
],
}
if (process.env.NODE_ENV === 'production'){
config.externals = {
'bootstrap/dist/css/bootstrap.min.css': 'bootstrap', //key是js文件中import语句后from的路径,value是from前接收的变量名,bootstrap我们引入时没取名,写个bootstrap代替一下
'axios': 'axios'
}
}
module.exports = config
然后在html文件中,使用如下代码进行设置,需要注意的是,在html中引入的css样式,优先级高于js中引入的css样式
<% if(htmlWebpackPlugin.options.useCdn){ %>
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.1/css/bootstrap.min.css">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.1/js/bootstrap.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.min.js"></script>
<% } %>
多页面打包
如果想对多页面进行打包,则进行如下配置,为了确保打包后location.href=的引入参数时路径不出错,最好将src文件和打包后的dist文件结构保持一致
entry: {
'login': path.resolve(__dirname,'src/login/index.js'),
'content' :path.resolve(__dirname,'src/content/index.js')
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: './[name]/index.js', //[name]对应的是entry中的'login','content'的名字
clean:true
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/login.html'),//此处不能使用[name]
filename: path.resolve(__dirname, 'dist/login/index.html'),
useCdn: process.env.NODE_ENV === 'production',
chunks: ['login']//打包后引用的js文件名,对应entry中的'login','content'的名字
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/content.html'),
filename: path.resolve(__dirname, 'dist/content/index.html'),
useCdn: process.env.NODE_ENV === 'production',
chunks: ['content']
}),
new MiniCssExtractPlugin({
filename:'./[name]/index.css'//更改css文件的位置。注意:filename后的属性只能设置相对路径,不能设置绝对路径
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
}),
],
当然,如果你存在公共引入的js文件,不想让公共代码被重复写入每个js文件,可以使用webpack自带的拆分工具
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups:{//分隔组
commons:{
minSize: 0,//抽取的chunk最小字节
minChunks: 2,//最小引用数
reuseExistingChunk: true,//当前chunk包含已从主bundle中拆分出的模块,则它将被重用
name(module,chunks,cacheGroupKey){//分离模块文件名
const allChunksNames = chunks.map((item)=>item.name).join('~')
return `./js/${allChunksNames}` //dist下的目录
}
},
},
}
},
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?