@bleedingdev/modern-js-app-tools 3.9.0-ultramodern.9 → 3.9.3-ultramodern.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/bin/modern-bundle-docs.js +2 -2
  2. package/bin/modern.js +2 -2
  3. package/dist/cjs/builder/generator/createCopyPattern.js +2 -1
  4. package/dist/cjs/builder/index.js +4 -0
  5. package/dist/cjs/builder/shared/builderPlugins/adapterHtml.js +2 -1
  6. package/dist/cjs/builder/shared/builderPlugins/adapterSSR.js +11 -6
  7. package/dist/cjs/builder/shared/lazyCompilation.js +26 -0
  8. package/dist/cjs/commands/build.js +1 -2
  9. package/dist/cjs/commands/deploy.js +1 -3
  10. package/dist/cjs/commands/index.js +10 -2
  11. package/dist/cjs/compat/hooks.js +1 -1
  12. package/dist/cjs/esm/ts-paths-loader.js +5 -4
  13. package/dist/cjs/esm/ts-paths-loader.mjs +5 -4
  14. package/dist/cjs/index.js +73 -99
  15. package/dist/cjs/plugins/analyze/getFileSystemEntry.js +1 -1
  16. package/dist/cjs/plugins/analyze/getServerRoutes.js +2 -2
  17. package/dist/cjs/plugins/analyze/index.js +2 -2
  18. package/dist/cjs/plugins/analyze/utils.js +6 -6
  19. package/dist/cjs/plugins/deploy/index.js +7 -28
  20. package/dist/cjs/plugins/deploy/platforms/netlify.js +2 -1
  21. package/dist/cjs/plugins/deploy/platforms/node.js +12 -3
  22. package/dist/cjs/plugins/deploy/platforms/templates/node-entry.cjs +3 -2
  23. package/dist/cjs/plugins/deploy/platforms/templates/node-entry.mjs +3 -2
  24. package/dist/cjs/plugins/deploy/platforms/vercel.js +2 -1
  25. package/dist/cjs/plugins/deploy/utils/index.js +15 -12
  26. package/dist/cjs/plugins/initialize/index.js +6 -5
  27. package/dist/cjs/plugins/serverBuild.js +0 -2
  28. package/dist/cjs/run/index.js +5 -5
  29. package/dist/cjs/types/config/base.js +62 -0
  30. package/dist/cjs/types/plugin-base.js +18 -0
  31. package/dist/cjs/types/plugin.js +46 -2
  32. package/dist/cjs/utils/initAppContext.js +1 -1
  33. package/dist/cjs/utils/loadPlugins.js +13 -7
  34. package/dist/cjs/utils/register.js +1 -1
  35. package/dist/esm/builder/generator/createCopyPattern.mjs +2 -1
  36. package/dist/esm/builder/index.mjs +1 -0
  37. package/dist/esm/builder/shared/builderPlugins/adapterHtml.mjs +2 -1
  38. package/dist/esm/builder/shared/builderPlugins/adapterSSR.mjs +9 -7
  39. package/dist/esm/builder/shared/lazyCompilation.mjs +14 -1
  40. package/dist/esm/commands/build.mjs +1 -2
  41. package/dist/esm/commands/deploy.mjs +1 -3
  42. package/dist/esm/commands/index.mjs +10 -2
  43. package/dist/esm/compat/hooks.mjs +1 -1
  44. package/dist/esm/esm/ts-paths-loader.mjs +5 -4
  45. package/dist/esm/index.mjs +9 -18
  46. package/dist/esm/plugins/analyze/getFileSystemEntry.mjs +1 -1
  47. package/dist/esm/plugins/analyze/getServerRoutes.mjs +2 -2
  48. package/dist/esm/plugins/analyze/index.mjs +2 -2
  49. package/dist/esm/plugins/analyze/utils.mjs +7 -7
  50. package/dist/esm/plugins/deploy/index.mjs +5 -21
  51. package/dist/esm/plugins/deploy/platforms/netlify.mjs +2 -1
  52. package/dist/esm/plugins/deploy/platforms/node.mjs +12 -3
  53. package/dist/esm/plugins/deploy/platforms/templates/node-entry.cjs +3 -2
  54. package/dist/esm/plugins/deploy/platforms/templates/node-entry.mjs +3 -2
  55. package/dist/esm/plugins/deploy/platforms/vercel.mjs +2 -1
  56. package/dist/esm/plugins/deploy/utils/index.mjs +17 -14
  57. package/dist/esm/plugins/initialize/index.mjs +6 -5
  58. package/dist/esm/plugins/serverBuild.mjs +0 -2
  59. package/dist/esm/run/index.mjs +5 -5
  60. package/dist/esm/types/config/base.mjs +1 -0
  61. package/dist/esm/types/plugin-base.mjs +0 -0
  62. package/dist/esm/types/plugin.mjs +1 -0
  63. package/dist/esm/utils/initAppContext.mjs +2 -2
  64. package/dist/esm/utils/loadPlugins.mjs +4 -8
  65. package/dist/esm/utils/register.mjs +1 -1
  66. package/dist/esm-node/builder/generator/createCopyPattern.mjs +2 -1
  67. package/dist/esm-node/builder/index.mjs +1 -0
  68. package/dist/esm-node/builder/shared/builderPlugins/adapterHtml.mjs +2 -1
  69. package/dist/esm-node/builder/shared/builderPlugins/adapterSSR.mjs +9 -7
  70. package/dist/esm-node/builder/shared/lazyCompilation.mjs +14 -1
  71. package/dist/esm-node/commands/build.mjs +1 -2
  72. package/dist/esm-node/commands/deploy.mjs +1 -3
  73. package/dist/esm-node/commands/index.mjs +10 -2
  74. package/dist/esm-node/compat/hooks.mjs +1 -1
  75. package/dist/esm-node/esm/ts-paths-loader.mjs +5 -4
  76. package/dist/esm-node/index.mjs +10 -20
  77. package/dist/esm-node/plugins/analyze/getFileSystemEntry.mjs +1 -1
  78. package/dist/esm-node/plugins/analyze/getServerRoutes.mjs +2 -2
  79. package/dist/esm-node/plugins/analyze/index.mjs +2 -2
  80. package/dist/esm-node/plugins/analyze/utils.mjs +7 -7
  81. package/dist/esm-node/plugins/deploy/index.mjs +5 -21
  82. package/dist/esm-node/plugins/deploy/platforms/netlify.mjs +2 -1
  83. package/dist/esm-node/plugins/deploy/platforms/node.mjs +12 -3
  84. package/dist/esm-node/plugins/deploy/platforms/templates/node-entry.cjs +3 -2
  85. package/dist/esm-node/plugins/deploy/platforms/templates/node-entry.mjs +3 -2
  86. package/dist/esm-node/plugins/deploy/platforms/vercel.mjs +2 -1
  87. package/dist/esm-node/plugins/deploy/utils/index.mjs +17 -15
  88. package/dist/esm-node/plugins/initialize/index.mjs +6 -5
  89. package/dist/esm-node/plugins/serverBuild.mjs +0 -2
  90. package/dist/esm-node/run/index.mjs +5 -5
  91. package/dist/esm-node/types/config/base.mjs +2 -0
  92. package/dist/esm-node/types/plugin-base.mjs +1 -0
  93. package/dist/esm-node/types/plugin.mjs +1 -0
  94. package/dist/esm-node/utils/initAppContext.mjs +2 -2
  95. package/dist/esm-node/utils/loadPlugins.mjs +4 -8
  96. package/dist/esm-node/utils/register.mjs +1 -1
  97. package/dist/types/builder/index.d.ts +1 -0
  98. package/dist/types/builder/shared/builderPlugins/adapterBasic.d.ts +4 -2
  99. package/dist/types/builder/shared/builderPlugins/adapterSSR.d.ts +2 -1
  100. package/dist/types/builder/shared/builderPlugins/builderHooks.d.ts +10 -2
  101. package/dist/types/builder/shared/lazyCompilation.d.ts +15 -0
  102. package/dist/types/compat/hooks.d.ts +3 -2
  103. package/dist/types/index.d.ts +1 -3
  104. package/dist/types/plugins/analyze/getBundleEntry.d.ts +5 -4
  105. package/dist/types/plugins/analyze/getFileSystemEntry.d.ts +5 -4
  106. package/dist/types/plugins/analyze/utils.d.ts +2 -2
  107. package/dist/types/plugins/deploy/index.d.ts +1 -4
  108. package/dist/types/plugins/deploy/utils/index.d.ts +1 -1
  109. package/dist/types/run/index.d.ts +1 -1
  110. package/dist/types/types/config/base.d.ts +58 -0
  111. package/dist/types/types/config/deploy.d.ts +2 -50
  112. package/dist/types/types/config/dev.d.ts +1 -1
  113. package/dist/types/types/config/index.d.ts +18 -42
  114. package/dist/types/types/config/output.d.ts +2 -2
  115. package/dist/types/types/config/testing.d.ts +1 -1
  116. package/dist/types/types/config/tools.d.ts +1 -1
  117. package/dist/types/types/plugin-base.d.ts +188 -0
  118. package/dist/types/types/plugin.d.ts +9 -183
  119. package/dist/types/utils/initAppContext.d.ts +1 -1
  120. package/docs/apis/app/commands.md +1 -0
  121. package/docs/configure/app/bff/effect.md +5 -12
  122. package/docs/configure/app/output/disable-css-module-extension.md +3 -3
  123. package/docs/configure/app/output/disable-svgr.md +4 -0
  124. package/docs/configure/app/output/svg-default-export.md +4 -0
  125. package/docs/configure/app/server/routes.md +1 -1
  126. package/docs/configure/app/server/ssr.md +1 -1
  127. package/docs/configure/app/source/react-compiler.md +2 -0
  128. package/docs/configure/app/tools/less.md +94 -19
  129. package/docs/configure/app/tools/sass.md +87 -18
  130. package/docs/configure/app/tools/svgr.md +91 -0
  131. package/docs/configure/app/tools/swc.md +2 -2
  132. package/docs/configure/app/tools/ts-checker.md +7 -21
  133. package/docs/guides/advanced-features/server-monitor/logger.md +5 -5
  134. package/docs/guides/basic-features/env-vars.md +6 -6
  135. package/docs/guides/basic-features/render/ssr-cache.md +14 -1
  136. package/docs/guides/basic-features/static-assets/svg-assets.md +29 -17
  137. package/docs/guides/basic-features/testing/rstest.md +0 -2
  138. package/docs/guides/get-started/quick-start.md +1 -1
  139. package/docs/guides/get-started/ultramodern.md +45 -14
  140. package/docs/llms.txt +4 -3
  141. package/docs/plugin/introduction.md +10 -10
  142. package/docs/plugin/server-plugins/api.md +1 -0
  143. package/package.json +59 -30
  144. package/dist/cjs/plugins/serverRuntime.js +0 -53
  145. package/dist/esm/plugins/serverRuntime.mjs +0 -15
  146. package/dist/esm-node/plugins/serverRuntime.mjs +0 -16
  147. package/dist/types/plugins/serverRuntime.d.ts +0 -3
@@ -1,5 +1,5 @@
1
1
  import { JS_EXTENSIONS, getCommand, normalizeToPosixPath } from "@modern-js/utils";
2
- import { parse } from "es-module-lexer";
2
+ import { init, parse } from "es-module-lexer";
3
3
  import { transform } from "esbuild";
4
4
  import fs from "fs";
5
5
  import path from "path";
@@ -9,14 +9,14 @@ const walkDirectory = (dir)=>fs.readdirSync(dir).reduce((previous, filename)=>{
9
9
  ...previous,
10
10
  ...walkDirectory(filePath)
11
11
  ];
12
- return [
12
+ else return [
13
13
  ...previous,
14
14
  filePath
15
15
  ];
16
16
  }, []);
17
17
  const replaceWithAlias = (base, filePath, alias)=>{
18
18
  if (filePath.includes(base)) return normalizeToPosixPath(path.join(alias, path.relative(base, filePath)));
19
- return filePath;
19
+ else return filePath;
20
20
  };
21
21
  const parseModule = async ({ source, filename })=>{
22
22
  let content = source;
@@ -35,10 +35,11 @@ const parseModule = async ({ source, filename })=>{
35
35
  });
36
36
  content = result.code;
37
37
  }
38
- return await parse(content);
38
+ await init();
39
+ return parse(content);
39
40
  };
40
41
  const getServerCombinedModuleFile = (internalDirectory, entryName)=>path.join(internalDirectory, entryName, 'server-loader-combined.js');
41
- const checkIsBuildCommands = (contextCommand)=>{
42
+ const checkIsBuildCommands = ()=>{
42
43
  const buildCommands = [
43
44
  'dev',
44
45
  'start',
@@ -48,8 +49,7 @@ const checkIsBuildCommands = (contextCommand)=>{
48
49
  'dev-worker'
49
50
  ];
50
51
  const command = getCommand();
51
- if (buildCommands.includes(command)) return true;
52
- return 'dev' === contextCommand || 'start' === contextCommand || 'build' === contextCommand || 'deploy' === contextCommand;
52
+ return buildCommands.includes(command);
53
53
  };
54
54
  const checkIsServeCommand = ()=>{
55
55
  const command = getCommand();
@@ -1,5 +1,5 @@
1
1
  import { createCloudflarePreset } from "@modern-js/app-tools-extensions/cloudflare";
2
- import { provider } from "std-env";
2
+ import { getDeployingTarget } from "@modern-js/app-tools-extensions/deploy-output/target";
3
3
  import { createGhPagesPreset } from "./platforms/gh-pages.mjs";
4
4
  import { createNetlifyPreset } from "./platforms/netlify.mjs";
5
5
  import { createNodePreset } from "./platforms/node.mjs";
@@ -12,24 +12,11 @@ const deployPresets = {
12
12
  ghPages: createGhPagesPreset,
13
13
  cloudflare: createCloudflarePreset
14
14
  };
15
- const getSupportedDeployTargets = ()=>Object.keys(deployPresets);
16
- const isDeployTarget = (target)=>Object.prototype.hasOwnProperty.call(deployPresets, target);
17
- const providerDeployTargets = {
18
- vercel: 'vercel',
19
- netlify: 'netlify',
20
- cloudflare: 'cloudflare',
21
- cloudflare_pages: 'cloudflare',
22
- cloudflare_workers: 'cloudflare'
23
- };
24
- const normalizeDetectedProvider = (value)=>value ? providerDeployTargets[value] : void 0;
25
- const resolveDeployTarget = (modernConfig, envDeployTarget = process.env.MODERNJS_DEPLOY, detectedProvider = provider)=>modernConfig.deploy?.target || envDeployTarget || normalizeDetectedProvider(detectedProvider) || 'node';
26
15
  async function getDeployPreset(appContext, modernConfig, deployTarget, api) {
27
16
  const { appDirectory, distDirectory, metaName } = appContext;
28
17
  const { useSSR, useAPI, useWebServer } = getProjectUsage(appDirectory, distDirectory, metaName);
29
18
  const needModernServer = useSSR || useAPI || useWebServer;
30
- if (!isDeployTarget(deployTarget)) throw new Error(`Unknown deploy target: '${deployTarget}'. deploy.target or MODERNJS_DEPLOY should be one of: ${getSupportedDeployTargets().join(', ')}.`);
31
- const createPreset = deployPresets[deployTarget];
32
- return createPreset({
19
+ return deployPresets[deployTarget]({
33
20
  appContext,
34
21
  modernConfig,
35
22
  needModernServer,
@@ -41,11 +28,9 @@ const deploy = ()=>({
41
28
  setup: (api)=>{
42
29
  api.deploy(async ()=>{
43
30
  const appContext = api.getAppContext();
44
- const { metaName } = appContext;
45
- const modernConfig = api.getNormalizedConfig();
46
- const deployTarget = resolveDeployTarget(modernConfig);
47
- if ('modern-js' !== metaName && !modernConfig.deploy?.target && !process.env.MODERNJS_DEPLOY) return;
48
- const deployPreset = await getDeployPreset(appContext, modernConfig, deployTarget, api);
31
+ const deployTarget = getDeployingTarget(appContext);
32
+ if (!deployTarget) return;
33
+ const deployPreset = await getDeployPreset(appContext, api.getNormalizedConfig(), deployTarget, api);
49
34
  deployPreset?.prepare && await deployPreset?.prepare();
50
35
  deployPreset?.writeOutput && await deployPreset?.writeOutput();
51
36
  deployPreset?.genEntry && await deployPreset?.genEntry();
@@ -54,4 +39,3 @@ const deploy = ()=>({
54
39
  }
55
40
  });
56
41
  export default deploy;
57
- export { getSupportedDeployTargets, resolveDeployTarget };
@@ -1,4 +1,5 @@
1
1
  import node_path from "node:path";
2
+ import { traceDeployFiles } from "@modern-js/app-tools-extensions/deploy-output/trace-files";
2
3
  import { fs, removeModuleSyncFromExports } from "@modern-js/utils";
3
4
  import { nodeDepEmit } from "ndepe";
4
5
  import { isMainEntry } from "../../../utils/routes.mjs";
@@ -71,8 +72,8 @@ const createNetlifyPreset = ({ appContext, modernConfig, needModernServer })=>{
71
72
  if (!needModernServer) return;
72
73
  const entry = isEsmProject ? await resolveESMDependency('@modern-js/prod-server') : require.resolve('@modern-js/prod-server');
73
74
  const netlifyEntry = isEsmProject ? await resolveESMDependency('@modern-js/prod-server/netlify') : require.resolve('@modern-js/prod-server/netlify');
74
- if (!entry || !netlifyEntry) throw new Error('Cannot find @modern-js/prod-server');
75
75
  await nodeDepEmit({
76
+ traceFiles: traceDeployFiles,
76
77
  appDir: appDirectory,
77
78
  sourceDir: funcsDirectory,
78
79
  includeEntries: [
@@ -1,10 +1,12 @@
1
+ import { createRequire } from "node:module";
1
2
  import node_path from "node:path";
3
+ import { traceDeployFiles } from "@modern-js/app-tools-extensions/deploy-output/trace-files";
2
4
  import { chalk, fs, removeModuleSyncFromExports } from "@modern-js/utils";
3
5
  import { nodeDepEmit } from "ndepe";
4
6
  import { readTemplate, resolveESMDependency } from "../utils/index.mjs";
5
7
  import { generateHandler } from "../utils/generator.mjs";
6
8
  const createNodePreset = ({ appContext, modernConfig })=>{
7
- const { appDirectory, distDirectory, moduleType } = appContext;
9
+ const { appDirectory, distDirectory, moduleType, serverPlugins } = appContext;
8
10
  const isEsmProject = 'module' === moduleType;
9
11
  const outputDirectory = node_path.join(appDirectory, '.output');
10
12
  const staticDirectory = node_path.join(outputDirectory, 'static');
@@ -34,12 +36,19 @@ const createNodePreset = ({ appContext, modernConfig })=>{
34
36
  async end () {
35
37
  const filter = (filePath)=>!filePath.startsWith(staticDirectory) && !filePath.endsWith('.map');
36
38
  const entry = isEsmProject ? await resolveESMDependency('@modern-js/prod-server') : require.resolve('@modern-js/prod-server');
37
- if (!entry) throw new Error('Cannot find @modern-js/prod-server');
39
+ const requireFromApp = createRequire(node_path.join(appDirectory, 'package.json'));
40
+ const pluginEntries = new Set();
41
+ for (const plugin of serverPlugins)for (const specifier of plugin.includeEntries ?? []){
42
+ pluginEntries.add(requireFromApp.resolve(specifier));
43
+ if (isEsmProject) pluginEntries.add(await resolveESMDependency(specifier, appDirectory));
44
+ }
38
45
  await nodeDepEmit({
46
+ traceFiles: traceDeployFiles,
39
47
  appDir: appDirectory,
40
48
  sourceDir: outputDirectory,
41
49
  includeEntries: [
42
- entry
50
+ entry,
51
+ ...pluginEntries
43
52
  ],
44
53
  copyWholePackage (pkgName) {
45
54
  return '@modern-js/utils' === pkgName;
@@ -35,10 +35,11 @@ async function main() {
35
35
  const app = await createProdServer(prodServerOptions);
36
36
  const port = process.env.PORT || 8080;
37
37
  app.listen({
38
- host: '::',
39
38
  port
40
39
  }, ()=>{
41
- console.log(`\x1b[32mServer is listening on http://[::]:${port}`, '\x1b[0m');
40
+ const address = app.address();
41
+ const loopback = 'IPv6' === address.family ? '[::1]' : '127.0.0.1';
42
+ console.log(`\x1b[32mServer is listening on http://${loopback}:${address.port}`, '\x1b[0m');
42
43
  });
43
44
  }
44
45
  main();
@@ -37,10 +37,11 @@ async function main() {
37
37
  const app = await createProdServer(prodServerOptions);
38
38
  const port = process.env.PORT || 8080;
39
39
  app.listen({
40
- host: '::',
41
40
  port
42
41
  }, ()=>{
43
- console.log(`\x1b[32mServer is listening on http://[::]:${port}`, '\x1b[0m');
42
+ const address = app.address();
43
+ const loopback = 'IPv6' === address.family ? '[::1]' : '127.0.0.1';
44
+ console.log(`\x1b[32mServer is listening on http://${loopback}:${address.port}`, '\x1b[0m');
44
45
  });
45
46
  }
46
47
  main();
@@ -1,4 +1,5 @@
1
1
  import node_path from "node:path";
2
+ import { traceDeployFiles } from "@modern-js/app-tools-extensions/deploy-output/trace-files";
2
3
  import { fs, removeModuleSyncFromExports } from "@modern-js/utils";
3
4
  import { nodeDepEmit } from "ndepe";
4
5
  import { isMainEntry } from "../../../utils/routes.mjs";
@@ -91,8 +92,8 @@ const createVercelPreset = ({ appContext, modernConfig, needModernServer })=>{
91
92
  async end () {
92
93
  if (!needModernServer) return;
93
94
  const entry = isEsmProject ? await resolveESMDependency('@modern-js/prod-server') : require.resolve('@modern-js/prod-server');
94
- if (!entry) throw new Error('Cannot find @modern-js/prod-server');
95
95
  await nodeDepEmit({
96
+ traceFiles: traceDeployFiles,
96
97
  appDir: appDirectory,
97
98
  sourceDir: funcsDirectory,
98
99
  includeEntries: [
@@ -1,6 +1,6 @@
1
- import { createRequire } from "node:module";
2
- import { pathToFileURL } from "node:url";
3
- import { ROUTE_SPEC_FILE, SERVER_DIR, dynamicImport, fs, getMeta } from "@modern-js/utils";
1
+ import { fileURLToPath, pathToFileURL } from "node:url";
2
+ import { ROUTE_SPEC_FILE, SERVER_DIR, fs, getMeta } from "@modern-js/utils";
3
+ import { moduleResolve } from "import-meta-resolve";
4
4
  import path from "path";
5
5
  const normalizePath = (filePath)=>filePath.replace(/\\/g, '/');
6
6
  const getProjectUsage = (appDirectory, distDirectory, metaName)=>{
@@ -26,17 +26,20 @@ const getProjectUsage = (appDirectory, distDirectory, metaName)=>{
26
26
  };
27
27
  const getTemplatePath = (file)=>path.join(__dirname, '../platforms/templates', file);
28
28
  const readTemplate = async (file)=>(await fs.readFile(getTemplatePath(file))).toString();
29
- const resolveESMDependency = async (entry)=>{
30
- const conditions = new Set([
31
- 'node',
32
- 'import',
33
- 'module',
34
- 'default'
35
- ]);
29
+ const DEPLOY_CONDITIONS = [
30
+ 'node',
31
+ 'import',
32
+ 'module',
33
+ 'default'
34
+ ];
35
+ const resolveESMDependency = async (entry, fromDirectory)=>{
36
+ const base = fromDirectory ? pathToFileURL(path.join(fromDirectory, 'package.json')) : pathToFileURL(`${__dirname}/`);
36
37
  try {
37
- const resolverPath = pathToFileURL(createRequire(__filename).resolve('import-meta-resolve')).href;
38
- const { moduleResolve } = await dynamicImport(resolverPath);
39
- return normalizePath(moduleResolve(entry, pathToFileURL(`${__dirname}/`), conditions, false).pathname.replace(/^\/(\w):/, '$1:'));
40
- } catch (err) {}
38
+ return normalizePath(fileURLToPath(moduleResolve(entry, base, new Set(DEPLOY_CONDITIONS), false)));
39
+ } catch (cause) {
40
+ throw new Error(`Cannot resolve "${entry}" with conditions [${DEPLOY_CONDITIONS.join(', ')}] from ${base.href}: ${cause.message}`, {
41
+ cause
42
+ });
43
+ }
41
44
  };
42
45
  export { getProjectUsage, getTemplatePath, normalizePath, readTemplate, resolveESMDependency };
@@ -1,4 +1,5 @@
1
1
  import { ensureAbsolutePath, getPort, isDev, isDevCommand } from "@modern-js/utils";
2
+ import { buildDefaultLazyCompilationTest } from "../../builder/shared/lazyCompilation.mjs";
2
3
  import { createDefaultConfig, isLazyCompilationSafeByDefault } from "../../config/index.mjs";
3
4
  const initialize = ()=>({
4
5
  name: '@modern-js/plugin-initialize',
@@ -17,7 +18,8 @@ const initialize = ()=>({
17
18
  ...defaultConfig.dev,
18
19
  lazyCompilation: {
19
20
  imports: true,
20
- entries: false
21
+ entries: false,
22
+ test: buildDefaultLazyCompilationTest(appContext.appDirectory, appContext.internalDirectory)
21
23
  }
22
24
  };
23
25
  return defaultConfig;
@@ -25,7 +27,7 @@ const initialize = ()=>({
25
27
  api.modifyResolvedConfig(async (resolved)=>{
26
28
  let appContext = api.getAppContext();
27
29
  const userConfig = api.getConfig();
28
- const port = await getServerPort(resolved, appContext.command);
30
+ const port = await getServerPort(resolved);
29
31
  appContext = {
30
32
  ...appContext,
31
33
  port,
@@ -60,10 +62,9 @@ function stabilizeConfig(resolve, config, keys) {
60
62
  resolve[key] = config[key] || {};
61
63
  });
62
64
  }
63
- async function getServerPort(config, contextCommand) {
65
+ async function getServerPort(config) {
64
66
  const prodPort = Number(process.env.PORT) || config.server.port || 8080;
65
- const isProgrammaticDev = 'dev' === contextCommand || 'start' === contextCommand;
66
- if (isDev() && (isDevCommand() || isProgrammaticDev)) return getPort(Number(process.env.PORT) || prodPort);
67
+ if (isDev() && isDevCommand()) return getPort(Number(process.env.PORT) || prodPort);
67
68
  return prodPort;
68
69
  }
69
70
  export default initialize;
@@ -29,10 +29,8 @@ const serverBuild = ()=>({
29
29
  sourceDirs.push(serverDir);
30
30
  if (fs.existsSync(sharedDir)) sourceDirs.push(sharedDir);
31
31
  }
32
- const { server } = modernConfig;
33
32
  const { alias } = modernConfig.source;
34
33
  if (sourceDirs.length > 0) await compile(appDirectory, {
35
- server,
36
34
  alias
37
35
  }, {
38
36
  sourceDirs,
@@ -7,21 +7,21 @@ import { loadInternalPlugins } from "../utils/loadPlugins.mjs";
7
7
  async function createRunOptions({ cwd, initialLog, metaName = 'modern-js', version, internalPlugins, configFile }) {
8
8
  const nodeVersion = process.versions.node;
9
9
  const versionArr = nodeVersion.split('.').map(Number);
10
- if (versionArr[0] < 26 || 26 === versionArr[0] && versionArr[1] < 7) throw new Error(`
10
+ if (versionArr[0] < 26 || 26 === versionArr[0] && versionArr[1] < 10) throw new Error(`
11
11
  ${chalk.bgRed.white.bold(' UNSUPPORTED NODE.JS RUNTIME ')}
12
12
 
13
- ${chalk.red.bold(`UltraModern.js requires Node.js >=26.7.0; detected v${nodeVersion}.`)}
13
+ ${chalk.red.bold(`UltraModern.js requires Node.js >=26.12.0; detected v${nodeVersion}.`)}
14
14
  ${chalk.red('- Legacy Node runtimes and TypeScript transpiler fallbacks are unsupported.')}
15
15
 
16
16
  ${chalk.yellow('▸ Detected Runtime:')} ${chalk.yellow.bold(`Node.js v${nodeVersion}`)}
17
- ${chalk.green('▸ Required Minimum:')} ${chalk.green.bold('Node.js v26.7.0 or higher')}
18
- ${chalk.green('▸ Pinned Runtime:')} ${chalk.green.bold('Node.js v26.7.0')}
17
+ ${chalk.green('▸ Required Minimum:')} ${chalk.green.bold('Node.js v26.12.0 or higher')}
18
+ ${chalk.green('▸ Pinned Runtime:')} ${chalk.green.bold('Node.js v26.12.0')}
19
19
 
20
20
  ${chalk.cyan('Immediate Action Required:')}
21
21
  ${chalk.gray('├──')} ${chalk.yellow('Recommended Upgrade')}
22
22
  ${chalk.bold('mise install && mise exec -- node --version')}
23
23
  ${chalk.gray('├──')} ${chalk.yellow('Manual Installation')}
24
- ${chalk.underline('https://nodejs.org/download/release/v26.7.0/')}
24
+ ${chalk.underline('https://nodejs.org/download/release/v26.12.0/')}
25
25
  ${chalk.gray('└──')} ${chalk.yellow('Environment Verification')}
26
26
  ${chalk.bold('node -v && npm -v')}
27
27
 
@@ -0,0 +1 @@
1
+ export * from "./output.mjs";
File without changes
@@ -0,0 +1 @@
1
+ export * from "./plugin-base.mjs";
@@ -1,4 +1,4 @@
1
- import { address, fs } from "@modern-js/utils";
1
+ import { fs, ip } from "@modern-js/utils";
2
2
  import path from "path";
3
3
  function isSymlinkedNodeModules(appDirectory) {
4
4
  try {
@@ -17,7 +17,7 @@ const initAppContext = ({ metaName, appDirectory, runtimeConfigFile, options, te
17
17
  const moduleType = fs.existsSync(pkgPath) ? fs.readJSONSync(pkgPath).type || 'commonjs' : 'commonjs';
18
18
  return {
19
19
  runtimeConfigFile,
20
- ip: address.ip(),
20
+ ip: ip(),
21
21
  port: 0,
22
22
  moduleType,
23
23
  apiDirectory: path.resolve(appDirectory, apiDir),
@@ -1,12 +1,13 @@
1
+ import node_path from "node:path";
1
2
  import { loadServerPlugins } from "@modern-js/server-core/node";
2
- import { compatibleRequire, createDebugger, dynamicImport, getInternalPlugins, tryResolve } from "@modern-js/utils";
3
+ import { compatibleRequire, createDebugger, getInternalPlugins, tryResolve } from "@modern-js/utils";
3
4
  const debug = createDebugger('load-plugins');
4
5
  async function getServerPlugins(api, metaName = 'modern-js') {
5
6
  const hooks = api.getHooks();
6
7
  const { plugins } = await hooks._internalServerPlugins.call({
7
8
  plugins: []
8
9
  });
9
- const filtedPlugins = plugins.filter((plugin)=>plugin.name.includes(metaName));
10
+ const filtedPlugins = plugins.filter((plugin)=>node_path.isAbsolute(plugin.name) || plugin.name.includes(metaName));
10
11
  api.updateAppContext({
11
12
  serverPlugins: filtedPlugins
12
13
  });
@@ -21,12 +22,7 @@ const resolveCliPlugin = async (p, appDirectory)=>{
21
22
  const pkg = 'string' == typeof p ? p : p[0];
22
23
  const pluginOptions = 'string' == typeof p ? void 0 : p[1];
23
24
  const path = tryResolve(pkg, appDirectory);
24
- let module;
25
- try {
26
- module = await compatibleRequire(path);
27
- } catch (e) {
28
- ({ default: module } = await dynamicImport(path));
29
- }
25
+ const module = await compatibleRequire(path);
30
26
  if ('function' == typeof module) {
31
27
  const result = module(pluginOptions);
32
28
  return result;
@@ -57,7 +57,7 @@ const resolveTsRuntimeRegisterMode = ()=>{
57
57
  return 'unsupported';
58
58
  };
59
59
  const setupTsRuntime = async (appDir, distDir, alias, options = {})=>{
60
- if ('unsupported' === resolveTsRuntimeRegisterMode()) throw new Error(`UltraModern.js requires Node.js >=26.7.0 with native TypeScript support; detected v${process.versions.node}. Legacy TypeScript runtime transpilers are unsupported.`);
60
+ if ('unsupported' === resolveTsRuntimeRegisterMode()) throw new Error(`UltraModern.js requires Node.js >=26.12.0 with native TypeScript support; detected v${process.versions.node}. Legacy TypeScript runtime transpilers are unsupported.`);
61
61
  const tsconfigPath = resolveServerTsconfig(appDir, options.tsconfigPath);
62
62
  const isTsProject = await fs.pathExists(tsconfigPath);
63
63
  if (!isTsProject) return;
@@ -15,7 +15,8 @@ function createPublicPattern(appContext, config, chain) {
15
15
  noErrorOnMissing: true,
16
16
  transform: (content, absoluteFrom)=>{
17
17
  if (!/\.html?$/.test(absoluteFrom)) return content;
18
- return content.toString('utf8').replace(/<%=\s*assetPrefix\s*%>/g, removeTailSlash(chain.output.get('publicPath')));
18
+ const publicPath = chain.output.get('publicPath');
19
+ return content.toString('utf8').replace(/<%=\s*assetPrefix\s*%>/g, removeTailSlash('string' == typeof publicPath ? publicPath : ''));
19
20
  }
20
21
  };
21
22
  }
@@ -4,5 +4,6 @@ async function createBuilderGenerator() {
4
4
  return createRspackBuilderForModern;
5
5
  }
6
6
  export { parseRspackConfig } from "@modern-js/builder";
7
+ export { getBundleEntry } from "../plugins/analyze/getBundleEntry.mjs";
7
8
  export { builderPluginAdapterBasic, builderPluginAdapterHooks } from "./shared/builderPlugins/index.mjs";
8
9
  export { createBuilderGenerator };
@@ -27,7 +27,8 @@ const builderPluginAdapterHtml = (options)=>({
27
27
  async function injectAssetPrefix({ chain }) {
28
28
  const entries = chain.entryPoints.entries() || {};
29
29
  const entryNames = Object.keys(entries);
30
- const assetPrefix = removeTailSlash(chain.output.get('publicPath') || '');
30
+ const publicPath = chain.output.get('publicPath');
31
+ const assetPrefix = removeTailSlash('string' == typeof publicPath ? publicPath : '');
31
32
  const code = `window.__assetPrefix__ = '${assetPrefix}';`;
32
33
  entryNames.forEach((entryName)=>{
33
34
  entries[entryName].prepend(createVirtualModule(code));
@@ -39,8 +39,8 @@ const builderPluginAdapterSSR = (options)=>({
39
39
  appNormalizedConfig: normalizedConfig
40
40
  });
41
41
  if (isUseSSRBundle(normalizedConfig) || isUseRsc(normalizedConfig)) {
42
- await applySSRLoaderEntry(chain, options, isServer);
43
- applySSRDataLoader(chain, options);
42
+ await applySSRLoaderEntry(chain, options, isServer, isServiceWorker);
43
+ applySSRDataLoader(chain, options, isServer || isServiceWorker);
44
44
  }
45
45
  if (!isHtmlDisabled(builderConfig, target)) applyAsyncChunkHtmlPlugin({
46
46
  chain,
@@ -125,7 +125,7 @@ function applyFilterEntriesBySSRConfig({ isProd, chain, appNormalizedConfig }) {
125
125
  if (!serverConfig?.rsc && !ssgEntries.includes(name) && !name.includes('server-loaders') && (ssr && ssrByEntries?.[name] === false || !ssr && !ssrByEntries?.[name])) chain.entryPoints.delete(name);
126
126
  });
127
127
  }
128
- async function applySSRLoaderEntry(chain, optinos, isServer) {
128
+ async function applySSRLoaderEntry(chain, optinos, isServer, isServiceWorker) {
129
129
  const { appContext } = optinos;
130
130
  const { internalDirectory } = appContext;
131
131
  const { entrypoints } = appContext;
@@ -136,15 +136,17 @@ async function applySSRLoaderEntry(chain, optinos, isServer) {
136
136
  await fs.access(serverLoadersFile, fs.constants.F_OK);
137
137
  chain.entry(`${entryName}-server-loaders`).add(serverLoadersFile);
138
138
  } catch (err) {}
139
- else if (isUseRsc(optinos.normalizedConfig)) chain.entry(`${entryName}-server-loaders`).add("data:text/javascript,export%20{};");
139
+ else if (!isServiceWorker && isUseRsc(optinos.normalizedConfig)) chain.entry(`${entryName}-server-loaders`).add("data:text/javascript,export%20{};");
140
140
  }));
141
141
  }
142
- function applySSRDataLoader(chain, options) {
142
+ function applySSRDataLoader(chain, options, server) {
143
143
  const { normalizedConfig, appContext } = options;
144
144
  const { appDirectory } = appContext;
145
145
  const { entriesDir = './src' } = normalizedConfig.source;
146
146
  const absolutePath = __rspack_external_path.resolve(appDirectory, entriesDir).split(__rspack_external_path.sep).join('(\\\\|/)');
147
147
  const reg = new RegExp(`${absolutePath}.*\\.(loader|data|data.client)\\.[t|j]sx?$`);
148
- chain.module.rule('ssr-data-loader').test(reg).use('data-loader').loader(require.resolve('@modern-js/plugin-data-loader/loader')).end();
148
+ chain.module.rule('ssr-data-loader').test(reg).enforce('pre').use('data-loader').loader(require.resolve('@modern-js/plugin-data-loader/loader')).options({
149
+ server
150
+ }).end();
149
151
  }
150
- export { builderPluginAdapterSSR, getSSRLazyCompilation };
152
+ export { applySSRLoaderEntry, builderPluginAdapterSSR, getSSRLazyCompilation };
@@ -1,4 +1,5 @@
1
1
  import "node:module";
2
+ import node_path from "node:path";
2
3
  import { collectRouteComponentFiles, normalizeModulePath } from "@modern-js/utils";
3
4
  function aggregateEagerRouteComponentFiles(byEntry) {
4
5
  const files = new Set();
@@ -21,6 +22,18 @@ function buildSSRLazyCompilationTest(eagerRouteFiles, userTest) {
21
22
  return userTestFn(m);
22
23
  };
23
24
  }
25
+ function buildDefaultLazyCompilationTest(appDirectory, internalDirectory) {
26
+ let dirs;
27
+ return (m)=>{
28
+ if (!('resource' in m) || 'string' != typeof m.resource) return true;
29
+ dirs ??= {
30
+ app: normalizeModulePath(appDirectory),
31
+ internal: normalizeModulePath(internalDirectory)
32
+ };
33
+ const file = m.resource.split('?')[0].split(node_path.sep).join('/');
34
+ return file.startsWith(`${dirs.app}/`) && !file.startsWith(`${dirs.internal}/`) && !file.slice(dirs.app.length).includes('/node_modules/');
35
+ };
36
+ }
24
37
  function planSSRLazyCompilation(current, info) {
25
38
  if (!current) return {
26
39
  apply: false
@@ -42,4 +55,4 @@ function planSSRLazyCompilation(current, info) {
42
55
  }
43
56
  };
44
57
  }
45
- export { aggregateEagerRouteComponentFiles, buildSSRLazyCompilationTest, collectRouteComponentFiles, normalizeModulePath, planSSRLazyCompilation };
58
+ export { aggregateEagerRouteComponentFiles, buildDefaultLazyCompilationTest, buildSSRLazyCompilationTest, collectRouteComponentFiles, normalizeModulePath, planSSRLazyCompilation };
@@ -57,9 +57,8 @@ const build = async (api, options)=>{
57
57
  logger.info('Starting production build...');
58
58
  if (!appContext.builder) throw new Error('Expect the Builder to have been initialized, But the appContext.builder received `undefined`');
59
59
  await appContext.builder.onAfterBuild(async ()=>copyEnvFiles(appContext.appDirectory, appContext.distDirectory));
60
- const buildResult = await appContext.builder.build({
60
+ await appContext.builder.build({
61
61
  watch: options?.watch
62
62
  });
63
- if (!options?.watch) await buildResult?.close();
64
63
  };
65
64
  export { build };
@@ -1,11 +1,9 @@
1
1
  import "node:module";
2
2
  import { getServerPlugins } from "../utils/loadPlugins.mjs";
3
- import { build } from "./build.mjs";
4
3
  const deploy = async (api, options = {})=>{
5
4
  const hooks = api.getHooks();
6
5
  const { metaName } = api.getAppContext();
7
- if (options.skipBuild) await getServerPlugins(api, metaName);
8
- else await build(api);
6
+ await getServerPlugins(api, metaName);
9
7
  await hooks.onBeforeDeploy.call(options);
10
8
  await hooks.deploy.call();
11
9
  await hooks.onAfterDeploy.call(options);
@@ -1,5 +1,9 @@
1
1
  import "node:module";
2
2
  import { i18n, localeKeys } from "../locale/index.mjs";
3
+ const deployTargetOption = [
4
+ '--deploy-target <target>',
5
+ 'deploy target; overrides deploy.target and MODERNJS_DEPLOY'
6
+ ];
3
7
  const devCommand = async (program, api)=>{
4
8
  program.command('dev').alias('start').usage('[options]').description(i18n.t(localeKeys.command.dev.describe)).option('-c --config <config>', i18n.t(localeKeys.command.shared.config)).option('-e --entry [entry...]', i18n.t(localeKeys.command.dev.entry)).option('--analyze', i18n.t(localeKeys.command.shared.analyze)).option('--api-only', i18n.t(localeKeys.command.dev.apiOnly)).option('--web-only', i18n.t(localeKeys.command.dev.webOnly)).action(async (options)=>{
5
9
  const { dev } = await import("./dev.mjs");
@@ -7,7 +11,7 @@ const devCommand = async (program, api)=>{
7
11
  });
8
12
  };
9
13
  const buildCommand = async (program, api)=>{
10
- program.command('build').usage('[options]').description(i18n.t(localeKeys.command.build.describe)).option('-c --config <config>', i18n.t(localeKeys.command.shared.config)).option('--analyze', i18n.t(localeKeys.command.shared.analyze)).option('-w --watch', i18n.t(localeKeys.command.build.watch)).action(async (options)=>{
14
+ program.command('build').usage('[options]').description(i18n.t(localeKeys.command.build.describe)).option('-c --config <config>', i18n.t(localeKeys.command.shared.config)).option('--analyze', i18n.t(localeKeys.command.shared.analyze)).option('-w --watch', i18n.t(localeKeys.command.build.watch)).option(...deployTargetOption).action(async (options)=>{
11
15
  const { build } = await import("./build.mjs");
12
16
  await build(api, options);
13
17
  });
@@ -19,7 +23,11 @@ const serverCommand = (program, api)=>{
19
23
  });
20
24
  };
21
25
  const deployCommand = (program, api)=>{
22
- program.command('deploy').usage('[options]').option('-c --config <config>', i18n.t(localeKeys.command.shared.config)).option('-s --skip-build', i18n.t(localeKeys.command.shared.skipBuild)).description(i18n.t(localeKeys.command.deploy.describe)).action(async (options)=>{
26
+ program.command('deploy').usage('[options]').option('-c --config <config>', i18n.t(localeKeys.command.shared.config)).option('-s --skip-build', i18n.t(localeKeys.command.shared.skipBuild)).option(...deployTargetOption).description(i18n.t(localeKeys.command.deploy.describe)).action(async (options)=>{
27
+ if (!options.skipBuild) {
28
+ const { build } = await import("./build.mjs");
29
+ await build(api);
30
+ }
23
31
  const { deploy } = await import("./deploy.mjs");
24
32
  await deploy(api, options);
25
33
  process.exit(0);
@@ -60,7 +60,7 @@ function handleSetupResult(setupResult, api) {
60
60
  if (newAPI && api[newAPI]) api[newAPI](async (...params)=>{
61
61
  const { isMultiple, params: transformParams } = transformHookParams(key, params);
62
62
  if (isMultiple) return transformHookResult(key, await fn(...transformParams));
63
- return transformHookResult(key, await fn(transformParams));
63
+ else return transformHookResult(key, await fn(transformParams));
64
64
  });
65
65
  }
66
66
  });
@@ -15,8 +15,9 @@ const getParentPath = (parentURL)=>{
15
15
  } catch {}
16
16
  return process.cwd();
17
17
  };
18
+ const resolveSourcePath = (resolvedPath, context, defaultResolve)=>defaultResolve(context.conditions?.find((condition)=>'require' === condition || 'import' === condition) === 'require' ? resolvedPath : pathToFileURL(resolvedPath).href, context, defaultResolve);
18
19
  async function initialize({ appDir: currentAppDir, baseUrl, paths }) {
19
- appDir = node_path.resolve(currentAppDir);
20
+ appDir = node_fs.existsSync(currentAppDir) ? node_fs.realpathSync(currentAppDir) : node_path.resolve(currentAppDir);
20
21
  matchPath = createMatchPath(baseUrl || './', paths || {});
21
22
  }
22
23
  function resolve(specifier, context, defaultResolve) {
@@ -26,12 +27,12 @@ function resolve(specifier, context, defaultResolve) {
26
27
  if ((specifier.startsWith('./') || specifier.startsWith('../')) && !node_path.extname(specifier) && isAppFile) {
27
28
  const matchedPath = node_path.resolve(parentPath, specifier);
28
29
  const resolvedPath = findSourceEntry(matchedPath) || matchedPath;
29
- if (resolvedPath && node_fs.existsSync(resolvedPath)) return defaultResolve(pathToFileURL(resolvedPath).href, context, defaultResolve);
30
+ if (resolvedPath && node_fs.existsSync(resolvedPath)) return resolveSourcePath(resolvedPath, context, defaultResolve);
30
31
  }
31
- if (!matchPath) return defaultResolve(specifier, context, defaultResolve);
32
+ if (!matchPath || !isAppFile) return defaultResolve(specifier, context, defaultResolve);
32
33
  const match = findMatchedSourcePath(matchPath, specifier);
33
34
  if (!match) return defaultResolve(specifier, context, defaultResolve);
34
35
  const resolvedPath = findSourceEntry(match) || match;
35
- return defaultResolve(pathToFileURL(resolvedPath).href, context, defaultResolve);
36
+ return resolveSourcePath(resolvedPath, context, defaultResolve);
36
37
  }
37
38
  export { initialize, resolve };