@flatjs/evolve 1.8.1-next.65 → 1.8.1-next.67

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/constants.js +17 -1
  3. package/dist/create-webpack/create-externals.js +6 -1
  4. package/dist/create-webpack/create-optimization.js +29 -1
  5. package/dist/create-webpack/create-output.js +35 -1
  6. package/dist/create-webpack/create-performance.js +7 -1
  7. package/dist/create-webpack/create-plugins.js +78 -1
  8. package/dist/create-webpack/create-resolve.js +31 -1
  9. package/dist/create-webpack/create-rule-sets.js +16 -1
  10. package/dist/create-webpack/load-webpack-config.js +55 -1
  11. package/dist/create-webpack/rule-sets/constants.js +3 -1
  12. package/dist/create-webpack/rule-sets/rule-assets.js +44 -1
  13. package/dist/create-webpack/rule-sets/rule-css.js +84 -1
  14. package/dist/create-webpack/rule-sets/rule-less.js +45 -1
  15. package/dist/create-webpack/rule-sets/rule-scripts.js +27 -1
  16. package/dist/create-webpack/rule-sets/rule-svg-icon.js +25 -1
  17. package/dist/create-webpack/rule-sets/rule-utils.js +10 -1
  18. package/dist/create-webpack/types.js +1 -1
  19. package/dist/default-options.js +79 -1
  20. package/dist/define-config/define-config.js +4 -1
  21. package/dist/define-config/index.js +1 -1
  22. package/dist/dev-server/add-compiler-to-dev-server.js +47 -1
  23. package/dist/dev-server/create-app-page-route.js +11 -1
  24. package/dist/dev-server/create-dev-server-compiler-tasks.js +51 -1
  25. package/dist/dev-server/create-dev-server-entries.js +27 -1
  26. package/dist/dev-server/create-dev-server.js +23 -1
  27. package/dist/dev-server/index.js +6 -1
  28. package/dist/dev-server/middlewares/create-page-middleware.js +164 -1
  29. package/dist/dev-server/middlewares/create-public-assets-middleware.js +25 -1
  30. package/dist/dev-server/middlewares/index.js +2 -1
  31. package/dist/errors/evolve-build-error.js +10 -1
  32. package/dist/helpers/allow-px2rem-for-module.js +6 -1
  33. package/dist/helpers/assert-only-single-entry-item.js +23 -1
  34. package/dist/helpers/chunk-entry-map.js +21 -1
  35. package/dist/helpers/enable-bundle-hashname-for-module.js +6 -1
  36. package/dist/helpers/filter-actived-entries.d.ts +1 -1
  37. package/dist/helpers/filter-actived-entries.js +41 -1
  38. package/dist/helpers/get-bundle-file-name.js +23 -1
  39. package/dist/helpers/get-git-root.js +4 -1
  40. package/dist/helpers/get-html-plugin-config.d.ts +9 -1
  41. package/dist/helpers/get-html-plugin-config.js +47 -1
  42. package/dist/helpers/get-max-process-tasks.d.ts +1 -0
  43. package/dist/helpers/get-max-process-tasks.js +7 -0
  44. package/dist/helpers/get-pacakge-dir.js +13 -1
  45. package/dist/helpers/index.js +15 -1
  46. package/dist/helpers/merge-babel-options.js +45 -1
  47. package/dist/helpers/normalize-entry-map.js +38 -1
  48. package/dist/helpers/open-page.js +15 -1
  49. package/dist/helpers/print-log.js +49 -1
  50. package/dist/helpers/refresh-evolve-mock-options.js +23 -1
  51. package/dist/helpers/resolve-entry-map-input-files.js +20 -1
  52. package/dist/helpers/script-injects.js +39 -1
  53. package/dist/helpers/should-enable-react-fast-refresh.js +8 -1
  54. package/dist/helpers/split-to-multi-compiler.js +22 -1
  55. package/dist/index.js +5 -1
  56. package/dist/load-config/index.js +1 -1
  57. package/dist/load-config/load-evolve-config.js +35 -1
  58. package/dist/main/env-verify.js +21 -1
  59. package/dist/main/index.js +4 -1
  60. package/dist/main/prepare-build.d.ts +4 -8
  61. package/dist/main/prepare-build.js +38 -1
  62. package/dist/main/prepare-serve.js +36 -1
  63. package/dist/main/prepare-static.js +28 -1
  64. package/dist/main/start-build-dynamic.d.ts +2 -1
  65. package/dist/main/start-build-dynamic.js +144 -1
  66. package/dist/main/start-build-worker.d.ts +14 -0
  67. package/dist/main/start-build-worker.js +41 -0
  68. package/dist/main/start-build.d.ts +1 -8
  69. package/dist/main/start-build.js +49 -1
  70. package/dist/main/start-one-entry-build.d.ts +13 -0
  71. package/dist/main/start-one-entry-build.js +35 -0
  72. package/dist/main/start-serve.js +32 -1
  73. package/dist/main/start-static.js +16 -1
  74. package/dist/minimizer/create-minimizers.js +25 -1
  75. package/dist/minimizer/default-options.js +14 -1
  76. package/dist/minimizer/image-minimizer.js +56 -1
  77. package/dist/minimizer/index.js +1 -1
  78. package/dist/minimizer/terser-minimizer.js +15 -3
  79. package/dist/minimizer/types.js +1 -1
  80. package/dist/plugins/clean-webpack/clean-webpack-plugin.js +173 -1
  81. package/dist/plugins/clean-webpack/index.js +22 -1
  82. package/dist/plugins/define-variable/define-variable-plugin.js +21 -1
  83. package/dist/plugins/define-variable/index.js +1 -1
  84. package/dist/plugins/html-inject-scripts/plugin-html-inject-script.js +27 -1
  85. package/dist/plugins/module-federation/external-template-remotes.js +92 -1
  86. package/dist/plugins/module-federation/index.js +1 -1
  87. package/dist/plugins/module-federation/module-federation.js +98 -1
  88. package/dist/plugins/multi-html/index.js +15 -1
  89. package/dist/plugins/multi-html/multi-html-cdn-plugin.js +84 -1
  90. package/dist/plugins/multi-html/multi-html-plugin.js +70 -1
  91. package/dist/types/index.js +8 -1
  92. package/dist/types/types-ci.js +1 -1
  93. package/dist/types/types-dev-server.js +1 -1
  94. package/dist/types/types-entry-map.js +1 -1
  95. package/dist/types/types-federation.js +1 -1
  96. package/dist/types/types-loader-options.js +1 -1
  97. package/dist/types/types-modular-import.js +1 -1
  98. package/dist/types/types-multi-html.d.ts +6 -5
  99. package/dist/types/types-multi-html.js +1 -1
  100. package/dist/types/types-options.js +1 -1
  101. package/dist/types/types-plugin-options.js +1 -1
  102. package/dist/types/types-webpack.d.ts +1 -1
  103. package/dist/types/types-webpack.js +1 -1
  104. package/package.json +14 -12
  105. package/templates/html-plugin/index-dev.html +31 -38
  106. package/templates/html-plugin/index-inte.html +31 -38
  107. package/templates/html-plugin/index-inte2.html +31 -38
  108. package/templates/html-plugin/index-inte3.html +31 -38
  109. package/templates/html-plugin/index-inte4.html +31 -38
  110. package/templates/html-plugin/index-me.html +31 -38
  111. package/templates/html-plugin/index-prod.html +31 -38
  112. package/templates/html-plugin/index-rc.html +31 -38
  113. package/templates/html-plugin/index-uat.html +31 -38
  114. package/templates/module.html +40 -55
@@ -1 +1,4 @@
1
- import{searchParentDir}from"@armit/package";export const getGitRoot=r=>searchParentDir(r,".git");
1
+ import { searchParentDir } from '@armit/package';
2
+ export const getGitRoot = (searchFrom) => {
3
+ return searchParentDir(searchFrom, '.git');
4
+ };
@@ -3,10 +3,18 @@ export declare const defaultHtmlPluginConfig: Required<MultiHtmlCDNEntryItem>;
3
3
  type Json = undefined | null | boolean | number | string | Json[] | {
4
4
  [prop: string]: Json;
5
5
  };
6
+ export type HtmlPluginConfigConfigData = {
7
+ mode: 'development' | 'production';
8
+ /**
9
+ * The random `cdn` for config via `env` template
10
+ */
11
+ envCdn: string;
12
+ };
13
+ export type HtmlPluginConfigTokenType<T extends Json> = T | ((configData: HtmlPluginConfigConfigData) => T);
6
14
  /**
7
15
  * 获取html plugin 模版相关定义字段.
8
16
  * @param preferredValue 用户首选的值, 如果返回为undefined, 将使用默认值
9
17
  * @returns
10
18
  */
11
- export declare const getHtmlPluginConfig: <T extends Json>(key: keyof typeof defaultHtmlPluginConfig, mode: 'development' | 'production', preferredValue?: T | ((mode: 'development' | 'production') => T) | undefined) => T;
19
+ export declare const getHtmlPluginConfig: <T extends Json>(key: keyof typeof defaultHtmlPluginConfig, configData: HtmlPluginConfigConfigData, preferredValue?: HtmlPluginConfigTokenType<T> | undefined) => T;
12
20
  export {};
@@ -1 +1,47 @@
1
- import{polyfill,viewportScripts}from"../constants.js";import{getPackageDir}from"./get-pacakge-dir.js";export const defaultHtmlPluginConfig={title:"",favicon:"",headBeforeHtmlTags:[],inlineScripts:[],headBeforeStyles:[],headBeforeScripts:[...polyfill],bodyAfterScripts:[],viewport:viewportScripts,excludeCdnEnvs:["me","dev","ntv"],htmlMinify:!0,templatePath:getPackageDir("templates/html-plugin/index-{0}.html")};export const getHtmlPluginConfig=(t,e,i)=>{let o;if(void 0!==i&&(o="function"==typeof i?i(e):i),void 0===o){const i=defaultHtmlPluginConfig[t];return"function"==typeof i?i(e):i}return o};
1
+ import { polyfill, viewportScripts } from '../constants.js';
2
+ import { getPackageDir } from './get-pacakge-dir.js';
3
+ export const defaultHtmlPluginConfig = {
4
+ // The page title
5
+ title: '',
6
+ // The page favicon url地址
7
+ favicon: '',
8
+ // The customized html tags should be inject to `<header />`
9
+ headBeforeHtmlTags: [],
10
+ // Allow us customized inline scripts into compiled html template.
11
+ inlineScripts: [],
12
+ // The ordered styles will be injected start of html head.
13
+ headBeforeStyles: [],
14
+ // The ordered scripts will be injected before html head.
15
+ headBeforeScripts: [...polyfill],
16
+ // The ordered scripts will be injected end of html body.
17
+ bodyAfterScripts: [],
18
+ // `allowPx2rem` default is true
19
+ viewport: viewportScripts,
20
+ // avoid use cdn `me`, `dev`, `ntv`
21
+ excludeCdnEnvs: ['me', 'dev', 'ntv'],
22
+ // `minify` is true, `dev` always don't minify.
23
+ htmlMinify: true,
24
+ // Default use It must be an absolute path.
25
+ templatePath: getPackageDir('templates/html-plugin/index-{0}.html'),
26
+ };
27
+ /**
28
+ * 获取html plugin 模版相关定义字段.
29
+ * @param preferredValue 用户首选的值, 如果返回为undefined, 将使用默认值
30
+ * @returns
31
+ */
32
+ export const getHtmlPluginConfig = (key, configData, preferredValue) => {
33
+ let userValue;
34
+ if (typeof preferredValue !== 'undefined') {
35
+ userValue =
36
+ typeof preferredValue === 'function'
37
+ ? preferredValue(configData)
38
+ : preferredValue;
39
+ }
40
+ if (typeof userValue === 'undefined') {
41
+ const defaultValue = defaultHtmlPluginConfig[key];
42
+ return typeof defaultValue === 'function'
43
+ ? defaultValue(configData)
44
+ : defaultValue;
45
+ }
46
+ return userValue;
47
+ };
@@ -0,0 +1 @@
1
+ export declare const getMaxProcessTasks: (totalTasks: number, maxProcesses?: string | number) => number;
@@ -0,0 +1,7 @@
1
+ import { cpus } from 'node:os';
2
+ export const getMaxProcessTasks = (totalTasks, maxProcesses) => {
3
+ const maxCpu = Math.max(1, typeof maxProcesses === 'string' && maxProcesses.endsWith('%')
4
+ ? Math.round((cpus().length * Number(maxProcesses.slice(0, -1))) / 100)
5
+ : Number(maxProcesses));
6
+ return totalTasks > maxCpu ? maxCpu : totalTasks;
7
+ };
@@ -1 +1,13 @@
1
- import{join}from"node:path";import{getDirname}from"@armit/file-utility";import{searchPackageDir}from"@armit/package";export const getPackageDir=(...r)=>{const e=getDirname(import.meta.url),o=searchPackageDir({cwd:e});if(!o)throw new Error("Could not resolve package root for `flatjs/evolve`");return join(o,...r)};
1
+ import { join } from 'node:path';
2
+ import { getDirname } from '@armit/file-utility';
3
+ import { searchPackageDir } from '@armit/package';
4
+ export const getPackageDir = (...paths) => {
5
+ const dir = getDirname(import.meta.url);
6
+ const packageDir = searchPackageDir({
7
+ cwd: dir,
8
+ });
9
+ if (!packageDir) {
10
+ throw new Error('Could not resolve package root for `flatjs/evolve`');
11
+ }
12
+ return join(packageDir, ...paths);
13
+ };
@@ -1 +1,15 @@
1
- export*from"./allow-px2rem-for-module.js";export*from"./assert-only-single-entry-item.js";export*from"./chunk-entry-map.js";export*from"./enable-bundle-hashname-for-module.js";export*from"./get-bundle-file-name.js";export*from"./get-html-plugin-config.js";export*from"./get-pacakge-dir.js";export*from"./merge-babel-options.js";export*from"./normalize-entry-map.js";export*from"./open-page.js";export*from"./print-log.js";export*from"./refresh-evolve-mock-options.js";export*from"./script-injects.js";export*from"./should-enable-react-fast-refresh.js";export*from"./split-to-multi-compiler.js";
1
+ export * from './allow-px2rem-for-module.js';
2
+ export * from './assert-only-single-entry-item.js';
3
+ export * from './chunk-entry-map.js';
4
+ export * from './enable-bundle-hashname-for-module.js';
5
+ export * from './get-bundle-file-name.js';
6
+ export * from './get-html-plugin-config.js';
7
+ export * from './get-pacakge-dir.js';
8
+ export * from './merge-babel-options.js';
9
+ export * from './normalize-entry-map.js';
10
+ export * from './open-page.js';
11
+ export * from './print-log.js';
12
+ export * from './refresh-evolve-mock-options.js';
13
+ export * from './script-injects.js';
14
+ export * from './should-enable-react-fast-refresh.js';
15
+ export * from './split-to-multi-compiler.js';
@@ -1 +1,45 @@
1
- import{logger,requireResolve}from"@flatjs/common";import{reactBabelPreset,vueBabelPreset}from"@flatjs/evolve-preset-babel";import babelMerge from"babel-merge";import{moduleName}from"../constants.js";export const mergeBabelOption=(e=[],r={usePreset:"react"})=>{const t=e.map((e=>[requireResolve("babel-plugin-import"),{transformToDefaultImport:!1,libraryDirectory:"dist",...e},e.libraryName])),{usePreset:a="react",...l}=r,o="react"===a?reactBabelPreset():"vue"===a?vueBabelPreset():reactBabelPreset();let s={};try{s=babelMerge(o,l),s.plugins?s.plugins.unshift(...t):s.plugins=t}catch(e){logger.error(e,moduleName)}return{...s,babelrc:!1,compact:!1}};
1
+ import { logger, requireResolve } from '@flatjs/common';
2
+ import { reactBabelPreset, vueBabelPreset } from '@flatjs/evolve-preset-babel';
3
+ import babelMerge from 'babel-merge';
4
+ import { moduleName } from '../constants.js';
5
+ export const mergeBabelOption = (modularImports = [], options = { usePreset: 'react' }) => {
6
+ const babelImports = modularImports.map((importItem) => {
7
+ return [
8
+ requireResolve('babel-plugin-import'),
9
+ {
10
+ transformToDefaultImport: false,
11
+ libraryDirectory: 'dist',
12
+ ...importItem,
13
+ },
14
+ importItem.libraryName,
15
+ ];
16
+ });
17
+ const { usePreset = 'react', ...overrideBabelOption } = options;
18
+ const baseBabelOption = usePreset === 'react'
19
+ ? reactBabelPreset()
20
+ : usePreset === 'vue'
21
+ ? vueBabelPreset()
22
+ : reactBabelPreset();
23
+ let mergedBabelOption = {};
24
+ try {
25
+ mergedBabelOption = babelMerge(baseBabelOption, overrideBabelOption);
26
+ // babelMerge only the last one will be retained, since there are multiple `babel-plugin-import` plugins with the same plugin id.
27
+ // https://github.com/ant-design/babel-plugin-import
28
+ if (mergedBabelOption.plugins) {
29
+ mergedBabelOption.plugins.unshift(...babelImports);
30
+ }
31
+ else {
32
+ mergedBabelOption.plugins = babelImports;
33
+ }
34
+ }
35
+ catch (err) {
36
+ logger.error(err, moduleName);
37
+ }
38
+ const finalBabelOptions = {
39
+ ...mergedBabelOption,
40
+ babelrc: false,
41
+ // Turns out the compact option is set to auto by default which removes "superfluous whitespace characters and line terminators [...] on input sizes >100KB".
42
+ compact: false,
43
+ };
44
+ return finalBabelOptions;
45
+ };
@@ -1 +1,38 @@
1
- import{join}from"node:path";import _ from"lodash";export const normalizeEvolveEntryName=(o,e)=>{const r=o.replace(/^\//,""),t=e.replace(/^\//,"");return(r.startsWith(t)?r:join(t,r)).replace(/\/$/,"")};export const normalizeEvolveEntryMap=(o={},e={})=>{const r={};for(const[t,n]of Object.entries(e)){const e={options:{}};o[t]&&(r[t]=_.merge({},e,n,o[t])),_.merge(n,e)}return r};
1
+ import { join } from 'node:path';
2
+ import _ from 'lodash';
3
+ /**
4
+ * Make sure that we have correct `virtualPath` for each webpack `entry`
5
+ * @param entryName the entryName defined via `flatjs-evolve.config.ts`.
6
+ * @param evolveOptions
7
+ * @returns
8
+ */
9
+ export const normalizeEvolveEntryName = (entryName, projectVirtualPath) => {
10
+ const servedEntryName = entryName.replace(/^\//, '');
11
+ const virtualPath = projectVirtualPath.replace(/^\//, '');
12
+ const withVirtualPath = servedEntryName.startsWith(virtualPath);
13
+ // Make sure that we have correct `virtualPath` for each webpack `entry`
14
+ const finalEntryName = withVirtualPath
15
+ ? servedEntryName
16
+ : join(virtualPath, servedEntryName);
17
+ return finalEntryName.replace(/\/$/, '');
18
+ };
19
+ /**
20
+ * Normalize flatjs.evolve entry map definition data.
21
+ * Merge default entry item configuration values.
22
+ * @param activedEntryMap actived entries
23
+ * @param definedEntryMap defined entries in flatjs.evolve.js
24
+ */
25
+ export const normalizeEvolveEntryMap = (activedEntryMap = {}, definedEntryMap = {}) => {
26
+ const newActivedEntries = {};
27
+ for (const [entryKey, itemConfig] of Object.entries(definedEntryMap)) {
28
+ // Setup default entry options.
29
+ const defaultEntryItemConfig = {
30
+ options: {},
31
+ };
32
+ if (activedEntryMap[entryKey]) {
33
+ newActivedEntries[entryKey] = _.merge({}, defaultEntryItemConfig, itemConfig, activedEntryMap[entryKey]);
34
+ }
35
+ _.merge(itemConfig, defaultEntryItemConfig);
36
+ }
37
+ return newActivedEntries;
38
+ };
@@ -1 +1,15 @@
1
- import opn from"better-opn";export const openPage=n=>{try{opn(n)}catch(n){console.warn("Unable to open browser. If you are running in a headless environment\n")}};
1
+ import opn from 'better-opn';
2
+ /**
3
+ * A better opn. Reuse the same tab on Chrome for
4
+ * @example
5
+ * `http://xxx.domain.com:3001/pages`
6
+ * @param openUrl the page url try to open.
7
+ */
8
+ export const openPage = (openUrl) => {
9
+ try {
10
+ opn(openUrl);
11
+ }
12
+ catch (err) {
13
+ console.warn(`Unable to open browser. If you are running in a headless environment\n`);
14
+ }
15
+ };
@@ -1 +1,49 @@
1
- import{logger}from"@flatjs/common";import{moduleName}from"../constants.js";export const printInfo=(r,o=!1)=>{o||logger.info(r,moduleName)};export const printError=r=>{logger.error(r,moduleName)};const formatCompilerError=(r,o=[])=>{if(!r)return o;if("string"==typeof r)o.push(r);else if(Array.isArray(r))for(const e of r)formatCompilerError(e,o);else if("object"==typeof r){const e=r.stack||r.message;delete r.stack,delete r.message;const t={...r,_newMsg:e};for(const[,r]of Object.entries(t))formatCompilerError(r,o)}return o};export const printCompilerError=r=>{const o=formatCompilerError(r,[]);for(const r of o)console.log(r);return o};
1
+ import { logger } from '@flatjs/common';
2
+ import { moduleName } from '../constants.js';
3
+ export const printInfo = (message, silent = false) => {
4
+ if (!silent) {
5
+ logger.info(message, moduleName);
6
+ }
7
+ };
8
+ export const printError = (message) => {
9
+ logger.error(message, moduleName);
10
+ };
11
+ const formatCompilerError = (errors, formattedMessages = []) => {
12
+ if (!errors) {
13
+ return formattedMessages;
14
+ }
15
+ if (typeof errors === 'string') {
16
+ formattedMessages.push(errors);
17
+ }
18
+ else if (Array.isArray(errors)) {
19
+ for (const error of errors) {
20
+ formatCompilerError(error, formattedMessages);
21
+ }
22
+ }
23
+ else if (typeof errors === 'object') {
24
+ // Only need to show `stack` or `message`
25
+ const onlyOneMsg = errors.stack || errors.message;
26
+ delete errors.stack;
27
+ delete errors.message;
28
+ const newErrors = {
29
+ ...errors,
30
+ _newMsg: onlyOneMsg,
31
+ };
32
+ for (const [, value] of Object.entries(newErrors)) {
33
+ formatCompilerError(value, formattedMessages);
34
+ }
35
+ }
36
+ return formattedMessages;
37
+ };
38
+ /**
39
+ * Do not use `logger` to print webpack compiler error, cause of it may have it's message formatting.
40
+ * @param errors
41
+ * @returns
42
+ */
43
+ export const printCompilerError = (errors) => {
44
+ const newErrors = formatCompilerError(errors, []);
45
+ for (const message of newErrors) {
46
+ console.log(message);
47
+ }
48
+ return newErrors;
49
+ };
@@ -1 +1,23 @@
1
- import{loadMockConfig}from"@flatjs/mock";import _ from"lodash";export const refreshEvolveMockOptions=async(o,t,s)=>{const e=t.devServer,n=s?.esmLoaderOptions,r=n?.externals||[],c=await loadMockConfig(o,e?.mockOptions||{},_.merge({},s,{configFile:"flatjs-mock",esmLoaderOptions:{externals:[...r,"@flatjs/mock"]}}));return e&&(e.mockOptions=c||{},e.mockOptions&&!e.mockOptions.https&&(e.mockOptions.https=e?.https)),t};
1
+ import { loadMockConfig } from '@flatjs/mock';
2
+ import _ from 'lodash';
3
+ export const refreshEvolveMockOptions = async (projectCwd, evolveOptions, configLoaderOptions) => {
4
+ const devServer = evolveOptions.devServer;
5
+ const esmLoaderOptions = configLoaderOptions?.esmLoaderOptions;
6
+ const externals = esmLoaderOptions?.externals || [];
7
+ // Try to load mock configuration from `flatjs-mock.config.ts`
8
+ const newMockOptions = await loadMockConfig(projectCwd, (devServer?.mockOptions || {}), _.merge({}, configLoaderOptions, {
9
+ configFile: 'flatjs-mock',
10
+ esmLoaderOptions: {
11
+ // load `flatjs-mock.config.ts` it will always import { defineConfig } from `@flatjs/mock`
12
+ externals: [...externals, '@flatjs/mock'],
13
+ },
14
+ }));
15
+ // we always has `devServer` config node.
16
+ if (devServer) {
17
+ devServer.mockOptions = newMockOptions || {};
18
+ if (devServer.mockOptions && !devServer.mockOptions.https) {
19
+ devServer.mockOptions.https = devServer?.https;
20
+ }
21
+ }
22
+ return evolveOptions;
23
+ };
@@ -1 +1,20 @@
1
- import{fileWalk}from"@armit/file-utility";import{arrayUnique}from"@flatjs/common";export const resolveEntryMapInputFiles=async(t,r)=>{const e=[];for(const[,t]of Object.entries(r)){const r=t.entry.map((t=>t.replace(/.(?:js|jsx|tsx|ts)$/,"")+".*"));e.push(...r)}const o=arrayUnique(e);return await fileWalk(o,{cwd:t,absolute:!0})};
1
+ import { fileWalk } from '@armit/file-utility';
2
+ import { arrayUnique } from '@flatjs/common';
3
+ /**
4
+ * Transform all entry files via `entryMap`
5
+ * @param projectCwd The project root directory
6
+ * @param entryMap The evolve entryMap definition
7
+ * @returns The absolute entry input files.
8
+ */
9
+ export const resolveEntryMapInputFiles = async (projectCwd, entryMap) => {
10
+ const pattern = [];
11
+ for (const [, config] of Object.entries(entryMap)) {
12
+ const entries = config.entry.map((s) => s.replace(/.(?:js|jsx|tsx|ts)$/, '') + '.*');
13
+ pattern.push(...entries);
14
+ }
15
+ const walkPattern = arrayUnique(pattern);
16
+ return await fileWalk(walkPattern, {
17
+ cwd: projectCwd,
18
+ absolute: true,
19
+ });
20
+ };
@@ -1 +1,39 @@
1
- export function httpUrlJoin(n="",e=""){return n.replace(/\/$/,"")+"/"+e.replace(/^\//,"")}export function cdnFinder(n,e){const r=window.location.href,o=/[?&]env(=([^&#]*)|&|#|$)/.exec(r);let t=o&&o[2]?decodeURIComponent(o[2].replace(/\+/g," ")):"prod";t=e&&e(r)||t;const c=n[t]||n.prod||[];return c[Math.floor(Math.random()*c.length)].replace(/\/$/,"")+"/"}export function findEnvCdn(n={},e="prod"){const r=n[e]||n.prod||[];return r[Math.floor(Math.random()*r.length)]}export function injectFederationScripts(n,e=function cdnResolver(){}){return`window.evolveFetchMicroWidgets = function () {\n var cdnConfig = ${JSON.stringify(n)};\n var cdnResolver = ${e.toString()};\n var cdnFinder = ${cdnFinder.toString()};\n return (cdnFinder(cdnConfig, cdnResolver) || '').replace(/\\/$/, '');\n }\n `}
1
+ export function httpUrlJoin(first = '', second = '') {
2
+ return first.replace(/\/$/, '') + '/' + second.replace(/^\//, '');
3
+ }
4
+ /**
5
+ * To extract the best matched CDN configuration url address, either use URL `query.env` or customize the `envRresolver`
6
+ * @param cdnConfig List of pre-configured cdn urls for each environment
7
+ * @param envResolver Get the specific environment variable by the currently requested host url address.
8
+ * @returns Returns the best matching address with a suffix (`/`)
9
+ */
10
+ export function cdnFinder(cdnConfig, envResolver) {
11
+ // eslint-disable-next-line regexp/no-unused-capturing-group
12
+ const regex = /[?&]env(=([^&#]*)|&|#|$)/;
13
+ const locationHref = window.location.href;
14
+ const results = regex.exec(locationHref);
15
+ let env = results && results[2]
16
+ ? decodeURIComponent(results[2].replace(/\+/g, ' '))
17
+ : 'prod';
18
+ // If we have customized cdn resolver using it first.
19
+ env = (envResolver && envResolver(locationHref)) || env;
20
+ const matchedCdnList = cdnConfig[env] || cdnConfig['prod'] || [];
21
+ const matchedCdn = matchedCdnList[Math.floor(Math.random() * matchedCdnList.length)];
22
+ // ensure has endfix slash
23
+ return matchedCdn.replace(/\/$/, '') + '/';
24
+ }
25
+ export function findEnvCdn(cdnConfig = {}, env = 'prod') {
26
+ const matchedCdnList = cdnConfig[env] || cdnConfig['prod'] || [];
27
+ return matchedCdnList[Math.floor(Math.random() * matchedCdnList.length)];
28
+ }
29
+ export function injectFederationScripts(cdnConfig, cdnResolver = function cdnResolver() {
30
+ return undefined;
31
+ }) {
32
+ return `window.evolveFetchMicroWidgets = function () {
33
+ var cdnConfig = ${JSON.stringify(cdnConfig)};
34
+ var cdnResolver = ${cdnResolver.toString()};
35
+ var cdnFinder = ${cdnFinder.toString()};
36
+ return (cdnFinder(cdnConfig, cdnResolver) || '').replace(/\\/$/, '');
37
+ }
38
+ `;
39
+ }
@@ -1 +1,8 @@
1
- export const shouldEnableReactFastRefresh=(e,t,o)=>{const s=t[1],n=!!s.options?.moduleFederation;return e&&"react"===o.loaderOptions.babelOptions?.usePreset&&!n};
1
+ export const shouldEnableReactFastRefresh = (serveMode, entryMapItem, evolveOptions) => {
2
+ const entryItemOption = entryMapItem[1];
3
+ const hasModuleFederation = !!entryItemOption.options?.moduleFederation;
4
+ // Inject `react-refresh` if we are using preset `react`
5
+ return (serveMode &&
6
+ evolveOptions.loaderOptions.babelOptions?.usePreset === 'react' &&
7
+ !hasModuleFederation);
8
+ };
@@ -1 +1,22 @@
1
- import{mergeOptions}from"@flatjs/common";import{normalizeEvolveEntryName}from"./normalize-entry-map.js";export function splitToMultiCompilerConfigs(e,o,t){const r=[];for(const[o,n]of Object.entries(e)){const e=normalizeEvolveEntryName(o,t.projectVirtualPath);r.push({[e]:n.entry})}return r.map((e=>mergeOptions(o,{name:Object.keys(e)[0],entry:e})))}
1
+ import { mergeOptions } from '@flatjs/common';
2
+ import { normalizeEvolveEntryName } from './normalize-entry-map.js';
3
+ /**
4
+ * Split the `webpack` to make sure that we have separated compiler process for each module
5
+ * @param webpackConfig `Omit<Configuration, 'entry'>` webpack final configuration
6
+ */
7
+ export function splitToMultiCompilerConfigs(servedEntries, webpackConfig, evolveOptions) {
8
+ const result = [];
9
+ for (const [entryName, entryItem] of Object.entries(servedEntries)) {
10
+ // Make sure that we have correct `virtualPath` for each webpack `entry`
11
+ const normalizedEntryName = normalizeEvolveEntryName(entryName, evolveOptions.projectVirtualPath);
12
+ result.push({
13
+ [normalizedEntryName]: entryItem.entry,
14
+ });
15
+ }
16
+ return result.map((newEntry) => {
17
+ return mergeOptions(webpackConfig, {
18
+ name: Object.keys(newEntry)[0],
19
+ entry: newEntry,
20
+ });
21
+ });
22
+ }
package/dist/index.js CHANGED
@@ -1 +1,5 @@
1
- export*from"./define-config/index.js";export*from"./load-config/index.js";export*from"./main/index.js";export*from"./types/types-options.js";export*from"./types/types-entry-map.js";
1
+ export * from './define-config/index.js';
2
+ export * from './load-config/index.js';
3
+ export * from './main/index.js';
4
+ export * from './types/types-options.js';
5
+ export * from './types/types-entry-map.js';
@@ -1 +1 @@
1
- export*from"./load-evolve-config.js";
1
+ export * from './load-evolve-config.js';
@@ -1 +1,35 @@
1
- import{mergeOptions,logger,searchConfig}from"@flatjs/common";import{configFileName,moduleName}from"../constants.js";import{defaultEvolveOptions}from"../default-options.js";import{refreshEvolveMockOptions}from"../helpers/refresh-evolve-mock-options.js";export const loadEvolveConfig=async(o,e,t={},n={configFile:configFileName,esmLoaderOptions:{externals:["@flatjs/evolve","@flatjs/mock"]}})=>{const{configFile:i,esmLoaderOptions:s}=n,r=await searchConfig(i,e,{esm:{...s,projectCwd:e}});let l={};l="function"==typeof r?.config?r?.config(o):r?.config||{};const f=mergeOptions(defaultEvolveOptions,l),m=mergeOptions(f,t),a=mergeOptions(m,{projectCwd:e}),c=await refreshEvolveMockOptions(e,a,n);return logger.debug(`Load evolve config:\n${JSON.stringify(c,null,2)}`,moduleName),c};
1
+ import { mergeOptions, logger, searchConfig, } from '@flatjs/common';
2
+ import { configFileName, moduleName } from '../constants.js';
3
+ import { defaultEvolveOptions } from '../default-options.js';
4
+ import { refreshEvolveMockOptions } from '../helpers/refresh-evolve-mock-options.js';
5
+ export const loadEvolveConfig = async (configEnv, projectCwd, overrideOptions = {}, configLoaderOptions = {
6
+ configFile: configFileName,
7
+ esmLoaderOptions: {
8
+ externals: ['@flatjs/evolve', '@flatjs/mock'],
9
+ },
10
+ }) => {
11
+ const { configFile, esmLoaderOptions } = configLoaderOptions;
12
+ const data = await searchConfig(configFile, projectCwd, {
13
+ esm: {
14
+ ...esmLoaderOptions,
15
+ projectCwd,
16
+ },
17
+ });
18
+ let localData = {};
19
+ if (typeof data?.config === 'function') {
20
+ localData = data?.config(configEnv);
21
+ }
22
+ else {
23
+ localData = data?.config || {};
24
+ }
25
+ // Merge user local config with default configure options.
26
+ const localConfigOptions = mergeOptions(defaultEvolveOptions, localData);
27
+ const mergedConfigOptions = mergeOptions(localConfigOptions, overrideOptions);
28
+ const finalData = mergeOptions(mergedConfigOptions, { projectCwd });
29
+ // We don't need to load mocks configuration from `flatjs-mock.config.js` while `build` phase.
30
+ const latestEvolveOptions = configEnv.command === 'build'
31
+ ? finalData
32
+ : await refreshEvolveMockOptions(projectCwd, finalData, configLoaderOptions);
33
+ logger.debug(`Load evolve config:\n${JSON.stringify(latestEvolveOptions, null, 2)}`, moduleName);
34
+ return latestEvolveOptions;
35
+ };
@@ -1 +1,21 @@
1
- import{illegalPackageChecker,keepPackageDepsUpToDateForNonMonoRepo}from"@armit/package";export const envVerify=async(e,a)=>{const{packageInstallChecker:o,needVerifyPackages:r}=a;!1!==o&&o?.enabled&&await illegalPackageChecker({cwd:e,modules:o?.detectModules,throwError:o?.throwError,showAllInstalledGraph:o?.showAllInstalledGraph}),!1!==r&&await keepPackageDepsUpToDateForNonMonoRepo({cwd:e,autoUpgrade:!0,needVerifyPackages:r||{}})};
1
+ import { illegalPackageChecker, keepPackageDepsUpToDateForNonMonoRepo, } from '@armit/package';
2
+ export const envVerify = async (projectCwd, evolveOptions) => {
3
+ const { packageInstallChecker, needVerifyPackages } = evolveOptions;
4
+ if (packageInstallChecker !== false && packageInstallChecker?.enabled) {
5
+ // Verify local install node modules
6
+ await illegalPackageChecker({
7
+ cwd: projectCwd,
8
+ modules: packageInstallChecker?.detectModules,
9
+ throwError: packageInstallChecker?.throwError,
10
+ showAllInstalledGraph: packageInstallChecker?.showAllInstalledGraph,
11
+ });
12
+ }
13
+ if (needVerifyPackages !== false) {
14
+ // Keep package deps up to date for non-monorepo
15
+ await keepPackageDepsUpToDateForNonMonoRepo({
16
+ cwd: projectCwd,
17
+ autoUpgrade: true,
18
+ needVerifyPackages: needVerifyPackages || {},
19
+ });
20
+ }
21
+ };
@@ -1 +1,4 @@
1
- export*from"./start-build.js";export*from"./start-serve.js";export*from"./start-static.js";export*from"./start-build-dynamic.js";
1
+ export * from './start-build.js';
2
+ export * from './start-serve.js';
3
+ export * from './start-static.js';
4
+ export * from './start-build-dynamic.js';
@@ -1,13 +1,9 @@
1
- import { type EvolveEntryMap } from '../types/types-entry-map.js';
1
+ import { type EntryMapItem } from '../types/types-entry-map.js';
2
2
  import { type FlatEvolveOptions } from '../types/types-options.js';
3
- export type EvolveBuildResult = {
4
- name?: string;
5
- warningStats?: unknown;
6
- };
3
+ import { type EvolveBuildResult } from './start-one-entry-build.js';
7
4
  /**
8
5
  * The main entry to start an evolve `build`
9
- * @param buildEntries All webpack entries we prepare to build.
6
+ * @param entryMapItem The `entryMapItem` for one entry build task
10
7
  * @param evolveOptions FlatEvolveOptions
11
- * @param clearCache The value indicates if we need to clear webpack cache resources.
12
8
  */
13
- export declare const prepareBuild: (projectCwd: string, buildEntries: EvolveEntryMap, evolveOptions: FlatEvolveOptions) => Promise<EvolveBuildResult[]>;
9
+ export declare const prepareBuild: (entryMapItem: EntryMapItem, evolveOptions: FlatEvolveOptions) => Promise<EvolveBuildResult>;
@@ -1 +1,38 @@
1
- import{cpus}from"node:os";import{ensureSlash,logger,mergeOptions}from"@flatjs/common";import ora from"ora";import webpack from"webpack";import{loadWebpackConfig}from"../create-webpack/load-webpack-config.js";import{EvolveBuildError}from"../errors/evolve-build-error.js";import{chunkEntryMap}from"../helpers/chunk-entry-map.js";import{printCompilerError}from"../helpers/print-log.js";import{splitToMultiCompilerConfigs}from"../helpers/split-to-multi-compiler.js";import{envVerify}from"./env-verify.js";const getMaxProcessTasks=(r,o)=>Math.max(1,"string"==typeof o&&o.endsWith("%")?Math.round(cpus().length*Number(o.slice(0,-1))/100):Number(o)||r),startSingleEntryBuild=async(r,o)=>{const t=await loadWebpackConfig("production",r,o),e=splitToMultiCompilerConfigs(r,t,o);if(e.length>1)throw new Error("startSingleEntryBuild() only support `compiler` at a time");const n=e[0];return new Promise(((r,t)=>{webpack(n,((e,s)=>{if(e)return t(e);const i=s?.toJson();return i?.errors?.length?t(i.errors):o.rejectWarnings&&i?.warnings?.length?t(i.warnings):void r({name:n.name,warningStats:i?.warnings})}))}))};export const prepareBuild=async(r,o,t)=>{await envVerify(r,t);const e=t.multiHtmlCdn?.prod||[];if(!e.length)throw new Error('No CDN configuration for env: "prod"');const n=ensureSlash(e[Math.floor(Math.random()*e.length)],!0),s=[],i=chunkEntryMap(o,getMaxProcessTasks(Object.keys(o).length,t.maxProcesses)),a=i.length;logger.info(`Preparing to run total ${a} tasks...`);for(let r=0;r<a;r++){const o=ora(`Run building task id:${r+1} ...`).start();try{const e=i[r],a=[];for(const[r,o]of Object.entries(e)){const e={[r]:o},s=o.options?.useRelativeAssetPath;a.push(startSingleEntryBuild(e,mergeOptions(t,{webpack:{publicPath:s?"auto":n}})))}const l=await Promise.all(a);s.push(...l),o.succeed()}catch(r){o.fail();const t=printCompilerError(r);throw new EvolveBuildError("BUILD_ERROR",t)}}return s};
1
+ import { ensureSlash, mergeOptions } from '@flatjs/common';
2
+ import { EvolveBuildError } from '../errors/evolve-build-error.js';
3
+ import { printCompilerError } from '../helpers/print-log.js';
4
+ import { startOneEntryBuild, } from './start-one-entry-build.js';
5
+ /**
6
+ * The main entry to start an evolve `build`
7
+ * @param entryMapItem The `entryMapItem` for one entry build task
8
+ * @param evolveOptions FlatEvolveOptions
9
+ */
10
+ export const prepareBuild = async (entryMapItem, evolveOptions) => {
11
+ const [entryKey, entryConfig] = entryMapItem;
12
+ // Fetch all configuration cdn
13
+ const cdnPath = evolveOptions.multiHtmlCdn?.prod || [];
14
+ if (!cdnPath.length) {
15
+ throw new Error(`No CDN config for env:"prod", moduleName: ${entryKey}`);
16
+ }
17
+ // Random choose one to publicPath
18
+ const cdnPublicPath = ensureSlash(cdnPath[Math.floor(Math.random() * cdnPath.length)], true);
19
+ // Construct single entry map item to build.
20
+ const toBuildEntryMapItem = {
21
+ [entryKey]: entryConfig,
22
+ };
23
+ try {
24
+ const useRelativeAssetPath = entryConfig.options?.useRelativeAssetPath;
25
+ const buildEvolveOptions = mergeOptions(evolveOptions, {
26
+ webpack: {
27
+ // Only for `assets` used at styling files (e.g.`xxx.less`)
28
+ publicPath: useRelativeAssetPath ? 'auto' : cdnPublicPath,
29
+ },
30
+ });
31
+ return await startOneEntryBuild(toBuildEntryMapItem, buildEvolveOptions);
32
+ }
33
+ catch (err) {
34
+ const formattedErrors = printCompilerError(err);
35
+ // Need re-throw error, in order to third API can capture this error.
36
+ throw new EvolveBuildError(`BUILD_ERROR`, formattedErrors);
37
+ }
38
+ };
@@ -1 +1,36 @@
1
- import{urlJoin}from"@flatjs/common";import{attachMockMiddlewares}from"@flatjs/mock";import{createAppPageRoute,createDevServer,createDevServerCompilerTasks,createDevServerEntries}from"../dev-server/index.js";import{openPage}from"../helpers/index.js";import{envVerify}from"./env-verify.js";export const prepareServe=async(e,r,t)=>{await envVerify(e,t);const{app:a,devPort:o,devHostUri:i}=await createDevServer(t);await attachMockMiddlewares(a,{...t.devServer?.mockOptions,projectCwd:e});const s=await createDevServerEntries(o,r,t);createAppPageRoute(e,a,i,s,t);const v=urlJoin(i,["/pages"]);t.devServer?.autoOpen&&openPage(v);const p=await createDevServerCompilerTasks(e,v,s,t);return Promise.all(p).then((()=>a))};
1
+ import { urlJoin } from '@flatjs/common';
2
+ import { attachMockMiddlewares } from '@flatjs/mock';
3
+ import { createAppPageRoute, createDevServer, createDevServerCompilerTasks, createDevServerEntries, } from '../dev-server/index.js';
4
+ import { openPage } from '../helpers/index.js';
5
+ import { envVerify } from './env-verify.js';
6
+ /**
7
+ * The main entry to start evolve serve
8
+ * @param projectCwd The Root directory (workspace) of this project.
9
+ * @param servedEntries All normalized webpack entries we have served.
10
+ * @param evolveOptions FlatEvolveOptions
11
+ */
12
+ export const prepareServe = async (projectCwd, servedEntries, evolveOptions) => {
13
+ // Verify if we have an correct project local environment.
14
+ await envVerify(projectCwd, evolveOptions);
15
+ // Create pure dev server.
16
+ const { app, devPort, devHostUri } = await createDevServer(evolveOptions);
17
+ // Attach core handlers for mock
18
+ await attachMockMiddlewares(app, {
19
+ ...evolveOptions.devServer?.mockOptions,
20
+ projectCwd,
21
+ });
22
+ // Create dev-server configurationn for all servedEntries.
23
+ const servedDevServerEntries = await createDevServerEntries(devPort, servedEntries, evolveOptions);
24
+ // Create new route `/pages*`,`*` to pure dev server
25
+ createAppPageRoute(projectCwd, app, devHostUri, servedDevServerEntries, evolveOptions);
26
+ const mainPage = urlJoin(devHostUri, ['/pages']);
27
+ // Open page via browser
28
+ if (evolveOptions.devServer?.autoOpen) {
29
+ openPage(mainPage);
30
+ }
31
+ // Create dev-server compiler tasks
32
+ const serveTasks = await createDevServerCompilerTasks(projectCwd, mainPage, servedDevServerEntries, evolveOptions);
33
+ return Promise.all(serveTasks).then(() => {
34
+ return app;
35
+ });
36
+ };
@@ -1 +1,28 @@
1
- import{chalk,logger,urlJoin}from"@flatjs/common";import{attachMockMiddlewares}from"@flatjs/mock";import{createAppPageRoute}from"../dev-server/create-app-page-route.js";import{createDevServer}from"../dev-server/create-dev-server.js";import{openPage}from"../helpers/open-page.js";export const prepareStatic=async(e,r)=>{const{app:a,devHostUri:o}=await createDevServer(r);await attachMockMiddlewares(a,{...r.devServer?.mockOptions,projectCwd:e}),createAppPageRoute(e,a,o,{},r);const t=urlJoin(o,["/pages"]);r.devServer?.autoOpen&&openPage(t),logger.info(`${"static page".padEnd(12," ")} ➩ ${chalk(["cyan"])(t)}`)};
1
+ import { chalk, logger, urlJoin } from '@flatjs/common';
2
+ import { attachMockMiddlewares } from '@flatjs/mock';
3
+ import { createAppPageRoute } from '../dev-server/create-app-page-route.js';
4
+ import { createDevServer } from '../dev-server/create-dev-server.js';
5
+ import { openPage } from '../helpers/open-page.js';
6
+ /**
7
+ * The main entry to start evolve serve
8
+ * @param projectCwd The Root directory (workspace) of this project.
9
+ * @param evolveOptions FlatEvolveOptions
10
+ */
11
+ export const prepareStatic = async (projectCwd, evolveOptions) => {
12
+ // Create pure dev server.
13
+ const { app, devHostUri } = await createDevServer(evolveOptions);
14
+ // Attach core handlers for mock
15
+ await attachMockMiddlewares(app, {
16
+ ...evolveOptions.devServer?.mockOptions,
17
+ projectCwd,
18
+ });
19
+ // Create new route `/pages*`,`*` to pure dev server
20
+ createAppPageRoute(projectCwd, app, devHostUri, {}, evolveOptions);
21
+ const mainPage = urlJoin(devHostUri, ['/pages']);
22
+ // Open page via browser
23
+ if (evolveOptions.devServer?.autoOpen) {
24
+ openPage(mainPage);
25
+ }
26
+ logger.info(`${'static page'.padEnd(12, ' ')} ➩ ${chalk(['cyan'])(mainPage)}`);
27
+ };
28
+ // Start up main page proxy server.