@flatjs/evolve 1.8.1-next.66 → 1.8.1-next.68
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +28 -0
- package/dist/constants.js +17 -1
- package/dist/create-webpack/create-externals.js +6 -1
- package/dist/create-webpack/create-optimization.js +29 -1
- package/dist/create-webpack/create-output.js +35 -1
- package/dist/create-webpack/create-performance.js +7 -1
- package/dist/create-webpack/create-plugins.js +78 -1
- package/dist/create-webpack/create-resolve.js +31 -1
- package/dist/create-webpack/create-rule-sets.js +16 -1
- package/dist/create-webpack/load-webpack-config.js +55 -1
- package/dist/create-webpack/rule-sets/constants.js +3 -1
- package/dist/create-webpack/rule-sets/rule-assets.js +44 -1
- package/dist/create-webpack/rule-sets/rule-css.js +84 -1
- package/dist/create-webpack/rule-sets/rule-less.js +45 -1
- package/dist/create-webpack/rule-sets/rule-scripts.js +27 -1
- package/dist/create-webpack/rule-sets/rule-svg-icon.js +25 -1
- package/dist/create-webpack/rule-sets/rule-utils.js +10 -1
- package/dist/create-webpack/types.js +1 -1
- package/dist/default-options.js +79 -1
- package/dist/define-config/define-config.js +4 -1
- package/dist/define-config/index.js +1 -1
- package/dist/dev-server/add-compiler-to-dev-server.js +47 -1
- package/dist/dev-server/create-app-page-route.js +11 -1
- package/dist/dev-server/create-dev-server-compiler-tasks.js +51 -1
- package/dist/dev-server/create-dev-server-entries.js +27 -1
- package/dist/dev-server/create-dev-server.js +23 -1
- package/dist/dev-server/index.js +6 -1
- package/dist/dev-server/middlewares/create-page-middleware.js +164 -1
- package/dist/dev-server/middlewares/create-public-assets-middleware.js +25 -1
- package/dist/dev-server/middlewares/index.js +2 -1
- package/dist/errors/evolve-build-error.js +10 -1
- package/dist/helpers/allow-px2rem-for-module.js +6 -1
- package/dist/helpers/assert-only-single-entry-item.js +23 -1
- package/dist/helpers/chunk-entry-map.js +21 -1
- package/dist/helpers/enable-bundle-hashname-for-module.js +6 -1
- package/dist/helpers/filter-actived-entries.d.ts +1 -1
- package/dist/helpers/filter-actived-entries.js +41 -1
- package/dist/helpers/get-bundle-file-name.js +23 -1
- package/dist/helpers/get-git-root.js +4 -1
- package/dist/helpers/get-html-plugin-config.d.ts +9 -1
- package/dist/helpers/get-html-plugin-config.js +47 -1
- package/dist/helpers/get-max-process-tasks.d.ts +1 -0
- package/dist/helpers/get-max-process-tasks.js +7 -0
- package/dist/helpers/get-pacakge-dir.js +13 -1
- package/dist/helpers/index.js +15 -1
- package/dist/helpers/merge-babel-options.js +45 -1
- package/dist/helpers/normalize-entry-map.js +38 -1
- package/dist/helpers/open-page.js +15 -1
- package/dist/helpers/print-log.js +49 -1
- package/dist/helpers/refresh-evolve-mock-options.js +23 -1
- package/dist/helpers/resolve-entry-map-input-files.js +20 -1
- package/dist/helpers/script-injects.js +39 -1
- package/dist/helpers/should-enable-react-fast-refresh.js +8 -1
- package/dist/helpers/split-to-multi-compiler.js +22 -1
- package/dist/index.js +5 -1
- package/dist/load-config/index.js +1 -1
- package/dist/load-config/load-evolve-config.js +35 -1
- package/dist/main/env-verify.js +21 -1
- package/dist/main/index.js +4 -1
- package/dist/main/prepare-build.d.ts +4 -8
- package/dist/main/prepare-build.js +38 -1
- package/dist/main/prepare-serve.js +36 -1
- package/dist/main/prepare-static.js +28 -1
- package/dist/main/start-build-dynamic.d.ts +2 -1
- package/dist/main/start-build-dynamic.js +144 -1
- package/dist/main/start-build-worker.d.ts +14 -0
- package/dist/main/start-build-worker.js +41 -0
- package/dist/main/start-build.d.ts +1 -8
- package/dist/main/start-build.js +49 -1
- package/dist/main/start-one-entry-build.d.ts +13 -0
- package/dist/main/start-one-entry-build.js +35 -0
- package/dist/main/start-serve.js +32 -1
- package/dist/main/start-static.js +16 -1
- package/dist/minimizer/create-minimizers.js +25 -1
- package/dist/minimizer/default-options.js +14 -1
- package/dist/minimizer/image-minimizer.js +56 -1
- package/dist/minimizer/index.js +1 -1
- package/dist/minimizer/terser-minimizer.js +15 -3
- package/dist/minimizer/types.js +1 -1
- package/dist/plugins/clean-webpack/clean-webpack-plugin.js +173 -1
- package/dist/plugins/clean-webpack/index.js +22 -1
- package/dist/plugins/define-variable/define-variable-plugin.js +21 -1
- package/dist/plugins/define-variable/index.js +1 -1
- package/dist/plugins/html-inject-scripts/plugin-html-inject-script.js +27 -1
- package/dist/plugins/module-federation/external-template-remotes.js +92 -1
- package/dist/plugins/module-federation/index.js +1 -1
- package/dist/plugins/module-federation/module-federation.js +98 -1
- package/dist/plugins/multi-html/index.js +15 -1
- package/dist/plugins/multi-html/multi-html-cdn-plugin.js +84 -1
- package/dist/plugins/multi-html/multi-html-plugin.js +70 -1
- package/dist/types/index.js +8 -1
- package/dist/types/types-ci.js +1 -1
- package/dist/types/types-dev-server.js +1 -1
- package/dist/types/types-entry-map.js +1 -1
- package/dist/types/types-federation.js +1 -1
- package/dist/types/types-loader-options.js +1 -1
- package/dist/types/types-modular-import.js +1 -1
- package/dist/types/types-multi-html.d.ts +6 -5
- package/dist/types/types-multi-html.js +1 -1
- package/dist/types/types-options.js +1 -1
- package/dist/types/types-plugin-options.js +1 -1
- package/dist/types/types-webpack.d.ts +1 -1
- package/dist/types/types-webpack.js +1 -1
- package/package.json +14 -12
- package/templates/html-plugin/index-dev.html +31 -38
- package/templates/html-plugin/index-inte.html +31 -38
- package/templates/html-plugin/index-inte2.html +31 -38
- package/templates/html-plugin/index-inte3.html +31 -38
- package/templates/html-plugin/index-inte4.html +31 -38
- package/templates/html-plugin/index-me.html +31 -38
- package/templates/html-plugin/index-prod.html +31 -38
- package/templates/html-plugin/index-rc.html +31 -38
- package/templates/html-plugin/index-uat.html +31 -38
- package/templates/module.html +40 -55
@@ -1 +1,173 @@
|
|
1
|
-
import
|
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 +1,22 @@
|
|
1
|
-
import{join}from
|
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 +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 +1 @@
|
|
1
|
-
export*from
|
1
|
+
export * from './define-variable-plugin.js';
|
@@ -1 +1,27 @@
|
|
1
|
-
import htmlWebpackPlugin from
|
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 +1,92 @@
|
|
1
|
-
import webpackSources from
|
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 +1 @@
|
|
1
|
-
export*from
|
1
|
+
export * from './module-federation.js';
|
@@ -1 +1,98 @@
|
|
1
|
-
import
|
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 +1,15 @@
|
|
1
|
-
import{FlatEvolveMultiCdnPlugin}from
|
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 +1,84 @@
|
|
1
|
-
import
|
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 +1,70 @@
|
|
1
|
-
import HtmlWebpackPlugin from
|
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
|
+
};
|
package/dist/types/index.js
CHANGED
@@ -1 +1,8 @@
|
|
1
|
-
export*from
|
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';
|
package/dist/types/types-ci.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export{};
|
1
|
+
export {};
|