Webpack basic
现代web开发的问题
- 不同浏览器对模块化的支持不一样,模块化本身有不同的设计规范
- 开发过程中为了提高效率,比如使用一些新特性如ts,sass,但是浏览器是不能直接识别这些资源的
- 实时监听开发过程使用热更新
- 项目结果打包压缩优化
webpack就是解决这样的事情,让开发者不关心过程,但是结果一定是可以在浏览器正常运行的代码。
webpack功能
为现代js应用提供静态模块打包
- 将不同类型资源按模块处理进行打包
- 静态:打包后最终产出静态资源
- webpack支持不同规范的模块化开发(怎么解决的不同语法问题,比如es6和commonjs)
使用一句话来描述!!webpack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。
webpack和其他打包工具的对比
- rollup:只是提供一个充分利用esm各项特性的高效打包器,构建出结构扁平,性能出众的类库。 而且tree-shaking是rollup提出的,这是因为rollup只处理esm,esm所有的依赖都是确定的,能够对代码进行静态分析。不需要依靠运行时去确定依赖关系,在构建一些lib的时候可以选择rollup, 而在构建一些应用的时候,选择webpack。
- Vite:基于原生 ESM,冷启动快(无需打包)。
核心组成
- entry,以起点打包,可抽象成输入
- module:模块,webpack中一切皆为模块,一个模块对应着一个文件,webpack会从配置的entry开始递归找到所有依赖的模块
- chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
- loader: 识别非js文件,因为 webpack只能理解 js 和 json 文件,loader 能将他们转换为有效模块
- plugin:打包的优化和压缩,一些扩展插件,解决loader无法完成的事情
- output:打包后的资源 bundle输出,告诉webpack在哪里输出所创建的bundle
loader
loader属性如下:
- test 属性,识别出哪些文件会被转换。
- use 属性,定义出在进行转换时,应该使用哪个 loader。
postcss-loader
这个loader是使用js转换样式的工具,它根据兼容性,来附加css样式,比如添加前缀webkit-等等。
{
test: /\.css$/,
use: ['style-loader', 'css-loader',
{
loader:'postcss-loader',
options:{
postcssOptions:{
plugins:[
require('autoprefixer')
]
}
}
}],
},以下是关于 style-loader、css-loader 和 postcss-loader 的作用、联系与协作流程的详细解析,结合 Webpack 工作流和实践场景:
核心作用对比
| Loader | 核心作用 | 典型场景 |
|---|---|---|
| style-loader | 将 CSS 注入 DOM(通过 <style> 标签或 CSSOM API) | 开发环境,实现 CSS 热更新(HMR) |
| css-loader | 解析 CSS 文件中的 @import 和 url() 依赖,支持 CSS 模块化(CSS Modules) | 处理 CSS 依赖关系,生成模块化类名 |
| postcss-loader | 通过 PostCSS 插件处理 CSS(如添加前缀、压缩、转换新语法) | 兼容性处理、代码优化、未来 CSS 语法转换 |
协作流程与执行顺序
在 Webpack 中,这三个 Loader 协同处理 CSS 文件,执行顺序为: postcss-loader → css-loader → style-loader (注意:Loader 从右向左执行,配置时需倒序书写)
处理流程示例:
假设处理一个包含 @import 和 CSS 嵌套语法的文件 app.css:
/* app.css */
@import "./reset.css";
.container {
display: flex;
& .item { color: red; }
}postcss-loader
- 使用
Autoprefixer添加浏览器前缀。 - 使用
postcss-preset-env转换嵌套语法。 - 输出:css
.container { display: -webkit-box; display: -ms-flexbox; display: flex; } .container .item { color: red; }
- 使用
css-loader
- 解析
@import "./reset.css",将其内容合并到当前文件。 - 若启用 CSS Modules,生成哈希类名(如
.container_1x2y3z)。 - 输出:包含所有依赖的 CSS 内容 + 模块映射表(用于 JS 导入)。
- 解析
style-loader
- 将最终 CSS 代码注入到 HTML 的
<style>标签中。 - 开发环境下支持 HMR(修改 CSS 后自动更新样式)。
- 将最终 CSS 代码注入到 HTML 的
file-loader 和 url-loader
当初在做qiankun嵌入时遇到一个问题的,element-ui找不到图标路径,体会到大文件不适合转为base64后内联,因为可能影响首屏加载速度 以下是关于 file-loader 和 url-loader 的核心作用、区别及实践场景的总结,结合 Webpack 工作流和性能优化策略:
一、主要区别
| Loader | 核心作用 | 关键特性 |
|---|---|---|
| file-loader | 处理文件(图片、字体等),将其复制到输出目录,并返回文件路径的公共 URL | 直接输出文件,不修改内容 |
| url-loader | 基于文件大小阈值,将小文件转换为 Base64 内联 URL,大文件回退到 file-loader | 减少 HTTP 请求,小文件内联优化 |
联系:
url-loader是file-loader的增强版,二者通常配合使用。- 当文件体积小于指定阈值时,
url-loader将文件转换为 Base64 URL;超过阈值时,自动调用file-loader输出文件。
二、基础配置
- file-loader 基础配置
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[hash:8].[ext]', // 输出文件名格式
outputPath: 'images/', // 输出目录
publicPath: '/dist/images/' // 公共访问路径(CDN 场景需配置)
}
}
]
}
]
}
};效果:
- 输入文件
logo.png→ 输出为/dist/images/logo.a1b2c3d4.png - 在 JS/CSS 中引用时返回该路径:
url('/dist/images/logo.a1b2c3d4.png')
- url-loader 配置(含回退机制)
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // 小于 8KB 的文件转为 Base64
name: '[name].[hash:8].[ext]',
outputPath: 'images/',
fallback: 'file-loader' // 超过 limit 时使用 file-loader
}
}
]
}
]
}
};效果:
- 若文件
icon.png(5KB)→ 转换为 Base64 字符串:url('data:image/png;base64,...') - 若文件
banner.jpg(12KB)→ 回退到file-loader,输出为/dist/images/banner.a1b2c3d4.jpg
三、应用场景对比
| 场景 | 推荐 Loader | 原因 |
|---|---|---|
| 小图标(< 10KB) | url-loader | 内联 Base64 减少 HTTP 请求,提升加载速度 |
| 大图/高清图(> 10KB) | file-loader | 避免 Base64 体积膨胀(Base64 体积比原文件大 ~33%) |
| 字体文件 | file-loader | 字体文件通常较大,直接输出文件更合理 |
| 需要按需加载的图片 | file-loader | 结合懒加载技术(如 loading="lazy"),延迟加载非关键图片 |
四、性能优化注意事项
合理设置
limit阈值- 推荐值:8KB~12KB(根据项目需求调整)。
- 权衡点:Base64 内联虽减少请求,但增加 HTML/CSS/JS 文件体积,可能影响首次加载速度。
文件名哈希处理
- 使用
[hash]或[contenthash]生成唯一文件名,利用浏览器缓存(代码不变时文件名不变)。
- 使用
CDN 路径配置
- 通过
publicPath指定资源在 CDN 上的绝对路径:javascriptoptions: { publicPath: 'https://cdn.example.com/assets/', // CDN 地址 outputPath: 'images/' // 本地输出目录 }
- 通过
五、与其他 Loader 的协作
与
html-loader配合 处理 HTML 中<img>标签引用的图片:javascript// webpack.config.js { test: /\.html$/, use: ['html-loader'] // 解析 HTML 中的图片路径 }与
css-loader配合 处理 CSS 中的url()引用:javascript{ test: /\.css$/, use: [ 'style-loader', 'css-loader', 'postcss-loader' ] }
六、常见问题与解决方案
- 图片路径错误(404)
- 原因:
publicPath配置错误或输出路径未对齐。 - 解决:检查
outputPath和publicPath是否匹配实际部署路径。
- Base64 内联导致 CSS 文件过大
- 现象:CSS 文件体积膨胀,影响首屏加载。
- 解决:调大
url-loader的limit值,减少内联文件数量。
- 字体文件未正确加载
- 原因:未正确配置字体文件的 loader 规则。
- 解决:为字体文件单独配置
file-loader:javascript{ test: /\.(woff2?|eot|ttf|otf)$/, use: [{ loader: 'file-loader', options: { outputPath: 'fonts/' } }] }
七、Webpack 5 内置资源模块 Webpack 5 提供了 Asset Modules,无需额外安装 file-loader 或 url-loader:
// Webpack 5 配置(替代 url-loader/file-loader)
{
test: /\.(png|jpe?g|gif|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8192 // 8KB 以下内联
}
},
generator: {
filename: 'images/[name].[hash:8][ext]' // 输出路径
}
}总结
- 选型策略:
- 优先
url-loader:适用于小文件内联优化。 - 回退
file-loader:处理大文件或需要单独加载的资源。
- 优先
- 性能平衡:根据项目类型(如移动端优先减少请求、PC 端关注缓存)调整
limit值。 - 现代替代:Webpack 5 的 Asset Modules 简化了配置,建议新项目直接使用。
plugin
loader 是用来转换类型,使用的时机是读取资源内容时 plugin 可以在打包的流水线中插入一些操作,比如每次新打包的时候,清空原来的dist目录,打包时css的压缩等等。 补充:plugin本质上就是一个类! 
还有很多其他场景:比如使用插件来实现目录拷贝,开发构建过程中measure构建速度
其他常见配置
babel
浏览器默认是不能识别像jsx ts es6的语法。因此babel将他们转化为浏览器能识别的内容,但是只有babel/core和babel/loader还不够,需要有额外的工具,比如将箭头函数转换为普通函数时,所以还可以配置很多预设。
polyfill
在webpack4中polyfill是默认打包进去的,而在5当中是可选的(为了优化打包速度),比如说有些浏览器不支持promise
热更新
更快模块热更新,一个模块有变更,不会影响到其他模块
resolve模块解析
webpack中的模块解析分为几类,
- 绝对路径
- 相对路径
- 模块名,直接去node_modules下面去查找
还有文件类型,文件还是文件夹,是文件的话要看扩展名,如果没有加扩展名,会默认进行补全,通过extension来配置
runtimeChunk
source-map
为什么使用它,映射的技术,转换后的代码-》源代码 调试时可以定位到源代码中的信息 分环境来配置,vue就是sourcemap 信息默认就是最全的 测试阶段 cheap-module-source-map
dll
目的是打包的时候不再重新打包。 比如vue,react包的更新并不频繁,打包的时候不需要重新打包,因此生成一个动态链接库,访问资源的时候直接访问链接库。
terser
对 js 代码进行处理(简化或者丑化,比如create-》c)
scope hoisting
作用域提升,优化打包速度 做静态分析,判断是否能提升,可以优化查询速度,减小代码体积 底层依赖于es module,这就是开发时要遵循某个规范的原因 在生产模式中,是默认使用的
tree-shaking
tree-shaking就是去除掉并未使用掉的模块的代码,减小打包体积 首先要明确的一点是commonjs不适合使用tree-shaking,
webpack和gulp
Webpack 已覆盖 80% 的 Gulp 场景:通过插件和 Loader 可高效处理资源压缩、合并、哈希等任务。 Gulp 退居边缘场景:仅用于复杂文件流、跨技术栈任务或遗留系统维护。
webpack4
webpack5
优化相关
配置优化
基础类库分包