UNPKG

4.51 kBJavaScriptView Raw
1"use strict";
2
3var _path = _interopRequireDefault(require("path"));
4
5var _worker = _interopRequireDefault(require("./worker"));
6
7var _loaderOptions = _interopRequireDefault(require("./loader-options.json"));
8
9var _utils = require("./utils.js");
10
11function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
13/** @typedef {import("schema-utils/declarations/validate").Schema} Schema */
14
15/** @typedef {import("webpack").Compilation} Compilation */
16
17/**
18 * @template T
19 * @typedef {Object} LoaderOptions<T>
20 * @property {string} [severityError] Allows to choose how errors are displayed.
21 * @property {import("./index").Minimizer<T> | import("./index").Minimizer<T>[]} [minimizer]
22 * @property {import("./index").Generator<T>[]} [generator]
23 */
24
25/**
26 * @template T
27 * @this {import("webpack").LoaderContext<LoaderOptions<T>>}
28 * @param {Buffer} content
29 */
30module.exports = async function loader(content) {
31 // Avoid optimize twice
32 if (this._module && this._module.buildMeta && this._module.buildMeta.imageMinimizerPluginInfo && (this._module.buildMeta.imageMinimizerPluginInfo.minimized || this._module.buildMeta.imageMinimizerPluginInfo.generated)) {
33 return content;
34 } // @ts-ignore
35
36
37 const options = this.getOptions(
38 /** @type {Schema} */
39 _loaderOptions.default);
40 const callback = this.async();
41 const {
42 generator,
43 minimizer,
44 severityError
45 } = options;
46
47 if (!minimizer && !generator) {
48 callback(new Error("Not configured 'minimizer' or 'generator' options, please setup them"));
49 return;
50 }
51
52 let transformer = minimizer;
53 let parsedQuery;
54
55 if (this.resourceQuery.length > 0) {
56 parsedQuery = new URLSearchParams(this.resourceQuery);
57
58 if (parsedQuery.has("as")) {
59 if (!generator) {
60 callback(new Error("Please specify the 'generator' option to use 'as' query param for generation purposes."));
61 return;
62 }
63
64 const as = parsedQuery.get("as");
65 const presets = generator.filter(item => item.preset === as);
66
67 if (presets.length > 1) {
68 callback(new Error("Found several identical pereset names, the 'preset' option should be unique"));
69 return;
70 }
71
72 if (presets.length === 0) {
73 callback(new Error(`Can't find '${as}' preset in the 'generator' option`));
74 return;
75 }
76
77 [transformer] = presets;
78 }
79 }
80
81 if (!transformer) {
82 callback(null, content);
83 return;
84 }
85
86 const isAbsolute = (0, _utils.isAbsoluteURL)(this.resourcePath);
87 const filename = isAbsolute ? this.resourcePath : _path.default.relative(this.rootContext, this.resourcePath);
88 const minifyOptions =
89 /** @type {import("./index").InternalWorkerOptions<T>} */
90 {
91 input: content,
92 filename,
93 severityError,
94 transformer,
95 generateFilename:
96 /** @type {Compilation} */
97 this._compilation.getAssetPath.bind(this._compilation)
98 };
99 const output = await (0, _worker.default)(minifyOptions);
100
101 if (output.errors && output.errors.length > 0) {
102 output.errors.forEach(error => {
103 this.emitError(error);
104 });
105 callback(null, content);
106 return;
107 }
108
109 if (output.warnings && output.warnings.length > 0) {
110 output.warnings.forEach(warning => {
111 this.emitWarning(warning);
112 });
113 } // Change content of the data URI after minimizer
114
115
116 if (this._module && this._module.resourceResolveData && this._module.resourceResolveData.encodedContent) {
117 // console.log(content.toString())
118 this._module.resourceResolveData.encodedContent = output.data.toString("base64");
119 } else {
120 let query = this.resourceQuery;
121
122 if (parsedQuery) {
123 // Remove query param from the bundle due we need that only for bundle purposes
124 const stringifiedParsedQuery = parsedQuery.toString();
125 query = stringifiedParsedQuery.length > 0 ? `?${stringifiedParsedQuery}` : "";
126 parsedQuery.delete("as");
127 } // Old approach for `file-loader` and other old loaders
128
129
130 this.resourcePath = isAbsolute ? output.filename : _path.default.join(this.rootContext, output.filename);
131 this.resourceQuery = query; // Change name of assets modules after generator
132
133 if (this._module && !this._module.matchResource) {
134 this._module.matchResource = `${output.filename}${query}`;
135 }
136 } // TODO: search better API
137
138
139 if (this._module) {
140 this._module.buildMeta = { ...this._module.buildMeta,
141 imageMinimizerPluginInfo: output.info
142 };
143 }
144
145 callback(null, output.data);
146};
147
148module.exports.raw = true;
\No newline at end of file