@workleap/webpack-configs 1.5.2 → 1.5.4
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/CHANGELOG.md +35 -23
- package/README.md +2 -2
- package/dist/build.d.ts +18 -19
- package/dist/build.js +219 -3
- package/dist/build.js.map +1 -0
- package/dist/dev.d.ts +16 -17
- package/dist/dev.js +208 -3
- package/dist/dev.js.map +1 -0
- package/dist/index.d.ts +6 -12
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -0
- package/dist/transformers/applyTransformers.d.ts +4 -7
- package/dist/transformers/applyTransformers.js +20 -1
- package/dist/transformers/applyTransformers.js.map +1 -0
- package/dist/transformers/moduleRules.d.ts +15 -17
- package/dist/transformers/moduleRules.js +166 -1
- package/dist/transformers/moduleRules.js.map +1 -0
- package/dist/transformers/plugins.d.ts +11 -14
- package/dist/transformers/plugins.js +69 -1
- package/dist/transformers/plugins.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +6 -1
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +4 -6
- package/dist/utils.js +22 -1
- package/dist/utils.js.map +1 -0
- package/package.json +21 -24
- package/src/build.ts +240 -0
- package/src/dev.ts +233 -0
- package/src/index.ts +7 -0
- package/src/transformers/applyTransformers.ts +28 -0
- package/src/transformers/moduleRules.ts +229 -0
- package/src/transformers/plugins.ts +102 -0
- package/src/types.ts +1 -0
- package/src/utils.ts +19 -0
- package/dist/chunk-2YARCRX5.js +0 -15
- package/dist/chunk-34O5ZLZ6.js +0 -154
- package/dist/chunk-5ACA7GOB.js +0 -17
- package/dist/chunk-6F4PWJZI.js +0 -1
- package/dist/chunk-CW54GSNS.js +0 -197
- package/dist/chunk-JPURRV2F.js +0 -71
- package/dist/chunk-JU2EHEXW.js +0 -186
|
@@ -1 +1,69 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
;// CONCATENATED MODULE: ./src/transformers/plugins.ts?__rslib_entry__
|
|
3
|
+
function matchConstructorName(name) {
|
|
4
|
+
const matcher = (plugin)=>{
|
|
5
|
+
return plugin?.constructor.name === name;
|
|
6
|
+
};
|
|
7
|
+
// Add contextual information about the matcher for debugging.
|
|
8
|
+
matcher.info = {
|
|
9
|
+
type: matchConstructorName.name,
|
|
10
|
+
value: name
|
|
11
|
+
};
|
|
12
|
+
return matcher;
|
|
13
|
+
}
|
|
14
|
+
function findPlugin(config, matcher) {
|
|
15
|
+
const matches = [];
|
|
16
|
+
config.plugins?.forEach((x, index, array)=>{
|
|
17
|
+
if (matcher(x, index, array)) {
|
|
18
|
+
matches.push({
|
|
19
|
+
plugin: x,
|
|
20
|
+
index
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
if (matches.length > 1) {
|
|
25
|
+
const matcherInfo = matcher.info;
|
|
26
|
+
throw new Error(`[webpack-configs] Found more than 1 matching plugin.\n[webp-configs] Matcher: "${JSON.stringify(matcherInfo)}"\n[webpack-configs] Matches: "${JSON.stringify(matches.map((x)=>x.plugin))}"`);
|
|
27
|
+
}
|
|
28
|
+
return matches[0];
|
|
29
|
+
}
|
|
30
|
+
function replacePlugin(config, matcher, newPlugin) {
|
|
31
|
+
const match = findPlugin(config, matcher);
|
|
32
|
+
if (match) {
|
|
33
|
+
config.plugins[match.index] = newPlugin;
|
|
34
|
+
} else {
|
|
35
|
+
const matcherInfo = matcher.info;
|
|
36
|
+
throw new Error(`[webpack-configs] Couldn't replace the plugin because no match has been found.\n[webpack-configs] Matcher: "${JSON.stringify(matcherInfo)}"`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function addBeforePlugin(config, matcher, newPlugins) {
|
|
40
|
+
const match = findPlugin(config, matcher);
|
|
41
|
+
if (match) {
|
|
42
|
+
config.plugins?.splice(match.index, 0, ...newPlugins);
|
|
43
|
+
} else {
|
|
44
|
+
const matcherInfo = matcher.info;
|
|
45
|
+
throw new Error(`[webpack-configs] Couldn't add the new plugins because no match has been found.\n[webpack-configs] Matcher: "${JSON.stringify(matcherInfo)}"`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function addAfterPlugin(config, matcher, newPlugins) {
|
|
49
|
+
const match = findPlugin(config, matcher);
|
|
50
|
+
if (match) {
|
|
51
|
+
config.plugins?.splice(match.index + 1, 0, ...newPlugins);
|
|
52
|
+
} else {
|
|
53
|
+
const matcherInfo = matcher.info;
|
|
54
|
+
throw new Error(`[webpack-configs] Couldn't add the new plugins because no match has been found.\n[webpack-configs] Matcher: "${JSON.stringify(matcherInfo)}"`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function removePlugin(config, matcher) {
|
|
58
|
+
const countBefore = config.plugins?.length ?? 0;
|
|
59
|
+
config.plugins = config.plugins?.filter((...args)=>!matcher(...args));
|
|
60
|
+
const countAfter = config.plugins?.length ?? 0;
|
|
61
|
+
if (countBefore === countAfter) {
|
|
62
|
+
const matcherInfo = matcher.info;
|
|
63
|
+
throw new Error(`[webpack-configs] Didn't remove any plugin because no match has been found.\n[webpack-configs] Matcher: "${JSON.stringify(matcherInfo)}"`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { addAfterPlugin, addBeforePlugin, findPlugin, matchConstructorName, removePlugin, replacePlugin };
|
|
68
|
+
|
|
69
|
+
//# sourceMappingURL=plugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformers/plugins.js","sources":["webpack://@workleap/webpack-configs/./src/transformers/plugins.ts"],"sourcesContent":["import type { WebpackConfig } from \"../types.ts\";\n\nexport type WebpackPlugin = NonNullable<WebpackConfig[\"plugins\"]>[number];\n\nexport type PluginMatcher = (plugin: WebpackPlugin, index: number, array: WebpackPlugin[]) => boolean;\n\nexport type WithPluginMatcherInfo = {\n info: {\n type: string;\n value: string;\n };\n} & PluginMatcher;\n\nexport function matchConstructorName(name: string): PluginMatcher {\n const matcher: WithPluginMatcherInfo = plugin => {\n return plugin?.constructor.name === name;\n };\n\n // Add contextual information about the matcher for debugging.\n matcher.info = {\n type: matchConstructorName.name,\n value: name\n };\n\n return matcher;\n}\n\nexport interface PluginMatch {\n plugin: WebpackPlugin;\n index: number;\n}\n\nexport function findPlugin(config: WebpackConfig, matcher: PluginMatcher) {\n const matches: PluginMatch[] = [];\n\n config.plugins?.forEach((x, index, array) => {\n if (matcher(x, index, array)) {\n matches.push({\n plugin: x,\n index\n });\n }\n });\n\n if (matches.length > 1) {\n const matcherInfo = (matcher as WithPluginMatcherInfo).info;\n\n throw new Error(`[webpack-configs] Found more than 1 matching plugin.\\n[webp-configs] Matcher: \"${JSON.stringify(matcherInfo)}\"\\n[webpack-configs] Matches: \"${JSON.stringify(matches.map(x => x.plugin))}\"`);\n }\n\n return matches[0];\n}\n\nexport function replacePlugin(config: WebpackConfig, matcher: PluginMatcher, newPlugin: WebpackPlugin) {\n const match = findPlugin(config, matcher);\n\n if (match) {\n config.plugins![match.index] = newPlugin;\n } else {\n const matcherInfo = (matcher as WithPluginMatcherInfo).info;\n\n throw new Error(`[webpack-configs] Couldn't replace the plugin because no match has been found.\\n[webpack-configs] Matcher: \"${JSON.stringify(matcherInfo)}\"`);\n }\n}\n\nexport function addBeforePlugin(config: WebpackConfig, matcher: PluginMatcher, newPlugins: WebpackPlugin[]) {\n const match = findPlugin(config, matcher);\n\n if (match) {\n config.plugins?.splice(match.index, 0, ...newPlugins);\n } else {\n const matcherInfo = (matcher as WithPluginMatcherInfo).info;\n\n throw new Error(`[webpack-configs] Couldn't add the new plugins because no match has been found.\\n[webpack-configs] Matcher: \"${JSON.stringify(matcherInfo)}\"`);\n }\n}\n\nexport function addAfterPlugin(config: WebpackConfig, matcher: PluginMatcher, newPlugins: WebpackPlugin[]) {\n const match = findPlugin(config, matcher);\n\n if (match) {\n config.plugins?.splice(match.index + 1, 0, ...newPlugins);\n } else {\n const matcherInfo = (matcher as WithPluginMatcherInfo).info;\n\n throw new Error(`[webpack-configs] Couldn't add the new plugins because no match has been found.\\n[webpack-configs] Matcher: \"${JSON.stringify(matcherInfo)}\"`);\n }\n}\n\nexport function removePlugin(config: WebpackConfig, matcher: PluginMatcher) {\n const countBefore = config.plugins?.length ?? 0;\n\n config.plugins = config.plugins?.filter((...args) => !matcher(...args));\n\n const countAfter = config.plugins?.length ?? 0;\n\n if (countBefore === countAfter) {\n const matcherInfo = (matcher as WithPluginMatcherInfo).info;\n\n throw new Error(`[webpack-configs] Didn't remove any plugin because no match has been found.\\n[webpack-configs] Matcher: \"${JSON.stringify(matcherInfo)}\"`);\n }\n}\n"],"names":["matchConstructorName","name","matcher","plugin","findPlugin","config","matches","x","index","array","matcherInfo","Error","JSON","replacePlugin","newPlugin","match","addBeforePlugin","newPlugins","addAfterPlugin","removePlugin","countBefore","args","countAfter"],"mappings":";;AAaO,SAASA,qBAAqBC,IAAY;IAC7C,MAAMC,UAAiCC,CAAAA;QACnC,OAAOA,QAAQ,YAAY,SAASF;IACxC;IAEA,8DAA8D;IAC9DC,QAAQ,IAAI,GAAG;QACX,MAAMF,qBAAqB,IAAI;QAC/B,OAAOC;IACX;IAEA,OAAOC;AACX;AAOO,SAASE,WAAWC,MAAqB,EAAEH,OAAsB;IACpE,MAAMI,UAAyB,EAAE;IAEjCD,OAAO,OAAO,EAAE,QAAQ,CAACE,GAAGC,OAAOC;QAC/B,IAAIP,QAAQK,GAAGC,OAAOC,QAAQ;YAC1BH,QAAQ,IAAI,CAAC;gBACT,QAAQC;gBACRC;YACJ;QACJ;IACJ;IAEA,IAAIF,QAAQ,MAAM,GAAG,GAAG;QACpB,MAAMI,cAAeR,QAAkC,IAAI;QAE3D,MAAM,IAAIS,MAAM,CAAC,+EAA+E,EAAEC,KAAK,SAAS,CAACF,aAAa,+BAA+B,EAAEE,KAAK,SAAS,CAACN,QAAQ,GAAG,CAACC,CAAAA,IAAKA,EAAE,MAAM,GAAG,CAAC,CAAC;IAChN;IAEA,OAAOD,OAAO,CAAC,EAAE;AACrB;AAEO,SAASO,cAAcR,MAAqB,EAAEH,OAAsB,EAAEY,SAAwB;IACjG,MAAMC,QAAQX,WAAWC,QAAQH;IAEjC,IAAIa,OAAO;QACPV,OAAO,OAAQ,CAACU,MAAM,KAAK,CAAC,GAAGD;IACnC,OAAO;QACH,MAAMJ,cAAeR,QAAkC,IAAI;QAE3D,MAAM,IAAIS,MAAM,CAAC,4GAA4G,EAAEC,KAAK,SAAS,CAACF,aAAa,CAAC,CAAC;IACjK;AACJ;AAEO,SAASM,gBAAgBX,MAAqB,EAAEH,OAAsB,EAAEe,UAA2B;IACtG,MAAMF,QAAQX,WAAWC,QAAQH;IAEjC,IAAIa,OAAO;QACPV,OAAO,OAAO,EAAE,OAAOU,MAAM,KAAK,EAAE,MAAME;IAC9C,OAAO;QACH,MAAMP,cAAeR,QAAkC,IAAI;QAE3D,MAAM,IAAIS,MAAM,CAAC,6GAA6G,EAAEC,KAAK,SAAS,CAACF,aAAa,CAAC,CAAC;IAClK;AACJ;AAEO,SAASQ,eAAeb,MAAqB,EAAEH,OAAsB,EAAEe,UAA2B;IACrG,MAAMF,QAAQX,WAAWC,QAAQH;IAEjC,IAAIa,OAAO;QACPV,OAAO,OAAO,EAAE,OAAOU,MAAM,KAAK,GAAG,GAAG,MAAME;IAClD,OAAO;QACH,MAAMP,cAAeR,QAAkC,IAAI;QAE3D,MAAM,IAAIS,MAAM,CAAC,6GAA6G,EAAEC,KAAK,SAAS,CAACF,aAAa,CAAC,CAAC;IAClK;AACJ;AAEO,SAASS,aAAad,MAAqB,EAAEH,OAAsB;IACtE,MAAMkB,cAAcf,OAAO,OAAO,EAAE,UAAU;IAE9CA,OAAO,OAAO,GAAGA,OAAO,OAAO,EAAE,OAAO,CAAC,GAAGgB,OAAS,CAACnB,WAAWmB;IAEjE,MAAMC,aAAajB,OAAO,OAAO,EAAE,UAAU;IAE7C,IAAIe,gBAAgBE,YAAY;QAC5B,MAAMZ,cAAeR,QAAkC,IAAI;QAE3D,MAAM,IAAIS,MAAM,CAAC,yGAAyG,EAAEC,KAAK,SAAS,CAACF,aAAa,CAAC,CAAC;IAC9J;AACJ"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { Configuration as WebpackConfig } from
|
|
1
|
+
export type { Configuration as WebpackConfig } from "webpack";
|
package/dist/types.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sources":["webpack://@workleap/webpack-configs/./src/types.ts"],"sourcesContent":["export type { Configuration as WebpackConfig } from \"webpack\";\n"],"names":[],"mappings":";;AAA8D"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
declare function isObject(value: any): value is Record<string, unknown>;
|
|
2
|
-
declare function isNull(value: any): value is null;
|
|
3
|
-
declare function isUndefined(value: any): value is undefined;
|
|
4
|
-
declare function isNil(value: any): value is null | undefined;
|
|
5
|
-
|
|
6
|
-
export { isNil, isNull, isObject, isUndefined };
|
|
1
|
+
export declare function isObject(value: any): value is Record<string, unknown>;
|
|
2
|
+
export declare function isNull(value: any): value is null;
|
|
3
|
+
export declare function isUndefined(value: any): value is undefined;
|
|
4
|
+
export declare function isNil(value: any): value is null | undefined;
|
package/dist/utils.js
CHANGED
|
@@ -1 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
;// CONCATENATED MODULE: ./src/utils.ts?__rslib_entry__
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
|
+
function isObject(value) {
|
|
5
|
+
return typeof value === "object" && !Array.isArray(value) && value != null;
|
|
6
|
+
}
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
+
function isNull(value) {
|
|
9
|
+
return value == null;
|
|
10
|
+
}
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
function isUndefined(value) {
|
|
13
|
+
return typeof value === "undefined" || value === undefined;
|
|
14
|
+
}
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
function isNil(value) {
|
|
17
|
+
return isNull(value) || isUndefined(value);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { isNil, isNull, isObject, isUndefined };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["webpack://@workleap/webpack-configs/./src/utils.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isObject(value: any): value is Record<string, unknown> {\n return typeof value === \"object\" && !Array.isArray(value) && value != null;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isNull(value: any): value is null {\n return value == null;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isUndefined(value: any): value is undefined {\n return typeof value === \"undefined\" || value === undefined;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isNil(value: any): value is null | undefined {\n return isNull(value) || isUndefined(value);\n}\n"],"names":["isObject","value","Array","isNull","isUndefined","undefined","isNil"],"mappings":";;AAAA,8DAA8D;AACvD,SAASA,SAASC,KAAU;IAC/B,OAAO,OAAOA,UAAU,YAAY,CAACC,MAAM,OAAO,CAACD,UAAUA,SAAS;AAC1E;AAEA,8DAA8D;AACvD,SAASE,OAAOF,KAAU;IAC7B,OAAOA,SAAS;AACpB;AAEA,8DAA8D;AACvD,SAASG,YAAYH,KAAU;IAClC,OAAO,OAAOA,UAAU,eAAeA,UAAUI;AACrD;AAEA,8DAA8D;AACvD,SAASC,MAAML,KAAU;IAC5B,OAAOE,OAAOF,UAAUG,YAAYH;AACxC"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workleap/webpack-configs",
|
|
3
3
|
"author": "Workleap",
|
|
4
|
-
"description": "Workleap recommended webpack
|
|
5
|
-
"version": "1.5.
|
|
4
|
+
"description": "Workleap recommended webpack configurations.",
|
|
5
|
+
"version": "1.5.4",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/
|
|
9
|
+
"url": "git+https://github.com/workleap/wl-web-configs.git",
|
|
10
10
|
"directory": "packages/webpack-configs"
|
|
11
11
|
},
|
|
12
12
|
"type": "module",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
|
+
"src",
|
|
25
26
|
"dist",
|
|
26
27
|
"CHANGELOG.md",
|
|
27
28
|
"README.md"
|
|
@@ -39,24 +40,6 @@
|
|
|
39
40
|
"optional": true
|
|
40
41
|
}
|
|
41
42
|
},
|
|
42
|
-
"devDependencies": {
|
|
43
|
-
"@svgr/core": "8.1.0",
|
|
44
|
-
"@swc/core": "1.10.1",
|
|
45
|
-
"@swc/helpers": "0.5.15",
|
|
46
|
-
"@swc/jest": "0.2.37",
|
|
47
|
-
"@types/jest": "29.5.14",
|
|
48
|
-
"@types/node": "22.10.1",
|
|
49
|
-
"@typescript-eslint/parser": "8.18.0",
|
|
50
|
-
"eslint": "8.57.0",
|
|
51
|
-
"jest": "29.7.0",
|
|
52
|
-
"ts-node": "10.9.2",
|
|
53
|
-
"tsup": "8.3.5",
|
|
54
|
-
"typescript": "5.5.4",
|
|
55
|
-
"@workleap/eslint-plugin": "3.2.4",
|
|
56
|
-
"@workleap/swc-configs": "2.2.3",
|
|
57
|
-
"@workleap/tsup-configs": "3.0.6",
|
|
58
|
-
"@workleap/typescript-configs": "3.0.2"
|
|
59
|
-
},
|
|
60
43
|
"dependencies": {
|
|
61
44
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
|
|
62
45
|
"@svgr/webpack": "^8.1.0",
|
|
@@ -67,12 +50,26 @@
|
|
|
67
50
|
"react-refresh": "^0.16.0",
|
|
68
51
|
"style-loader": "^4.0.0",
|
|
69
52
|
"swc-loader": "^0.2.6",
|
|
70
|
-
"terser-webpack-plugin": "^5.3.
|
|
53
|
+
"terser-webpack-plugin": "^5.3.14"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@rsbuild/core": "1.2.19",
|
|
57
|
+
"@rslib/core": "0.5.4",
|
|
58
|
+
"@svgr/core": "8.1.0",
|
|
59
|
+
"@types/node": "22.13.10",
|
|
60
|
+
"@typescript-eslint/parser": "8.26.1",
|
|
61
|
+
"eslint": "8.57.0",
|
|
62
|
+
"typescript": "5.8.2",
|
|
63
|
+
"vitest": "3.0.9",
|
|
64
|
+
"@workleap/eslint-plugin": "3.3.1",
|
|
65
|
+
"@workleap/rslib-configs": "1.0.3",
|
|
66
|
+
"@workleap/swc-configs": "2.2.5",
|
|
67
|
+
"@workleap/typescript-configs": "3.0.2"
|
|
71
68
|
},
|
|
72
69
|
"scripts": {
|
|
73
|
-
"build": "
|
|
70
|
+
"build": "rslib build -c rslib.config.ts",
|
|
74
71
|
"eslint": "eslint . --max-warnings=-0 --cache --cache-location node_modules/.cache/eslint",
|
|
75
72
|
"typecheck": "tsc",
|
|
76
|
-
"test": "
|
|
73
|
+
"test": "vitest --config vitest.config.ts --no-watch"
|
|
77
74
|
}
|
|
78
75
|
}
|
package/src/build.ts
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import type { Config as SvgrOptions } from "@svgr/core";
|
|
2
|
+
import type { Config as SwcConfig } from "@swc/core";
|
|
3
|
+
import HtmlWebpackPlugin from "html-webpack-plugin";
|
|
4
|
+
import MiniCssExtractPlugin from "mini-css-extract-plugin";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import TerserPlugin from "terser-webpack-plugin";
|
|
8
|
+
import webpack from "webpack";
|
|
9
|
+
import { applyTransformers, type WebpackConfigTransformer } from "./transformers/applyTransformers.ts";
|
|
10
|
+
import type { WebpackConfig } from "./types.ts";
|
|
11
|
+
import { isObject } from "./utils.ts";
|
|
12
|
+
|
|
13
|
+
// Aliases
|
|
14
|
+
const DefinePlugin = webpack.DefinePlugin;
|
|
15
|
+
|
|
16
|
+
// Using node:module.createRequire until
|
|
17
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta/resolve
|
|
18
|
+
// is available
|
|
19
|
+
const require = createRequire(import.meta.url);
|
|
20
|
+
|
|
21
|
+
export function defineBuildHtmlWebpackPluginConfig(options: HtmlWebpackPlugin.Options = {}): HtmlWebpackPlugin.Options {
|
|
22
|
+
const {
|
|
23
|
+
template = path.resolve("./public/index.html"),
|
|
24
|
+
...rest
|
|
25
|
+
} = options;
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
...rest,
|
|
29
|
+
template
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type MiniCssExtractPluginOptions = NonNullable<ConstructorParameters<typeof MiniCssExtractPlugin>[number]>;
|
|
34
|
+
|
|
35
|
+
export function defineMiniCssExtractPluginConfig(options: MiniCssExtractPluginOptions = {}): MiniCssExtractPluginOptions {
|
|
36
|
+
const {
|
|
37
|
+
filename = "[name].css",
|
|
38
|
+
...rest
|
|
39
|
+
} = options;
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
...rest,
|
|
43
|
+
filename
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type WebpackOptimization = NonNullable<WebpackConfig["optimization"]>;
|
|
48
|
+
export type OptimizeOption = boolean | "readable";
|
|
49
|
+
|
|
50
|
+
export function getOptimizationConfig(optimize: OptimizeOption): WebpackOptimization {
|
|
51
|
+
if (optimize === "readable") {
|
|
52
|
+
return {
|
|
53
|
+
minimize: true,
|
|
54
|
+
minimizer: [
|
|
55
|
+
new TerserPlugin({
|
|
56
|
+
minify: TerserPlugin.swcMinify,
|
|
57
|
+
terserOptions: {
|
|
58
|
+
toplevel: true,
|
|
59
|
+
mangle: false,
|
|
60
|
+
keep_classnames: true,
|
|
61
|
+
keep_fnames: true,
|
|
62
|
+
compress: {
|
|
63
|
+
toplevel: true,
|
|
64
|
+
hoist_props: false
|
|
65
|
+
},
|
|
66
|
+
output: {
|
|
67
|
+
comments: true
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
],
|
|
72
|
+
chunkIds: "named",
|
|
73
|
+
moduleIds: "named",
|
|
74
|
+
mangleExports: false,
|
|
75
|
+
mangleWasmImports: false
|
|
76
|
+
};
|
|
77
|
+
} else if (optimize) {
|
|
78
|
+
return {
|
|
79
|
+
minimize: true,
|
|
80
|
+
minimizer: [
|
|
81
|
+
new TerserPlugin({
|
|
82
|
+
minify: TerserPlugin.swcMinify
|
|
83
|
+
})
|
|
84
|
+
]
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Doesn't turnoff everything but is good enough to help with debugging scenarios.
|
|
89
|
+
return {
|
|
90
|
+
minimize: false,
|
|
91
|
+
chunkIds: "named",
|
|
92
|
+
moduleIds: "named",
|
|
93
|
+
concatenateModules: false,
|
|
94
|
+
flagIncludedChunks: false,
|
|
95
|
+
mangleExports: false,
|
|
96
|
+
mangleWasmImports: false,
|
|
97
|
+
removeAvailableModules: false,
|
|
98
|
+
usedExports: false
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface DefineBuildConfigOptions {
|
|
103
|
+
entry?: string;
|
|
104
|
+
outputPath?: string;
|
|
105
|
+
publicPath?: `${string}/` | "auto";
|
|
106
|
+
moduleRules?: NonNullable<WebpackConfig["module"]>["rules"];
|
|
107
|
+
plugins?: WebpackConfig["plugins"];
|
|
108
|
+
htmlWebpackPlugin?: boolean | HtmlWebpackPlugin.Options;
|
|
109
|
+
miniCssExtractPluginOptions?: MiniCssExtractPluginOptions;
|
|
110
|
+
optimize?: OptimizeOption;
|
|
111
|
+
cssModules?: boolean;
|
|
112
|
+
svgr?: boolean | SvgrOptions;
|
|
113
|
+
environmentVariables?: Record<string, unknown>;
|
|
114
|
+
transformers?: WebpackConfigTransformer[];
|
|
115
|
+
verbose?: boolean;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function defineBuildConfig(swcConfig: SwcConfig, options: DefineBuildConfigOptions = {}) {
|
|
119
|
+
const {
|
|
120
|
+
entry = path.resolve("./src/index.tsx"),
|
|
121
|
+
outputPath = path.resolve("dist"),
|
|
122
|
+
// The trailing / is very important, otherwise paths will not be resolved correctly.
|
|
123
|
+
publicPath = "http://localhost:8080/",
|
|
124
|
+
moduleRules = [],
|
|
125
|
+
plugins = [],
|
|
126
|
+
htmlWebpackPlugin = defineBuildHtmlWebpackPluginConfig(),
|
|
127
|
+
miniCssExtractPluginOptions = defineMiniCssExtractPluginConfig(),
|
|
128
|
+
optimize = true,
|
|
129
|
+
cssModules = false,
|
|
130
|
+
svgr = true,
|
|
131
|
+
// Using an empty object literal as the default value to ensure
|
|
132
|
+
// "process.env" is always available.
|
|
133
|
+
environmentVariables = {},
|
|
134
|
+
transformers = [],
|
|
135
|
+
verbose = false
|
|
136
|
+
} = options;
|
|
137
|
+
|
|
138
|
+
const config: WebpackConfig = {
|
|
139
|
+
mode: "production",
|
|
140
|
+
target: "web",
|
|
141
|
+
entry,
|
|
142
|
+
output: {
|
|
143
|
+
path: outputPath,
|
|
144
|
+
filename: "[name].js",
|
|
145
|
+
publicPath,
|
|
146
|
+
clean: true,
|
|
147
|
+
assetModuleFilename: "[name][ext][query]"
|
|
148
|
+
},
|
|
149
|
+
optimization: getOptimizationConfig(optimize),
|
|
150
|
+
infrastructureLogging: verbose ? {
|
|
151
|
+
appendOnly: true,
|
|
152
|
+
level: "verbose",
|
|
153
|
+
debug: /PackFileCache/
|
|
154
|
+
} : undefined,
|
|
155
|
+
module: {
|
|
156
|
+
rules: [
|
|
157
|
+
{
|
|
158
|
+
test: /\.(js|jsx|ts|tsx)$/i,
|
|
159
|
+
exclude: /node_modules/,
|
|
160
|
+
loader: require.resolve("swc-loader"),
|
|
161
|
+
options: swcConfig
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
// https://stackoverflow.com/questions/69427025/programmatic-webpack-jest-esm-cant-resolve-module-without-js-file-exten
|
|
165
|
+
test: /\.js$/i,
|
|
166
|
+
include: /node_modules/,
|
|
167
|
+
resolve: {
|
|
168
|
+
fullySpecified: false
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
test: /\.css$/i,
|
|
173
|
+
use: [
|
|
174
|
+
{ loader: MiniCssExtractPlugin.loader },
|
|
175
|
+
{
|
|
176
|
+
loader: require.resolve("css-loader"),
|
|
177
|
+
options: cssModules
|
|
178
|
+
? {
|
|
179
|
+
// Must match the number of loaders applied before this one.
|
|
180
|
+
importLoaders: 1,
|
|
181
|
+
modules: true
|
|
182
|
+
}
|
|
183
|
+
: undefined
|
|
184
|
+
},
|
|
185
|
+
{ loader: require.resolve("postcss-loader") }
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
...(svgr
|
|
189
|
+
? [
|
|
190
|
+
{
|
|
191
|
+
test: /\.svg$/i,
|
|
192
|
+
loader: require.resolve("@svgr/webpack"),
|
|
193
|
+
options: isObject(svgr) ? svgr : undefined
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
test: /\.(png|jpe?g|gif)$/i,
|
|
197
|
+
type: "asset/resource"
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
: [
|
|
201
|
+
{
|
|
202
|
+
test: /\.(png|jpe?g|gif|svg)$/i,
|
|
203
|
+
type: "asset/resource"
|
|
204
|
+
}
|
|
205
|
+
]),
|
|
206
|
+
...moduleRules
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
resolve: {
|
|
210
|
+
extensions: [".js", ".jsx", ".ts", ".tsx", ".css"],
|
|
211
|
+
alias: {
|
|
212
|
+
// Fixes Module not found: Error: Can't resolve '@swc/helpers/_/_class_private_field_init'.
|
|
213
|
+
// View https://github.com/vercel/next.js/pull/38174 for more information and https://github.com/vercel/next.js/issues/48593.
|
|
214
|
+
"@swc/helpers": path.dirname(require.resolve("@swc/helpers/package.json"))
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
plugins: [
|
|
218
|
+
htmlWebpackPlugin && new HtmlWebpackPlugin(isObject(htmlWebpackPlugin) ? htmlWebpackPlugin : defineBuildHtmlWebpackPluginConfig()),
|
|
219
|
+
new MiniCssExtractPlugin(miniCssExtractPluginOptions),
|
|
220
|
+
// Stringify the environment variables because the plugin does a direct text replacement. Otherwise, "production" would become production
|
|
221
|
+
// after replacement and cause an undefined var error because the production var doesn't exist.
|
|
222
|
+
// For more information, view: https://webpack.js.org/plugins/define-plugin.
|
|
223
|
+
new DefinePlugin({
|
|
224
|
+
"process.env": Object.keys(environmentVariables).reduce((acc, key) => {
|
|
225
|
+
acc[key] = JSON.stringify(environmentVariables[key]);
|
|
226
|
+
|
|
227
|
+
return acc;
|
|
228
|
+
}, {} as Record<string, string>)
|
|
229
|
+
}),
|
|
230
|
+
...plugins
|
|
231
|
+
].filter(Boolean) as WebpackConfig["plugins"]
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const transformedConfig = applyTransformers(config, transformers, {
|
|
235
|
+
environment: "build",
|
|
236
|
+
verbose
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
return transformedConfig;
|
|
240
|
+
}
|