@modern-js/app-tools 2.23.1 → 2.24.0

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 (44) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/cjs/analyze/generateCode.js +5 -5
  3. package/dist/cjs/analyze/getBundleEntry.js +7 -2
  4. package/dist/cjs/analyze/getFileSystemEntry.js +4 -0
  5. package/dist/cjs/analyze/getHtmlTemplate.js +2 -2
  6. package/dist/cjs/analyze/getServerRoutes.js +4 -3
  7. package/dist/cjs/analyze/nestedRoutes.js +36 -12
  8. package/dist/cjs/analyze/templates.js +2 -2
  9. package/dist/cjs/builder/shared/builderPlugins/adapterHtml.js +4 -2
  10. package/dist/cjs/builder/shared/bundlerPlugins/RouterPlugin.js +1 -1
  11. package/dist/cjs/config/default.js +3 -0
  12. package/dist/cjs/config/legacy/createSourceConfig.js +2 -1
  13. package/dist/cjs/schema/index.js +3 -0
  14. package/dist/cjs/schema/legacy.js +3 -0
  15. package/dist/esm/analyze/generateCode.js +7 -7
  16. package/dist/esm/analyze/getBundleEntry.js +7 -2
  17. package/dist/esm/analyze/getFileSystemEntry.js +4 -0
  18. package/dist/esm/analyze/getHtmlTemplate.js +4 -4
  19. package/dist/esm/analyze/getServerRoutes.js +4 -3
  20. package/dist/esm/analyze/nestedRoutes.js +26 -11
  21. package/dist/esm/analyze/templates.js +2 -2
  22. package/dist/esm/builder/shared/builderPlugins/adapterHtml.js +5 -3
  23. package/dist/esm/builder/shared/bundlerPlugins/RouterPlugin.js +1 -1
  24. package/dist/esm/config/default.js +3 -0
  25. package/dist/esm/config/legacy/createSourceConfig.js +2 -1
  26. package/dist/esm/schema/index.js +3 -0
  27. package/dist/esm/schema/legacy.js +3 -0
  28. package/dist/esm-node/analyze/generateCode.js +5 -5
  29. package/dist/esm-node/analyze/getBundleEntry.js +7 -2
  30. package/dist/esm-node/analyze/getFileSystemEntry.js +4 -0
  31. package/dist/esm-node/analyze/getHtmlTemplate.js +3 -3
  32. package/dist/esm-node/analyze/getServerRoutes.js +4 -3
  33. package/dist/esm-node/analyze/nestedRoutes.js +25 -10
  34. package/dist/esm-node/analyze/templates.js +2 -2
  35. package/dist/esm-node/builder/shared/builderPlugins/adapterHtml.js +5 -3
  36. package/dist/esm-node/builder/shared/bundlerPlugins/RouterPlugin.js +1 -1
  37. package/dist/esm-node/config/default.js +3 -0
  38. package/dist/esm-node/config/legacy/createSourceConfig.js +2 -1
  39. package/dist/esm-node/schema/index.js +3 -0
  40. package/dist/esm-node/schema/legacy.js +3 -0
  41. package/dist/types/analyze/nestedRoutes.d.ts +2 -1
  42. package/dist/types/types/config/source.d.ts +1 -0
  43. package/dist/types/types/legacyConfig/source.d.ts +1 -0
  44. package/package.json +24 -24
@@ -3,28 +3,43 @@ import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
3
3
  import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props";
4
4
  import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
5
5
  import * as path from "path";
6
- import { fs, getRouteId } from "@modern-js/utils";
6
+ import { fs, normalizeToPosixPath } from "@modern-js/utils";
7
7
  import { JS_EXTENSIONS, NESTED_ROUTE } from "./constants";
8
8
  import { replaceWithAlias } from "./utils";
9
9
  var conventionNames = Object.values(NESTED_ROUTE);
10
10
  var replaceDynamicPath = function(routePath) {
11
11
  return routePath.replace(/\[(.*?)\]/g, ":$1");
12
12
  };
13
- var createIndexRoute = function(routeInfo, rootDir, filename, entryName) {
13
+ var getPathWithoutExt = function(filename) {
14
+ var extname = path.extname(filename);
15
+ return filename.slice(0, -extname.length);
16
+ };
17
+ export var getRouteId = function(componentPath, routesDir, entryName, isMainEntry) {
18
+ var relativePath = normalizeToPosixPath(path.relative(routesDir, componentPath));
19
+ var pathWithoutExt = getPathWithoutExt(relativePath);
20
+ var id = "";
21
+ if (isMainEntry) {
22
+ id = pathWithoutExt;
23
+ } else {
24
+ id = "".concat(entryName, "_").concat(pathWithoutExt);
25
+ }
26
+ return id.replace(/\[(.*?)\]/g, "($1)");
27
+ };
28
+ var createIndexRoute = function(routeInfo, rootDir, filename, entryName, isMainEntry) {
14
29
  return createRoute(_object_spread_props(_object_spread({}, routeInfo), {
15
30
  index: true,
16
31
  children: void 0
17
- }), rootDir, filename, entryName);
32
+ }), rootDir, filename, entryName, isMainEntry);
18
33
  };
19
- var createRoute = function(routeInfo, rootDir, filename, entryName) {
20
- var id = getRouteId(filename, rootDir, entryName);
34
+ var createRoute = function(routeInfo, rootDir, filename, entryName, isMainEntry) {
35
+ var id = getRouteId(filename, rootDir, entryName, isMainEntry);
21
36
  return _object_spread_props(_object_spread({}, routeInfo), {
22
37
  id: id,
23
38
  type: "nested"
24
39
  });
25
40
  };
26
41
  export var walk = function() {
27
- var _ref = _async_to_generator(function(dirname, rootDir, alias, entryName) {
42
+ var _ref = _async_to_generator(function(dirname, rootDir, alias, entryName, isMainEntry) {
28
43
  var _route_children, isDirectory, relativeDir, pathSegments, lastSegment, isRoot, isPathlessLayout, isWithoutLayoutPath, routePath, route, pageLoaderFile, pageRoute, splatLoaderFile, splatRoute, pageConfigFile, items, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, item, itemPath, extname, itemWithoutExt, isDirectory1, childRoute, _route_children1, _route_children2, _route_children3, err, finalRoute, childRoute1, _$path;
29
44
  return _ts_generator(this, function(_state) {
30
45
  switch (_state.label) {
@@ -113,7 +128,7 @@ export var walk = function() {
113
128
  ];
114
129
  return [
115
130
  4,
116
- walk(itemPath, rootDir, alias, entryName)
131
+ walk(itemPath, rootDir, alias, entryName, isMainEntry)
117
132
  ];
118
133
  case 7:
119
134
  childRoute = _state.sent();
@@ -152,7 +167,7 @@ export var walk = function() {
152
167
  ;
153
168
  pageRoute = createIndexRoute({
154
169
  _component: replaceWithAlias(alias.basename, itemPath, alias.name)
155
- }, rootDir, itemPath, entryName);
170
+ }, rootDir, itemPath, entryName, isMainEntry);
156
171
  if (pageLoaderFile) {
157
172
  pageRoute.loader = pageLoaderFile;
158
173
  }
@@ -169,7 +184,7 @@ export var walk = function() {
169
184
  splatRoute = createRoute({
170
185
  _component: replaceWithAlias(alias.basename, itemPath, alias.name),
171
186
  path: "*"
172
- }, rootDir, itemPath, entryName);
187
+ }, rootDir, itemPath, entryName, isMainEntry);
173
188
  if (splatLoaderFile) {
174
189
  splatRoute.loader = splatLoaderFile;
175
190
  }
@@ -215,7 +230,7 @@ export var walk = function() {
215
230
  7
216
231
  ];
217
232
  case 13:
218
- finalRoute = createRoute(route, rootDir, path.join(dirname, "".concat(NESTED_ROUTE.LAYOUT_FILE, ".ts")), entryName);
233
+ finalRoute = createRoute(route, rootDir, path.join(dirname, "".concat(NESTED_ROUTE.LAYOUT_FILE, ".ts")), entryName, isMainEntry);
219
234
  if (isPathlessLayout) {
220
235
  delete finalRoute.path;
221
236
  }
@@ -244,7 +259,7 @@ export var walk = function() {
244
259
  }
245
260
  });
246
261
  });
247
- return function walk2(dirname, rootDir, alias, entryName) {
262
+ return function walk2(dirname, rootDir, alias, entryName, isMainEntry) {
248
263
  return _ref.apply(this, arguments);
249
264
  };
250
265
  }();
@@ -316,9 +316,9 @@ export var fileSystemRoutes = function() {
316
316
  };
317
317
  }();
318
318
  export function ssrLoaderCombinedModule(entrypoints, entrypoint, config, appContext) {
319
- var entryName = entrypoint.entryName;
319
+ var entryName = entrypoint.entryName, isMainEntry = entrypoint.isMainEntry;
320
320
  var packageName = appContext.packageName, internalDirectory = appContext.internalDirectory;
321
- var ssr = getEntryOptions(entryName, config.server.ssr, config.server.ssrByEntries, packageName);
321
+ var ssr = getEntryOptions(entryName, isMainEntry, config.server.ssr, config.server.ssrByEntries, packageName);
322
322
  var ssg = isSSGEntry(config, entryName, entrypoints);
323
323
  if (entrypoint.nestedRoutesEntry && (ssr || ssg)) {
324
324
  var serverLoaderRuntime = require.resolve("@modern-js/plugin-data-loader/runtime");
@@ -4,7 +4,7 @@ import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
4
4
  import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props";
5
5
  import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
6
6
  import { isHtmlDisabled, createVirtualModule } from "@modern-js/builder-shared";
7
- import { getEntryOptions, removeTailSlash } from "@modern-js/utils";
7
+ import { MAIN_ENTRY_NAME, getEntryOptions, removeTailSlash } from "@modern-js/utils";
8
8
  import { template as lodashTemplate } from "@modern-js/utils/lodash";
9
9
  import { BottomTemplatePlugin } from "../bundlerPlugins";
10
10
  export var builderPluginAdapterHtml = function(options) {
@@ -113,11 +113,13 @@ function applyBottomHtmlPlugin(param) {
113
113
  try {
114
114
  var _loop = function() {
115
115
  var entryName = _step.value;
116
+ var mainEntryName = modernConfig.source.mainEntryName;
117
+ var isMainEntry = entryName === (mainEntryName || MAIN_ENTRY_NAME);
116
118
  var baseTemplateParams = _object_spread({
117
119
  entryName: entryName,
118
- title: getEntryOptions(entryName, modernConfig.html.title, modernConfig.html.titleByEntries, appContext.packageName),
120
+ title: getEntryOptions(entryName, isMainEntry, modernConfig.html.title, modernConfig.html.titleByEntries, appContext.packageName),
119
121
  mountId: modernConfig.html.mountId
120
- }, getEntryOptions(entryName, modernConfig.html.templateParameters, modernConfig.html.templateParametersByEntries, appContext.packageName));
122
+ }, getEntryOptions(entryName, isMainEntry, modernConfig.html.templateParameters, modernConfig.html.templateParametersByEntries, appContext.packageName));
121
123
  chain.plugin("".concat(CHAIN_ID.PLUGIN.HTML, "-").concat(entryName)).tap(function(args) {
122
124
  return [
123
125
  _object_spread_props(_object_spread({}, args[0] || {}), {
@@ -137,7 +137,7 @@ export var RouterPlugin = /* @__PURE__ */ function() {
137
137
  if (!asset) {
138
138
  continue;
139
139
  }
140
- newContent = "".concat(injectedContent).concat(asset.source().toString());
140
+ newContent = "".concat(asset.source().toString()).concat(injectedContent);
141
141
  newAssetsMap.set(path.join(outputPath, file), newContent);
142
142
  compilation.updateAsset(
143
143
  file,
@@ -2,6 +2,7 @@ import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
2
  import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
3
3
  import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props";
4
4
  import { createDefaultConfig as createDefaultBuilderConfig } from "@modern-js/builder-webpack-provider";
5
+ import { MAIN_ENTRY_NAME } from "@modern-js/utils";
5
6
  import { getAutoInjectEnv } from "../utils/env";
6
7
  export function createDefaultConfig(appContext, bundler) {
7
8
  var defaultBuilderConfig = createDefaultBuilderConfig();
@@ -16,6 +17,7 @@ export function createDefaultConfig(appContext, bundler) {
16
17
  var _obj;
17
18
  var source = _object_spread_props(_object_spread({}, defaultBuilderConfig.source), {
18
19
  entries: void 0,
20
+ mainEntryName: MAIN_ENTRY_NAME,
19
21
  enableAsyncEntry: false,
20
22
  disableDefaultEntries: false,
21
23
  entriesDir: "./src",
@@ -68,6 +70,7 @@ export function createLegacyDefaultConfig(appContext) {
68
70
  var defaultAlias = appContext ? (_obj = {}, _define_property(_obj, appContext.internalDirAlias, appContext.internalDirectory), _define_property(_obj, appContext.internalSrcAlias, appContext.srcDirectory), _define_property(_obj, "@", appContext.srcDirectory), _define_property(_obj, "@shared", appContext.sharedDirectory), _obj) : {};
69
71
  var sourceDefaults = {
70
72
  entries: void 0,
73
+ mainEntryName: MAIN_ENTRY_NAME,
71
74
  enableAsyncEntry: false,
72
75
  disableDefaultEntries: false,
73
76
  entriesDir: "./src",
@@ -1,5 +1,5 @@
1
1
  export function createSourceConfig(config) {
2
- var _config_source = config.source, alias = _config_source.alias, envVars = _config_source.envVars, globalVars = _config_source.globalVars, include = _config_source.include, moduleScopes = _config_source.moduleScopes, preEntry = _config_source.preEntry, entries = _config_source.entries, enableAsyncEntry = _config_source.enableAsyncEntry, disableDefaultEntries = _config_source.disableDefaultEntries, entriesDir = _config_source.entriesDir, configDir = _config_source.configDir;
2
+ var _config_source = config.source, alias = _config_source.alias, envVars = _config_source.envVars, globalVars = _config_source.globalVars, include = _config_source.include, moduleScopes = _config_source.moduleScopes, preEntry = _config_source.preEntry, entries = _config_source.entries, mainEntryName = _config_source.mainEntryName, enableAsyncEntry = _config_source.enableAsyncEntry, disableDefaultEntries = _config_source.disableDefaultEntries, entriesDir = _config_source.entriesDir, configDir = _config_source.configDir;
3
3
  var builderGlobalVars = globalVars || {};
4
4
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
5
5
  try {
@@ -29,6 +29,7 @@ export function createSourceConfig(config) {
29
29
  include: include,
30
30
  preEntry: preEntry,
31
31
  entries: entries,
32
+ mainEntryName: mainEntryName,
32
33
  enableAsyncEntry: enableAsyncEntry,
33
34
  disableDefaultEntries: disableDefaultEntries,
34
35
  entriesDir: entriesDir,
@@ -36,6 +36,9 @@ var source = {
36
36
  }
37
37
  })
38
38
  },
39
+ mainEntryName: {
40
+ type: "string"
41
+ },
39
42
  enableAsyncEntry: {
40
43
  type: "boolean"
41
44
  },
@@ -33,6 +33,9 @@ var source = {
33
33
  }
34
34
  })
35
35
  },
36
+ mainEntryName: {
37
+ type: "string"
38
+ },
36
39
  preEntry: {
37
40
  type: [
38
41
  "string",
@@ -60,7 +60,7 @@ export const generateCode = async (appContext, config, entrypoints, api) => {
60
60
  importsStatemets
61
61
  };
62
62
  async function generateEntryCode(entrypoint) {
63
- const { entryName, isAutoMount, fileSystemRoutes } = entrypoint;
63
+ const { entryName, isMainEntry, isAutoMount, fileSystemRoutes } = entrypoint;
64
64
  if (isAutoMount) {
65
65
  if (fileSystemRoutes) {
66
66
  var _config_output;
@@ -79,7 +79,7 @@ export const generateCode = async (appContext, config, entrypoints, api) => {
79
79
  nestedRoute = await walk(entrypoint.nestedRoutesEntry, entrypoint.nestedRoutesEntry, {
80
80
  name: internalSrcAlias,
81
81
  basename: srcDirectory
82
- }, entrypoint.entryName);
82
+ }, entrypoint.entryName, entrypoint.isMainEntry);
83
83
  if (nestedRoute) {
84
84
  initialRoutes.unshift(nestedRoute);
85
85
  }
@@ -89,7 +89,7 @@ export const generateCode = async (appContext, config, entrypoints, api) => {
89
89
  routes: initialRoutes
90
90
  });
91
91
  const config2 = api.useResolvedConfigContext();
92
- const ssr = getEntryOptions(entryName, config2.server.ssr, config2.server.ssrByEntries, packageName);
92
+ const ssr = getEntryOptions(entryName, isMainEntry, config2.server.ssr, config2.server.ssrByEntries, packageName);
93
93
  const useSSG = isSSGEntry(config2, entryName, entrypoints);
94
94
  let mode;
95
95
  if (ssr) {
@@ -149,7 +149,7 @@ export const generateIndexCode = async ({ appContext, api, entrypoints, config,
149
149
  const { mountId } = config.html;
150
150
  const { internalDirectory, packageName } = appContext;
151
151
  await Promise.all(entrypoints.map(async (entrypoint) => {
152
- const { entryName, isAutoMount, customBootstrap, fileSystemRoutes } = entrypoint;
152
+ const { entryName, isMainEntry, isAutoMount, customBootstrap, fileSystemRoutes } = entrypoint;
153
153
  if (isAutoMount) {
154
154
  const { plugins } = await hookRunners.modifyEntryRuntimePlugins({
155
155
  entrypoint,
@@ -178,7 +178,7 @@ export const generateIndexCode = async ({ appContext, api, entrypoints, config,
178
178
  const entryFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_FILE_NAME}`);
179
179
  if (config.source.enableAsyncEntry) {
180
180
  let rawAsyncEntryCode = `import('./${ENTRY_BOOTSTRAP_FILE_NAME}');`;
181
- const ssr = getEntryOptions(entryName, config.server.ssr, config.server.ssrByEntries, packageName);
181
+ const ssr = getEntryOptions(entryName, isMainEntry, config.server.ssr, config.server.ssrByEntries, packageName);
182
182
  if (ssr) {
183
183
  rawAsyncEntryCode = `
184
184
  export const ${SERVER_RENDER_FUNCTION_NAME} = async (...args) => {
@@ -24,19 +24,21 @@ const ifAlreadyExists = (entrypoints, checked) => entrypoints.some((entrypoint)
24
24
  });
25
25
  export const getBundleEntry = (appContext, config) => {
26
26
  const { appDirectory, packageName } = appContext;
27
- const { disableDefaultEntries, entries, entriesDir } = config.source;
27
+ const { disableDefaultEntries, entries, entriesDir, mainEntryName } = config.source;
28
28
  const defaults = disableDefaultEntries ? [] : getFileSystemEntry(appContext, config);
29
29
  if (entries) {
30
30
  Object.keys(entries).forEach((name) => {
31
31
  const value = entries[name];
32
32
  const entrypoint = typeof value === "string" ? {
33
33
  entryName: name,
34
+ isMainEntry: false,
34
35
  entry: ensureAbsolutePath(appDirectory, value),
35
36
  absoluteEntryDir: isDirectory(ensureAbsolutePath(appDirectory, value)) ? ensureAbsolutePath(appDirectory, value) : path.dirname(ensureAbsolutePath(appDirectory, value)),
36
37
  isAutoMount: true,
37
38
  fileSystemRoutes: fs.statSync(ensureAbsolutePath(appDirectory, value)).isDirectory() ? {} : void 0
38
39
  } : {
39
40
  entryName: name,
41
+ isMainEntry: false,
40
42
  entry: ensureAbsolutePath(appDirectory, value.entry),
41
43
  absoluteEntryDir: isDirectory(ensureAbsolutePath(appDirectory, value.entry)) ? ensureAbsolutePath(appDirectory, value.entry) : path.dirname(ensureAbsolutePath(appDirectory, value.entry)),
42
44
  isAutoMount: !value.disableMount,
@@ -54,7 +56,10 @@ export const getBundleEntry = (appContext, config) => {
54
56
  if (!disableDefaultEntries) {
55
57
  const entriesDirAbs = ensureAbsolutePath(appDirectory, entriesDir || "");
56
58
  const found = defaults.find(({ entryName, entry, nestedRoutesEntry = "" }) => entryName === packageName || path.dirname(entry) === entriesDirAbs || path.dirname(nestedRoutesEntry) === entriesDirAbs);
57
- found && (found.entryName = MAIN_ENTRY_NAME);
59
+ if (found) {
60
+ found.entryName = mainEntryName || MAIN_ENTRY_NAME;
61
+ found.isMainEntry = true;
62
+ }
58
63
  }
59
64
  return defaults;
60
65
  };
@@ -15,6 +15,7 @@ const scanDir = (dirs) => dirs.map((dir) => {
15
15
  if (indexFile && !customBootstrap) {
16
16
  return {
17
17
  entryName,
18
+ isMainEntry: false,
18
19
  entry: indexFile,
19
20
  absoluteEntryDir: path.resolve(dir),
20
21
  isAutoMount: false
@@ -24,6 +25,7 @@ const scanDir = (dirs) => dirs.map((dir) => {
24
25
  if (isHasApp) {
25
26
  return {
26
27
  entryName,
28
+ isMainEntry: false,
27
29
  entry: path.join(dir, APP_FILE_NAME),
28
30
  isAutoMount: true,
29
31
  absoluteEntryDir: path.resolve(dir),
@@ -35,6 +37,7 @@ const scanDir = (dirs) => dirs.map((dir) => {
35
37
  if (isHasNestedRoutes || isHasPages) {
36
38
  const entrypoint = {
37
39
  entryName,
40
+ isMainEntry: false,
38
41
  entry: "",
39
42
  fileSystemRoutes: {
40
43
  globalApp: findExists(JS_EXTENSIONS.map((ext) => path.resolve(dir, `./${PAGES_DIR_NAME}/${FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT}${ext}`)))
@@ -55,6 +58,7 @@ const scanDir = (dirs) => dirs.map((dir) => {
55
58
  }
56
59
  return {
57
60
  entryName,
61
+ isMainEntry: false,
58
62
  entry: indexFile,
59
63
  absoluteEntryDir: path.resolve(dir),
60
64
  isAutoMount: false
@@ -1,5 +1,5 @@
1
1
  import path from "path";
2
- import { fs, findExists, MAIN_ENTRY_NAME } from "@modern-js/utils";
2
+ import { fs, findExists } from "@modern-js/utils";
3
3
  import { HTML_PARTIALS_EXTENSIONS, HTML_PARTIALS_FOLDER } from "./constants";
4
4
  import * as templates from "./templates";
5
5
  var PartialPosition;
@@ -27,8 +27,8 @@ export const getHtmlTemplate = async (entrypoints, api, { appContext, config })
27
27
  const htmlDir = path.resolve(appDirectory, configDir || "", HTML_PARTIALS_FOLDER);
28
28
  const htmlTemplates = {};
29
29
  for (const entrypoint of entrypoints) {
30
- const { entryName } = entrypoint;
31
- const name = entrypoints.length === 1 && entryName === MAIN_ENTRY_NAME ? "" : entryName;
30
+ const { entryName, isMainEntry } = entrypoint;
31
+ const name = entrypoints.length === 1 && isMainEntry ? "" : entryName;
32
32
  const customIndexTemplate = findPartials(htmlDir, name, PartialPosition.INDEX);
33
33
  if (customIndexTemplate) {
34
34
  htmlTemplates[entryName] = customIndexTemplate.file;
@@ -69,17 +69,18 @@ const applyRouteOptions = (original, routeOptions) => {
69
69
  };
70
70
  const collectHtmlRoutes = (entrypoints, appContext, config) => {
71
71
  var _deploy_worker;
72
- const { html: { disableHtmlFolder }, output: { distPath: { html: htmlPath } = {} }, server: { baseUrl, routes, ssr, ssrByEntries }, deploy } = config;
72
+ const { source: { mainEntryName }, html: { disableHtmlFolder }, output: { distPath: { html: htmlPath } = {} }, server: { baseUrl, routes, ssr, ssrByEntries }, deploy } = config;
73
73
  const { packageName } = appContext;
74
74
  const workerSSR = deploy === null || deploy === void 0 ? void 0 : (_deploy_worker = deploy.worker) === null || _deploy_worker === void 0 ? void 0 : _deploy_worker.ssr;
75
75
  let htmlRoutes = entrypoints.reduce((previous, { entryName }) => {
76
- const entryOptions = getEntryOptions(entryName, ssr, ssrByEntries, packageName);
76
+ const isMainEntry = entryName === (mainEntryName || MAIN_ENTRY_NAME);
77
+ const entryOptions = getEntryOptions(entryName, isMainEntry, ssr, ssrByEntries, packageName);
77
78
  const isSSR = Boolean(entryOptions);
78
79
  const isWorker = Boolean(workerSSR);
79
80
  const isStream = typeof entryOptions === "object" && entryOptions.mode === "stream";
80
81
  const { resHeaders } = (routes === null || routes === void 0 ? void 0 : routes[entryName]) || {};
81
82
  let route = {
82
- urlPath: `/${entryName === MAIN_ENTRY_NAME ? "" : entryName}`,
83
+ urlPath: `/${isMainEntry ? "" : entryName}`,
83
84
  entryName,
84
85
  entryPath: removeLeadingSlash(path.posix.normalize(`${htmlPath}/${entryName}${disableHtmlFolder ? ".html" : "/index.html"}`)),
85
86
  isSPA: true,
@@ -1,27 +1,42 @@
1
1
  import * as path from "path";
2
- import { fs, getRouteId } from "@modern-js/utils";
2
+ import { fs, normalizeToPosixPath } from "@modern-js/utils";
3
3
  import { JS_EXTENSIONS, NESTED_ROUTE } from "./constants";
4
4
  import { replaceWithAlias } from "./utils";
5
5
  const conventionNames = Object.values(NESTED_ROUTE);
6
6
  const replaceDynamicPath = (routePath) => {
7
7
  return routePath.replace(/\[(.*?)\]/g, ":$1");
8
8
  };
9
- const createIndexRoute = (routeInfo, rootDir, filename, entryName) => {
9
+ const getPathWithoutExt = (filename) => {
10
+ const extname = path.extname(filename);
11
+ return filename.slice(0, -extname.length);
12
+ };
13
+ export const getRouteId = (componentPath, routesDir, entryName, isMainEntry) => {
14
+ const relativePath = normalizeToPosixPath(path.relative(routesDir, componentPath));
15
+ const pathWithoutExt = getPathWithoutExt(relativePath);
16
+ let id = ``;
17
+ if (isMainEntry) {
18
+ id = pathWithoutExt;
19
+ } else {
20
+ id = `${entryName}_${pathWithoutExt}`;
21
+ }
22
+ return id.replace(/\[(.*?)\]/g, "($1)");
23
+ };
24
+ const createIndexRoute = (routeInfo, rootDir, filename, entryName, isMainEntry) => {
10
25
  return createRoute({
11
26
  ...routeInfo,
12
27
  index: true,
13
28
  children: void 0
14
- }, rootDir, filename, entryName);
29
+ }, rootDir, filename, entryName, isMainEntry);
15
30
  };
16
- const createRoute = (routeInfo, rootDir, filename, entryName) => {
17
- const id = getRouteId(filename, rootDir, entryName);
31
+ const createRoute = (routeInfo, rootDir, filename, entryName, isMainEntry) => {
32
+ const id = getRouteId(filename, rootDir, entryName, isMainEntry);
18
33
  return {
19
34
  ...routeInfo,
20
35
  id,
21
36
  type: "nested"
22
37
  };
23
38
  };
24
- export const walk = async (dirname, rootDir, alias, entryName) => {
39
+ export const walk = async (dirname, rootDir, alias, entryName, isMainEntry) => {
25
40
  var _route_children;
26
41
  if (!await fs.pathExists(dirname)) {
27
42
  return null;
@@ -58,7 +73,7 @@ export const walk = async (dirname, rootDir, alias, entryName) => {
58
73
  const itemWithoutExt = item.slice(0, -extname.length);
59
74
  const isDirectory2 = (await fs.stat(itemPath)).isDirectory();
60
75
  if (isDirectory2) {
61
- const childRoute = await walk(itemPath, rootDir, alias, entryName);
76
+ const childRoute = await walk(itemPath, rootDir, alias, entryName, isMainEntry);
62
77
  if (childRoute) {
63
78
  var _route_children1;
64
79
  (_route_children1 = route.children) === null || _route_children1 === void 0 ? void 0 : _route_children1.push(childRoute);
@@ -90,7 +105,7 @@ export const walk = async (dirname, rootDir, alias, entryName) => {
90
105
  var _route_children2;
91
106
  pageRoute = createIndexRoute({
92
107
  _component: replaceWithAlias(alias.basename, itemPath, alias.name)
93
- }, rootDir, itemPath, entryName);
108
+ }, rootDir, itemPath, entryName, isMainEntry);
94
109
  if (pageLoaderFile) {
95
110
  pageRoute.loader = pageLoaderFile;
96
111
  }
@@ -107,7 +122,7 @@ export const walk = async (dirname, rootDir, alias, entryName) => {
107
122
  splatRoute = createRoute({
108
123
  _component: replaceWithAlias(alias.basename, itemPath, alias.name),
109
124
  path: "*"
110
- }, rootDir, itemPath, entryName);
125
+ }, rootDir, itemPath, entryName, isMainEntry);
111
126
  if (splatLoaderFile) {
112
127
  splatRoute.loader = splatLoaderFile;
113
128
  }
@@ -120,7 +135,7 @@ export const walk = async (dirname, rootDir, alias, entryName) => {
120
135
  route.error = replaceWithAlias(alias.basename, itemPath, alias.name);
121
136
  }
122
137
  }
123
- let finalRoute = createRoute(route, rootDir, path.join(dirname, `${NESTED_ROUTE.LAYOUT_FILE}.ts`), entryName);
138
+ let finalRoute = createRoute(route, rootDir, path.join(dirname, `${NESTED_ROUTE.LAYOUT_FILE}.ts`), entryName, isMainEntry);
124
139
  if (isPathlessLayout) {
125
140
  delete finalRoute.path;
126
141
  }
@@ -298,9 +298,9 @@ export const fileSystemRoutes = async ({ routes, ssrMode, nestedRoutesEntry, ent
298
298
  `;
299
299
  };
300
300
  export function ssrLoaderCombinedModule(entrypoints, entrypoint, config, appContext) {
301
- const { entryName } = entrypoint;
301
+ const { entryName, isMainEntry } = entrypoint;
302
302
  const { packageName, internalDirectory } = appContext;
303
- const ssr = getEntryOptions(entryName, config.server.ssr, config.server.ssrByEntries, packageName);
303
+ const ssr = getEntryOptions(entryName, isMainEntry, config.server.ssr, config.server.ssrByEntries, packageName);
304
304
  const ssg = isSSGEntry(config, entryName, entrypoints);
305
305
  if (entrypoint.nestedRoutesEntry && (ssr || ssg)) {
306
306
  const serverLoaderRuntime = require.resolve("@modern-js/plugin-data-loader/runtime");
@@ -1,5 +1,5 @@
1
1
  import { isHtmlDisabled, createVirtualModule } from "@modern-js/builder-shared";
2
- import { getEntryOptions, removeTailSlash } from "@modern-js/utils";
2
+ import { MAIN_ENTRY_NAME, getEntryOptions, removeTailSlash } from "@modern-js/utils";
3
3
  import { template as lodashTemplate } from "@modern-js/utils/lodash";
4
4
  import { BottomTemplatePlugin } from "../bundlerPlugins";
5
5
  export const builderPluginAdapterHtml = (options) => ({
@@ -49,11 +49,13 @@ async function injectAssetPrefix({ api, chain }) {
49
49
  function applyBottomHtmlPlugin({ api, chain, options, CHAIN_ID, HtmlBundlerPlugin }) {
50
50
  const { normalizedConfig: modernConfig, appContext } = options;
51
51
  for (const entryName of Object.keys(api.context.entry)) {
52
+ const { source: { mainEntryName } } = modernConfig;
53
+ const isMainEntry = entryName === (mainEntryName || MAIN_ENTRY_NAME);
52
54
  const baseTemplateParams = {
53
55
  entryName,
54
- title: getEntryOptions(entryName, modernConfig.html.title, modernConfig.html.titleByEntries, appContext.packageName),
56
+ title: getEntryOptions(entryName, isMainEntry, modernConfig.html.title, modernConfig.html.titleByEntries, appContext.packageName),
55
57
  mountId: modernConfig.html.mountId,
56
- ...getEntryOptions(entryName, modernConfig.html.templateParameters, modernConfig.html.templateParametersByEntries, appContext.packageName)
58
+ ...getEntryOptions(entryName, isMainEntry, modernConfig.html.templateParameters, modernConfig.html.templateParametersByEntries, appContext.packageName)
57
59
  };
58
60
  chain.plugin(`${CHAIN_ID.PLUGIN.HTML}-${entryName}`).tap((args) => [
59
61
  {
@@ -98,7 +98,7 @@ export class RouterPlugin {
98
98
  if (!asset) {
99
99
  continue;
100
100
  }
101
- const newContent = `${injectedContent}${asset.source().toString()}`;
101
+ const newContent = `${asset.source().toString()}${injectedContent}`;
102
102
  newAssetsMap.set(path.join(outputPath, file), newContent);
103
103
  compilation.updateAsset(
104
104
  file,
@@ -1,4 +1,5 @@
1
1
  import { createDefaultConfig as createDefaultBuilderConfig } from "@modern-js/builder-webpack-provider";
2
+ import { MAIN_ENTRY_NAME } from "@modern-js/utils";
2
3
  import { getAutoInjectEnv } from "../utils/env";
3
4
  export function createDefaultConfig(appContext, bundler) {
4
5
  const defaultBuilderConfig = createDefaultBuilderConfig();
@@ -15,6 +16,7 @@ export function createDefaultConfig(appContext, bundler) {
15
16
  const source = {
16
17
  ...defaultBuilderConfig.source,
17
18
  entries: void 0,
19
+ mainEntryName: MAIN_ENTRY_NAME,
18
20
  enableAsyncEntry: false,
19
21
  disableDefaultEntries: false,
20
22
  entriesDir: "./src",
@@ -79,6 +81,7 @@ export function createLegacyDefaultConfig(appContext) {
79
81
  } : {};
80
82
  const sourceDefaults = {
81
83
  entries: void 0,
84
+ mainEntryName: MAIN_ENTRY_NAME,
82
85
  enableAsyncEntry: false,
83
86
  disableDefaultEntries: false,
84
87
  entriesDir: "./src",
@@ -1,5 +1,5 @@
1
1
  export function createSourceConfig(config) {
2
- const { alias, envVars, globalVars, include, moduleScopes, preEntry, entries, enableAsyncEntry, disableDefaultEntries, entriesDir, configDir } = config.source;
2
+ const { alias, envVars, globalVars, include, moduleScopes, preEntry, entries, mainEntryName, enableAsyncEntry, disableDefaultEntries, entriesDir, configDir } = config.source;
3
3
  const builderGlobalVars = globalVars || {};
4
4
  for (const envVar of envVars || []) {
5
5
  const envVarValue = process.env[envVar];
@@ -12,6 +12,7 @@ export function createSourceConfig(config) {
12
12
  include,
13
13
  preEntry,
14
14
  entries,
15
+ mainEntryName,
15
16
  enableAsyncEntry,
16
17
  disableDefaultEntries,
17
18
  entriesDir,
@@ -37,6 +37,9 @@ const source = {
37
37
  }
38
38
  }
39
39
  },
40
+ mainEntryName: {
41
+ type: "string"
42
+ },
40
43
  enableAsyncEntry: {
41
44
  type: "boolean"
42
45
  },
@@ -34,6 +34,9 @@ const source = {
34
34
  }
35
35
  }
36
36
  },
37
+ mainEntryName: {
38
+ type: "string"
39
+ },
37
40
  preEntry: {
38
41
  type: [
39
42
  "string",
@@ -1,5 +1,6 @@
1
1
  import type { NestedRoute } from '@modern-js/types';
2
+ export declare const getRouteId: (componentPath: string, routesDir: string, entryName: string, isMainEntry: boolean) => string;
2
3
  export declare const walk: (dirname: string, rootDir: string, alias: {
3
4
  name: string;
4
5
  basename: string;
5
- }, entryName: string) => Promise<NestedRoute | null>;
6
+ }, entryName: string, isMainEntry: boolean) => Promise<NestedRoute | null>;
@@ -11,6 +11,7 @@ export type Entry = string | {
11
11
  export type Entries = Record<string, Entry>;
12
12
  export interface SharedSourceConfig extends BuilderSharedSourceConfig {
13
13
  entries?: Entries;
14
+ mainEntryName?: string;
14
15
  enableAsyncEntry?: boolean;
15
16
  disableDefaultEntries?: boolean;
16
17
  entriesDir?: string;
@@ -5,6 +5,7 @@ export type SourceLegacyUserConfig = {
5
5
  entry: string;
6
6
  disableMount?: boolean;
7
7
  }>;
8
+ mainEntryName?: string;
8
9
  preEntry?: string | string[];
9
10
  enableAsyncEntry?: boolean;
10
11
  disableDefaultEntries?: boolean;