UNPKG

2.92 kBJavaScriptView Raw
1/* eslint-disable @typescript-eslint/no-var-requires */
2/* eslint-disable no-undef */
3/* eslint-disable no-param-reassign */
4const browserslist = require("browserslist");
5// eslint-disable-next-line @typescript-eslint/no-var-requires
6const { readFileSync } = require("fs");
7const path = require("path");
8
9/** @type {import('webpack').library.AbstractLibraryPlugin} */
10class WebpackObsoletePlugin {
11 constructor(options) {
12 const defaultOptions = {
13 name: "obsolete",
14 };
15
16 this.options = {
17 ...defaultOptions,
18 ...options,
19 };
20 }
21
22 /**
23 * Code indentation.
24 *
25 * @param {string} str
26 * @param {number} size
27 */
28 indent(str, size) {
29 return " ".repeat(size) + str.replace(/\n/g, `$&${" ".repeat(size)}`);
30 }
31
32 stringify(json, indent = 2) {
33 return JSON.stringify(json, null, indent)
34 .replace(/"/g, `'`)
35 .replace(/'(\w+)':/g, "$1:");
36 }
37
38 filterObject(object, callback, thisArg) {
39 const ret = {};
40
41 Object.entries(object).forEach(([key, value]) => {
42 if (callback.call(thisArg, value, key, object)) {
43 ret[key] = value;
44 }
45 });
46 return ret;
47 }
48
49 /** @type {import('webpack').library.AbstractLibraryPlugin['apply']} */
50 apply(compiler) {
51 compiler.hooks.compilation.tap(this.constructor.name, (compilation) => {
52 compilation.hooks.processAssets.tap(
53 {
54 name: this.constructor.name,
55 stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_PRE_PROCESS,
56 },
57 () => {
58 const chunk = compilation.addChunk("obsolete");
59 chunk.id = "obsolete";
60 chunk.ids = ["obsolete"];
61 // eslint-disable-next-line no-restricted-syntax
62 for (const entrypoint of compilation.entrypoints.values()) {
63 if (entrypoint.pushChunk(chunk)) {
64 chunk.addGroup(entrypoint);
65 }
66 }
67 const tmpFile = "obsolete.js";
68 chunk.files.add(tmpFile);
69 const { RawSource } = compiler.webpack.sources;
70 const obsoleteFileContent = this.composeCode(this.options);
71
72 compilation.assets[tmpFile] = new RawSource(obsoleteFileContent);
73 compilation.updateAsset(tmpFile, (v) => v);
74 }
75 );
76 });
77 }
78
79 composeCode(context) {
80 const slimOptions = this.filterObject(context, (value) => !["", null, undefined].includes(value));
81 const fileContent = readFileSync(path.resolve(__dirname, "obsolete.js"), {
82 encoding: "utf-8",
83 });
84 return (
85 fileContent +
86 [
87 this.indent(`(function() {`, 0),
88 this.indent(`'use strict';`, 2),
89 this.indent(`obsolete(${this.stringify(browserslist())},${this.stringify(slimOptions)});`, 2),
90 this.indent(`})();\n`, 0),
91 ].join("\n")
92 );
93 }
94}
95module.exports = WebpackObsoletePlugin;