@bleedingdev/modern-js-app-tools 3.9.0-ultramodern.8 → 3.9.3-ultramodern.1

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 (149) hide show
  1. package/bin/modern-bundle-docs.js +2 -2
  2. package/bin/modern.js +2 -2
  3. package/dist/cjs/builder/generator/adapterCopy.js +26 -0
  4. package/dist/cjs/builder/generator/createCopyPattern.js +2 -1
  5. package/dist/cjs/builder/index.js +4 -0
  6. package/dist/cjs/builder/shared/builderPlugins/adapterHtml.js +2 -1
  7. package/dist/cjs/builder/shared/builderPlugins/adapterSSR.js +11 -6
  8. package/dist/cjs/builder/shared/lazyCompilation.js +26 -0
  9. package/dist/cjs/commands/build.js +1 -2
  10. package/dist/cjs/commands/deploy.js +1 -3
  11. package/dist/cjs/commands/index.js +10 -2
  12. package/dist/cjs/compat/hooks.js +1 -1
  13. package/dist/cjs/esm/ts-paths-loader.js +5 -4
  14. package/dist/cjs/esm/ts-paths-loader.mjs +5 -4
  15. package/dist/cjs/index.js +89 -110
  16. package/dist/cjs/plugins/analyze/getFileSystemEntry.js +1 -1
  17. package/dist/cjs/plugins/analyze/getServerRoutes.js +1 -1
  18. package/dist/cjs/plugins/analyze/index.js +2 -2
  19. package/dist/cjs/plugins/analyze/utils.js +6 -6
  20. package/dist/cjs/plugins/deploy/index.js +7 -28
  21. package/dist/cjs/plugins/deploy/platforms/netlify.js +2 -1
  22. package/dist/cjs/plugins/deploy/platforms/node.js +12 -3
  23. package/dist/cjs/plugins/deploy/platforms/templates/node-entry.cjs +3 -2
  24. package/dist/cjs/plugins/deploy/platforms/templates/node-entry.mjs +3 -2
  25. package/dist/cjs/plugins/deploy/platforms/vercel.js +2 -1
  26. package/dist/cjs/plugins/deploy/utils/index.js +15 -12
  27. package/dist/cjs/plugins/initialize/index.js +6 -5
  28. package/dist/cjs/plugins/serverBuild.js +0 -2
  29. package/dist/cjs/run/index.js +5 -5
  30. package/dist/cjs/{plugins/serverRuntime.js → server-plugin.js} +13 -16
  31. package/dist/cjs/types/config/base.js +62 -0
  32. package/dist/cjs/types/plugin-base.js +18 -0
  33. package/dist/cjs/types/plugin.js +46 -2
  34. package/dist/cjs/utils/initAppContext.js +1 -1
  35. package/dist/cjs/utils/loadPlugins.js +13 -7
  36. package/dist/cjs/utils/register.js +1 -1
  37. package/dist/esm/builder/generator/adapterCopy.mjs +23 -1
  38. package/dist/esm/builder/generator/createCopyPattern.mjs +2 -1
  39. package/dist/esm/builder/index.mjs +1 -0
  40. package/dist/esm/builder/shared/builderPlugins/adapterHtml.mjs +2 -1
  41. package/dist/esm/builder/shared/builderPlugins/adapterSSR.mjs +9 -7
  42. package/dist/esm/builder/shared/lazyCompilation.mjs +14 -1
  43. package/dist/esm/commands/build.mjs +1 -2
  44. package/dist/esm/commands/deploy.mjs +1 -3
  45. package/dist/esm/commands/index.mjs +10 -2
  46. package/dist/esm/compat/hooks.mjs +1 -1
  47. package/dist/esm/esm/ts-paths-loader.mjs +5 -4
  48. package/dist/esm/index.mjs +13 -20
  49. package/dist/esm/plugins/analyze/getFileSystemEntry.mjs +1 -1
  50. package/dist/esm/plugins/analyze/getServerRoutes.mjs +1 -1
  51. package/dist/esm/plugins/analyze/index.mjs +2 -2
  52. package/dist/esm/plugins/analyze/utils.mjs +7 -7
  53. package/dist/esm/plugins/deploy/index.mjs +5 -21
  54. package/dist/esm/plugins/deploy/platforms/netlify.mjs +2 -1
  55. package/dist/esm/plugins/deploy/platforms/node.mjs +12 -3
  56. package/dist/esm/plugins/deploy/platforms/templates/node-entry.cjs +3 -2
  57. package/dist/esm/plugins/deploy/platforms/templates/node-entry.mjs +3 -2
  58. package/dist/esm/plugins/deploy/platforms/vercel.mjs +2 -1
  59. package/dist/esm/plugins/deploy/utils/index.mjs +17 -14
  60. package/dist/esm/plugins/initialize/index.mjs +6 -5
  61. package/dist/esm/plugins/serverBuild.mjs +0 -2
  62. package/dist/esm/run/index.mjs +5 -5
  63. package/dist/esm/server-plugin.mjs +1 -0
  64. package/dist/esm/types/config/base.mjs +1 -0
  65. package/dist/esm/types/plugin-base.mjs +0 -0
  66. package/dist/esm/types/plugin.mjs +1 -0
  67. package/dist/esm/utils/initAppContext.mjs +2 -2
  68. package/dist/esm/utils/loadPlugins.mjs +4 -8
  69. package/dist/esm/utils/register.mjs +1 -1
  70. package/dist/esm-node/builder/generator/adapterCopy.mjs +23 -1
  71. package/dist/esm-node/builder/generator/createCopyPattern.mjs +2 -1
  72. package/dist/esm-node/builder/index.mjs +1 -0
  73. package/dist/esm-node/builder/shared/builderPlugins/adapterHtml.mjs +2 -1
  74. package/dist/esm-node/builder/shared/builderPlugins/adapterSSR.mjs +9 -7
  75. package/dist/esm-node/builder/shared/lazyCompilation.mjs +14 -1
  76. package/dist/esm-node/commands/build.mjs +1 -2
  77. package/dist/esm-node/commands/deploy.mjs +1 -3
  78. package/dist/esm-node/commands/index.mjs +10 -2
  79. package/dist/esm-node/compat/hooks.mjs +1 -1
  80. package/dist/esm-node/esm/ts-paths-loader.mjs +5 -4
  81. package/dist/esm-node/index.mjs +14 -22
  82. package/dist/esm-node/plugins/analyze/getFileSystemEntry.mjs +1 -1
  83. package/dist/esm-node/plugins/analyze/getServerRoutes.mjs +1 -1
  84. package/dist/esm-node/plugins/analyze/index.mjs +2 -2
  85. package/dist/esm-node/plugins/analyze/utils.mjs +7 -7
  86. package/dist/esm-node/plugins/deploy/index.mjs +5 -21
  87. package/dist/esm-node/plugins/deploy/platforms/netlify.mjs +2 -1
  88. package/dist/esm-node/plugins/deploy/platforms/node.mjs +12 -3
  89. package/dist/esm-node/plugins/deploy/platforms/templates/node-entry.cjs +3 -2
  90. package/dist/esm-node/plugins/deploy/platforms/templates/node-entry.mjs +3 -2
  91. package/dist/esm-node/plugins/deploy/platforms/vercel.mjs +2 -1
  92. package/dist/esm-node/plugins/deploy/utils/index.mjs +17 -15
  93. package/dist/esm-node/plugins/initialize/index.mjs +6 -5
  94. package/dist/esm-node/plugins/serverBuild.mjs +0 -2
  95. package/dist/esm-node/run/index.mjs +5 -5
  96. package/dist/esm-node/server-plugin.mjs +2 -0
  97. package/dist/esm-node/types/config/base.mjs +2 -0
  98. package/dist/esm-node/types/plugin-base.mjs +1 -0
  99. package/dist/esm-node/types/plugin.mjs +1 -0
  100. package/dist/esm-node/utils/initAppContext.mjs +2 -2
  101. package/dist/esm-node/utils/loadPlugins.mjs +4 -8
  102. package/dist/esm-node/utils/register.mjs +1 -1
  103. package/dist/types/builder/generator/adapterCopy.d.ts +13 -1
  104. package/dist/types/builder/index.d.ts +1 -0
  105. package/dist/types/builder/shared/builderPlugins/adapterBasic.d.ts +4 -2
  106. package/dist/types/builder/shared/builderPlugins/adapterSSR.d.ts +2 -1
  107. package/dist/types/builder/shared/builderPlugins/builderHooks.d.ts +10 -2
  108. package/dist/types/builder/shared/lazyCompilation.d.ts +15 -0
  109. package/dist/types/compat/hooks.d.ts +3 -2
  110. package/dist/types/index.d.ts +3 -4
  111. package/dist/types/plugins/analyze/getBundleEntry.d.ts +5 -4
  112. package/dist/types/plugins/analyze/getFileSystemEntry.d.ts +5 -4
  113. package/dist/types/plugins/analyze/utils.d.ts +2 -2
  114. package/dist/types/plugins/deploy/index.d.ts +1 -4
  115. package/dist/types/plugins/deploy/utils/generator.d.ts +1 -1
  116. package/dist/types/plugins/deploy/utils/index.d.ts +1 -1
  117. package/dist/types/run/index.d.ts +1 -1
  118. package/dist/types/server-plugin.d.ts +10 -0
  119. package/dist/types/types/config/base.d.ts +58 -0
  120. package/dist/types/types/config/deploy.d.ts +2 -50
  121. package/dist/types/types/config/dev.d.ts +1 -1
  122. package/dist/types/types/config/index.d.ts +18 -42
  123. package/dist/types/types/config/output.d.ts +2 -2
  124. package/dist/types/types/config/testing.d.ts +1 -1
  125. package/dist/types/types/config/tools.d.ts +1 -1
  126. package/dist/types/types/plugin-base.d.ts +188 -0
  127. package/dist/types/types/plugin.d.ts +9 -183
  128. package/dist/types/utils/initAppContext.d.ts +2 -2
  129. package/docs/apis/app/commands.md +1 -0
  130. package/docs/configure/app/bff/effect.md +5 -12
  131. package/docs/configure/app/output/disable-svgr.md +4 -0
  132. package/docs/configure/app/output/svg-default-export.md +4 -0
  133. package/docs/configure/app/source/react-compiler.md +2 -0
  134. package/docs/configure/app/tools/less.md +94 -19
  135. package/docs/configure/app/tools/sass.md +87 -18
  136. package/docs/configure/app/tools/svgr.md +91 -0
  137. package/docs/configure/app/tools/ts-checker.md +7 -21
  138. package/docs/guides/basic-features/render/ssr-cache.md +14 -1
  139. package/docs/guides/basic-features/static-assets/svg-assets.md +29 -17
  140. package/docs/guides/basic-features/testing/rstest.md +0 -2
  141. package/docs/guides/get-started/quick-start.md +1 -1
  142. package/docs/guides/get-started/ultramodern.md +45 -14
  143. package/docs/llms.txt +4 -3
  144. package/docs/plugin/introduction.md +10 -10
  145. package/docs/plugin/server-plugins/api.md +1 -0
  146. package/package.json +67 -30
  147. package/dist/esm/plugins/serverRuntime.mjs +0 -15
  148. package/dist/esm-node/plugins/serverRuntime.mjs +0 -16
  149. package/dist/types/plugins/serverRuntime.d.ts +0 -3
@@ -1,7 +1,9 @@
1
+ import { resolveDeployTarget } from "@modern-js/app-tools-extensions/deploy-output/target";
2
+ import { createPolicyDefaultsPlugin } from "@modern-js/app-tools-extensions/policy-defaults";
1
3
  import { castArray } from "@modern-js/builder";
2
4
  import { getLocaleLanguage } from "@modern-js/i18n-utils/language-detector";
3
5
  import { createAsyncHook } from "@modern-js/plugin";
4
- import { cleanRequireCache, deprecatedCommands, emptyDir, getArgv, getCommand } from "@modern-js/utils";
6
+ import { deprecatedCommands, emptyDir, getArgv, getCommand } from "@modern-js/utils";
5
7
  import path from "path";
6
8
  import { buildCommand, deployCommand, devCommand, infoCommand, inspectCommand, serverCommand } from "./commands/index.mjs";
7
9
  import { compatPlugin } from "./compat/index.mjs";
@@ -11,21 +13,20 @@ import analyze from "./plugins/analyze/index.mjs";
11
13
  import deploy from "./plugins/deploy/index.mjs";
12
14
  import initialize from "./plugins/initialize/index.mjs";
13
15
  import serverBuild from "./plugins/serverBuild.mjs";
14
- import serverRuntime from "./plugins/serverRuntime.mjs";
15
16
  import { generateWatchFiles } from "./utils/generateWatchFiles.mjs";
16
17
  import { initAppContext } from "./utils/initAppContext.mjs";
17
18
  import { restart } from "./utils/restart.mjs";
18
19
  export * from "./defineConfig.mjs";
19
20
  export * from "./types/index.mjs";
20
- const appTools = ()=>({
21
+ const appTools = (options = {})=>({
21
22
  name: '@modern-js/app-tools',
22
23
  usePlugins: [
23
- serverRuntime(),
24
24
  compatPlugin(),
25
25
  initialize(),
26
26
  analyze(),
27
27
  serverBuild(),
28
- deploy()
28
+ deploy(),
29
+ createPolicyDefaultsPlugin(options)
29
30
  ],
30
31
  post: [
31
32
  '@modern-js/plugin-initialize',
@@ -72,6 +73,11 @@ const appTools = ()=>({
72
73
  deprecatedCommands(program);
73
74
  });
74
75
  api.onPrepare(async ()=>{
76
+ api.updateAppContext({
77
+ deployTarget: resolveDeployTarget({
78
+ configTarget: api.getNormalizedConfig().deploy?.target
79
+ })
80
+ });
75
81
  const command = getCommand();
76
82
  if ('deploy' === command) {
77
83
  const isSkipBuild = [
@@ -80,18 +86,12 @@ const appTools = ()=>({
80
86
  ].some((tag)=>getArgv().includes(tag));
81
87
  if (isSkipBuild) return;
82
88
  }
83
- const { command: contextCommand } = api.getAppContext();
84
- const shouldClean = [
89
+ if ([
85
90
  'dev',
86
91
  'start',
87
92
  'build',
88
93
  'deploy'
89
- ].includes(command) || [
90
- 'dev',
91
- 'start',
92
- 'build'
93
- ].includes(contextCommand);
94
- if (shouldClean) {
94
+ ].includes(command)) {
95
95
  const resolvedConfig = api.getNormalizedConfig();
96
96
  if (resolvedConfig.output.cleanDistPath) {
97
97
  const appContext = api.getAppContext();
@@ -122,17 +122,10 @@ const appTools = ()=>({
122
122
  await restart(api.getHooks(), filename);
123
123
  }
124
124
  });
125
- api.onBeforeRestart(()=>{
126
- cleanRequireCache([
127
- require.resolve('./plugins/analyze')
128
- ]);
129
- });
130
125
  }
131
126
  });
132
127
  const src = appTools;
133
128
  export { defineConfig } from "./defineConfig.mjs";
134
- export { build } from "./commands/build.mjs";
135
- export { deploy } from "./commands/deploy.mjs";
136
129
  export { dev } from "./commands/dev.mjs";
137
130
  export { serve } from "./commands/serve.mjs";
138
131
  export { resolveModernRsbuildConfig } from "./rsbuild.mjs";
@@ -61,6 +61,6 @@ const getFileSystemEntry = async (hooks, appContext, config)=>{
61
61
  }));
62
62
  return scanDir(hooks, dirs);
63
63
  } else throw Error("source.entriesDir accept a directory.");
64
- throw Error(`src dir ${entriesDir} not found.`);
64
+ else throw Error(`src dir ${entriesDir} not found.`);
65
65
  };
66
66
  export { getFileSystemEntry, hasEntry, hasServerEntry };
@@ -26,7 +26,7 @@ const applyRouteOptions = (original, routeOptions)=>{
26
26
  ...original,
27
27
  urlPath: url
28
28
  };
29
- {
29
+ else {
30
30
  const { path: urlPath, ...other } = url;
31
31
  return {
32
32
  ...original,
@@ -23,7 +23,7 @@ const analyze = ()=>({
23
23
  const resolvedConfig = api.getNormalizedConfig();
24
24
  const hooks = api.getHooks();
25
25
  try {
26
- if (checkIsBuildCommands(appContext.command)) fs.emptydirSync(appContext.internalDirectory);
26
+ if (checkIsBuildCommands()) fs.emptydirSync(appContext.internalDirectory);
27
27
  } catch {}
28
28
  const apiOnly = await isApiOnly(appContext.appDirectory, resolvedConfig.source?.entriesDir, appContext.apiDirectory);
29
29
  const [{ getProdEntrypoints, getProdServerRoutes }] = await Promise.all([
@@ -125,7 +125,7 @@ const analyze = ()=>({
125
125
  htmlTemplates
126
126
  };
127
127
  api.updateAppContext(appContext);
128
- if (checkIsBuildCommands(appContext.command)) {
128
+ if (checkIsBuildCommands()) {
129
129
  await hooks.generateEntryCode.call({
130
130
  entrypoints
131
131
  });
@@ -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.10.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.10.0 or higher')}
18
+ ${chalk.green('▸ Pinned Runtime:')} ${chalk.green.bold('Node.js v26.10.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.10.0/')}
25
25
  ${chalk.gray('└──')} ${chalk.yellow('Environment Verification')}
26
26
  ${chalk.bold('node -v && npm -v')}
27
27
 
@@ -0,0 +1 @@
1
+ export { default } from "@modern-js/server-runtime-extensions/server-plugin";
@@ -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.10.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;
@@ -1,7 +1,22 @@
1
1
  import "node:module";
2
+ import node_fs from "node:fs";
2
3
  import path from "path";
3
4
  import { createCopyInfo } from "../shared/index.mjs";
4
5
  import { createPublicPattern } from "./createCopyPattern.mjs";
6
+ class MissingCopyContextPlugin {
7
+ apply(compiler) {
8
+ compiler.hooks.afterCompile.tap('MissingCopyContextPlugin', (compilation)=>{
9
+ for (const context of this.contexts)if (!node_fs.existsSync(context)) {
10
+ compilation.contextDependencies.delete(context);
11
+ compilation.missingDependencies.add(context);
12
+ for(let parent = path.dirname(context); parent !== path.dirname(parent) && !node_fs.existsSync(parent); parent = path.dirname(parent))compilation.missingDependencies.add(parent);
13
+ }
14
+ });
15
+ }
16
+ constructor(contexts){
17
+ this.contexts = contexts;
18
+ }
19
+ }
5
20
  const builderPluginAdapterCopy = (options)=>({
6
21
  name: 'builder-plugin-adapter-copy',
7
22
  setup (api) {
@@ -29,8 +44,15 @@ const builderPluginAdapterCopy = (options)=>({
29
44
  ]
30
45
  }
31
46
  ]);
47
+ const patterns = chain.plugin(CHAIN_ID.PLUGIN.COPY).get('args')?.[0]?.patterns ?? [];
48
+ const optionalContexts = patterns.flatMap((pattern)=>pattern && 'object' == typeof pattern && 'noErrorOnMissing' in pattern && pattern.noErrorOnMissing && 'context' in pattern && 'string' == typeof pattern.context ? [
49
+ path.resolve(appContext.appDirectory, pattern.context)
50
+ ] : []);
51
+ if (optionalContexts.length) chain.plugin('modern-missing-copy-context').use(MissingCopyContextPlugin, [
52
+ optionalContexts
53
+ ]);
32
54
  }
33
55
  });
34
56
  }
35
57
  });
36
- export { builderPluginAdapterCopy };
58
+ export { MissingCopyContextPlugin, builderPluginAdapterCopy };
@@ -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 };