@flatjs/evolve 1.8.1-next.72 → 1.8.1-next.73

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.
Files changed (98) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/constants.js +1 -17
  3. package/dist/create-webpack/create-externals.js +1 -6
  4. package/dist/create-webpack/create-optimization.js +1 -29
  5. package/dist/create-webpack/create-output.js +1 -35
  6. package/dist/create-webpack/create-performance.js +1 -7
  7. package/dist/create-webpack/create-plugins.js +1 -78
  8. package/dist/create-webpack/create-resolve.js +1 -31
  9. package/dist/create-webpack/create-rule-sets.js +1 -16
  10. package/dist/create-webpack/load-webpack-config.js +1 -55
  11. package/dist/create-webpack/rule-sets/constants.js +1 -3
  12. package/dist/create-webpack/rule-sets/rule-assets.js +1 -44
  13. package/dist/create-webpack/rule-sets/rule-css.js +1 -84
  14. package/dist/create-webpack/rule-sets/rule-less.js +1 -45
  15. package/dist/create-webpack/rule-sets/rule-scripts.js +1 -27
  16. package/dist/create-webpack/rule-sets/rule-svg-icon.js +1 -25
  17. package/dist/create-webpack/rule-sets/rule-utils.js +1 -10
  18. package/dist/create-webpack/types.js +1 -1
  19. package/dist/default-options.js +1 -80
  20. package/dist/define-config/define-config.js +1 -4
  21. package/dist/define-config/index.js +1 -1
  22. package/dist/dev-server/add-compiler-to-dev-server.js +1 -47
  23. package/dist/dev-server/create-app-page-route.js +1 -11
  24. package/dist/dev-server/create-dev-server-compiler-tasks.js +1 -51
  25. package/dist/dev-server/create-dev-server-entries.js +1 -27
  26. package/dist/dev-server/create-dev-server.js +1 -23
  27. package/dist/dev-server/index.js +1 -6
  28. package/dist/dev-server/middlewares/create-page-middleware.js +1 -164
  29. package/dist/dev-server/middlewares/create-public-assets-middleware.js +1 -25
  30. package/dist/dev-server/middlewares/index.js +1 -2
  31. package/dist/errors/evolve-build-error.js +1 -10
  32. package/dist/helpers/allow-px2rem-for-module.js +1 -6
  33. package/dist/helpers/assert-only-single-entry-item.js +1 -23
  34. package/dist/helpers/chunk-entry-map.js +1 -21
  35. package/dist/helpers/enable-bundle-hashname-for-module.js +1 -6
  36. package/dist/helpers/filter-actived-entries.js +1 -41
  37. package/dist/helpers/get-bundle-file-name.js +1 -23
  38. package/dist/helpers/get-git-root.js +1 -4
  39. package/dist/helpers/get-html-plugin-config.js +1 -47
  40. package/dist/helpers/get-max-process-tasks.js +1 -7
  41. package/dist/helpers/get-pacakge-dir.js +1 -13
  42. package/dist/helpers/index.d.ts +1 -0
  43. package/dist/helpers/index.js +1 -15
  44. package/dist/helpers/json-serializer.d.ts +7 -0
  45. package/dist/helpers/json-serializer.js +1 -0
  46. package/dist/helpers/merge-babel-options.js +1 -45
  47. package/dist/helpers/normalize-entry-map.js +1 -38
  48. package/dist/helpers/open-page.js +1 -15
  49. package/dist/helpers/print-log.js +1 -49
  50. package/dist/helpers/refresh-evolve-mock-options.js +1 -29
  51. package/dist/helpers/resolve-entry-map-input-files.js +1 -20
  52. package/dist/helpers/script-injects.js +1 -39
  53. package/dist/helpers/should-enable-react-fast-refresh.js +1 -8
  54. package/dist/helpers/split-to-multi-compiler.js +1 -22
  55. package/dist/index.js +1 -5
  56. package/dist/load-config/index.js +1 -1
  57. package/dist/load-config/load-evolve-config.js +1 -35
  58. package/dist/main/env-verify.js +1 -21
  59. package/dist/main/index.js +1 -4
  60. package/dist/main/prepare-build.js +1 -38
  61. package/dist/main/prepare-serve.js +1 -36
  62. package/dist/main/prepare-static.js +1 -28
  63. package/dist/main/start-build-dynamic.js +1 -144
  64. package/dist/main/start-build-worker.d.ts +2 -4
  65. package/dist/main/start-build-worker.js +1 -41
  66. package/dist/main/start-build.js +1 -49
  67. package/dist/main/start-one-entry-build.js +1 -35
  68. package/dist/main/start-serve.js +1 -32
  69. package/dist/main/start-static.js +1 -16
  70. package/dist/minimizer/create-minimizers.js +1 -25
  71. package/dist/minimizer/default-options.js +1 -14
  72. package/dist/minimizer/image-minimizer.js +1 -56
  73. package/dist/minimizer/index.js +1 -1
  74. package/dist/minimizer/terser-minimizer.js +3 -15
  75. package/dist/minimizer/types.js +1 -1
  76. package/dist/plugins/clean-webpack/clean-webpack-plugin.js +1 -173
  77. package/dist/plugins/clean-webpack/index.js +1 -22
  78. package/dist/plugins/define-variable/define-variable-plugin.js +1 -21
  79. package/dist/plugins/define-variable/index.js +1 -1
  80. package/dist/plugins/html-inject-scripts/plugin-html-inject-script.js +1 -27
  81. package/dist/plugins/module-federation/external-template-remotes.js +1 -92
  82. package/dist/plugins/module-federation/index.js +1 -1
  83. package/dist/plugins/module-federation/module-federation.js +1 -98
  84. package/dist/plugins/multi-html/index.js +1 -15
  85. package/dist/plugins/multi-html/multi-html-cdn-plugin.js +1 -84
  86. package/dist/plugins/multi-html/multi-html-plugin.js +1 -70
  87. package/dist/types/index.js +1 -8
  88. package/dist/types/types-ci.js +1 -1
  89. package/dist/types/types-dev-server.js +1 -1
  90. package/dist/types/types-entry-map.js +1 -1
  91. package/dist/types/types-federation.js +1 -1
  92. package/dist/types/types-loader-options.js +1 -1
  93. package/dist/types/types-modular-import.js +1 -1
  94. package/dist/types/types-multi-html.js +1 -1
  95. package/dist/types/types-options.js +1 -1
  96. package/dist/types/types-plugin-options.js +1 -1
  97. package/dist/types/types-webpack.js +1 -1
  98. package/package.json +2 -2
@@ -1,173 +1 @@
1
- import { rmSync } from 'node:fs';
2
- import { relative } from 'node:path';
3
- import { fileWalkSync } from '@armit/file-utility';
4
- import { logger } from '@flatjs/common';
5
- import { moduleName } from '../../constants.js';
6
- export class CleanWebpackPlugin {
7
- constructor(options = {}) {
8
- this.verbose = options.verbose === true || false;
9
- this.projectCwd = options.projectCwd || process.cwd();
10
- this.cleanStaleWebpackAssets =
11
- options.cleanStaleWebpackAssets === true ||
12
- options.cleanStaleWebpackAssets === false
13
- ? options.cleanStaleWebpackAssets
14
- : true;
15
- this.protectWebpackAssets =
16
- options.protectWebpackAssets === true ||
17
- options.protectWebpackAssets === false
18
- ? options.protectWebpackAssets
19
- : true;
20
- this.cleanAfterEveryBuildPatterns = Array.isArray(options.cleanAfterEveryBuildPatterns)
21
- ? options.cleanAfterEveryBuildPatterns
22
- : [];
23
- this.cleanOnceBeforeBuildPatterns = Array.isArray(options.cleanOnceBeforeBuildPatterns)
24
- ? options.cleanOnceBeforeBuildPatterns
25
- : ['**/*'];
26
- /**
27
- * Store webpack build assets
28
- */
29
- this.currentAssets = [];
30
- /**
31
- * Only used with cleanOnceBeforeBuildPatterns
32
- */
33
- this.initialClean = false;
34
- this.outputPath = '';
35
- this.apply = this.apply.bind(this);
36
- this.handleInitial = this.handleInitial.bind(this);
37
- this.handleDone = this.handleDone.bind(this);
38
- this.removeFiles = this.removeFiles.bind(this);
39
- }
40
- apply(compiler) {
41
- if (!compiler.options.output || !compiler.options.output.path) {
42
- logger.warn('clean-webpack-plugin: options.output.path not defined. Plugin disabled...', moduleName);
43
- return;
44
- }
45
- this.outputPath = compiler.options.output.path;
46
- /**
47
- * webpack 4+ comes with a new plugin system.
48
- *
49
- * Check for hooks in-order to support old plugin system
50
- */
51
- const hooks = compiler.hooks;
52
- if (this.cleanOnceBeforeBuildPatterns.length !== 0) {
53
- hooks.emit.tap('clean-webpack-plugin', (compilation) => {
54
- this.handleInitial(compilation);
55
- });
56
- }
57
- hooks.done.tap('clean-webpack-plugin', (stats) => {
58
- this.handleDone(stats);
59
- });
60
- }
61
- /**
62
- * Initially remove files from output directory prior to build.
63
- *
64
- * Only happens once.
65
- *
66
- * Warning: It is recommended to initially clean your build directory outside of webpack to minimize unexpected behavior.
67
- */
68
- handleInitial(compilation) {
69
- if (this.initialClean) {
70
- return;
71
- }
72
- /**
73
- * Do not remove files if there are compilation errors
74
- *
75
- * Handle logging inside this.handleDone
76
- */
77
- const stats = compilation.getStats();
78
- if (stats.hasErrors()) {
79
- return;
80
- }
81
- this.initialClean = true;
82
- this.removeFiles(this.cleanOnceBeforeBuildPatterns);
83
- }
84
- handleDone(stats) {
85
- /**
86
- * Do nothing if there is a webpack error
87
- */
88
- if (stats.hasErrors()) {
89
- if (this.verbose) {
90
- logger.warn('clean-webpack-plugin: pausing due to webpack errors', moduleName);
91
- }
92
- return;
93
- }
94
- /**
95
- * Fetch Webpack's output asset files
96
- */
97
- const assets = stats.toJson({
98
- assets: true,
99
- }).assets || [];
100
- const assetList = assets.map((asset) => {
101
- return asset.name;
102
- });
103
- /**
104
- * Get all files that were in the previous build but not the current
105
- *
106
- * (relies on del's cwd: outputPath option)
107
- */
108
- const staleFiles = this.currentAssets.filter((previousAsset) => {
109
- return assetList.includes(previousAsset) === false;
110
- });
111
- /**
112
- * Save assets for next compilation
113
- */
114
- this.currentAssets = assetList.sort();
115
- const removePatterns = [];
116
- /**
117
- * Remove unused webpack assets
118
- */
119
- if (this.cleanStaleWebpackAssets === true && staleFiles.length !== 0) {
120
- removePatterns.push(...staleFiles);
121
- }
122
- /**
123
- * Remove cleanAfterEveryBuildPatterns
124
- */
125
- if (this.cleanAfterEveryBuildPatterns.length !== 0) {
126
- removePatterns.push(...this.cleanAfterEveryBuildPatterns);
127
- }
128
- if (removePatterns.length !== 0) {
129
- this.removeFiles(removePatterns);
130
- }
131
- }
132
- removeFiles(patterns) {
133
- try {
134
- const deleted = fileWalkSync(patterns, {
135
- absolute: true,
136
- unique: true,
137
- // Change context to build directory
138
- cwd: this.outputPath,
139
- dot: true,
140
- ignore: this.protectWebpackAssets ? this.currentAssets : [],
141
- });
142
- for (const filepath of deleted) {
143
- rmSync(filepath, {
144
- force: true,
145
- recursive: true,
146
- });
147
- }
148
- /**
149
- * Log if verbose is enabled
150
- */
151
- if (this.verbose) {
152
- deleted.forEach((file) => {
153
- const filename = relative(this.projectCwd, file);
154
- const message = 'removed';
155
- /**
156
- * Use console.warn over .log
157
- * https://github.com/webpack/webpack/issues/1904
158
- * https://github.com/johnagan/clean-webpack-plugin/issues/11
159
- */
160
- logger.debug(`clean-webpack-plugin: ${message} ${filename}`, moduleName);
161
- });
162
- }
163
- }
164
- catch (error) {
165
- const needsForce = /Cannot delete files\/folders outside the current working directory\./.test(error.message);
166
- if (needsForce) {
167
- const message = 'clean-webpack-plugin: Cannot delete files/folders outside the current working directory. Can be overridden with the `dangerouslyAllowCleanPatternsOutsideProject` option.';
168
- throw new Error(message);
169
- }
170
- throw error;
171
- }
172
- }
173
- }
1
+ import{rmSync}from"node:fs";import{relative}from"node:path";import{fileWalkSync}from"@armit/file-utility";import{logger}from"@flatjs/common";import{moduleName}from"../../constants.js";export class CleanWebpackPlugin{constructor(e={}){this.verbose=!0===e.verbose||!1,this.projectCwd=e.projectCwd||process.cwd(),this.cleanStaleWebpackAssets=!0!==e.cleanStaleWebpackAssets&&!1!==e.cleanStaleWebpackAssets||e.cleanStaleWebpackAssets,this.protectWebpackAssets=!0!==e.protectWebpackAssets&&!1!==e.protectWebpackAssets||e.protectWebpackAssets,this.cleanAfterEveryBuildPatterns=Array.isArray(e.cleanAfterEveryBuildPatterns)?e.cleanAfterEveryBuildPatterns:[],this.cleanOnceBeforeBuildPatterns=Array.isArray(e.cleanOnceBeforeBuildPatterns)?e.cleanOnceBeforeBuildPatterns:["**/*"],this.currentAssets=[],this.initialClean=!1,this.outputPath="",this.apply=this.apply.bind(this),this.handleInitial=this.handleInitial.bind(this),this.handleDone=this.handleDone.bind(this),this.removeFiles=this.removeFiles.bind(this)}apply(e){if(!e.options.output||!e.options.output.path)return void logger.warn("clean-webpack-plugin: options.output.path not defined. Plugin disabled...",moduleName);this.outputPath=e.options.output.path;const t=e.hooks;0!==this.cleanOnceBeforeBuildPatterns.length&&t.emit.tap("clean-webpack-plugin",(e=>{this.handleInitial(e)})),t.done.tap("clean-webpack-plugin",(e=>{this.handleDone(e)}))}handleInitial(e){if(this.initialClean)return;e.getStats().hasErrors()||(this.initialClean=!0,this.removeFiles(this.cleanOnceBeforeBuildPatterns))}handleDone(e){if(e.hasErrors())return void(this.verbose&&logger.warn("clean-webpack-plugin: pausing due to webpack errors",moduleName));const t=(e.toJson({assets:!0}).assets||[]).map((e=>e.name)),s=this.currentAssets.filter((e=>!1===t.includes(e)));this.currentAssets=t.sort();const i=[];!0===this.cleanStaleWebpackAssets&&0!==s.length&&i.push(...s),0!==this.cleanAfterEveryBuildPatterns.length&&i.push(...this.cleanAfterEveryBuildPatterns),0!==i.length&&this.removeFiles(i)}removeFiles(e){try{const t=fileWalkSync(e,{absolute:!0,unique:!0,cwd:this.outputPath,dot:!0,ignore:this.protectWebpackAssets?this.currentAssets:[]});for(const e of t)rmSync(e,{force:!0,recursive:!0});this.verbose&&t.forEach((e=>{const t=relative(this.projectCwd,e);logger.debug(`clean-webpack-plugin: removed ${t}`,moduleName)}))}catch(e){if(/Cannot delete files\/folders outside the current working directory\./.test(e.message)){throw new Error("clean-webpack-plugin: Cannot delete files/folders outside the current working directory. Can be overridden with the `dangerouslyAllowCleanPatternsOutsideProject` option.")}throw e}}}
@@ -1,22 +1 @@
1
- import { join } from 'node:path';
2
- import { ensureSlash } from '@flatjs/common';
3
- import { CleanWebpackPlugin } from './clean-webpack-plugin.js';
4
- /**
5
- * Cleaning up the /dist folder for `production` build
6
- * @param singleEntryItem
7
- * @returns
8
- */
9
- export const createCleanWebpackPlugin = (serveMode, entryMapItem, evolveOptions) => {
10
- if (serveMode) {
11
- return [];
12
- }
13
- return [
14
- new CleanWebpackPlugin({
15
- verbose: true,
16
- projectCwd: evolveOptions.projectCwd,
17
- cleanOnceBeforeBuildPatterns: [
18
- `${join(ensureSlash(entryMapItem[0], true), '**/*')}`,
19
- ],
20
- }),
21
- ];
22
- };
1
+ import{join}from"node:path";import{ensureSlash}from"@flatjs/common";import{CleanWebpackPlugin}from"./clean-webpack-plugin.js";export const createCleanWebpackPlugin=(e,n,o)=>e?[]:[new CleanWebpackPlugin({verbose:!0,projectCwd:o.projectCwd,cleanOnceBeforeBuildPatterns:[`${join(ensureSlash(n[0],!0),"**/*")}`]})];
@@ -1,21 +1 @@
1
- /* eslint-disable @typescript-eslint/naming-convention */
2
- import { getLastCommitHash, gitBranchName } from '@armit/git';
3
- import webpack from 'webpack';
4
- /**
5
- * The DefinePlugin replaces variables in your code with other values or expressions at compile time.
6
- * `__SENTRY_DEBUG__`,`process.env.FLAT_BUILD_DATE`, `process.env.FLAT_COMMIT_HASH`, `process.env.FLAT_BRANCH_NAME`
7
- * @returns
8
- */
9
- export const createBuiltinDefineVariables = async (serveMode, evolveOptions) => {
10
- const commitHash = await getLastCommitHash();
11
- const branchName = await gitBranchName();
12
- return [
13
- new webpack.DefinePlugin({
14
- __SENTRY_DEBUG__: serveMode,
15
- 'process.env.FLAT_BUILD_DATE': JSON.stringify(new Date().toISOString()),
16
- 'process.env.FLAT_COMMIT_HASH': JSON.stringify(commitHash),
17
- 'process.env.FLAT_BRANCH_NAME': JSON.stringify(branchName),
18
- ...evolveOptions.pluginOptions.definePlugin,
19
- }),
20
- ];
21
- };
1
+ import{getLastCommitHash,gitBranchName}from"@armit/git";import webpack from"webpack";export const createBuiltinDefineVariables=async(e,i)=>{const t=await getLastCommitHash(),n=await gitBranchName();return[new webpack.DefinePlugin({__SENTRY_DEBUG__:e,"process.env.FLAT_BUILD_DATE":JSON.stringify((new Date).toISOString()),"process.env.FLAT_COMMIT_HASH":JSON.stringify(t),"process.env.FLAT_BRANCH_NAME":JSON.stringify(n),...i.pluginOptions.definePlugin})]};
@@ -1 +1 @@
1
- export * from './define-variable-plugin.js';
1
+ export*from"./define-variable-plugin.js";
@@ -1,27 +1 @@
1
- import htmlWebpackPlugin from 'html-webpack-plugin';
2
- const PLUGIN_PREFIX = `HtmlInjectScriptPlugin`;
3
- export class HtmlInjectScriptPlugin {
4
- constructor(scripts) {
5
- this.scripts = scripts || [];
6
- }
7
- processScripts() {
8
- return this.scripts.filter(Boolean).map((asset) => {
9
- return {
10
- tagName: 'script',
11
- innerHTML: asset,
12
- voidTag: false,
13
- attributes: {},
14
- meta: { plugin: 'html-inject-script-webpack-plugin' },
15
- };
16
- });
17
- }
18
- apply(compiler) {
19
- compiler.hooks.compilation.tap(`${PLUGIN_PREFIX}_compilation`, (compilation) => {
20
- const hooks = htmlWebpackPlugin.getHooks(compilation);
21
- hooks.alterAssetTags.tap(`${PLUGIN_PREFIX}_alterAssetTags`, (data) => {
22
- data.assetTags.scripts.unshift(...this.processScripts());
23
- return data;
24
- });
25
- });
26
- }
27
- }
1
+ import htmlWebpackPlugin from"html-webpack-plugin";const PLUGIN_PREFIX="HtmlInjectScriptPlugin";export class HtmlInjectScriptPlugin{constructor(t){this.scripts=t||[]}processScripts(){return this.scripts.filter(Boolean).map((t=>({tagName:"script",innerHTML:t,voidTag:!1,attributes:{},meta:{plugin:"html-inject-script-webpack-plugin"}})))}apply(t){t.hooks.compilation.tap(`${PLUGIN_PREFIX}_compilation`,(t=>{htmlWebpackPlugin.getHooks(t).alterAssetTags.tap(`${PLUGIN_PREFIX}_alterAssetTags`,(t=>(t.assetTags.scripts.unshift(...this.processScripts()),t)))}))}}
@@ -1,92 +1 @@
1
- import webpackSources from 'webpack-sources';
2
- const PLUGIN_NAME = 'ExternalTemplateRemotesPlugin';
3
- const isExternalModule = (module) => {
4
- return module.constructor.name === 'ExternalModule';
5
- };
6
- /**
7
- * @param {string} urlAndGlobal the script request
8
- * @returns {string[]} script url and its global variable
9
- */
10
- function extractUrlAndGlobal(urlAndGlobal) {
11
- const index = urlAndGlobal.indexOf('@');
12
- if (index <= 0 || index === urlAndGlobal.length - 1) {
13
- throw new Error(`Invalid request "${urlAndGlobal}"`);
14
- }
15
- return [urlAndGlobal.substring(index + 1), urlAndGlobal.substring(0, index)];
16
- }
17
- export class ExternalTemplateRemotesPlugin {
18
- apply(compiler) {
19
- compiler.hooks.make.tap(PLUGIN_NAME, (compilation) => {
20
- const scriptExternalModules = [];
21
- compilation.hooks.buildModule.tap(PLUGIN_NAME, (module) => {
22
- if (isExternalModule(module) && module.externalType === 'script') {
23
- scriptExternalModules.push(module);
24
- }
25
- });
26
- compilation.hooks.afterCodeGeneration.tap(PLUGIN_NAME, () => {
27
- scriptExternalModules.forEach((module) => {
28
- const urlTemplate = extractUrlAndGlobal(module.request)[0];
29
- const urlExpression = toExpression(urlTemplate);
30
- const sourceMap = compilation.codeGenerationResults.get(module, undefined).sources;
31
- const rawSource = sourceMap.get('javascript');
32
- if (rawSource) {
33
- const source = new webpackSources.RawSource(rawSource
34
- .source()
35
- .toString()
36
- .replace(`"${urlTemplate}"`, urlExpression));
37
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
- sourceMap.set('javascript', source);
39
- }
40
- });
41
- });
42
- });
43
- }
44
- }
45
- /**
46
- * app2@localhost/remoteEntry.js --> "\"app2@localhost/remoteEntry.js\""
47
- * app2@[window.app2Url]/remoteEntry.js --> "\"app2@\" + window.app2Url + \"/remoteEntry.js\""
48
- * @param templateUrl
49
- * @returns
50
- */
51
- // eslint-disable-next-line sonarjs/cognitive-complexity
52
- function toExpression(templateUrl) {
53
- const result = [];
54
- const current = [];
55
- let isExpression = false;
56
- let invalid = false;
57
- for (const c of templateUrl) {
58
- if (c === '[') {
59
- if (isExpression) {
60
- invalid = true;
61
- break;
62
- }
63
- isExpression = true;
64
- if (current.length) {
65
- result.push(`"${current.join('')}"`);
66
- current.length = 0;
67
- }
68
- }
69
- else if (c === ']') {
70
- if (!isExpression) {
71
- invalid = true;
72
- break;
73
- }
74
- isExpression = false;
75
- if (current.length) {
76
- result.push(`${current.join('')}`);
77
- current.length = 0;
78
- }
79
- current.length = 0;
80
- }
81
- else {
82
- current.push(c);
83
- }
84
- }
85
- if (isExpression || invalid) {
86
- throw new Error(`Invalid template URL "${templateUrl}"`);
87
- }
88
- if (current.length) {
89
- result.push(`"${current.join('')}"`);
90
- }
91
- return result.join(' + ');
92
- }
1
+ import webpackSources from"webpack-sources";const PLUGIN_NAME="ExternalTemplateRemotesPlugin",isExternalModule=e=>"ExternalModule"===e.constructor.name;function extractUrlAndGlobal(e){const t=e.indexOf("@");if(t<=0||t===e.length-1)throw new Error(`Invalid request "${e}"`);return[e.substring(t+1),e.substring(0,t)]}export class ExternalTemplateRemotesPlugin{apply(e){e.hooks.make.tap(PLUGIN_NAME,(e=>{const t=[];e.hooks.buildModule.tap(PLUGIN_NAME,(e=>{isExternalModule(e)&&"script"===e.externalType&&t.push(e)})),e.hooks.afterCodeGeneration.tap(PLUGIN_NAME,(()=>{t.forEach((t=>{const o=extractUrlAndGlobal(t.request)[0],n=toExpression(o),r=e.codeGenerationResults.get(t,void 0).sources,s=r.get("javascript");if(s){const e=new webpackSources.RawSource(s.source().toString().replace(`"${o}"`,n));r.set("javascript",e)}}))}))}))}}function toExpression(e){const t=[],o=[];let n=!1,r=!1;for(const s of e)if("["===s){if(n){r=!0;break}n=!0,o.length&&(t.push(`"${o.join("")}"`),o.length=0)}else if("]"===s){if(!n){r=!0;break}n=!1,o.length&&(t.push(`${o.join("")}`),o.length=0),o.length=0}else o.push(s);if(n||r)throw new Error(`Invalid template URL "${e}"`);return o.length&&t.push(`"${o.join("")}"`),t.join(" + ")}
@@ -1 +1 @@
1
- export * from './module-federation.js';
1
+ export*from"./module-federation.js";
@@ -1,98 +1 @@
1
- import { join } from 'node:path';
2
- import { ensureSlash } from '@flatjs/common';
3
- import webpack from 'webpack';
4
- import { normalizeEvolveEntryName } from '../../helpers/normalize-entry-map.js';
5
- import { injectFederationScripts } from '../../helpers/script-injects.js';
6
- import { HtmlInjectScriptPlugin } from '../html-inject-scripts/plugin-html-inject-script.js';
7
- import { ExternalTemplateRemotesPlugin } from './external-template-remotes.js';
8
- /**
9
- * `${projectVirtualPath}/mine` --> evolve_demo_mine
10
- * @param entryPath `${projectVirtualPath}/mine`
11
- */
12
- const normalizeWidgetName = (entryPath = '') => {
13
- return entryPath.replace(/[/-]/g, '_').toLowerCase();
14
- };
15
- const remoteFileName = (entryName) => {
16
- return join(entryName, `micro-remote-module.js`);
17
- };
18
- export const createModuleFederationPlugin = (serveMode, entryMapItem, evolveOptions) => {
19
- const projectVirtualPath = evolveOptions.projectVirtualPath;
20
- const [entryName, entryConfig] = entryMapItem;
21
- const multiCdnConfig = evolveOptions.multiHtmlCdn;
22
- const multiHtmlCdnResolver = evolveOptions.multiHtmlCdnEnvResolver;
23
- const moduleFederation = entryConfig.options?.moduleFederation;
24
- const plugins = [];
25
- if (moduleFederation) {
26
- const { remotes, exposes, ...restFederationOptions } = moduleFederation;
27
- // e.g. `flatjs/evolve/mine` => `flatjs/evolve/home/micro-remote-module.js`
28
- const entryRemoteFileName = remoteFileName(entryName);
29
- // e.g. `flatjs/evolve/mine` => `flatjs_evolve_mine`
30
- const containerName = normalizeWidgetName(entryName);
31
- const patchExposes = exposes
32
- ? Array.isArray(exposes)
33
- ? exposes
34
- : [exposes]
35
- : [];
36
- const myExposes = patchExposes.map((s) => {
37
- const exposeItem = {};
38
- for (const [key, config] of Object.entries(s)) {
39
- exposeItem[key] = {
40
- ...config,
41
- name: join(entryName, config.name.replace(/^\//, '')),
42
- };
43
- }
44
- return exposeItem;
45
- });
46
- const myRemotes = (remotes || []).map(({ name, endpoint }) => {
47
- // e.g. `flatjs/evolve/home`
48
- const normalizedEntryName = normalizeEvolveEntryName(name, projectVirtualPath);
49
- // e.g. `flatjs_evolve_home`
50
- const remoteWidgetName = normalizeWidgetName(normalizedEntryName);
51
- // e.g. `flatjs/evolve/home/micro-remote-module.js`
52
- const refRemoteEntryFileName = remoteFileName(normalizedEntryName);
53
- // construct endpoint for remote widget name.
54
- const endpointPath = endpoint
55
- ? ensureSlash(endpoint(name, normalizedEntryName), false)
56
- : `[window.evolveFetchMicroWidgets()]`;
57
- return {
58
- [remoteWidgetName]: `${remoteWidgetName}@${endpointPath}/${refRemoteEntryFileName}`,
59
- };
60
- });
61
- plugins.push(
62
- // https://webpack.js.org/plugins/module-federation-plugin/
63
- new webpack.container.ModuleFederationPlugin({
64
- /**
65
- * The name of the container
66
- * `${projectName}-${moduleName}` e.g. `flatjs_evolve_home`
67
- */
68
- name: containerName,
69
- /**
70
- * The filename of the container as relative path inside the `output.path` directory.
71
- * `${entryName}/micro-remote-module.js`, e.g. `flatjs/evolve/home/micro-remote-module.js`
72
- */
73
- filename: entryRemoteFileName,
74
- /**
75
- * Container locations and request scopes from which modules should be resolved and loaded at runtime.
76
- * When provided, property name is used as request scope, otherwise request scope is automatically inferred from container location.
77
- */
78
- remotes: myRemotes,
79
- /**
80
- * Modules that should be exposed by this container.
81
- * When provided, property name is used as public name, otherwise public name is automatically inferred from request.
82
- */
83
- exposes: myExposes,
84
- /**
85
- * Options for library.
86
- * library: { type: 'var', name: containerName },
87
- * other module federation configurations
88
- */
89
- ...restFederationOptions,
90
- }), new ExternalTemplateRemotesPlugin());
91
- if (!serveMode) {
92
- plugins.unshift(new HtmlInjectScriptPlugin([
93
- injectFederationScripts(multiCdnConfig, multiHtmlCdnResolver),
94
- ]));
95
- }
96
- }
97
- return plugins;
98
- };
1
+ import{join}from"node:path";import{ensureSlash}from"@flatjs/common";import webpack from"webpack";import{normalizeEvolveEntryName}from"../../helpers/normalize-entry-map.js";import{injectFederationScripts}from"../../helpers/script-injects.js";import{HtmlInjectScriptPlugin}from"../html-inject-scripts/plugin-html-inject-script.js";import{ExternalTemplateRemotesPlugin}from"./external-template-remotes.js";const normalizeWidgetName=(e="")=>e.replace(/[/-]/g,"_").toLowerCase(),remoteFileName=e=>join(e,"micro-remote-module.js");export const createModuleFederationPlugin=(e,t,r)=>{const o=r.projectVirtualPath,[n,i]=t,m=r.multiHtmlCdn,a=r.multiHtmlCdnEnvResolver,l=i.options?.moduleFederation,s=[];if(l){const{remotes:t,exposes:r,...i}=l,p=remoteFileName(n),c=normalizeWidgetName(n),u=(r?Array.isArray(r)?r:[r]:[]).map((e=>{const t={};for(const[r,o]of Object.entries(e))t[r]={...o,name:join(n,o.name.replace(/^\//,""))};return t})),d=(t||[]).map((({name:e,endpoint:t})=>{const r=normalizeEvolveEntryName(e,o),n=normalizeWidgetName(r),i=remoteFileName(r);return{[n]:`${n}@${t?ensureSlash(t(e,r),!1):"[window.evolveFetchMicroWidgets()]"}/${i}`}}));s.push(new webpack.container.ModuleFederationPlugin({name:c,filename:p,remotes:d,exposes:u,...i}),new ExternalTemplateRemotesPlugin),e||s.unshift(new HtmlInjectScriptPlugin([injectFederationScripts(m,a)]))}return s};
@@ -1,15 +1 @@
1
- import { FlatEvolveMultiCdnPlugin } from './multi-html-cdn-plugin.js';
2
- import { createMultiHtmlWebpackPlugin } from './multi-html-plugin.js';
3
- export const createHtmlPlugins = (serveMode, entryMapItem, evolveOptions) => {
4
- const plugins = [];
5
- // Only for `production`
6
- if (serveMode) {
7
- return plugins;
8
- }
9
- // Attach `html-webpack-plugin` first
10
- const allEnv = Object.keys(evolveOptions.multiHtmlCdn);
11
- plugins.push(...createMultiHtmlWebpackPlugin(serveMode, evolveOptions, entryMapItem, allEnv));
12
- // Attach `@flatjs/evolve-plugin-multi-html-cdn`
13
- plugins.push(new FlatEvolveMultiCdnPlugin(evolveOptions));
14
- return plugins;
15
- };
1
+ import{FlatEvolveMultiCdnPlugin}from"./multi-html-cdn-plugin.js";import{createMultiHtmlWebpackPlugin}from"./multi-html-plugin.js";export const createHtmlPlugins=(t,l,u)=>{const i=[];if(t)return i;const n=Object.keys(u.multiHtmlCdn);return i.push(...createMultiHtmlWebpackPlugin(t,u,l,n)),i.push(new FlatEvolveMultiCdnPlugin(u)),i};
@@ -1,84 +1 @@
1
- import { basename } from 'node:path';
2
- import HtmlWebpackPlugin from 'html-webpack-plugin';
3
- import webpack from 'webpack';
4
- import { cdnFinder, findEnvCdn, httpUrlJoin, } from '../../helpers/script-injects.js';
5
- export class FlatEvolveMultiCdnPlugin {
6
- constructor(evolveOptions) {
7
- this.pluginName = 'FlatEvolveMultiCdnPlugin';
8
- // https://github.com/webpack/webpack/blob/3d653290fafe385277b48e5a36807124618b9561/lib/MainTemplate.js#L12
9
- // the bundle public path RuntimeGlobals.publicPath: '__webpack_require__.p';
10
- this.requireFn = webpack.RuntimeGlobals.publicPath;
11
- this.config = evolveOptions.multiHtmlCdn;
12
- this.cdnResolver =
13
- evolveOptions.multiHtmlCdnEnvResolver ||
14
- function cdnResolver() {
15
- return undefined;
16
- };
17
- // Make sure we have `prod` configuration for each cdn node at least.
18
- if (!this.config?.prod) {
19
- throw new Error('We must setup `prod` for each CDN config node!');
20
- }
21
- }
22
- /**
23
- * Apply the plugin to check if there are non initial chunks which need to be imported using `require-ensure` or `import`
24
- * https://github.com/webpack/webpack/blob/3d653290fafe385277b48e5a36807124618b9561/lib/MainTemplate.js#L158
25
- * https://www.npmjs.com/package/vscode-webpack-debugger
26
- * https://www.cnblogs.com/Scar007/p/9166068.html
27
- * https://www.cnblogs.com/pluslius/p/10271537.html
28
- */
29
- apply(compiler) {
30
- // Handle chunk assets while `Compilation:before-chunk-assets`
31
- // https://github.com/webpack/webpack/blob/3d653290fafe385277b48e5a36807124618b9561/lib/MainTemplate.js#L58
32
- compiler.hooks.thisCompilation.tap(this.pluginName, (compilation) => {
33
- compilation.mainTemplate.hooks.requireExtensions.tap(this.pluginName, (_source, chunk) => {
34
- const buf = [];
35
- buf.push('// Dynamic assets path override(`@flatjs/evolve`) plugin-multi-html-cdn`)');
36
- const runtimeRequirements = compilation.chunkGraph?.getTreeRuntimeRequirements(chunk);
37
- if (runtimeRequirements &&
38
- runtimeRequirements.has(webpack.RuntimeGlobals.requireScope)) {
39
- buf.push('(function () {');
40
- buf.push(webpack.Template.indent(`var flatjsMultiCdn = {`));
41
- buf.push(webpack.Template.indent(webpack.Template.indent([
42
- `cdnConfig: ${JSON.stringify(this.config || {})},`,
43
- ])));
44
- buf.push(webpack.Template.indent(webpack.Template.indent([
45
- `cdnResolver: ${this.cdnResolver.toString()},`,
46
- ])));
47
- buf.push(webpack.Template.indent(webpack.Template.indent([`cdnFinder: ${cdnFinder.toString()}`])));
48
- buf.push(webpack.Template.indent(`};`));
49
- buf.push(webpack.Template.indent(`${this.requireFn} = flatjsMultiCdn.cdnFinder(flatjsMultiCdn.cdnConfig, flatjsMultiCdn.cdnResolver) || ${this.requireFn};`));
50
- buf.push('})();');
51
- }
52
- return webpack.Template.asString(buf);
53
- });
54
- });
55
- // Using html webpack plugin hooks to replace `scripts` `styles` before inject to html temlate file.
56
- compiler.hooks.compilation.tap(this.pluginName, (compilation) => {
57
- HtmlWebpackPlugin.getHooks(compilation).beforeAssetTagGeneration.tap(this.pluginName, (data) => {
58
- const { assets } = data;
59
- const { userOptions } = data.plugin;
60
- const multiCdn = userOptions.multiCdn;
61
- const publicPath = assets.publicPath;
62
- const scripts = assets.js.map((scriptItem) => {
63
- // Normally for `index-dev.html` we need to use relative path.
64
- if (multiCdn.disabled) {
65
- return basename(scriptItem);
66
- }
67
- const randomCdn = findEnvCdn(this.config, multiCdn.env);
68
- return httpUrlJoin(randomCdn, scriptItem.replace(publicPath, ''));
69
- });
70
- const styles = assets.css.map((styleItem) => {
71
- // Normally for `index-dev.html` we need to use relative path.
72
- if (multiCdn.disabled) {
73
- return basename(styleItem);
74
- }
75
- const randomCdn = findEnvCdn(this.config, multiCdn.env);
76
- return httpUrlJoin(randomCdn, styleItem.replace(publicPath, ''));
77
- });
78
- data.assets.js = scripts;
79
- data.assets.css = styles;
80
- return data;
81
- });
82
- });
83
- }
84
- }
1
+ import{basename}from"node:path";import HtmlWebpackPlugin from"html-webpack-plugin";import webpack from"webpack";import{cdnFinder,findEnvCdn,httpUrlJoin}from"../../helpers/script-injects.js";export class FlatEvolveMultiCdnPlugin{constructor(e){if(this.pluginName="FlatEvolveMultiCdnPlugin",this.requireFn=webpack.RuntimeGlobals.publicPath,this.config=e.multiHtmlCdn,this.cdnResolver=e.multiHtmlCdnEnvResolver||function cdnResolver(){},!this.config?.prod)throw new Error("We must setup `prod` for each CDN config node!")}apply(e){e.hooks.thisCompilation.tap(this.pluginName,(e=>{e.mainTemplate.hooks.requireExtensions.tap(this.pluginName,((n,t)=>{const i=[];i.push("// Dynamic assets path override(`@flatjs/evolve`) plugin-multi-html-cdn`)");const s=e.chunkGraph?.getTreeRuntimeRequirements(t);return s&&s.has(webpack.RuntimeGlobals.requireScope)&&(i.push("(function () {"),i.push(webpack.Template.indent("var flatjsMultiCdn = {")),i.push(webpack.Template.indent(webpack.Template.indent([`cdnConfig: ${JSON.stringify(this.config||{})},`]))),i.push(webpack.Template.indent(webpack.Template.indent([`cdnResolver: ${this.cdnResolver.toString()},`]))),i.push(webpack.Template.indent(webpack.Template.indent([`cdnFinder: ${cdnFinder.toString()}`]))),i.push(webpack.Template.indent("};")),i.push(webpack.Template.indent(`${this.requireFn} = flatjsMultiCdn.cdnFinder(flatjsMultiCdn.cdnConfig, flatjsMultiCdn.cdnResolver) || ${this.requireFn};`)),i.push("})();")),webpack.Template.asString(i)}))})),e.hooks.compilation.tap(this.pluginName,(e=>{HtmlWebpackPlugin.getHooks(e).beforeAssetTagGeneration.tap(this.pluginName,(e=>{const{assets:n}=e,{userOptions:t}=e.plugin,i=t.multiCdn,s=n.publicPath,a=n.js.map((e=>{if(i.disabled)return basename(e);const n=findEnvCdn(this.config,i.env);return httpUrlJoin(n,e.replace(s,""))})),p=n.css.map((e=>{if(i.disabled)return basename(e);const n=findEnvCdn(this.config,i.env);return httpUrlJoin(n,e.replace(s,""))}));return e.assets.js=a,e.assets.css=p,e}))}))}}
@@ -1,70 +1 @@
1
- import HtmlWebpackPlugin from 'html-webpack-plugin';
2
- import { allowPx2remForModule } from '../../helpers/allow-px2rem-for-module.js';
3
- import { getHtmlPluginConfig, } from '../../helpers/get-html-plugin-config.js';
4
- import { findEnvCdn } from '../../helpers/script-injects.js';
5
- const minifyOpts = {
6
- minifyJS: true,
7
- removeComments: true,
8
- collapseWhitespace: true,
9
- collapseBooleanAttributes: false,
10
- };
11
- /**
12
- * Create `html-webpack-plugin` for this build, refer to best practices
13
- * We'd better pass only one entry for each `build` cycle
14
- * @param buildEntryItem the entries for this `build`
15
- * @param allEnv
16
- */
17
- export const createMultiHtmlWebpackPlugin = (serveMode, evolveOptions, entryMapItem, allEnv) => {
18
- const [entryKey, entryConfig] = entryMapItem;
19
- const htmlPlugins = [];
20
- const { options } = entryConfig;
21
- const mode = serveMode ? 'development' : 'production';
22
- for (const env of allEnv) {
23
- const envCdn = findEnvCdn(evolveOptions.multiHtmlCdn, env);
24
- const configData = {
25
- mode,
26
- envCdn,
27
- };
28
- htmlPlugins.push(new HtmlWebpackPlugin({
29
- inject: 'body',
30
- title: getHtmlPluginConfig('title', configData, options?.title),
31
- chunks: [entryKey],
32
- // `minify` is true, `dev` always don't minify.
33
- minify: options?.htmlMinify === false || ['me', 'dev'].includes(env)
34
- ? false
35
- : minifyOpts,
36
- // output file path
37
- filename: `${entryKey}/index${env === 'prod' ? '' : `-${env}`}.html`,
38
- // html template
39
- template: getHtmlPluginConfig('templatePath', configData, options?.templatePath).replace(`{0}`, env),
40
- // template parameters
41
- templateParameters: {
42
- // The page title
43
- title: getHtmlPluginConfig('title', configData, options?.title),
44
- // The page favicon
45
- favicon: getHtmlPluginConfig('favicon', configData, options?.favicon),
46
- // The customized inject head tags.
47
- headBeforeHtmlTags: getHtmlPluginConfig('headBeforeHtmlTags', configData, options?.headBeforeHtmlTags),
48
- // The customized inject inline scripts.
49
- inlineScripts: getHtmlPluginConfig('inlineScripts', configData, options?.inlineScripts),
50
- // The ordered styles will be injected start of html head.
51
- headBeforeStyles: getHtmlPluginConfig('headBeforeStyles', configData, options?.headBeforeStyles),
52
- // The ordered scripts will be injected before html head.
53
- headBeforeScripts: getHtmlPluginConfig('headBeforeScripts', configData, options?.headBeforeScripts),
54
- // The ordered scripts will be injected end of html body.
55
- bodyAfterScripts: getHtmlPluginConfig('bodyAfterScripts', configData, options?.bodyAfterScripts),
56
- // `allowPx2rem` default is true
57
- viewport: allowPx2remForModule(entryMapItem, evolveOptions)
58
- ? getHtmlPluginConfig('viewport', configData, options?.viewport)
59
- : '',
60
- },
61
- // Some options for plugin used the `hook` of `html-webpack-plugin`
62
- multiCdn: {
63
- env,
64
- // use relative path for `me`, `dev`, `ntv`
65
- disabled: (options?.excludeCdnEnvs || ['me', 'dev', 'ntv']).includes(env),
66
- },
67
- }));
68
- }
69
- return htmlPlugins;
70
- };
1
+ import HtmlWebpackPlugin from"html-webpack-plugin";import{allowPx2remForModule}from"../../helpers/allow-px2rem-for-module.js";import{getHtmlPluginConfig}from"../../helpers/get-html-plugin-config.js";import{findEnvCdn}from"../../helpers/script-injects.js";const minifyOpts={minifyJS:!0,removeComments:!0,collapseWhitespace:!0,collapseBooleanAttributes:!1};export const createMultiHtmlWebpackPlugin=(e,t,i,l)=>{const[n,o]=i,r=[],{options:m}=o,g=e?"development":"production";for(const e of l){const l={mode:g,envCdn:findEnvCdn(t.multiHtmlCdn,e)};r.push(new HtmlWebpackPlugin({inject:"body",title:getHtmlPluginConfig("title",l,m?.title),chunks:[n],minify:!1!==m?.htmlMinify&&!["me","dev"].includes(e)&&minifyOpts,filename:`${n}/index${"prod"===e?"":`-${e}`}.html`,template:getHtmlPluginConfig("templatePath",l,m?.templatePath).replace("{0}",e),templateParameters:{title:getHtmlPluginConfig("title",l,m?.title),favicon:getHtmlPluginConfig("favicon",l,m?.favicon),headBeforeHtmlTags:getHtmlPluginConfig("headBeforeHtmlTags",l,m?.headBeforeHtmlTags),inlineScripts:getHtmlPluginConfig("inlineScripts",l,m?.inlineScripts),headBeforeStyles:getHtmlPluginConfig("headBeforeStyles",l,m?.headBeforeStyles),headBeforeScripts:getHtmlPluginConfig("headBeforeScripts",l,m?.headBeforeScripts),bodyAfterScripts:getHtmlPluginConfig("bodyAfterScripts",l,m?.bodyAfterScripts),viewport:allowPx2remForModule(i,t)?getHtmlPluginConfig("viewport",l,m?.viewport):""},multiCdn:{env:e,disabled:(m?.excludeCdnEnvs||["me","dev","ntv"]).includes(e)}}))}return r};
@@ -1,8 +1 @@
1
- export * from './types-dev-server.js';
2
- export * from './types-entry-map.js';
3
- export * from './types-federation.js';
4
- export * from './types-modular-import.js';
5
- export * from './types-multi-html.js';
6
- export * from './types-options.js';
7
- export * from './types-loader-options.js';
8
- export * from './types-webpack.js';
1
+ export*from"./types-dev-server.js";export*from"./types-entry-map.js";export*from"./types-federation.js";export*from"./types-modular-import.js";export*from"./types-multi-html.js";export*from"./types-options.js";export*from"./types-loader-options.js";export*from"./types-webpack.js";
@@ -1 +1 @@
1
- export {};
1
+ export{};