@rsbuild/plugin-image-compress 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,6 +31,8 @@ export default {
31
31
  };
32
32
  ```
33
33
 
34
+ This plugin is compatible with both Rsbuild and Rspack. If you are using Rspack instead of Rsbuild, you can import the `ImageMinimizerPlugin` from the package, see [Rspack Usage](#rspack-usage).
35
+
34
36
  ## Default Compressors
35
37
 
36
38
  By default, the plugin will enable `jpeg`, `png`, `ico` image compressors, which are equivalent to the following two examples:
@@ -98,6 +100,52 @@ For example, the `png` compressor will take precedence over the `pngLossless` co
98
100
  pluginImageCompress(["jpeg", "pngLossless", "ico", "png"]);
99
101
  ```
100
102
 
103
+ ## Rspack Usage
104
+
105
+ The plugin is also compatible with Rspack.
106
+
107
+ If you are using Rspack instead of Rsbuild, you can import the `ImageMinimizerPlugin` from the package, use it in the [optimization.minimizer](https://rspack.dev/config/optimization#optimizationminimizer) array.
108
+
109
+ ```ts
110
+ // rspack.config.mjs
111
+ import { ImageMinimizerPlugin } from "@rsbuild/plugin-image-compress";
112
+ import { defineConfig } from "@rspack/cli";
113
+
114
+ export default defineConfig({
115
+ mode: process.env.NODE_ENV === "production" ? "production" : "development",
116
+ optimization: {
117
+ minimizer: [
118
+ // Use `...` to preserve the default JS and CSS minimizers of Rspack
119
+ '...',
120
+ // Add the image minimizer plugins
121
+ new ImageMinimizerPlugin({
122
+ use: "jpeg",
123
+ test: /\.(?:jpg|jpeg)$/,
124
+ }),
125
+ new ImageMinimizerPlugin({
126
+ use: "png",
127
+ test: /\.png$/,
128
+ maxQuality: 50,
129
+ }),
130
+ new ImageMinimizerPlugin({
131
+ use: "avif",
132
+ test: /\.avif$/,
133
+ quality: 80,
134
+ }),
135
+ new ImageMinimizerPlugin({
136
+ use: "svg",
137
+ test: /\.svg$/,
138
+ floatPrecision: 2,
139
+ }),
140
+ new ImageMinimizerPlugin({
141
+ use: "ico",
142
+ test: /\.(?:ico|icon)$/,
143
+ }),
144
+ ],
145
+ },
146
+ });
147
+ ```
148
+
101
149
  ## License
102
150
 
103
151
  [MIT](./LICENSE).
package/dist/index.cjs CHANGED
@@ -1,40 +1,27 @@
1
1
  "use strict";
2
- // The require scope
3
2
  var __webpack_require__ = {};
4
- /************************************************************************/ // webpack/runtime/compat_get_default_export
5
3
  (()=>{
6
- // getDefaultExport function for compatibility with non-ESM modules
7
- __webpack_require__.n = function(module) {
8
- var getter = module && module.__esModule ? function() {
9
- return module['default'];
10
- } : function() {
11
- return module;
12
- };
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
13
6
  __webpack_require__.d(getter, {
14
7
  a: getter
15
8
  });
16
9
  return getter;
17
10
  };
18
11
  })();
19
- // webpack/runtime/define_property_getters
20
12
  (()=>{
21
- __webpack_require__.d = function(exports1, definition) {
13
+ __webpack_require__.d = (exports1, definition)=>{
22
14
  for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
23
15
  enumerable: true,
24
16
  get: definition[key]
25
17
  });
26
18
  };
27
19
  })();
28
- // webpack/runtime/has_own_property
29
20
  (()=>{
30
- __webpack_require__.o = function(obj, prop) {
31
- return Object.prototype.hasOwnProperty.call(obj, prop);
32
- };
21
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
33
22
  })();
34
- // webpack/runtime/make_namespace_object
35
23
  (()=>{
36
- // define __esModule on exports
37
- __webpack_require__.r = function(exports1) {
24
+ __webpack_require__.r = (exports1)=>{
38
25
  if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
39
26
  value: 'Module'
40
27
  });
@@ -43,14 +30,13 @@ var __webpack_require__ = {};
43
30
  });
44
31
  };
45
32
  })();
46
- /************************************************************************/ var __webpack_exports__ = {};
47
- // ESM COMPAT FLAG
33
+ var __webpack_exports__ = {};
48
34
  __webpack_require__.r(__webpack_exports__);
49
- // EXPORTS
50
35
  __webpack_require__.d(__webpack_exports__, {
51
- DEFAULT_OPTIONS: ()=>/* binding */ DEFAULT_OPTIONS,
52
- pluginImageCompress: ()=>/* binding */ pluginImageCompress,
53
- PLUGIN_IMAGE_COMPRESS_NAME: ()=>/* binding */ PLUGIN_IMAGE_COMPRESS_NAME
36
+ pluginImageCompress: ()=>pluginImageCompress,
37
+ DEFAULT_OPTIONS: ()=>DEFAULT_OPTIONS,
38
+ PLUGIN_IMAGE_COMPRESS_NAME: ()=>PLUGIN_IMAGE_COMPRESS_NAME,
39
+ ImageMinimizerPlugin: ()=>ImageMinimizerPlugin
54
40
  });
55
41
  const external_node_assert_namespaceObject = require("node:assert");
56
42
  var external_node_assert_default = /*#__PURE__*/ __webpack_require__.n(external_node_assert_namespaceObject);
@@ -107,8 +93,7 @@ const svgCodec = {
107
93
  test: /\.svg$/
108
94
  }
109
95
  };
110
- // biome-ignore lint/suspicious/noExplicitAny:allow any
111
- const codecs = {
96
+ const codecs_codecs = {
112
97
  jpeg: jpegCodec,
113
98
  png: pngCodec,
114
99
  pngLossless: pngLosslessCodec,
@@ -116,7 +101,7 @@ const codecs = {
116
101
  svg: svgCodec,
117
102
  avif: avifCodec
118
103
  };
119
- /* ESM default export */ const shared_codecs = codecs;
104
+ const codecs = codecs_codecs;
120
105
  function _define_property(obj, key, value) {
121
106
  if (key in obj) Object.defineProperty(obj, key, {
122
107
  value: value,
@@ -140,7 +125,7 @@ class ImageMinimizerPlugin {
140
125
  if (error instanceof Error) ret.error = error;
141
126
  return ret;
142
127
  };
143
- const codec = shared_codecs[this.options.use];
128
+ const codec = codecs[this.options.use];
144
129
  if (!codec) compilation.errors.push(buildError(new Error(`Codec ${this.options.use} is not supported`)));
145
130
  const opts = {
146
131
  ...codec.defaultOptions,
@@ -150,8 +135,6 @@ class ImageMinimizerPlugin {
150
135
  var _compilation_getAsset;
151
136
  const info = null === (_compilation_getAsset = compilation.getAsset(name)) || void 0 === _compilation_getAsset ? void 0 : _compilation_getAsset.info;
152
137
  const fileName = name.split('?')[0];
153
- // 1. Skip double minimize assets from child compilation
154
- // 2. Test file by options (e.g. test, include, exclude)
155
138
  if ((null == info ? void 0 : info.minimized) || !matchObject(opts, fileName)) return;
156
139
  const asset = compilation.getAsset(name);
157
140
  if (!asset) return;
@@ -162,7 +145,7 @@ class ImageMinimizerPlugin {
162
145
  try {
163
146
  if (!result) {
164
147
  const input = inputSource.source();
165
- const buf = await codec.handler(external_node_buffer_namespaceObject.Buffer.from(input), opts);
148
+ const buf = await codec.handler('string' == typeof input ? external_node_buffer_namespaceObject.Buffer.from(input) : input, opts);
166
149
  result = {
167
150
  source: new RawSource(buf)
168
151
  };
@@ -183,7 +166,6 @@ class ImageMinimizerPlugin {
183
166
  compilation.hooks.processAssets.tapPromise({
184
167
  name: this.name,
185
168
  stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE,
186
- // @ts-expect-error unsupported by Rspack
187
169
  additionalAssets: true
188
170
  }, (assets)=>this.optimize(compiler, compilation, assets));
189
171
  compilation.hooks.statsPrinter.tap(this.name, (stats)=>{
@@ -202,7 +184,7 @@ const withDefaultOptions = (opt)=>{
202
184
  const options = 'string' == typeof opt ? {
203
185
  use: opt
204
186
  } : opt;
205
- const { defaultOptions } = shared_codecs[options.use];
187
+ const { defaultOptions } = codecs[options.use];
206
188
  const ret = {
207
189
  ...defaultOptions,
208
190
  ...options
@@ -217,9 +199,7 @@ const DEFAULT_OPTIONS = [
217
199
  ];
218
200
  const castOptions = (args)=>{
219
201
  const head = args[0];
220
- // expect [['png', { use: 'jpeg' }]]
221
202
  if (Array.isArray(head)) return head;
222
- // expect ['png', { use: 'jpeg' }]
223
203
  const ret = [];
224
204
  for (const arg of args){
225
205
  external_node_assert_default()(!Array.isArray(arg));
@@ -233,7 +213,7 @@ const normalizeOptions = (options)=>{
233
213
  return normalized;
234
214
  };
235
215
  const PLUGIN_IMAGE_COMPRESS_NAME = 'rsbuild:image-compress';
236
- /** Options enable by default: {@link DEFAULT_OPTIONS} */ const pluginImageCompress = (...args)=>({
216
+ const pluginImageCompress = (...args)=>({
237
217
  name: PLUGIN_IMAGE_COMPRESS_NAME,
238
218
  setup (api) {
239
219
  const opts = normalizeOptions(castOptions(args));
@@ -246,8 +226,16 @@ const PLUGIN_IMAGE_COMPRESS_NAME = 'rsbuild:image-compress';
246
226
  });
247
227
  }
248
228
  });
249
- var __webpack_export_target__ = exports;
250
- for(var __webpack_i__ in __webpack_exports__)__webpack_export_target__[__webpack_i__] = __webpack_exports__[__webpack_i__];
251
- if (__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, '__esModule', {
229
+ exports.DEFAULT_OPTIONS = __webpack_exports__.DEFAULT_OPTIONS;
230
+ exports.ImageMinimizerPlugin = __webpack_exports__.ImageMinimizerPlugin;
231
+ exports.PLUGIN_IMAGE_COMPRESS_NAME = __webpack_exports__.PLUGIN_IMAGE_COMPRESS_NAME;
232
+ exports.pluginImageCompress = __webpack_exports__.pluginImageCompress;
233
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
234
+ "DEFAULT_OPTIONS",
235
+ "ImageMinimizerPlugin",
236
+ "PLUGIN_IMAGE_COMPRESS_NAME",
237
+ "pluginImageCompress"
238
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
239
+ Object.defineProperty(exports, '__esModule', {
252
240
  value: true
253
241
  });
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { RsbuildPlugin } from '@rsbuild/core';
2
+ import { ImageMinimizerPlugin } from './minimizer.js';
2
3
  import type { Codecs, Options } from './types.js';
3
4
  export type PluginImageCompressOptions = Options[];
4
5
  export declare const DEFAULT_OPTIONS: Codecs[];
@@ -7,5 +8,6 @@ export interface IPluginImageCompress {
7
8
  (options: Options[]): RsbuildPlugin;
8
9
  }
9
10
  export declare const PLUGIN_IMAGE_COMPRESS_NAME = "rsbuild:image-compress";
11
+ export { ImageMinimizerPlugin };
10
12
  /** Options enable by default: {@link DEFAULT_OPTIONS} */
11
13
  export declare const pluginImageCompress: IPluginImageCompress;
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import * as __WEBPACK_EXTERNAL_MODULE_node_assert__ from "node:assert";
2
- import * as __WEBPACK_EXTERNAL_MODULE_node_buffer__ from "node:buffer";
3
- import * as __WEBPACK_EXTERNAL_MODULE__napi_rs_image__ from "@napi-rs/image";
1
+ import * as __WEBPACK_EXTERNAL_MODULE_node_assert_3e74d44e__ from "node:assert";
2
+ import * as __WEBPACK_EXTERNAL_MODULE_node_buffer_fb286294__ from "node:buffer";
3
+ import * as __WEBPACK_EXTERNAL_MODULE__napi_rs_image_caba25d1__ from "@napi-rs/image";
4
4
  import * as __WEBPACK_EXTERNAL_MODULE_svgo__ from "svgo";
5
5
  const jpegCodec = {
6
6
  handler (buf, options) {
7
- return (0, __WEBPACK_EXTERNAL_MODULE__napi_rs_image__.compressJpeg)(buf, options);
7
+ return (0, __WEBPACK_EXTERNAL_MODULE__napi_rs_image_caba25d1__.compressJpeg)(buf, options);
8
8
  },
9
9
  defaultOptions: {
10
10
  test: /\.(?:jpg|jpeg)$/
@@ -12,7 +12,7 @@ const jpegCodec = {
12
12
  };
13
13
  const pngCodec = {
14
14
  handler (buf, options) {
15
- return (0, __WEBPACK_EXTERNAL_MODULE__napi_rs_image__.pngQuantize)(buf, options);
15
+ return (0, __WEBPACK_EXTERNAL_MODULE__napi_rs_image_caba25d1__.pngQuantize)(buf, options);
16
16
  },
17
17
  defaultOptions: {
18
18
  test: /\.png$/
@@ -20,7 +20,7 @@ const pngCodec = {
20
20
  };
21
21
  const pngLosslessCodec = {
22
22
  handler (buf, options) {
23
- return (0, __WEBPACK_EXTERNAL_MODULE__napi_rs_image__.losslessCompressPng)(buf, options);
23
+ return (0, __WEBPACK_EXTERNAL_MODULE__napi_rs_image_caba25d1__.losslessCompressPng)(buf, options);
24
24
  },
25
25
  defaultOptions: {
26
26
  test: /\.png$/
@@ -28,7 +28,7 @@ const pngLosslessCodec = {
28
28
  };
29
29
  const icoCodec = {
30
30
  handler (buf) {
31
- return new __WEBPACK_EXTERNAL_MODULE__napi_rs_image__.Transformer(buf).ico();
31
+ return new __WEBPACK_EXTERNAL_MODULE__napi_rs_image_caba25d1__.Transformer(buf).ico();
32
32
  },
33
33
  defaultOptions: {
34
34
  test: /\.(?:ico|icon)$/
@@ -36,7 +36,7 @@ const icoCodec = {
36
36
  };
37
37
  const avifCodec = {
38
38
  handler (buf, options) {
39
- return new __WEBPACK_EXTERNAL_MODULE__napi_rs_image__.Transformer(buf).avif(options);
39
+ return new __WEBPACK_EXTERNAL_MODULE__napi_rs_image_caba25d1__.Transformer(buf).avif(options);
40
40
  },
41
41
  defaultOptions: {
42
42
  test: /\.avif$/
@@ -45,14 +45,13 @@ const avifCodec = {
45
45
  const svgCodec = {
46
46
  async handler (buf, options) {
47
47
  const result = __WEBPACK_EXTERNAL_MODULE_svgo__["default"].optimize(buf.toString(), options);
48
- return __WEBPACK_EXTERNAL_MODULE_node_buffer__.Buffer.from(result.data);
48
+ return __WEBPACK_EXTERNAL_MODULE_node_buffer_fb286294__.Buffer.from(result.data);
49
49
  },
50
50
  defaultOptions: {
51
51
  test: /\.svg$/
52
52
  }
53
53
  };
54
- // biome-ignore lint/suspicious/noExplicitAny:allow any
55
- const codecs = {
54
+ const codecs_codecs = {
56
55
  jpeg: jpegCodec,
57
56
  png: pngCodec,
58
57
  pngLossless: pngLosslessCodec,
@@ -60,7 +59,7 @@ const codecs = {
60
59
  svg: svgCodec,
61
60
  avif: avifCodec
62
61
  };
63
- /* ESM default export */ const shared_codecs = codecs;
62
+ const codecs = codecs_codecs;
64
63
  function _define_property(obj, key, value) {
65
64
  if (key in obj) Object.defineProperty(obj, key, {
66
65
  value: value,
@@ -84,7 +83,7 @@ class ImageMinimizerPlugin {
84
83
  if (error instanceof Error) ret.error = error;
85
84
  return ret;
86
85
  };
87
- const codec = shared_codecs[this.options.use];
86
+ const codec = codecs[this.options.use];
88
87
  if (!codec) compilation.errors.push(buildError(new Error(`Codec ${this.options.use} is not supported`)));
89
88
  const opts = {
90
89
  ...codec.defaultOptions,
@@ -94,8 +93,6 @@ class ImageMinimizerPlugin {
94
93
  var _compilation_getAsset;
95
94
  const info = null === (_compilation_getAsset = compilation.getAsset(name)) || void 0 === _compilation_getAsset ? void 0 : _compilation_getAsset.info;
96
95
  const fileName = name.split('?')[0];
97
- // 1. Skip double minimize assets from child compilation
98
- // 2. Test file by options (e.g. test, include, exclude)
99
96
  if ((null == info ? void 0 : info.minimized) || !matchObject(opts, fileName)) return;
100
97
  const asset = compilation.getAsset(name);
101
98
  if (!asset) return;
@@ -106,7 +103,7 @@ class ImageMinimizerPlugin {
106
103
  try {
107
104
  if (!result) {
108
105
  const input = inputSource.source();
109
- const buf = await codec.handler(__WEBPACK_EXTERNAL_MODULE_node_buffer__.Buffer.from(input), opts);
106
+ const buf = await codec.handler('string' == typeof input ? __WEBPACK_EXTERNAL_MODULE_node_buffer_fb286294__.Buffer.from(input) : input, opts);
110
107
  result = {
111
108
  source: new RawSource(buf)
112
109
  };
@@ -127,7 +124,6 @@ class ImageMinimizerPlugin {
127
124
  compilation.hooks.processAssets.tapPromise({
128
125
  name: this.name,
129
126
  stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE,
130
- // @ts-expect-error unsupported by Rspack
131
127
  additionalAssets: true
132
128
  }, (assets)=>this.optimize(compiler, compilation, assets));
133
129
  compilation.hooks.statsPrinter.tap(this.name, (stats)=>{
@@ -146,12 +142,12 @@ const withDefaultOptions = (opt)=>{
146
142
  const options = 'string' == typeof opt ? {
147
143
  use: opt
148
144
  } : opt;
149
- const { defaultOptions } = shared_codecs[options.use];
145
+ const { defaultOptions } = codecs[options.use];
150
146
  const ret = {
151
147
  ...defaultOptions,
152
148
  ...options
153
149
  };
154
- (0, __WEBPACK_EXTERNAL_MODULE_node_assert__["default"])('test' in ret);
150
+ (0, __WEBPACK_EXTERNAL_MODULE_node_assert_3e74d44e__["default"])('test' in ret);
155
151
  return ret;
156
152
  };
157
153
  const DEFAULT_OPTIONS = [
@@ -161,12 +157,10 @@ const DEFAULT_OPTIONS = [
161
157
  ];
162
158
  const castOptions = (args)=>{
163
159
  const head = args[0];
164
- // expect [['png', { use: 'jpeg' }]]
165
160
  if (Array.isArray(head)) return head;
166
- // expect ['png', { use: 'jpeg' }]
167
161
  const ret = [];
168
162
  for (const arg of args){
169
- (0, __WEBPACK_EXTERNAL_MODULE_node_assert__["default"])(!Array.isArray(arg));
163
+ (0, __WEBPACK_EXTERNAL_MODULE_node_assert_3e74d44e__["default"])(!Array.isArray(arg));
170
164
  ret.push(arg);
171
165
  }
172
166
  return ret;
@@ -177,7 +171,7 @@ const normalizeOptions = (options)=>{
177
171
  return normalized;
178
172
  };
179
173
  const PLUGIN_IMAGE_COMPRESS_NAME = 'rsbuild:image-compress';
180
- /** Options enable by default: {@link DEFAULT_OPTIONS} */ const pluginImageCompress = (...args)=>({
174
+ const pluginImageCompress = (...args)=>({
181
175
  name: PLUGIN_IMAGE_COMPRESS_NAME,
182
176
  setup (api) {
183
177
  const opts = normalizeOptions(castOptions(args));
@@ -190,4 +184,4 @@ const PLUGIN_IMAGE_COMPRESS_NAME = 'rsbuild:image-compress';
190
184
  });
191
185
  }
192
186
  });
193
- export { DEFAULT_OPTIONS, PLUGIN_IMAGE_COMPRESS_NAME, pluginImageCompress };
187
+ export { DEFAULT_OPTIONS, ImageMinimizerPlugin, PLUGIN_IMAGE_COMPRESS_NAME, pluginImageCompress };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsbuild/plugin-image-compress",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "repository": "https://github.com/rspack-contrib/rsbuild-plugin-image-compress",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -38,14 +38,14 @@
38
38
  },
39
39
  "devDependencies": {
40
40
  "@biomejs/biome": "^1.9.4",
41
- "@playwright/test": "^1.49.0",
42
- "@rsbuild/core": "1.1.6",
43
- "@rslib/core": "^0.1.1",
44
- "@types/node": "^22.10.1",
41
+ "@playwright/test": "^1.51.1",
42
+ "@rsbuild/core": "1.3.1",
43
+ "@rslib/core": "^0.6.1",
44
+ "@types/node": "^22.13.14",
45
45
  "nano-staged": "^0.8.0",
46
- "playwright": "^1.49.0",
47
- "simple-git-hooks": "^2.11.1",
48
- "typescript": "^5.7.2"
46
+ "playwright": "^1.51.1",
47
+ "simple-git-hooks": "^2.12.1",
48
+ "typescript": "^5.8.2"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "@rsbuild/core": "1.x"
@@ -55,7 +55,7 @@
55
55
  "optional": true
56
56
  }
57
57
  },
58
- "packageManager": "pnpm@9.14.4",
58
+ "packageManager": "pnpm@10.7.0",
59
59
  "publishConfig": {
60
60
  "access": "public",
61
61
  "registry": "https://registry.npmjs.org/"