webpack笔记
webpack作用:处理代码压缩混淆、浏览器端js的兼容性以及性能优化
webpack在项目中安装过程
npm i webpack webpack-cli -g //全局安装webpack(必须)
npm i webpack@5.42.1 webpack-cli@4.7.2 -D //局部安装 Webpack 到项目(必须)
webpack.config.js 配置
/*
webpack.config.js:指示webpack干哪些活(当你运行webpack指令时,会加载这里面的内容)
注:所有构建工具都是基于node.js平台运行的 模块化采用commonjs
*/
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin"); //新建模板骨架插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //引入从js中提取css的插件
const WorkboxWebpackPlugin=require("workbox-webpack-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin"); //压缩css插件
//如果browserslist要开发模式则需要设置nodejs的环境变量
process.env.NODE_ENV = "development";
/*
缓存:
babel缓存:
设置 cacheDirectory:true, 作用:开启缓存机制。让第二次打包速度更快
文件资源缓存:
hash每次webpack构建都会生成唯一的hash值
问题:因为css和js用的是同一个hash值,如果重新打包则会导致所有缓存失效
但我可能只改动了一个文件
解决:Chunkhash 根据打包入口生成的hash值。入口一样chunk一样
问题:css和js还是同一个hash值 因为css是在js中被引入的 所有同属一个chunk
最终解决:使用contenthash:根据文件内容生成hash值,文件内容不一样hash值一定不一样(不考虑哈希碰撞)
作用:让代码上线运行缓存更好使用
*/
/*
tree shaking(树摇 把没有用的叶子摇下去): 去除在应用程序中没有应用到的代码,使代码体积更小
前提:1、必须使用es6模块化 2、开启production环境
在package.json中配置 "sideEffects":false 即所有代码没有副作用都可以进行"树摇" 可能会误摇css或者js文件
例:不要摇css文件 则在package.json中配置 "sideEffects":["*.css"]
*/
/*
PWA(离线访问技术):workbox-webpack-plugin
*/
/* 复用css */
const commonCssLoader = [
//在页面中创建style标签,将js中的'样式字符串'插入标签并添加到head生效
// "style-loader",
/*
取代style-loader 提取js中的css单独成文件 同时html自动引入
将CSS文件变成commonjs模块加载到js中,里面内容是样式字符串
*/
MiniCssExtractPlugin.loader,
"css-loader",
/*
解决CSS兼容性问题:postcss-loader --> postcss-preset-env
帮postcss找到package-json中的browserslist里面的配置,通过配置加载指定的兼容性
*/
//修改配置要以对象的方式 browserslist默认是生产模式 与mode无关
{
loader: "postcss-loader",
options: {
ident: "postcss",
plugins: () => [
//postcss的插件
require("postcss-preset-env")(),
],
},
},
],;
module.export = {
entry: "./src/index.js", //单页面 单入口
/*
entry: {
index:"./src/index.js",
text:"./src/text.js" //多页面 多入口 一个入口生成一个bundle.js文件 kv形式
},
*/
output: {
//[name]取文件名 多入口的情况下使用 1强2
filename: "js/[name].[Contenthash:10].js", //输出文件名
path: resolve(__dirname, "build"), //_dirname是当前文件的目录绝对路径(即Webpack)
},
//loader的配置
//不同文件要配置不同的loader处理
module: {
rules: [
{
/* 对js进行语法检查 eslint-loader eslint
注:只检查自己写的源代码,第三方的库不用检查
检查规则在package.json中eslintConfig中设置
"eslintConfig":{
"extends":"airbnb-base" 继承下载的airbnb-base库中的规则
}
airbnb规则需要三个插件 eslint-config-airbnb-base、eslint、eslint-plugin-import
*/
test: /\.js$/,
exclude: /node_modules/, //排除检查第三方库是否错误
loader: "eslint-loader",
enforce:'pre', //一般情况下一个文件一个loader执行 enforce设置为pre表示该loader优先执行
options: {
//自动修复js中的语法错误
fix: true,
},
},
/*
oneOf中只能使用一个loader处理一种类型的文件,不能两个配置处理同一类的文件。如果需要两个则提取到oneOf以外
防止一个文件反复的被多个loader执行。优化生产环境的打包速度
*/
],
oneOf:[
{
//匹配以CSS为后缀的文件
test: /\.css$/,
//use数组中loader的执行顺序:右到左,下到上
use: [
...commonCssLoader
],
},
{
test: /\.less$/,
//使用多个loader用use
use: [
...commonCssLoader, //...commonCssLoader为展开commonCssLoader
"less-loader", //less-loader将less文件转换为css文件
],
},
{
test: /\.(png|jpg|gif)$/,
loader: "url-loader", //处理样式文件中的img图片
//使用一个loader要下载file-loader,通常用use
options: {
//图片size小于8kb,就会被base64处理
//base处理的优点是减少请求数量降低服务器压力 缺点是图片体积变大图片请求速度会变慢
limit: 8 * 1024,
/*
由于url-loader默认采用es6解析,而html-loader引入图片是commonjs,解析时候会冲突
所有关闭url-loader的es6解析,采用commonjs解析
*/
esModule: false,
//图片名字过长 使用name重命名
name: "[hash:10].[ext]",
outputPath: "imgs",
},
},
{
test: /\.html$/, //处理HTML中的img图片
loader: "html-loader",
outputPath: "imgs",
},
{
//打包其他资源 排除常用资源就是其他资源
exclude: /\.(html|css|js)$/,
loader: "file-loader",
options: {
limit: 8 * 1024,
esModule: false,
name: "[hash:10].[ext]",
},
outputPath: "media",
},
{
/*
js兼容性处理:
babel-loader @babel/core
1.@babel/preset-env 能够解决简单的js语法 es6如promise就不能解决兼容 在options中的presets预设
2.@babel/polyfill 直接在所需的js文件中import '@babel/polyfill'即可 但文件体积大了
3.core-js 按需分配(最佳方案1+3) 使用第三种就不能使用第二种
*/
text: /\.js$/,
exclude: /node_modules/, //排除检查第三方库
loader: ":babel-loader",
options: {
//presets(预设):指示babel做怎么样js兼容
presets: [
"@babel/preset-env",
//按需分配
{
useBuiltIns: "usage",
//指定core-js版本
corejs: {
version: "3",
},
//指定兼容性做到哪个版本浏览器
target: {
chrome: "60",
firefox: "60",
ie: "9",
safari: "10",
},
},
],
//开启babel缓存,第二次构建会优先读取缓存,提升速度
cacheDirectory:true,
},
},
]
},
//plugins比loader多一步引入
plugins: [
new HtmlWebpackPlugin({
option:{
title:'我是网页title'
},
template: "./src/index.html", //创建一个HTML,模板为index.html 并引入打包输出的所有资源
minify: {
//压缩html代码
//移除空格
collapseWhitespace: true,
//移除注释
removeComments: true,
},
}),
new MiniCssExtractPlugin({
//对打包的css重命名
filename: "/css/main.[Contenthash:10].css",
}),
new OptimizeCssAssetsWebpackPlugin(), //压缩css文件
new WorkboxWebpackPlugin.GenerateSW({
/* 1、帮助serviceworker快速启动
2、删除旧的serviceworker
生成一个 serviceworker配置文件
*/
clientsClaim:true,
skipWaiting:true
})
],
/*
针对js文件
单入口 将node_module中的代码单独打包成一个chunk+入口chunk输出 实现并行加载提高运行速度
多入口 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk
optimization在生产环境中才有意义 除了chunk:'all' 其他均为默认配置
*/
optimization:{
splitChunks:{
chunk:'all',
miniSize:'30*1024', //大于最小才会分割
maxSize:'0', //不限制大小
miniChunk:'1', //要提取的提取的chunk至少被引用一次
maxAsyncRequests:'5', //按需加载时 最大并行加载数量为5
maxInitialRequests:'3', //入口js最大并行为3
autoMaticNameDelimiter:'~', //名称连接符为~
name:true, //可以使用命名规则
cacheGroups:{
//分割chunk的组
/*
>............<省略配置
*/
}
},
runtimeChunk:{
//当前模块记录其他模块的hash单独打包成一个文件runtime 解决由于a文件改动导致b文件的contentchash改变
name:entrypoint=>`runtime-${entrypoint.name}`
}
},
mode: "development",
resolve:{ //允许引入模块的属性
alias:{
$css:resolve(__dirname,'src/css'), //设置路径别名为$css 优化简写路径
},
extensions:['.js','.json','css'], //配置省略文件路径的后缀名 省略什么加什么
modules:[resolve(__dirname,'../Webpack/node_modules'),'node_modules'], //指定webpack解析模块的目录
},
externals:"jquery", //最终的bundle不打包jquery
/*
开发服务器devServer:自动化编译,打开浏览器,刷新浏览器
特点:只会在内存中编译打包,不会有输出
启动devServer指令为:npx webpack-dev-server(因为是下载在本地 所以要用npx启动dev-server服务器)
正常打包指令为:webpack --mode=development
注:修改了webpack配置要重启服务才会生效
*/
devServer: {
//构建后的目录路径
contentBase: resolve(__dirname, "build"),
//监视构建的目录,一旦文件发生变化自动reload
watchContentBase:true,
//忽略文件变化选项
watchOptions:{
ignored:/node_module/,
},
//启动gzip压缩 让代码运行速度更快
compress: true,
//开发服务器的端口号
port: 5000,
//自动打开默认浏览器
open: true,
// HMR:热模块替换 作用:当一个模块发生变化,只会重新打包这一个模块,而不是打包所有。提升构建速度
hot:true,
//关闭服务器启动日志
clientLogLevel:'none',
//除了基本启动信息,其他信息都不要显示 一般和clientLogLevel:'none'联用
quiet:true,
//如果发生错误,不要全屏提示
overlay:false,
//服务器代理(解决跨域问题),一旦devsevery接收到./api开头的请求转发到'http://localhost:3000'服务器上处理
proxy:{
'./api':{
target:'http://localhost:3000',
pathRewrite:{
'^/api':'', //重写路径 转发的时候去掉api
}
}
}
},
devtool:'source-map' //优化调试
/*
内联和外部的区别是:外部生成文件,内联没有生成文件 #内联速度更快
source-map提供源代码到构建后代码的映射技术(如果构建代码错误了,可以查到源代码哪里出现错误)
(1) source-map:外部
错误代码准确信息和源代码错误位置
(2) inline-source-map:内联(只生成一个内联source-map)
错误代码准确信息和源代码错误位置
(3)hidden-source-map:外部
错误代码的错误原因,没有错误位置,不能追踪到源代码错误位置,只能追踪到构建后代码的错误位置
(4)eval-source-map:内联
错误代码准确信息和源代码错误位置 多了个哈希值
(5)nosources-source-map:外部
错误代码的准确信息,但没有源代码信息(防止源代码泄露)
(6)cheap-source-map:外部
错误代码准确信息和源代码错误位置(只能到一整行,不能具体到一行中的某一列错误)
(7)cheap-modle-source-map:外部
错误代码准确信息和源代码错误位置
开发环境
速度快:eval-cheap-source-map
调试友好:source-map
最佳方案:eval-source-map
生成环境(是否需要隐藏源代码)
需要以下二选一
hidden-source-map
nosources-source-map
不需要 最佳方案:cheap-module-source-map
*/
};
3、在package-json的script节点下新增dev和bulid命令用来打包
"dev":"webpack serve"
"build": "webpack --mode production"
4、根据入口文件输出打包文件,然后所需的地方导入打包文件就可以认webpack帮我们处理兼容性问题,打包文件放在内存中修改比较快
webpack中的默认约定
1、默认打包入口为src->index.js
2、默认的输出文件路径dist->main.js
查看webpack和webpack-cli版本
node_modules/.bin/webpack -v
node_modules/.bin/webpack-cli -v
webpack的各个插件
#安装dev-Server 一修改源代码就自动打包 无需手动打包 但页面不会实时刷新
npm i webpack-dev-server -D
#打包html插件(需要require引入)
npm i html-webpack-plugin -D
#html压缩
在HtmlWebpackPlugin中的minify设置
webpack遇见非.js的文件要对应的loader插件解析
#样式的loader插件 采用base64格式的图片可以防止多余的图片加载请求 但是图片大小会变大
#打包脚本中的图片资源
npm i style-loader css-loader less-loader less -D
#打包样式中图片资源
npm i file-loader url-loader -D
#打包骨架中的图片
npm i html-loader -D
#自动清除dist目录的旧文件(插件需引入)
npm i clean-webpack-plugin -D
#从js中提取css(插件需引入)
npm i mini-css-extract-plugin -D
#压缩css(插件需引入)
npm i optimize-css-assets-webpack-plugin -D
#css兼容性问题
npm i postcss postcss-loader postcss-preset-env -D
// 同时在packjson中进行browserslist配置
#js语法规范检查
npm i eslint-loader eslint-config-airbnb-base、eslint、eslint-plugin-import -D
同时在packjson中进行eslintConfig配置
#js兼容性问题
npm i -D babel-loader @babel/core @babel/preset-env core-js
// 第三种插件可替换方案
(@babel/preset-env 解决基本的js兼容问题)
(@babel/polyfill 解决全部es6语法的兼容性问题)
(core-js 解决所需的js兼容性问题 )
#js压缩
生产模式下会自动压缩js代码
#多进程打包(一般为js)
npm i thread-loader -D
#将某个资源打包输出,并在html中引入该资源
npm i add-asset-html-webpack-plugin -D
webpack优化
1、开发环境性能优化
(1)优化打包构建速度 :HMR热模块替换 //如果只有一个模块发生变化就只会重新构建该模块,其他模块使用之前的缓存
(2)优化代码调试:devtool:'eval-source-map' /(存储着压缩混淆后的代码所对应的转换前的位置(行号),可 看见源码) 开发环境用 devtool:'nosources-source-map' //可见位置不可见源码 生产环境用
2、生产环境性能优化
(1)优化打包速度:
一、oneOf
二、babel缓存 //缓存运行结果,第二次打开速度更快
三、多进程打包
四、externals:防止某些包最终打包到bundle中(彻底不打包 要用直接cdn链接)
五、dll:(动态连接库),单独打包某些库,将多个库打包成一个chunk(先单独打包 在告诉webpack这个不用打包 提高效率,同时将该包引入到html中)
(2)优化代码运行性能:
一、缓存(contenthash) //对文件进行缓存 第二次缓存速度快
二、tree shaking (概念并非插件或者需要设置) 1、必须使用es6模块化 2、production环境有个插件自动启动tree shaking
去除在应用程序中没有应用到的代码,使代码体积更小
三、单入口:引进只有一个chunk 输出只有一个bundle
optimization:{
splitChunks:{
chunk:'all' //一般是将node_module分割 单独打包成一个bundle 总共生成两个bundle
} }, 然后可以通过dll对node_module中的第三方库再一次打包 更加细化
import("./text")
.then((result) => {
console.log('文件加载成功'+result); //或者通过import分割指定的js代码
})
.catch(() => {
console.log("文件加载失败");
});
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具