Skip to content

图片

导入图像

webpack4 常用 file-loaderurl-loaderraw-loader,处理图像的加载

webpack5 内置了 file-loaderurl-loaderraw-loader,只需要通过 module.rules.type 属性指定资源类型即可

asset/resource

  • 4 使用 file-loader,原始图片会被重命名并复制到产物文件夹,同时在代码中插入图片 URL 地址
js
module.exports = {
  module: {
    rules: [{
      test: /\.(png|jpg)$/,
      use: ['file-loader']
    }],
  },
};
  • 5 添加 asset/resource,起到与 file-loader 同样的效果
diff
module.exports = {
  module: {
    rules: [{
      test: /\.(png|jpg)$/,
-     use: ['file-loader']
+     type: 'asset/resource'
    }],
  },
};

asset 或 asset/inline

  • 4 使用 url-loader,对于小于阈值 limit 的图像直接转化为 base64 编码;大于阈值的图像则调用 file-loader 进行加载
js
module.exports = {
  // ...
  module: {
    rules: [{
      test: /\.(png|jpg)$/,
      use: [{
        loader: 'url-loader',
        options: {
          limit: 1024 // 小于 1024B 的图片会被转译为 Base64 编码
        }
      }]
    }],
  },
};
diff
module.exports = {
  module: {
    rules: [{
      test: /\.(png|jpg)$/,
-     use: [{
-       loader: 'url-loader',
-       options: {
-         limit: 1024
-       }
-     }]
+     type: "asset",
+     parser: {
+        dataUrlCondition: {
+          maxSize: 1024
+        }
+     }
    }],
  },
};

asset/source

  • 4 使用 raw-loader,可以将 SVG 资源直接复制成字符串形式
js
module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/i,
        use: ['raw-loader'],
      },
    ],
  },
};
  • 5 添加 asset/source,起到与 raw-loader 同样的效果
diff
module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/i,
-       use: ['raw-loader']
+       type: "asset/source"
      },
    ],
  },
};

webpack5 引入 module.rules.type 并不只是为了取代 Loader 那么简单,更重要的目的是在 JavaScript Module 之外增加对其它资源 —— Asset Module 的原生支持,让 Webpack 有机会介入这些多媒体资源的解析、生成过程,从而有机会实现更标准、高效的资源处理模型

目前 module.rules.type 已经支持 JSON、WebAssemsbly、二进制、文本等资源类型

优化:压缩

image-webpack-loader 组件功能齐全且用法简单,可以方便简易的达到压缩效果

  1. 安装依赖
shell
npm i -D image-webpack-loader
  1. 配置
js
module.exports = {
  // ...
  module: {
    rules: [{
      test: /\.(gif|png|jpe?g|svg)$/i,
      // type 属性适用于 Webpack5,旧版本可使用 file-loader
      type: "asset/resource",
      use: [{
        loader: 'image-webpack-loader',
        options: {
          // jpeg 压缩配置
          mozjpeg: {
            quality: 80
          },
        }
      }]
    }],
  },
};

image-webpack-loader 底层依赖于 imagemin 及一系列的图像优化工具:

  • mozjpeg:用于压缩 JPG(JPEG) 图片;
  • optipng:用于压缩 PNG 图片;
  • pngquant:同样用于压缩 PNG 图片;
  • svgo:用于压缩 SVG 图片;
  • gifsicle:用于压缩 Gif 图;
  • webp:用于将 JPG/PNG 图压缩并转化为 WebP 图片格式。

图像压缩是一种非常耗时的操作,建议只在生产环境下开启:

diff
{
    loader: 'image-webpack-loader',
    options: {
+     disable: process.env.NODE_ENV !== 'production'
    }
}

优化:响应式图片

响应式图片:同一张图片(主要是位图)在不同设备中,如果显示尺寸大于原始尺寸,最终效果会有明显颗粒感;而如果显示尺寸小于原始尺寸,又会造成带宽浪费。理想的解决方案是为不同设备提供不同的分辨率、不同尺寸的图片

  1. 安装依赖:
shell
npm i -D responsive-loader sharp
  1. 配置

    实践中我们通常没必要对项目里所有图片都施加响应式特性,因此这里使用 resourceQuery 过滤出带 size/sizes 参数的图片引用

js
module.exports = {
  // ...
  module: {
    rules: [{
      test: /\.(png|jpg)$/,
      oneOf: [{
        type: "javascript/auto",
        resourceQuery: /sizes?/,
        use: [{
          loader: "responsive-loader",
          options: {
            adapter: require("responsive-loader/sharp"),
          },
        }],
      }, {
        type: "asset/resource",
      }],
    }],
  }
};
  1. 引入图片

    最终将生成宽度分别为 300、600、1024 三张图片

js
import responsiveImage from './webpack.jpg?sizes[]=300,sizes[]=600,sizes[]=1024';

const Picture = function () {
  return (
    <img
      srcSet={responsiveImage.srcSet}
      src={responsiveImage.src}
      sizes="(min-width: 1024px) 1024px, 100vw"
      loading="lazy"
    />
  );
};