Skip to content

Webpack basic

现代web开发的问题

  1. 不同浏览器对模块化的支持不一样,模块化本身有不同的设计规范
  2. 开发过程中为了提高效率,比如使用一些新特性如ts,sass,但是浏览器是不能直接识别这些资源的
  3. 实时监听开发过程使用热更新
  4. 项目结果打包压缩优化

webpack就是解决这样的事情,让开发者不关心过程,但是结果一定是可以在浏览器正常运行的代码。

webpack功能

为现代js应用提供静态模块打包

  1. 将不同类型资源按模块处理进行打包
  2. 静态:打包后最终产出静态资源
  3. webpack支持不同规范的模块化开发(怎么解决的不同语法问题,比如es6和commonjs)

使用一句话来描述!!webpack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。

webpack和其他打包工具的对比

  1. rollup:只是提供一个充分利用esm各项特性的高效打包器,构建出结构扁平,性能出众的类库。 而且tree-shaking是rollup提出的,这是因为rollup只处理esm,esm所有的依赖都是确定的,能够对代码进行静态分析。不需要依靠运行时去确定依赖关系,在构建一些lib的时候可以选择rollup, 而在构建一些应用的时候,选择webpack。
  2. Vite:基于原生 ESM,冷启动快(无需打包)。

核心组成

  1. entry,以起点打包,可抽象成输入
  2. module:模块,webpack中一切皆为模块,一个模块对应着一个文件,webpack会从配置的entry开始递归找到所有依赖的模块
  3. chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
  4. loader: 识别非js文件,因为 webpack只能理解 js 和 json 文件,loader 能将他们转换为有效模块
  5. plugin:打包的优化和压缩,一些扩展插件,解决loader无法完成的事情
  6. output:打包后的资源 bundle输出,告诉webpack在哪里输出所创建的bundle

loader

loader属性如下:

  • test 属性,识别出哪些文件会被转换。
  • use 属性,定义出在进行转换时,应该使用哪个 loader。

postcss-loader

这个loader是使用js转换样式的工具,它根据兼容性,来附加css样式,比如添加前缀webkit-等等。

js
{
  test: /\.css$/,
    use: ['style-loader', 'css-loader',
  {
    loader:'postcss-loader',
    options:{
      postcssOptions:{
        plugins:[
          require('autoprefixer')
        ]
      }
    }
  }],
},

以下是关于 style-loadercss-loaderpostcss-loader 的作用、联系与协作流程的详细解析,结合 Webpack 工作流和实践场景:


核心作用对比

Loader核心作用典型场景
style-loader将 CSS 注入 DOM(通过 <style> 标签或 CSSOM API)开发环境,实现 CSS 热更新(HMR)
css-loader解析 CSS 文件中的 @importurl() 依赖,支持 CSS 模块化(CSS Modules)处理 CSS 依赖关系,生成模块化类名
postcss-loader通过 PostCSS 插件处理 CSS(如添加前缀、压缩、转换新语法)兼容性处理、代码优化、未来 CSS 语法转换

协作流程与执行顺序

在 Webpack 中,这三个 Loader 协同处理 CSS 文件,执行顺序为: postcss-loadercss-loaderstyle-loader (注意:Loader 从右向左执行,配置时需倒序书写)

处理流程示例:

假设处理一个包含 @import 和 CSS 嵌套语法的文件 app.css

css
/* app.css */
@import "./reset.css";

.container {
  display: flex;
  & .item { color: red; }
}
  1. postcss-loader

    • 使用 Autoprefixer 添加浏览器前缀。
    • 使用 postcss-preset-env 转换嵌套语法。
    • 输出
      css
      .container {
        display: -webkit-box;
        display: -ms-flexbox;
        display: flex;
      }
      .container .item { color: red; }
  2. css-loader

    • 解析 @import "./reset.css",将其内容合并到当前文件。
    • 若启用 CSS Modules,生成哈希类名(如 .container_1x2y3z)。
    • 输出:包含所有依赖的 CSS 内容 + 模块映射表(用于 JS 导入)。
  3. style-loader

    • 将最终 CSS 代码注入到 HTML 的 <style> 标签中。
    • 开发环境下支持 HMR(修改 CSS 后自动更新样式)。

file-loader 和 url-loader

当初在做qiankun嵌入时遇到一个问题的,element-ui找不到图标路径,体会到大文件不适合转为base64后内联,因为可能影响首屏加载速度 以下是关于 file-loaderurl-loader 的核心作用、区别及实践场景的总结,结合 Webpack 工作流和性能优化策略:


一、主要区别

Loader核心作用关键特性
file-loader处理文件(图片、字体等),将其复制到输出目录,并返回文件路径的公共 URL直接输出文件,不修改内容
url-loader基于文件大小阈值,将小文件转换为 Base64 内联 URL,大文件回退到 file-loader减少 HTTP 请求,小文件内联优化

联系

  • url-loaderfile-loader 的增强版,二者通常配合使用。
  • 当文件体积小于指定阈值时,url-loader 将文件转换为 Base64 URL;超过阈值时,自动调用 file-loader 输出文件。

二、基础配置

  1. file-loader 基础配置
javascript
// 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')

  1. url-loader 配置(含回退机制)
javascript
// 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"),延迟加载非关键图片

四、性能优化注意事项

  1. 合理设置 limit 阈值

    • 推荐值:8KB~12KB(根据项目需求调整)。
    • 权衡点:Base64 内联虽减少请求,但增加 HTML/CSS/JS 文件体积,可能影响首次加载速度。
  2. 文件名哈希处理

    • 使用 [hash][contenthash] 生成唯一文件名,利用浏览器缓存(代码不变时文件名不变)。
  3. CDN 路径配置

    • 通过 publicPath 指定资源在 CDN 上的绝对路径:
      javascript
      options: {
        publicPath: 'https://cdn.example.com/assets/', // CDN 地址
        outputPath: 'images/' // 本地输出目录
      }

五、与其他 Loader 的协作

  1. html-loader 配合 处理 HTML 中 <img> 标签引用的图片:

    javascript
    // webpack.config.js
    {
      test: /\.html$/,
      use: ['html-loader'] // 解析 HTML 中的图片路径
    }
  2. css-loader 配合 处理 CSS 中的 url() 引用:

    javascript
    {
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader',
        'postcss-loader'
      ]
    }

六、常见问题与解决方案

  1. 图片路径错误(404)
  • 原因publicPath 配置错误或输出路径未对齐。
  • 解决:检查 outputPathpublicPath 是否匹配实际部署路径。
  1. Base64 内联导致 CSS 文件过大
  • 现象:CSS 文件体积膨胀,影响首屏加载。
  • 解决:调大 url-loaderlimit 值,减少内联文件数量。
  1. 字体文件未正确加载
  • 原因:未正确配置字体文件的 loader 规则。
  • 解决:为字体文件单独配置 file-loader
    javascript
    {
      test: /\.(woff2?|eot|ttf|otf)$/,
      use: [{
        loader: 'file-loader',
        options: { outputPath: 'fonts/' }
      }]
    }

七、Webpack 5 内置资源模块 Webpack 5 提供了 Asset Modules,无需额外安装 file-loaderurl-loader

javascript
// 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本质上就是一个类! image.png
还有很多其他场景:比如使用插件来实现目录拷贝,开发构建过程中measure构建速度

其他常见配置

babel

浏览器默认是不能识别像jsx ts es6的语法。因此babel将他们转化为浏览器能识别的内容,但是只有babel/core和babel/loader还不够,需要有额外的工具,比如将箭头函数转换为普通函数时,所以还可以配置很多预设。

polyfill

在webpack4中polyfill是默认打包进去的,而在5当中是可选的(为了优化打包速度),比如说有些浏览器不支持promise

热更新

更快模块热更新,一个模块有变更,不会影响到其他模块

resolve模块解析

webpack中的模块解析分为几类,

  1. 绝对路径
  2. 相对路径
  3. 模块名,直接去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

优化相关

配置优化

基础类库分包

打包构建优化

  1. 多线程
  2. 文件系统缓存 https://juejin.cn/post/7148366005301952525