@flatjs/evolve 2.1.0-next.10 → 2.1.0-next.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. package/dist/constants.js +36 -1
  2. package/dist/create-webpack/create-externals.js +6 -1
  3. package/dist/create-webpack/create-optimization.js +43 -1
  4. package/dist/create-webpack/create-output.js +35 -1
  5. package/dist/create-webpack/create-performance.js +7 -1
  6. package/dist/create-webpack/create-plugins.js +78 -1
  7. package/dist/create-webpack/create-resolve.js +37 -1
  8. package/dist/create-webpack/create-rule-sets.js +20 -1
  9. package/dist/create-webpack/load-webpack-config.js +57 -1
  10. package/dist/create-webpack/resolve-public-path.js +15 -1
  11. package/dist/create-webpack/rule-sets/constants.js +3 -1
  12. package/dist/create-webpack/rule-sets/rule-assets.js +52 -1
  13. package/dist/create-webpack/rule-sets/rule-css.js +111 -1
  14. package/dist/create-webpack/rule-sets/rule-less.js +44 -1
  15. package/dist/create-webpack/rule-sets/rule-scripts.js +34 -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 +83 -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 +58 -1
  23. package/dist/dev-server/create-app-page-route.js +13 -1
  24. package/dist/dev-server/create-dev-server-compiler-task.js +55 -1
  25. package/dist/dev-server/create-dev-server-entries.js +25 -1
  26. package/dist/dev-server/create-dev-server.js +24 -1
  27. package/dist/dev-server/index.js +6 -1
  28. package/dist/dev-server/middlewares/create-page-middleware.js +33 -1
  29. package/dist/dev-server/middlewares/create-public-assets-middleware.js +25 -1
  30. package/dist/dev-server/middlewares/get-all-sorted-modules.js +24 -1
  31. package/dist/dev-server/middlewares/get-bundle-asset.js +7 -1
  32. package/dist/dev-server/middlewares/get-dev-server-host-uri.js +5 -1
  33. package/dist/dev-server/middlewares/get-hmr-runtime-chunks.js +14 -1
  34. package/dist/dev-server/middlewares/get-normalized-entry-name.js +14 -1
  35. package/dist/dev-server/middlewares/get-page-main-html.js +49 -1
  36. package/dist/dev-server/middlewares/get-page-module-html.js +123 -1
  37. package/dist/dev-server/middlewares/get-project-virtual-path.js +3 -1
  38. package/dist/dev-server/middlewares/get-runtime-manifest.js +25 -1
  39. package/dist/dev-server/middlewares/index.js +2 -1
  40. package/dist/dev-server/middlewares/types.js +1 -1
  41. package/dist/errors/evolve-build-error.js +10 -1
  42. package/dist/helpers/allow-px2rem-for-module.js +6 -1
  43. package/dist/helpers/assert-group-entry-item.js +19 -1
  44. package/dist/helpers/assert-single-compiler.js +45 -1
  45. package/dist/helpers/chunk-entry-map.js +21 -1
  46. package/dist/helpers/delete-object-keys.js +20 -1
  47. package/dist/helpers/enable-bundle-hashname-for-module.js +6 -1
  48. package/dist/helpers/filter-actived-entries.js +42 -1
  49. package/dist/helpers/flat-entry-map.js +11 -1
  50. package/dist/helpers/get-bundle-file-name.js +23 -1
  51. package/dist/helpers/get-git-root.js +4 -1
  52. package/dist/helpers/get-html-plugin-config.js +47 -1
  53. package/dist/helpers/get-max-process-tasks.js +7 -1
  54. package/dist/helpers/get-pacakge-dir.js +13 -1
  55. package/dist/helpers/get-runtime-cdn-base.js +21 -1
  56. package/dist/helpers/index.js +27 -1
  57. package/dist/helpers/is-deep-equal.js +67 -1
  58. package/dist/helpers/json-serializer.js +52 -1
  59. package/dist/helpers/merge-babel-options.js +45 -1
  60. package/dist/helpers/normalize-check-entry-options.js +28 -1
  61. package/dist/helpers/normalize-entry-map.js +59 -1
  62. package/dist/helpers/normalize-group-name.js +16 -1
  63. package/dist/helpers/normalize-page-proxy.js +9 -1
  64. package/dist/helpers/normalize-resolve-alias.js +7 -1
  65. package/dist/helpers/normalize-template-inject-tokens.js +22 -1
  66. package/dist/helpers/open-page.js +15 -1
  67. package/dist/helpers/print-log.js +49 -1
  68. package/dist/helpers/refresh-evolve-mock-options.js +34 -1
  69. package/dist/helpers/resolve-entry-map-input-files.js +20 -1
  70. package/dist/helpers/script-injects.js +39 -1
  71. package/dist/helpers/should-enable-react-fast-refresh.js +14 -1
  72. package/dist/helpers/split-to-entry-group.d.ts +5 -5
  73. package/dist/helpers/split-to-entry-group.js +139 -1
  74. package/dist/helpers/verify-group-entry-options.js +21 -1
  75. package/dist/index.js +5 -1
  76. package/dist/load-config/index.js +1 -1
  77. package/dist/load-config/load-evolve-config.js +41 -1
  78. package/dist/load-config/types.js +1 -1
  79. package/dist/main/create-thread-worker.js +51 -1
  80. package/dist/main/env-verify.js +21 -1
  81. package/dist/main/get-worker-path.js +5 -1
  82. package/dist/main/index.js +4 -1
  83. package/dist/main/prepare-build.js +39 -1
  84. package/dist/main/prepare-serve.js +69 -1
  85. package/dist/main/prepare-static.js +30 -1
  86. package/dist/main/start-build-dynamic.js +171 -1
  87. package/dist/main/start-build-worker.js +44 -1
  88. package/dist/main/start-build.js +69 -1
  89. package/dist/main/start-group-entry-build.js +32 -1
  90. package/dist/main/start-serve.js +34 -1
  91. package/dist/main/start-static.js +19 -1
  92. package/dist/minimizer/create-minimizers.js +25 -1
  93. package/dist/minimizer/default-options.js +14 -1
  94. package/dist/minimizer/image-minimizer.js +65 -1
  95. package/dist/minimizer/index.js +1 -1
  96. package/dist/minimizer/terser-minimizer.js +15 -3
  97. package/dist/minimizer/types.js +1 -1
  98. package/dist/plugins/circular-dependency/circular-dependency-plugin.js +119 -1
  99. package/dist/plugins/circular-dependency/index.js +15 -1
  100. package/dist/plugins/clean-webpack/clean-webpack-plugin.js +173 -1
  101. package/dist/plugins/clean-webpack/index.js +22 -1
  102. package/dist/plugins/define-variable/define-variable-plugin.js +28 -1
  103. package/dist/plugins/define-variable/index.js +1 -1
  104. package/dist/plugins/html-inject-scripts/plugin-html-inject-script.js +27 -1
  105. package/dist/plugins/module-federation/external-template-remotes.js +92 -1
  106. package/dist/plugins/module-federation/index.js +1 -1
  107. package/dist/plugins/module-federation/module-federation.js +100 -1
  108. package/dist/plugins/multi-html/index.js +16 -1
  109. package/dist/plugins/multi-html/multi-html-cdn-plugin.js +83 -1
  110. package/dist/plugins/multi-html/multi-html-plugin.js +65 -1
  111. package/dist/plugins/ts-checker/index.js +1 -1
  112. package/dist/plugins/ts-checker/ts-checker-plugin.js +24 -1
  113. package/dist/types/index.js +8 -1
  114. package/dist/types/types-ci.js +1 -1
  115. package/dist/types/types-dev-server.js +1 -1
  116. package/dist/types/types-entry-map.js +1 -1
  117. package/dist/types/types-federation.js +1 -1
  118. package/dist/types/types-loader-options.d.ts +30 -3
  119. package/dist/types/types-loader-options.js +1 -1
  120. package/dist/types/types-modular-import.js +1 -1
  121. package/dist/types/types-multi-html.js +1 -1
  122. package/dist/types/types-options.js +1 -1
  123. package/dist/types/types-plugin-options.js +1 -1
  124. package/dist/types/types-threads-options.js +1 -1
  125. package/dist/types/types-webpack.js +1 -1
  126. package/package.json +2 -2
@@ -1 +1,25 @@
1
- import{getDirname}from"@armit/file-utility";import{isIconSvg}from"./rule-utils.js";export const ruleSvgIcon=()=>({test:e=>isIconSvg(e),use:[{loader:getDirname(import.meta.url,"../../loaders/loader-icon.cjs"),options:{svgo:{plugins:[{name:"removeTitle"},{name:"removeDimensions"}]}}}]});
1
+ import { getDirname } from '@armit/file-utility';
2
+ import { isIconSvg } from './rule-utils.js';
3
+ /**
4
+ * Preparing svg loader for `icons`
5
+ * Note we must be put all *.svg into folder `icons`
6
+ */
7
+ export const ruleSvgIcon = () => {
8
+ const loader = {
9
+ test(resource) {
10
+ return isIconSvg(resource);
11
+ },
12
+ use: [
13
+ {
14
+ // FIXME: we need to always keep the directory structures here to make sure correct loader path resolve.
15
+ loader: getDirname(import.meta.url, '../../loaders/loader-icon.cjs'),
16
+ options: {
17
+ svgo: {
18
+ plugins: [{ name: 'removeTitle' }, { name: 'removeDimensions' }],
19
+ },
20
+ },
21
+ },
22
+ ],
23
+ };
24
+ return loader;
25
+ };
@@ -1 +1,10 @@
1
- import{ICON_PATH_REGEX}from"./constants.js";export const isIconSvg=s=>ICON_PATH_REGEX.test(s)&&s.endsWith(".svg");
1
+ import { ICON_PATH_REGEX } from './constants.js';
2
+ /**
3
+ * Causeof we expose a component <Icon /> from `@wove/react` it can be optimized via icon-loader.
4
+ * limitation assets match `svg-icons/**\/*.svg` to icon loader resolver.
5
+ * @param resource
6
+ * @returns
7
+ */
8
+ export const isIconSvg = (resource) => {
9
+ return ICON_PATH_REGEX.test(resource) && resource.endsWith('.svg');
10
+ };
@@ -1 +1 @@
1
- export{};
1
+ export {};
@@ -1 +1,83 @@
1
- export const defaultEvolveOptions={projectCwd:process.cwd(),projectVirtualPath:"flatjs/evolve",rejectWarnings:!1,devServer:{autoOpen:!0,pageProxy:"/pages",mockOptions:{mockBaseDir:"mocks"},clientOverlay:{errors:!0,warnings:!1},webSocketURL:"localIp",middlewares:[],watchOptions:{poll:1e3,ignored:["**/node_modules","**/mocks"],aggregateTimeout:500},defaultServeGlobalData:()=>Promise.resolve({}),bundleDirResolver:e=>e},webpack:{target:["web","es5"],plugins:[],ruleSets:[],publicPath:"auto",resolve:{},externals:{vue:"Vue",react:"React","react-dom":"ReactDOM"},outputDir:"public",enableBundleHashName:!0},pluginOptions:{},loaderOptions:{assetDataUrlMaxSize:4096,babelOptions:{usePreset:"react",plugins:[],presets:[]},runTsChecker:!0,lessOptions:{},postcssOptions:{cssnanoOptions:{}},pixelOptions:{rootValue:{px:100,rpx:1},outputUnit:"rem"},modularImports:[]},entryMap:{},multiHtmlCdn:{},multiHtmlCdnEnvResolver:function cdnResolver(){},needVerifyPackages:{},packageInstallChecker:{enabled:!1,detectModules:["@dimjs/*"],throwError:!1,showAllInstalledGraph:!0},ci:{basedBranch:"origin/master"}};
1
+ export const defaultEvolveOptions = {
2
+ projectCwd: process.cwd(),
3
+ projectVirtualPath: 'flatjs/evolve',
4
+ rejectWarnings: false,
5
+ devServer: {
6
+ autoOpen: true,
7
+ pageProxy: '/pages',
8
+ mockOptions: {
9
+ mockBaseDir: 'mocks',
10
+ },
11
+ clientOverlay: {
12
+ errors: true,
13
+ warnings: false,
14
+ },
15
+ webSocketURL: 'localIp',
16
+ middlewares: [],
17
+ watchOptions: {
18
+ poll: 1000,
19
+ // Use array here, easy can add a new ignore dynamic at runtime.
20
+ ignored: ['**/node_modules', '**/mocks'],
21
+ aggregateTimeout: 500,
22
+ },
23
+ defaultServeGlobalData: () => Promise.resolve({}),
24
+ bundleDirResolver: (dir) => dir,
25
+ },
26
+ webpack: {
27
+ // The default is es5
28
+ target: ['web', 'es5'],
29
+ plugins: [],
30
+ ruleSets: [],
31
+ publicPath: 'auto',
32
+ resolve: {},
33
+ externals: {
34
+ vue: 'Vue',
35
+ react: 'React',
36
+ // eslint-disable-next-line @typescript-eslint/naming-convention
37
+ 'react-dom': 'ReactDOM',
38
+ },
39
+ outputDir: 'public',
40
+ enableBundleHashName: true,
41
+ },
42
+ pluginOptions: {},
43
+ loaderOptions: {
44
+ assetDataUrlMaxSize: 4 * 1024,
45
+ babelOptions: {
46
+ // 默认值的必须使用object类型, 如果使用函数, 会导致merge默认值失败.
47
+ usePreset: 'react',
48
+ plugins: [],
49
+ presets: [],
50
+ },
51
+ runTsChecker: true,
52
+ lessOptions: {},
53
+ postcssOptions: {
54
+ cssnanoOptions: {},
55
+ },
56
+ pixelOptions: {
57
+ rootValue: { px: 100, rpx: 1 },
58
+ outputUnit: 'rem',
59
+ },
60
+ // Always defined in evolve.config.js
61
+ modularImports: [],
62
+ },
63
+ entryMap: {},
64
+ // The configurations for plugin `@flatjs/evolve`, `multi-cdn-plugin`
65
+ multiHtmlCdn: {},
66
+ // Do not use arrow function here.
67
+ multiHtmlCdnEnvResolver: function cdnResolver() {
68
+ return undefined;
69
+ },
70
+ needVerifyPackages: {},
71
+ packageInstallChecker: {
72
+ enabled: false,
73
+ detectModules: ['@dimjs/*'],
74
+ throwError: false,
75
+ showAllInstalledGraph: true,
76
+ },
77
+ /**
78
+ * CI default configurations.
79
+ */
80
+ ci: {
81
+ basedBranch: 'origin/master',
82
+ },
83
+ };
@@ -1 +1,4 @@
1
- import{defineConfig as myDefineConfig}from"@armit/config-loader";export const defineConfig=i=>myDefineConfig(i);
1
+ import { defineConfig as myDefineConfig, } from '@armit/config-loader';
2
+ export const defineConfig = (userConfig) => {
3
+ return myDefineConfig(userConfig);
4
+ };
@@ -1 +1 @@
1
- export*from"./define-config.js";
1
+ export * from './define-config.js';
@@ -1 +1,58 @@
1
- import{join}from"node:path";import WebpackDevServer from"webpack-dev-server";export const addCompilerToDevServer=(e,o,r,t,s)=>{const{projectCwd:p,devServer:c}=s,l=new WebpackDevServer({server:{type:c?.https?"https":"http",options:{...c?.https}},open:!1,compress:!0,port:r,hot:o,liveReload:!o,allowedHosts:"all",static:{directory:`${join(p,"/public")}`},headers:{"Access-Control-Allow-Origin":"*"},client:{progress:!0,overlay:c?.clientOverlay,webSocketURL:"localIp"===c?.webSocketURL?{hostname:t||void 0}:{hostname:"0.0.0.0",...c?.webSocketURL}}},e);return new Promise(((e,o)=>{l.startCallback((r=>{if(r)return o(r);e(!0)}))}))};
1
+ import { join } from 'node:path';
2
+ import WebpackDevServer from 'webpack-dev-server';
3
+ /**
4
+ * Integrated webpack-dev-server with `mock` server together
5
+ * @param compiler Webpack compiler(s)
6
+ * @param enabledHmr Value indicates if we need to liveReload or `HMR`
7
+ * @param devPort The port number of `@flatjs/mock`
8
+ * @param publicIp The public ip address of local server
9
+ * @param evolveOptions The configuration of `@flatjs/evolve` (FlatEvolveOptions)
10
+ */
11
+ export const addCompilerToDevServer = (compiler, enabledHmr, devPort, publicIp, evolveOptions) => {
12
+ const { projectCwd, devServer } = evolveOptions;
13
+ const server = new WebpackDevServer({
14
+ server: {
15
+ type: devServer?.https ? 'https' : 'http',
16
+ options: {
17
+ // Load https
18
+ ...devServer?.https,
19
+ },
20
+ },
21
+ open: false,
22
+ compress: true,
23
+ port: devPort,
24
+ hot: enabledHmr,
25
+ liveReload: !enabledHmr,
26
+ // Enable firewall or set hosts that are allowed to access the dev server.
27
+ allowedHosts: 'all',
28
+ static: {
29
+ directory: `${join(projectCwd, '/public')}`,
30
+ },
31
+ headers: {
32
+ // eslint-disable-next-line @typescript-eslint/naming-convention
33
+ 'Access-Control-Allow-Origin': '*',
34
+ },
35
+ client: {
36
+ progress: true,
37
+ overlay: devServer?.clientOverlay,
38
+ webSocketURL: devServer?.webSocketURL === 'localIp'
39
+ ? {
40
+ hostname: publicIp || undefined,
41
+ }
42
+ : {
43
+ // always use public ip address cause of charles proxy to mobile devices don't work on `ws://${domain host}:port`
44
+ // if we use https, we don't need to specify the hostname or specify the https domain address
45
+ hostname: '0.0.0.0',
46
+ ...devServer?.webSocketURL,
47
+ },
48
+ },
49
+ }, compiler);
50
+ return new Promise((resolve, reject) => {
51
+ server.startCallback((err) => {
52
+ if (err) {
53
+ return reject(err);
54
+ }
55
+ resolve(true);
56
+ });
57
+ });
58
+ };
@@ -1 +1,13 @@
1
- import{normalizePageProxy}from"../helpers/normalize-page-proxy.js";import{createPageMiddleware,createPublicAssetsMiddleware}from"./middlewares/index.js";export const createAppPageRoute=(e,r,a,o,i)=>{const{devServer:s}=i,t=normalizePageProxy(s?.pageProxy||"/pages");r.use(t,...createPageMiddleware(a,s?.mockOptions?.apiContext||"api",o,i)),r.use("*",createPublicAssetsMiddleware(e,t))};
1
+ import { normalizePageProxy } from '../helpers/normalize-page-proxy.js';
2
+ import { createPageMiddleware, createPublicAssetsMiddleware, } from './middlewares/index.js';
3
+ /**
4
+ * Add route `/pages`, `*` to main web-server
5
+ */
6
+ export const createAppPageRoute = (projectCwd, app, devHostUri, servedDevServerEntries, evolveOptions) => {
7
+ const { devServer } = evolveOptions;
8
+ const pageProxy = normalizePageProxy(devServer?.pageProxy || '/pages');
9
+ // Attach request handlers for context `/page/*`
10
+ app.use(pageProxy, ...createPageMiddleware(devHostUri, devServer?.mockOptions?.apiContext || 'api', servedDevServerEntries, evolveOptions));
11
+ // handle all no-matched page request.
12
+ app.use('*', createPublicAssetsMiddleware(projectCwd, pageProxy));
13
+ };
@@ -1 +1,55 @@
1
- import{relative}from"node:path";import{chalk,logger,mergeOptions,urlJoin}from"@flatjs/common";import webpack from"webpack";import{loadWebpackConfig}from"../create-webpack/load-webpack-config.js";import{assertSingleCompiler}from"../helpers/assert-single-compiler.js";import{flatEntryMap}from"../helpers/flat-entry-map.js";import{shouldEnableReactFastRefresh}from"../helpers/should-enable-react-fast-refresh.js";import{addCompilerToDevServer}from"./add-compiler-to-dev-server.js";export const createDevServerCompilerTask=async(e,r,o,t,a,n)=>{const[i,s]=Object.entries(t)[0],{devServerPort:l,devServerHostUri:p}=s;for(const[,e]of Object.entries(t)){const r=e.entryConfig,o=r.options?.moduleFederation,t=o?.remotes||[],n=flatEntryMap(a);t.forEach((e=>{e.endpoint=e=>{const r=n[e];if(!r)throw new Error(`No servedDevServerEntry found via "${e}"`);return urlJoin(r?.devServerHostUri,["/public"])}}))}const c=Object.keys(t).reduce(((e,r)=>(e[r]=t[r].entryConfig,e)),{}),m=urlJoin(p,["public"]),f=await loadWebpackConfig("development",c,mergeOptions(n,{webpack:{publicPath:m}})),d=shouldEnableReactFastRefresh(!0,[i,s.entryConfig],n),v=assertSingleCompiler(c,f,n,d),g=webpack(v),h=addCompilerToDevServer(g,d,l,o,n),b=g.name||"";return g.hooks.invalid.tap("fileChange",(r=>{const o=relative(e,r||"");logger.info(`file change ➩ ${chalk(["cyan"])(o)}`,b)})),g.hooks.done.tap("compileDone",(()=>{logger.info(`debug page ➩ ${chalk(["cyan"])(r)}`,b)})),h};
1
+ import { relative } from 'node:path';
2
+ import { chalk, logger, mergeOptions, urlJoin } from '@flatjs/common';
3
+ import webpack from 'webpack';
4
+ import { loadWebpackConfig } from '../create-webpack/load-webpack-config.js';
5
+ import { assertSingleCompiler } from '../helpers/assert-single-compiler.js';
6
+ import { flatEntryMap } from '../helpers/flat-entry-map.js';
7
+ import { shouldEnableReactFastRefresh } from '../helpers/should-enable-react-fast-refresh.js';
8
+ import { addCompilerToDevServer } from './add-compiler-to-dev-server.js';
9
+ export const createDevServerCompilerTask = async (projectCwd, mainPage, publicIp, servedDevServerEntries, servedDevServerEntryList, evolveOptions) => {
10
+ // First entry option in a group
11
+ const [firstDevServeEntryName, firstDevServeEntryOption] = Object.entries(servedDevServerEntries)[0];
12
+ const { devServerPort, devServerHostUri } = firstDevServeEntryOption;
13
+ for (const [, servedDevServerEntry] of Object.entries(servedDevServerEntries)) {
14
+ const itemEntryConfig = servedDevServerEntry.entryConfig;
15
+ const moduleFederation = itemEntryConfig.options?.moduleFederation;
16
+ const moduleFederationRemotes = moduleFederation?.remotes || [];
17
+ const allServedDevServerEntries = flatEntryMap(servedDevServerEntryList);
18
+ moduleFederationRemotes.forEach((remote) => {
19
+ // Dynamic construct remote endpoint as hostUri
20
+ remote.endpoint = (shortName) => {
21
+ const servedDevServerEntry = allServedDevServerEntries[shortName];
22
+ if (!servedDevServerEntry) {
23
+ throw new Error(`No servedDevServerEntry found via "${shortName}"`);
24
+ }
25
+ return urlJoin(servedDevServerEntry?.devServerHostUri, ['/public']);
26
+ };
27
+ });
28
+ }
29
+ const devEvolveEntryMap = Object.keys(servedDevServerEntries).reduce((previousValue, currentValue) => {
30
+ previousValue[currentValue] =
31
+ servedDevServerEntries[currentValue].entryConfig;
32
+ return previousValue;
33
+ }, {});
34
+ // e.g. `http://dev.flatjs.com:3002/public/`
35
+ const servePublicPath = urlJoin(devServerHostUri, ['public']);
36
+ const webpackConfig = await loadWebpackConfig('development', devEvolveEntryMap, mergeOptions(evolveOptions, {
37
+ webpack: {
38
+ publicPath: servePublicPath,
39
+ },
40
+ }));
41
+ const enabledHmr = shouldEnableReactFastRefresh(true, [firstDevServeEntryName, firstDevServeEntryOption.entryConfig], evolveOptions);
42
+ const config = assertSingleCompiler(devEvolveEntryMap, webpackConfig, evolveOptions, enabledHmr);
43
+ const compiler = webpack(config);
44
+ // '@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js',
45
+ const serveTask = addCompilerToDevServer(compiler, enabledHmr, devServerPort, publicIp, evolveOptions);
46
+ const title = compiler.name || '';
47
+ compiler.hooks.invalid.tap('fileChange', (fileName) => {
48
+ const relativeFileName = relative(projectCwd, fileName || '');
49
+ logger.info(`file change ➩ ${chalk(['cyan'])(relativeFileName)}`, title);
50
+ });
51
+ compiler.hooks.done.tap('compileDone', () => {
52
+ logger.info(`debug page ➩ ${chalk(['cyan'])(mainPage)}`, title);
53
+ });
54
+ return serveTask;
55
+ };
@@ -1 +1,25 @@
1
- import{mergeOptions}from"@flatjs/common";import{prepareMockDomain}from"@flatjs/mock";import{normalizeEvolveEntryName}from"../helpers/normalize-entry-map.js";export const createDevServerEntries=async(r,e,o)=>{const{devServer:t,projectVirtualPath:n}=o,m={},{mockPort:a,hostUri:i}=await prepareMockDomain(mergeOptions(t?.mockOptions||{},{port:r}));for(const[r,o]of Object.entries(e)){const e=normalizeEvolveEntryName(r,n);m[r]={entryConfig:o,devServerPort:a,devServerHostUri:i,normalizedEntryName:e}}return m};
1
+ import { mergeOptions } from '@flatjs/common';
2
+ import { prepareMockDomain } from '@flatjs/mock';
3
+ import { normalizeEvolveEntryName } from '../helpers/normalize-entry-map.js';
4
+ export const createDevServerEntries = async (lastPort, servedEntries, evolveOptions) => {
5
+ const { devServer, projectVirtualPath } = evolveOptions;
6
+ const servedDevServerEntries = {};
7
+ // https://github.com/webpack/webpack-dev-server/issues/2692
8
+ // For `webpack-dev-server@4.0.0` we should run dev server on each compiler
9
+ // Create individual devPort for each compiler here.
10
+ const { mockPort: devServerPort, hostUri: devServerHostUri } = await prepareMockDomain(mergeOptions(devServer?.mockOptions || {}, {
11
+ port: lastPort,
12
+ }));
13
+ // Prepare devServer ports for each served entry.
14
+ for (const [entryName, entryConfig] of Object.entries(servedEntries)) {
15
+ // entryName: `home` should be normalized to ${`projectVirtualPath`}/home
16
+ const normalizedEntryName = normalizeEvolveEntryName(entryName, projectVirtualPath);
17
+ servedDevServerEntries[entryName] = {
18
+ entryConfig,
19
+ devServerPort,
20
+ devServerHostUri,
21
+ normalizedEntryName,
22
+ };
23
+ }
24
+ return servedDevServerEntries;
25
+ };
@@ -1 +1,24 @@
1
- import https from"node:https";import{prepareMockDomain}from"@flatjs/mock";import express from"express";export const createDevServer=async e=>{const r=express(),t=e.devServer?.mockOptions,{mockPort:o,hostUri:p,publicIp:s}=await prepareMockDomain(t||{});return new Promise((t=>{const i=e.devServer?.https?https.createServer(e.devServer?.https,r):r;r.set("hostUri",p),i.listen(o,(()=>{t({app:r,publicIp:s,devHostUri:p,devPort:o})}))}))};
1
+ import https from 'node:https';
2
+ import { prepareMockDomain } from '@flatjs/mock';
3
+ import express from 'express';
4
+ export const createDevServer = async (evolveOptions) => {
5
+ const app = express();
6
+ const mockOptions = evolveOptions.devServer?.mockOptions;
7
+ const { mockPort, hostUri, publicIp } = await prepareMockDomain(mockOptions || {});
8
+ return new Promise((resolve) => {
9
+ // Https
10
+ const httpsServer = evolveOptions.devServer?.https
11
+ ? https.createServer(evolveOptions.devServer?.https, app)
12
+ : app;
13
+ // Attach hostUri to application instance without last slash `/`.
14
+ app.set('hostUri', hostUri);
15
+ httpsServer.listen(mockPort, () => {
16
+ resolve({
17
+ app,
18
+ publicIp,
19
+ devHostUri: hostUri,
20
+ devPort: mockPort,
21
+ });
22
+ });
23
+ });
24
+ };
@@ -1 +1,6 @@
1
- export*from"./middlewares/index.js";export*from"./add-compiler-to-dev-server.js";export*from"./create-dev-server.js";export*from"./create-app-page-route.js";export*from"./create-dev-server-entries.js";export*from"./create-dev-server-compiler-task.js";
1
+ export * from './middlewares/index.js';
2
+ export * from './add-compiler-to-dev-server.js';
3
+ export * from './create-dev-server.js';
4
+ export * from './create-app-page-route.js';
5
+ export * from './create-dev-server-entries.js';
6
+ export * from './create-dev-server-compiler-task.js';
@@ -1 +1,33 @@
1
- import{getPageMainHtml}from"./get-page-main-html.js";import{getPageModuleHtml}from"./get-page-module-html.js";import{getRuntimeManifest}from"./get-runtime-manifest.js";export const createPageMiddleware=(e,t,a,m)=>(m.devServer?.middlewares||[]).concat((async(i,n)=>{let g;if("/runtime/manifest.json"===i.path){const t=await getRuntimeManifest(a,e,m);return n.json(t)}g="/"===i.path?await getPageMainHtml(a,e,m):await getPageModuleHtml(a,i,e,t,m),n.send(g)}));
1
+ import { getPageMainHtml } from './get-page-main-html.js';
2
+ import { getPageModuleHtml } from './get-page-module-html.js';
3
+ import { getRuntimeManifest } from './get-runtime-manifest.js';
4
+ /**
5
+ * A middleware to proxy the page modules template.
6
+ * @example `http://dev.flatjs.com:3001/pages`
7
+ * @param mode The mode of this dev server instance.
8
+ * @param hostUri The main host base url.
9
+ * @param apiContext apiBase e.g. `api`
10
+ * @param servedDevServerEntries The served webpack entries
11
+ * @param forPageMiddlewares Allow us provider customized middlewares for `page`, `modules`
12
+ * @param evolveOptions The evolve config options
13
+ */
14
+ export const createPageMiddleware = (devHostUri, apiContext, servedDevServerEntries, evolveOptions) => {
15
+ const handler = async (req, res) => {
16
+ let html;
17
+ // Expose a special runtime manifest.json for other system to intergration
18
+ if (req.path === '/runtime/manifest.json') {
19
+ const jsonManifest = await getRuntimeManifest(servedDevServerEntries, devHostUri, evolveOptions);
20
+ return res.json(jsonManifest);
21
+ }
22
+ // For root main page
23
+ if (req.path === '/') {
24
+ html = await getPageMainHtml(servedDevServerEntries, devHostUri, evolveOptions);
25
+ }
26
+ else {
27
+ // For serve page modules
28
+ html = await getPageModuleHtml(servedDevServerEntries, req, devHostUri, apiContext, evolveOptions);
29
+ }
30
+ res.send(html);
31
+ };
32
+ return (evolveOptions.devServer?.middlewares || []).concat(handler);
33
+ };
@@ -1 +1,25 @@
1
- import{extname,join}from"node:path";import{fileWalk}from"@armit/file-utility";export const createPublicAssetsMiddleware=(e,i)=>async(t,s)=>{const a=t.baseUrl;if(a.startsWith("/public")){const i=await fileWalk(join("public/","**/*.{js,css}"),{cwd:e}),t=extname(a),l=i.find((e=>extname(e)===t&&-1!==e.indexOf(a.replace(/\.(?:js|css)$/,""))));l?s.sendFile(l):s.sendFile(join(e,a))}else s.redirect(i)};
1
+ import { extname, join } from 'node:path';
2
+ import { fileWalk } from '@armit/file-utility';
3
+ export const createPublicAssetsMiddleware = (projectCwd, pageProxy) => async (req, res) => {
4
+ const baseUrl = req.baseUrl;
5
+ // exclude `/public` leave it fallback into webpack hot server
6
+ if (!baseUrl.startsWith('/public')) {
7
+ res.redirect(pageProxy);
8
+ }
9
+ else {
10
+ const publicFiles = await fileWalk(join('public/', '**/*.{js,css}'), {
11
+ cwd: projectCwd,
12
+ });
13
+ const extension = extname(baseUrl);
14
+ const matchedBundleFile = publicFiles.find((file) => {
15
+ return (extname(file) === extension &&
16
+ file.indexOf(baseUrl.replace(/\.(?:js|css)$/, '')) !== -1);
17
+ });
18
+ if (matchedBundleFile) {
19
+ res.sendFile(matchedBundleFile);
20
+ }
21
+ else {
22
+ res.sendFile(join(projectCwd, baseUrl));
23
+ }
24
+ }
25
+ };
@@ -1 +1,24 @@
1
- import{getDevServerHostUri}from"./get-dev-server-host-uri.js";import{getNormalizedEntryName}from"./get-normalized-entry-name.js";import{getProjectVirtualPath}from"./get-project-virtual-path.js";export function getSortedModules(e,t,r){const o=[],n=getProjectVirtualPath(e);for(const[i,a]of Object.entries(e.entryMap)){const s=Object.keys(t).includes(i),m=getDevServerHostUri(t,i,r),v=getNormalizedEntryName(i,n,t,e.devServer);o.push({entryName:i,entryContent:a,devHostUri:r,devServerHostUri:m,normalizedEntryName:v,projectVirtualPath:n,isServedEntry:s})}return o}
1
+ import { getDevServerHostUri } from './get-dev-server-host-uri.js';
2
+ import { getNormalizedEntryName } from './get-normalized-entry-name.js';
3
+ import { getProjectVirtualPath } from './get-project-virtual-path.js';
4
+ export function getSortedModules(evolveOptions, servedDevServerEntries, devHostUri) {
5
+ const sortedModules = [];
6
+ const projectVirtualPath = getProjectVirtualPath(evolveOptions);
7
+ for (const [entryName, entryContent] of Object.entries(evolveOptions.entryMap)) {
8
+ // `home`, servedDevServerEntries[key] => `home`
9
+ const isServedEntry = Object.keys(servedDevServerEntries).includes(entryName);
10
+ const devServerHostUri = getDevServerHostUri(servedDevServerEntries, entryName, devHostUri);
11
+ // `flatjs/evolve/home`
12
+ const normalizedEntryName = getNormalizedEntryName(entryName, projectVirtualPath, servedDevServerEntries, evolveOptions.devServer);
13
+ sortedModules.push({
14
+ entryName,
15
+ entryContent,
16
+ devHostUri,
17
+ devServerHostUri,
18
+ normalizedEntryName,
19
+ projectVirtualPath,
20
+ isServedEntry,
21
+ });
22
+ }
23
+ return sortedModules;
24
+ }
@@ -1 +1,7 @@
1
- import{join}from"node:path/posix";import{urlJoin}from"@flatjs/common";export const getBundleAsset=(o,n,i)=>urlJoin(o,[join("public",n,`bundle${i}`)]);
1
+ import { join } from 'node:path/posix';
2
+ import { urlJoin } from '@flatjs/common';
3
+ export const getBundleAsset = (devServerHostUri, normalizedCurrEntry, extension) => {
4
+ return urlJoin(devServerHostUri, [
5
+ join('public', normalizedCurrEntry, `bundle${extension}`),
6
+ ]);
7
+ };
@@ -1 +1,5 @@
1
- export function getDevServerHostUri(e,r,t){const o=e[r];return o?.devServerHostUri||t}
1
+ export function getDevServerHostUri(servedDevServerEntries, currEntry, devHostUri) {
2
+ const currDevServerEntry = servedDevServerEntries[currEntry];
3
+ // Maybe No currEntry found in servedDevServerEntries, use default `hostUri`, e.g. `static` mode.
4
+ return currDevServerEntry?.devServerHostUri || devHostUri;
5
+ }
@@ -1 +1,14 @@
1
- import{join}from"node:path";import{devReactFastRefresh}from"../../constants.js";import{shouldEnableReactFastRefresh}from"../../helpers/should-enable-react-fast-refresh.js";import{getBundleAsset}from"./get-bundle-asset.js";export function getHmrRuntimeChunks(e,t,s,r,n,a){if(e[t]&&shouldEnableReactFastRefresh(!0,[s,r],n)){return[getBundleAsset(a,join(s,devReactFastRefresh.runtime),".js"),getBundleAsset(a,join(s,devReactFastRefresh.reactRefreshSetup),".js")]}return[]}
1
+ import { join } from 'node:path';
2
+ import { devReactFastRefresh } from '../../constants.js';
3
+ import { shouldEnableReactFastRefresh } from '../../helpers/should-enable-react-fast-refresh.js';
4
+ import { getBundleAsset } from './get-bundle-asset.js';
5
+ export function getHmrRuntimeChunks(servedDevServerEntries, entryName, normalizedCurrEntry, currEntryItem, evolveOptions, devServerHostUri) {
6
+ const enabledHmr = servedDevServerEntries[entryName] &&
7
+ shouldEnableReactFastRefresh(true, [normalizedCurrEntry, currEntryItem], evolveOptions);
8
+ if (enabledHmr) {
9
+ const runtimeAsset = getBundleAsset(devServerHostUri, join(normalizedCurrEntry, devReactFastRefresh.runtime), '.js');
10
+ const reactRefreshSetup = getBundleAsset(devServerHostUri, join(normalizedCurrEntry, devReactFastRefresh.reactRefreshSetup), '.js');
11
+ return [runtimeAsset, reactRefreshSetup];
12
+ }
13
+ return [];
14
+ }
@@ -1 +1,14 @@
1
- import{normalizeEvolveEntryName}from"../../helpers/normalize-entry-map.js";export function getNormalizedEntryName(e,r,t,l){let n=normalizeEvolveEntryName(e,r);if(l?.bundleDirResolver){const o=Object.keys(t).includes(e);n=l?.bundleDirResolver(n,{currEntry:e,projectVirtualPath:r,isServedModule:o})}return n}
1
+ import { normalizeEvolveEntryName } from '../../helpers/normalize-entry-map.js';
2
+ export function getNormalizedEntryName(entryName, projectVirtualPath, servedDevServerEntries, devServer) {
3
+ let normalizedEntryName = normalizeEvolveEntryName(entryName, projectVirtualPath);
4
+ // Check if we have customized dir resolver
5
+ if (devServer?.bundleDirResolver) {
6
+ const isServedEntry = Object.keys(servedDevServerEntries).includes(entryName);
7
+ normalizedEntryName = devServer?.bundleDirResolver(normalizedEntryName, {
8
+ currEntry: entryName,
9
+ projectVirtualPath,
10
+ isServedModule: isServedEntry,
11
+ });
12
+ }
13
+ return normalizedEntryName;
14
+ }
@@ -1 +1,49 @@
1
- import{readFileSync}from"node:fs";import{join}from"node:path";import{urlJoin}from"@flatjs/common";import _ from"lodash";import{getPackageDir}from"../../helpers/get-pacakge-dir.js";import{normalizePageProxy}from"../../helpers/normalize-page-proxy.js";import{getSortedModules}from"./get-all-sorted-modules.js";export const getPageMainHtml=async(e,r,t)=>{const o=getPackageDir(),a=readFileSync(join(o,"./templates/main.html"),"utf-8"),n=getSortedModules(t,e,r),i=normalizePageProxy(t.devServer?.pageProxy||"/pages"),m=n.map((e=>{const{entryName:t,entryContent:o,isServedEntry:a,projectVirtualPath:n,normalizedEntryName:m}=e,s=urlJoin(r,[i,m],{env:"me"}),l=o.options?.servePageMainLinkFn||(e=>e);return{link:l(s,{hostUri:r,entryName:t,virtualPath:n}),name:t.replace(n,"").replace(/^\//,""),flagText:a?"serve":"static",isServed:a?1:0}}));m.push({flagText:"serve",isServed:1,link:urlJoin(r,[i,"/runtime/manifest.json"]),name:"Runtime Manifest"});const s={title:"@flatjs/evolve",modules:m.sort(((e,r)=>r.isServed-e.isServed))};return _.template(a)(s)};
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { urlJoin } from '@flatjs/common';
4
+ import _ from 'lodash';
5
+ import { getPackageDir } from '../../helpers/get-pacakge-dir.js';
6
+ import { normalizePageProxy } from '../../helpers/normalize-page-proxy.js';
7
+ import { getSortedModules, } from './get-all-sorted-modules.js';
8
+ export const getPageMainHtml = async (servedDevServerEntries, devHostUri, evolveOptions) => {
9
+ const evolveCwd = getPackageDir();
10
+ const templateStr = readFileSync(join(evolveCwd, './templates/main.html'), 'utf-8');
11
+ const sortedModules = getSortedModules(evolveOptions, servedDevServerEntries, devHostUri);
12
+ const pageProxy = normalizePageProxy(evolveOptions.devServer?.pageProxy || '/pages');
13
+ const templateModules = sortedModules.map((module) => {
14
+ const { entryName, entryContent, isServedEntry, projectVirtualPath, normalizedEntryName, } = module;
15
+ const linkHref = urlJoin(devHostUri, [pageProxy, normalizedEntryName], {
16
+ env: 'me',
17
+ });
18
+ // Allow customized page main link.
19
+ const servePageMainLinkFn = entryContent.options?.servePageMainLinkFn || ((link) => link);
20
+ const link = servePageMainLinkFn(linkHref, {
21
+ hostUri: devHostUri,
22
+ entryName,
23
+ virtualPath: projectVirtualPath,
24
+ });
25
+ const displayName = entryName
26
+ .replace(projectVirtualPath, '')
27
+ .replace(/^\//, '');
28
+ return {
29
+ link,
30
+ name: displayName,
31
+ flagText: isServedEntry ? 'serve' : 'static',
32
+ isServed: isServedEntry ? 1 : 0,
33
+ };
34
+ });
35
+ // Add `runtime manifest` to the main page modules list
36
+ templateModules.push({
37
+ flagText: 'serve',
38
+ isServed: 1,
39
+ link: urlJoin(devHostUri, [pageProxy, '/runtime/manifest.json']),
40
+ name: 'Runtime Manifest',
41
+ });
42
+ const templateData = {
43
+ title: '@flatjs/evolve',
44
+ modules: templateModules.sort((a, b) => {
45
+ return b.isServed - a.isServed;
46
+ }),
47
+ };
48
+ return _.template(templateStr)(templateData);
49
+ };