@modern-js/app-tools 1.21.3 → 2.0.0-beta.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 (146) hide show
  1. package/CHANGELOG.md +138 -16
  2. package/dist/js/modern/analyze/constants.js +1 -0
  3. package/dist/js/modern/analyze/generateCode.js +118 -16
  4. package/dist/js/modern/analyze/getBundleEntry.js +3 -2
  5. package/dist/js/modern/analyze/getClientRoutes/getRoutes.js +198 -0
  6. package/dist/js/modern/analyze/{getClientRoutes.js → getClientRoutes/getRoutesLegacy.js} +8 -28
  7. package/dist/js/modern/analyze/getClientRoutes/index.js +2 -0
  8. package/dist/js/modern/analyze/getClientRoutes/utils.js +21 -0
  9. package/dist/js/modern/analyze/getFileSystemEntry.js +31 -12
  10. package/dist/js/modern/analyze/index.js +2 -1
  11. package/dist/js/modern/analyze/nestedRoutes.js +127 -0
  12. package/dist/js/modern/analyze/templates.js +164 -10
  13. package/dist/js/modern/analyze/utils.js +2 -1
  14. package/dist/js/modern/builder/builderPlugins/compatModern.js +226 -0
  15. package/dist/js/modern/builder/createHtmlConfig.js +58 -0
  16. package/dist/js/modern/builder/createOutputConfig.js +67 -0
  17. package/dist/js/modern/builder/createSourceConfig.js +85 -0
  18. package/dist/js/modern/builder/createToolsConfig.js +94 -0
  19. package/dist/js/modern/builder/index.js +106 -0
  20. package/dist/js/modern/builder/share.js +48 -0
  21. package/dist/js/modern/builder/webpackPlugins/htmlAsyncChunkPlugin.js +37 -0
  22. package/dist/js/modern/builder/webpackPlugins/htmlBottomTemplate.js +44 -0
  23. package/dist/js/modern/commands/build.js +41 -95
  24. package/dist/js/modern/commands/dev.js +15 -19
  25. package/dist/js/modern/commands/inspect.js +17 -58
  26. package/dist/js/modern/commands/start.js +2 -1
  27. package/dist/js/modern/index.js +14 -4
  28. package/dist/js/modern/locale/en.js +0 -1
  29. package/dist/js/modern/locale/zh.js +0 -1
  30. package/dist/js/modern/utils/commands.js +5 -0
  31. package/dist/js/modern/utils/createCompiler.js +37 -40
  32. package/dist/js/modern/utils/createServer.js +16 -0
  33. package/dist/js/modern/utils/printInstructions.js +1 -1
  34. package/dist/js/node/analyze/constants.js +3 -1
  35. package/dist/js/node/analyze/generateCode.js +121 -14
  36. package/dist/js/node/analyze/getBundleEntry.js +3 -2
  37. package/dist/js/node/analyze/getClientRoutes/getRoutes.js +221 -0
  38. package/dist/js/node/analyze/{getClientRoutes.js → getClientRoutes/getRoutesLegacy.js} +16 -35
  39. package/dist/js/node/analyze/getClientRoutes/index.js +21 -0
  40. package/dist/js/node/analyze/getClientRoutes/utils.js +42 -0
  41. package/dist/js/node/analyze/getFileSystemEntry.js +30 -11
  42. package/dist/js/node/analyze/index.js +2 -1
  43. package/dist/js/node/analyze/nestedRoutes.js +144 -0
  44. package/dist/js/node/analyze/templates.js +167 -10
  45. package/dist/js/node/analyze/utils.js +6 -2
  46. package/dist/js/node/builder/builderPlugins/compatModern.js +245 -0
  47. package/dist/js/node/builder/createHtmlConfig.js +76 -0
  48. package/dist/js/node/builder/createOutputConfig.js +75 -0
  49. package/dist/js/node/builder/createSourceConfig.js +99 -0
  50. package/dist/js/node/builder/createToolsConfig.js +103 -0
  51. package/dist/js/node/builder/index.js +129 -0
  52. package/dist/js/node/builder/share.js +63 -0
  53. package/dist/js/node/builder/webpackPlugins/htmlAsyncChunkPlugin.js +46 -0
  54. package/dist/js/node/builder/webpackPlugins/htmlBottomTemplate.js +53 -0
  55. package/dist/js/node/commands/build.js +44 -98
  56. package/dist/js/node/commands/dev.js +13 -23
  57. package/dist/js/node/commands/inspect.js +18 -74
  58. package/dist/js/node/commands/start.js +3 -1
  59. package/dist/js/node/index.js +19 -2
  60. package/dist/js/node/locale/en.js +0 -1
  61. package/dist/js/node/locale/zh.js +0 -1
  62. package/dist/js/node/utils/commands.js +14 -0
  63. package/dist/js/node/utils/createCompiler.js +43 -49
  64. package/dist/js/node/utils/createServer.js +21 -2
  65. package/dist/js/node/utils/printInstructions.js +1 -1
  66. package/dist/js/treeshaking/analyze/constants.js +16 -0
  67. package/dist/js/treeshaking/analyze/generateCode.js +412 -0
  68. package/dist/js/treeshaking/analyze/getBundleEntry.js +77 -0
  69. package/dist/js/treeshaking/analyze/getClientRoutes/getRoutes.js +210 -0
  70. package/dist/js/treeshaking/analyze/getClientRoutes/getRoutesLegacy.js +211 -0
  71. package/dist/js/treeshaking/analyze/getClientRoutes/index.js +2 -0
  72. package/dist/js/treeshaking/analyze/getClientRoutes/utils.js +27 -0
  73. package/dist/js/treeshaking/analyze/getFileSystemEntry.js +109 -0
  74. package/dist/js/treeshaking/analyze/getHtmlTemplate.js +153 -0
  75. package/dist/js/treeshaking/analyze/getServerRoutes.js +170 -0
  76. package/dist/js/treeshaking/analyze/index.js +214 -0
  77. package/dist/js/treeshaking/analyze/isDefaultExportFunction.js +32 -0
  78. package/dist/js/treeshaking/analyze/makeLegalIdentifier.js +18 -0
  79. package/dist/js/treeshaking/analyze/nestedRoutes.js +207 -0
  80. package/dist/js/treeshaking/analyze/templates.js +189 -0
  81. package/dist/js/treeshaking/analyze/utils.js +95 -0
  82. package/dist/js/treeshaking/builder/builderPlugins/compatModern.js +231 -0
  83. package/dist/js/treeshaking/builder/createHtmlConfig.js +59 -0
  84. package/dist/js/treeshaking/builder/createOutputConfig.js +67 -0
  85. package/dist/js/treeshaking/builder/createSourceConfig.js +100 -0
  86. package/dist/js/treeshaking/builder/createToolsConfig.js +90 -0
  87. package/dist/js/treeshaking/builder/index.js +172 -0
  88. package/dist/js/treeshaking/builder/share.js +50 -0
  89. package/dist/js/treeshaking/builder/webpackPlugins/htmlAsyncChunkPlugin.js +58 -0
  90. package/dist/js/treeshaking/builder/webpackPlugins/htmlBottomTemplate.js +53 -0
  91. package/dist/js/treeshaking/commands/build.js +168 -0
  92. package/dist/js/treeshaking/commands/deploy.js +29 -0
  93. package/dist/js/treeshaking/commands/dev.js +146 -0
  94. package/dist/js/treeshaking/commands/index.js +3 -0
  95. package/dist/js/treeshaking/commands/inspect.js +52 -0
  96. package/dist/js/treeshaking/commands/start.js +78 -0
  97. package/dist/js/treeshaking/exports/server.js +1 -0
  98. package/dist/js/treeshaking/hooks.js +21 -0
  99. package/dist/js/treeshaking/index.js +304 -0
  100. package/dist/js/treeshaking/locale/en.js +34 -0
  101. package/dist/js/treeshaking/locale/index.js +9 -0
  102. package/dist/js/treeshaking/locale/zh.js +34 -0
  103. package/dist/js/treeshaking/utils/commands.js +5 -0
  104. package/dist/js/treeshaking/utils/config.js +140 -0
  105. package/dist/js/treeshaking/utils/createCompiler.js +117 -0
  106. package/dist/js/treeshaking/utils/createServer.js +83 -0
  107. package/dist/js/treeshaking/utils/getSpecifiedEntries.js +68 -0
  108. package/dist/js/treeshaking/utils/language.js +5 -0
  109. package/dist/js/treeshaking/utils/printInstructions.js +35 -0
  110. package/dist/js/treeshaking/utils/routes.js +33 -0
  111. package/dist/js/treeshaking/utils/types.js +0 -0
  112. package/dist/types/analyze/constants.d.ts +1 -0
  113. package/dist/types/analyze/generateCode.d.ts +1 -1
  114. package/dist/types/analyze/{getClientRoutes.d.ts → getClientRoutes/getRoutes.d.ts} +2 -7
  115. package/dist/types/analyze/getClientRoutes/getRoutesLegacy.d.ts +15 -0
  116. package/dist/types/analyze/getClientRoutes/index.d.ts +2 -0
  117. package/dist/types/analyze/getClientRoutes/utils.d.ts +5 -0
  118. package/dist/types/analyze/index.d.ts +2 -2
  119. package/dist/types/analyze/nestedRoutes.d.ts +5 -0
  120. package/dist/types/analyze/templates.d.ts +17 -3
  121. package/dist/types/analyze/utils.d.ts +2 -1
  122. package/dist/types/builder/builderPlugins/compatModern.d.ts +14 -0
  123. package/dist/types/builder/createHtmlConfig.d.ts +6 -0
  124. package/dist/types/builder/createOutputConfig.d.ts +3 -0
  125. package/dist/types/builder/createSourceConfig.d.ts +5 -0
  126. package/dist/types/builder/createToolsConfig.d.ts +13 -0
  127. package/dist/types/builder/index.d.ts +19 -0
  128. package/dist/types/builder/share.d.ts +26 -0
  129. package/dist/types/builder/webpackPlugins/htmlAsyncChunkPlugin.d.ts +8 -0
  130. package/dist/types/builder/webpackPlugins/htmlBottomTemplate.d.ts +10 -0
  131. package/dist/types/commands/build.d.ts +2 -1
  132. package/dist/types/commands/deploy.d.ts +2 -1
  133. package/dist/types/commands/dev.d.ts +2 -1
  134. package/dist/types/commands/inspect.d.ts +5 -6
  135. package/dist/types/commands/start.d.ts +2 -1
  136. package/dist/types/hooks.d.ts +15 -10
  137. package/dist/types/index.d.ts +4 -2
  138. package/dist/types/locale/en.d.ts +0 -1
  139. package/dist/types/locale/index.d.ts +0 -2
  140. package/dist/types/locale/zh.d.ts +0 -1
  141. package/dist/types/utils/commands.d.ts +1 -0
  142. package/dist/types/utils/createCompiler.d.ts +9 -10
  143. package/dist/types/utils/createServer.d.ts +8 -1
  144. package/dist/types/utils/printInstructions.d.ts +3 -2
  145. package/dist/types/utils/types.d.ts +2 -3
  146. package/package.json +25 -43
package/CHANGELOG.md CHANGED
@@ -1,21 +1,143 @@
1
1
  # @modern-js/app-tools
2
2
 
3
- ## 1.21.3
4
-
5
- ### Patch Changes
6
-
7
- - @modern-js/upgrade@1.21.3
8
- - @modern-js/new-action@1.21.3
9
- - @modern-js/core@1.21.3
10
- - @modern-js/plugin-i18n@1.21.3
11
- - @modern-js/plugin-jarvis@1.21.3
12
- - @modern-js/webpack@1.21.3
13
- - @modern-js/prod-server@1.21.3
14
- - @modern-js/server@1.21.3
15
- - @modern-js/node-bundle-require@1.21.3
16
- - @modern-js/plugin@1.21.3
17
- - @modern-js/types@1.21.3
18
- - @modern-js/utils@1.21.3
3
+ ## 2.0.0-beta.0
4
+
5
+ ### Major Changes
6
+
7
+ - dda38c9: chore: v2
8
+
9
+ ### Minor Changes
10
+
11
+ - edd1cfb1a: feat: modernjs Access builder compiler
12
+ feat: modernjs 接入 builder 构建
13
+ - 543be95: feat: compile server loader and support handle loader request
14
+ feat: 编译 server loader 并支持处理 loader 的请求
15
+
16
+ ### Patch Changes
17
+
18
+ - c9f912c: feat(app-tools): improve build logs of dev and build command
19
+
20
+ feat(app-tools): 优化 dev 和 build 过程中的日志展示
21
+
22
+ - 103973c: fix: builder tools.webpackChain config args not match the Modernjs tools.webpackChain
23
+ fix: builder tools.webpackChain 配置传参无法匹配 Modernjs tools.webpackChain
24
+ - 0b2d1ef: fix: repeat register `babel-plugin-lodash`
25
+ fix: 重复注册 `babel-plugin-lodash`
26
+ - 82cef85: fix: specify builder compiler framework
27
+ fix: 指明 builder 构建时框架
28
+ - 85edee8: feat(app-tools): support tools.htmlPlugin config
29
+
30
+ feat(app-tools): 支持 tools.htmlPlugin 配置项
31
+
32
+ - dc8eeb9: fix: clear distDirectory in prepare hook & inject data loader plugin to server
33
+ fix: 在 prepare hook 中清理 dist 目录,并且向 server 中注入 data loader plugin
34
+ - cc971eabf: refactor: move server plugin load logic in `@modern-js/core`
35
+ refactor:移除在 `@modern-js/core` 中的 server 插件加载逻辑
36
+ - 5b9049f: feat: inject async js chunk when streaming ssr
37
+ feat: streaming ssr 时, 注入 async 类型的 js chunk
38
+ - 6bda14ed7: feat: refactor router with react-router@6.4
39
+
40
+ feat: 使用 react-router@6.4 重构路由模块
41
+
42
+ - d36c6ee: fix(app-tools): failed to run inspect command
43
+
44
+ fix(app-tools): 修复运行 inspect 命令失败的问题
45
+
46
+ - b8bbe036c: feat: change type logic
47
+ feat: 修改类型相关的逻辑
48
+ - af4422d: feat(builder): complete utils of tools.webpack
49
+
50
+ feat(builder): 补全 tools.webpack 提供的 utils 方法
51
+
52
+ - c258e34: fix: add builder hooks `beforeBuild` params
53
+ fix: 新增 builder hooks `beforeBuild` 的参数
54
+ - 8b8e1bb57: feat: support nested routes
55
+ feat: 支持嵌套路由
56
+ - c677bef: fix(app-tools): compat legacy resolve behavior
57
+
58
+ fix(app-tools): 兼容旧版本 node_modules 解析逻辑
59
+
60
+ - 3f7cde5: fix: builder plugin setup can't get config
61
+ fix: builder 插件在 setup 阶段无法拿到 config
62
+ - 99213e4: fix: process does't exit when exec command
63
+ fix: 修复执行命令时进程未退出的问题
64
+ - b16fd96: fix: `modern-js/app-tools` pass error config to builder.
65
+ fix: `modern-js/app-tools` 传递错误的 config 给 builder.
66
+ - 7eefedd: fix: add html-webpack-plugin `__internal__` options, for bottom template
67
+ fix: 为了 bottom template, 增加 `html-webpack-plugin` `__internal__` 配置项,
68
+ - 14b712d: fix: use consistent alias type and default value across packages
69
+
70
+ fix: 在各个包中使用一致的 alias 类型定义和默认值
71
+
72
+ - Updated dependencies [c9f912c]
73
+ - Updated dependencies [95be7cc49]
74
+ - Updated dependencies [e439457a5]
75
+ - Updated dependencies [4d1545f]
76
+ - Updated dependencies [2bc090c08]
77
+ - Updated dependencies [f96a725]
78
+ - Updated dependencies [828f42f9c]
79
+ - Updated dependencies [c745686]
80
+ - Updated dependencies [c9e800d39]
81
+ - Updated dependencies [0ff846f]
82
+ - Updated dependencies [57077b2]
83
+ - Updated dependencies [287f29899]
84
+ - Updated dependencies [15bf09d9c]
85
+ - Updated dependencies [423188db7]
86
+ - Updated dependencies [fd2d652]
87
+ - Updated dependencies [0c2d8dae3]
88
+ - Updated dependencies [85edee8]
89
+ - Updated dependencies [a2509bf]
90
+ - Updated dependencies [399887579]
91
+ - Updated dependencies [399887579]
92
+ - Updated dependencies [ba86b8b]
93
+ - Updated dependencies [61f21d1e7]
94
+ - Updated dependencies [2ae58176f]
95
+ - Updated dependencies [edd1cfb1a]
96
+ - Updated dependencies [5d67c26]
97
+ - Updated dependencies [cc971eabf]
98
+ - Updated dependencies [5b9049f]
99
+ - Updated dependencies [18360a38d]
100
+ - Updated dependencies [6bda14ed7]
101
+ - Updated dependencies [0b314e694]
102
+ - Updated dependencies [b8bbe036c]
103
+ - Updated dependencies [af4422d]
104
+ - Updated dependencies [d5a31df78]
105
+ - Updated dependencies [dda38c9]
106
+ - Updated dependencies [102d32e4b]
107
+ - Updated dependencies [c258e34]
108
+ - Updated dependencies [7248342e4]
109
+ - Updated dependencies [568eab1e4]
110
+ - Updated dependencies [8b8e1bb57]
111
+ - Updated dependencies [3bbea92b2]
112
+ - Updated dependencies [ae71096d4]
113
+ - Updated dependencies [73cd29dd9]
114
+ - Updated dependencies [a23010138]
115
+ - Updated dependencies [75d1b2657]
116
+ - Updated dependencies [8a6d45f]
117
+ - Updated dependencies [90e2879]
118
+ - Updated dependencies [f727e5c6c]
119
+ - Updated dependencies [5e3cecd52]
120
+ - Updated dependencies [abf3421]
121
+ - Updated dependencies [da2d1fc3c]
122
+ - Updated dependencies [543be95]
123
+ - Updated dependencies [14b712d]
124
+ - @modern-js/builder-webpack-provider@2.0.0-beta.0
125
+ - @modern-js/builder-shared@2.0.0-beta.0
126
+ - @modern-js/core@2.0.0-beta.0
127
+ - @modern-js/prod-server@2.0.0-beta.0
128
+ - @modern-js/builder-plugin-esbuild@2.0.0-beta.0
129
+ - @modern-js/server@2.0.0-beta.0
130
+ - @modern-js/node-bundle-require@2.0.0-beta.0
131
+ - @modern-js/builder-plugin-node-polyfill@2.0.0-beta.0
132
+ - @modern-js/utils@2.0.0-beta.0
133
+ - @modern-js/types@2.0.0-beta.0
134
+ - @modern-js/plugin@2.0.0-beta.0
135
+ - @modern-js/builder@2.0.0-beta.0
136
+ - @modern-js/plugin-data-loader@2.0.0-beta.0
137
+ - @modern-js/plugin-i18n@2.0.0-beta.0
138
+ - @modern-js/plugin-jarvis@2.0.0-beta.0
139
+ - @modern-js/new-action@2.0.0-beta.0
140
+ - @modern-js/upgrade@2.0.0-beta.0
19
141
 
20
142
  ## 1.21.2
21
143
 
@@ -2,6 +2,7 @@ export const JS_EXTENSIONS = ['.js', '.ts', '.jsx', '.tsx'];
2
2
  export const INDEX_FILE_NAME = 'index';
3
3
  export const APP_FILE_NAME = 'App';
4
4
  export const PAGES_DIR_NAME = 'pages';
5
+ export const NESTED_ROUTES_DIR = 'routes';
5
6
  export const FILE_SYSTEM_ROUTES_FILE_NAME = 'routes.js';
6
7
  export const ENTRY_POINT_FILE_NAME = 'index.js';
7
8
  export const ENTRY_BOOTSTRAP_FILE_NAME = 'bootstrap.js';
@@ -1,9 +1,13 @@
1
1
  import path from 'path';
2
- import { fs } from '@modern-js/utils';
2
+ import { fs, logger } from '@modern-js/utils';
3
+ import { useResolvedConfigContext } from '@modern-js/core';
4
+ import esbuild from 'esbuild';
5
+ import { getCommand } from "../utils/commands";
3
6
  import * as templates from "./templates";
4
- import { getClientRoutes } from "./getClientRoutes";
7
+ import { getClientRoutes, getClientRoutesLegacy } from "./getClientRoutes";
5
8
  import { FILE_SYSTEM_ROUTES_FILE_NAME, ENTRY_POINT_FILE_NAME, ENTRY_BOOTSTRAP_FILE_NAME } from "./constants";
6
9
  import { getDefaultImports } from "./utils";
10
+ import { walk } from "./nestedRoutes";
7
11
 
8
12
  const createImportSpecifier = specifiers => {
9
13
  let defaults = '';
@@ -65,21 +69,68 @@ export const createImportStatements = statements => {
65
69
  initialize
66
70
  }) => `import ${createImportSpecifier(specifiers)} from '${value}';\n${initialize || ''}`).join('\n');
67
71
  };
72
+
73
+ const buildLoader = async (entry, outfile) => {
74
+ const loader = {
75
+ '.js': 'jsx',
76
+ '.ts': 'tsx'
77
+ };
78
+ const EXTERNAL_REGEXP = /^[^./]|^\.[^./]|^\.\.[^/]/;
79
+ const command = getCommand();
80
+ await esbuild.build({
81
+ format: 'cjs',
82
+ platform: 'node',
83
+ target: 'esnext',
84
+ loader,
85
+ watch: command === 'dev' && {},
86
+ bundle: true,
87
+ logLevel: 'error',
88
+ entryPoints: [entry],
89
+ outfile,
90
+ plugins: [{
91
+ name: 'make-all-packages-external',
92
+
93
+ setup(build) {
94
+ // https://github.com/evanw/esbuild/issues/619#issuecomment-751995294
95
+ build.onResolve({
96
+ filter: EXTERNAL_REGEXP
97
+ }, args => {
98
+ let external = true; // FIXME: windows external entrypoint
99
+
100
+ if (args.kind === 'entry-point') {
101
+ external = false;
102
+ }
103
+
104
+ return {
105
+ path: args.path,
106
+ external
107
+ };
108
+ });
109
+ }
110
+
111
+ }]
112
+ });
113
+ };
114
+
68
115
  export const generateCode = async (appContext, config, entrypoints, api) => {
116
+ var _config$runtime, _config$runtime$route;
117
+
69
118
  const {
70
119
  internalDirectory,
120
+ distDirectory,
71
121
  srcDirectory,
72
122
  internalDirAlias,
73
123
  internalSrcAlias
74
124
  } = appContext;
75
125
  const hookRunners = api.useHookRunners();
126
+ const islegacy = Boolean(config === null || config === void 0 ? void 0 : (_config$runtime = config.runtime) === null || _config$runtime === void 0 ? void 0 : (_config$runtime$route = _config$runtime.router) === null || _config$runtime$route === void 0 ? void 0 : _config$runtime$route.legacy);
76
127
  const {
77
- output: {
78
- mountId
79
- }
80
- } = config;
128
+ mountId
129
+ } = config.output;
130
+ const getRoutes = islegacy ? getClientRoutesLegacy : getClientRoutes;
131
+ await Promise.all(entrypoints.map(generateEntryCode));
81
132
 
82
- for (const entrypoint of entrypoints) {
133
+ async function generateEntryCode(entrypoint) {
83
134
  const {
84
135
  entryName,
85
136
  isAutoMount,
@@ -90,27 +141,78 @@ export const generateCode = async (appContext, config, entrypoints, api) => {
90
141
  if (isAutoMount) {
91
142
  // generate routes file for file system routes entrypoint.
92
143
  if (fileSystemRoutes) {
93
- const initialRoutes = getClientRoutes({
94
- entrypoint,
95
- srcDirectory,
96
- srcAlias: internalSrcAlias,
97
- internalDirectory,
98
- internalDirAlias
99
- });
144
+ let initialRoutes = [];
145
+ let nestedRoute = null;
146
+
147
+ if (entrypoint.entry) {
148
+ initialRoutes = getRoutes({
149
+ entrypoint,
150
+ srcDirectory,
151
+ srcAlias: internalSrcAlias,
152
+ internalDirectory,
153
+ internalDirAlias
154
+ });
155
+ }
156
+
157
+ if (entrypoint.nestedRoutesEntry) {
158
+ if (!islegacy) {
159
+ nestedRoute = await walk(entrypoint.nestedRoutesEntry, entrypoint.nestedRoutesEntry, {
160
+ name: internalSrcAlias,
161
+ basename: srcDirectory
162
+ });
163
+
164
+ if (nestedRoute) {
165
+ initialRoutes.unshift(nestedRoute);
166
+ }
167
+ } else {
168
+ logger.error('Nested routes is not supported in legacy mode.'); // eslint-disable-next-line no-process-exit
169
+
170
+ process.exit(1);
171
+ }
172
+ }
173
+
100
174
  const {
101
175
  routes
102
176
  } = await hookRunners.modifyFileSystemRoutes({
103
177
  entrypoint,
104
178
  routes: initialRoutes
105
179
  });
180
+ const config = useResolvedConfigContext();
181
+ const ssr = config === null || config === void 0 ? void 0 : config.server.ssr;
182
+ let mode;
183
+
184
+ if (ssr) {
185
+ mode = typeof ssr === 'object' ? ssr.mode || 'string' : 'string';
186
+ } else {
187
+ mode = false;
188
+ }
189
+
106
190
  const {
107
191
  code
108
192
  } = await hookRunners.beforeGenerateRoutes({
109
193
  entrypoint,
110
194
  code: templates.fileSystemRoutes({
111
- routes
195
+ routes,
196
+ ssrMode: mode,
197
+ nestedRoutesEntry: entrypoint.nestedRoutesEntry
112
198
  })
113
- });
199
+ }); // extract nested router loaders
200
+
201
+ if (entrypoint.nestedRoutesEntry) {
202
+ const routesServerFile = path.join(internalDirectory, entryName, 'routes.server.js');
203
+ const outputRoutesServerFile = path.join(distDirectory, 'loader-routes', entryName, 'index.js');
204
+ const code = templates.routesForServer({
205
+ routes: routes,
206
+ alias: {
207
+ name: internalSrcAlias,
208
+ basename: srcDirectory
209
+ }
210
+ });
211
+ await fs.ensureFile(routesServerFile);
212
+ await fs.writeFile(routesServerFile, code);
213
+ await buildLoader(routesServerFile, outputRoutesServerFile);
214
+ }
215
+
114
216
  fs.outputFileSync(path.resolve(internalDirectory, `./${entryName}/${FILE_SYSTEM_ROUTES_FILE_NAME}`), code, 'utf8');
115
217
  } // call modifyEntryImports hook
116
218
 
@@ -66,8 +66,9 @@ export const getBundleEntry = (appContext, config) => {
66
66
  const entriesDirAbs = ensureAbsolutePath(appDirectory, entriesDir);
67
67
  const found = defaults.find(({
68
68
  entryName,
69
- entry
70
- }) => entryName === packageName || path.dirname(entry) === entriesDirAbs);
69
+ entry,
70
+ nestedRoutesEntry: _nestedRoutesEntry = ''
71
+ }) => entryName === packageName || path.dirname(entry) === entriesDirAbs || path.dirname(_nestedRoutesEntry) === entriesDirAbs);
71
72
  found && (found.entryName = MAIN_ENTRY_NAME);
72
73
  }
73
74
 
@@ -0,0 +1,198 @@
1
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
2
+
3
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
4
+
5
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
+
7
+ import path from 'path';
8
+ import { fs } from '@modern-js/utils';
9
+ import { makeLegalIdentifier } from "../makeLegalIdentifier";
10
+ import { FILE_SYSTEM_ROUTES_COMPONENTS_DIR, FILE_SYSTEM_ROUTES_DYNAMIC_REGEXP, FILE_SYSTEM_ROUTES_INDEX, FILE_SYSTEM_ROUTES_LAYOUT } from "../constants";
11
+ import { replaceWithAlias } from "../utils";
12
+ import { debug, findLayout, shouldSkip, getRouteWeight } from "./utils";
13
+
14
+ const compName = (srcDirectory, filePath) => {
15
+ const legalCompName = makeLegalIdentifier(path.relative(srcDirectory, filePath));
16
+ return `Comp_${legalCompName}`;
17
+ };
18
+
19
+ const layoutNameAbbr = filePath => {
20
+ const prefix = 'L_';
21
+ const dirName = path.dirname(filePath).split('/').pop() || '';
22
+ return `${prefix}${makeLegalIdentifier(dirName)}`;
23
+ };
24
+
25
+ const parents = [];
26
+ /* eslint-disable no-param-reassign */
27
+
28
+ const recursiveReadDir = ({
29
+ dir,
30
+ routes,
31
+ basePath: _basePath = '/',
32
+ srcDirectory,
33
+ srcAlias
34
+ }) => {
35
+ let hasDynamicRoute = false;
36
+ let resetParent = false;
37
+ let parent = parents[parents.length - 1];
38
+ const layout = findLayout(dir);
39
+
40
+ if (layout) {
41
+ if (_basePath === '/') {
42
+ throw new Error(`should use _app instead of _layout in ${dir}`);
43
+ } else {
44
+ const alias = replaceWithAlias(srcDirectory, layout, srcAlias);
45
+ const componentName = compName(srcDirectory, layout);
46
+ const route = {
47
+ path: `${_basePath.substring(0, _basePath.length - 1)}`,
48
+ children: [],
49
+ _component: alias,
50
+ component: componentName,
51
+ parent,
52
+ type: 'page'
53
+ };
54
+ parent = route;
55
+ resetParent = true;
56
+ routes.push(route);
57
+ parents.push(route);
58
+ routes = route.children;
59
+ }
60
+ }
61
+
62
+ for (const relative of fs.readdirSync(dir)) {
63
+ const filePath = path.join(dir, relative);
64
+
65
+ if (!shouldSkip(filePath)) {
66
+ const filename = path.basename(filePath, path.extname(filePath));
67
+ const alias = replaceWithAlias(srcDirectory, filePath, srcAlias);
68
+ const componentName = compName(srcDirectory, filePath);
69
+ const dynamicRouteMatched = FILE_SYSTEM_ROUTES_DYNAMIC_REGEXP.exec(filename);
70
+
71
+ if (dynamicRouteMatched) {
72
+ if (hasDynamicRoute) {
73
+ throw new Error(`Can't set two dynamic route in one directory: ${dir}`);
74
+ } else {
75
+ hasDynamicRoute = true;
76
+ }
77
+ }
78
+
79
+ const route = {
80
+ path: `${_basePath}${dynamicRouteMatched ? `:${dynamicRouteMatched[1]}${dynamicRouteMatched[2]}` : filename}`,
81
+ _component: alias,
82
+ component: componentName,
83
+ parent,
84
+ type: 'page'
85
+ };
86
+
87
+ if (fs.statSync(filePath).isDirectory()) {
88
+ recursiveReadDir({
89
+ dir: filePath,
90
+ routes,
91
+ basePath: `${route.path}/`,
92
+ srcDirectory,
93
+ srcAlias
94
+ });
95
+ continue;
96
+ }
97
+
98
+ if (filename === FILE_SYSTEM_ROUTES_LAYOUT) {
99
+ continue;
100
+ }
101
+
102
+ if (filename === FILE_SYSTEM_ROUTES_INDEX) {
103
+ route.path = _basePath === '/' ? _basePath : `${_basePath.substring(0, _basePath.length - 1)}`;
104
+ }
105
+
106
+ if (filename === '404' && _basePath === '/') {
107
+ route.path = '*';
108
+ }
109
+
110
+ routes.push(route);
111
+ }
112
+ }
113
+
114
+ if (resetParent) {
115
+ parents.pop();
116
+ }
117
+ };
118
+ /* eslint-enable no-param-reassign */
119
+
120
+
121
+ const normalizeNestedRoutes = (nested, internalComponentsDir, internalDirectory, internalDirAlias) => {
122
+ const flat = routes => routes.reduce((memo, route) => memo.concat(Array.isArray(route.children) ? flat(route.children) : [route]), []);
123
+
124
+ const generate = route => {
125
+ const codes = [];
126
+ let lastComponent = route.component;
127
+ const imports = [`import React from 'react';`, `import ${lastComponent} from '${route._component}'`]; // eslint-disable-next-line no-param-reassign, no-cond-assign
128
+
129
+ while (route = route.parent) {
130
+ const layoutComponent = route.component;
131
+ const layoutComponentAbbr = layoutNameAbbr(route._component);
132
+ imports.push(`import ${layoutComponent} from '${route._component}';`);
133
+ const currentComponent = `${layoutComponentAbbr}_${lastComponent}`;
134
+ codes.push(`const ${currentComponent} = props => <${layoutComponent} Component={${lastComponent}} {...props} />;`);
135
+ lastComponent = currentComponent;
136
+ }
137
+
138
+ const file = path.resolve(internalComponentsDir, `${lastComponent}.jsx`);
139
+ fs.outputFileSync(file, `${imports.join('\n')}\n${codes.join('\n')}\nexport default ${lastComponent}`);
140
+ return {
141
+ component: lastComponent,
142
+ _component: replaceWithAlias(internalDirectory, file, internalDirAlias)
143
+ };
144
+ };
145
+
146
+ const normalized = flat(nested).map(route => route.parent ? _objectSpread(_objectSpread(_objectSpread({}, route), generate(route)), {}, {
147
+ parent: undefined
148
+ }) : _objectSpread(_objectSpread({}, route), {}, {
149
+ parent: undefined
150
+ }));
151
+ return normalized;
152
+ };
153
+
154
+ export const getClientRoutes = ({
155
+ entrypoint,
156
+ srcDirectory,
157
+ srcAlias,
158
+ internalDirectory,
159
+ internalDirAlias
160
+ }) => {
161
+ const {
162
+ entry,
163
+ entryName
164
+ } = entrypoint;
165
+
166
+ if (!fs.existsSync(entry)) {
167
+ throw new Error(`generate file system routes error, ${entry} directory not found.`);
168
+ }
169
+
170
+ if (!(fs.existsSync(entry) && fs.statSync(entry).isDirectory())) {
171
+ throw new Error(`generate file system routes error, ${entry} should be directory.`);
172
+ }
173
+
174
+ let routes = [];
175
+ recursiveReadDir({
176
+ dir: entry,
177
+ routes,
178
+ basePath: '/',
179
+ srcDirectory,
180
+ srcAlias
181
+ });
182
+ const internalComponentsDir = path.resolve(internalDirectory, `${entryName}/${FILE_SYSTEM_ROUTES_COMPONENTS_DIR}`);
183
+ fs.emptyDirSync(internalComponentsDir);
184
+ routes = normalizeNestedRoutes(routes, internalComponentsDir, internalDirectory, internalDirAlias);
185
+ parents.length = 0; // FIXME: support more situations
186
+
187
+ routes.sort((a, b) => {
188
+ const delta = getRouteWeight(a.path) - getRouteWeight(b.path);
189
+
190
+ if (delta === 0) {
191
+ return a.path.length - b.path.length;
192
+ }
193
+
194
+ return delta;
195
+ });
196
+ debug(`fileSystem routes: %o`, routes);
197
+ return routes;
198
+ };
@@ -5,29 +5,11 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
5
5
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
6
 
7
7
  import path from 'path';
8
- import { fs, createDebugger, findExists, normalizeToPosixPath } from '@modern-js/utils';
9
- import { makeLegalIdentifier } from "./makeLegalIdentifier";
10
- import { FILE_SYSTEM_ROUTES_COMPONENTS_DIR, FILE_SYSTEM_ROUTES_DYNAMIC_REGEXP, FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT, FILE_SYSTEM_ROUTES_IGNORED_REGEX, FILE_SYSTEM_ROUTES_INDEX, FILE_SYSTEM_ROUTES_LAYOUT, JS_EXTENSIONS } from "./constants";
11
- const debug = createDebugger('get-client-routes');
12
-
13
- const findLayout = dir => findExists(JS_EXTENSIONS.map(ext => path.resolve(dir, `${FILE_SYSTEM_ROUTES_LAYOUT}${ext}`)));
14
-
15
- const shouldSkip = file => {
16
- // should not skip directory.
17
- if (fs.statSync(file).isDirectory()) {
18
- return false;
19
- }
20
-
21
- const ext = path.extname(file);
22
-
23
- if (FILE_SYSTEM_ROUTES_IGNORED_REGEX.test(file) || !JS_EXTENSIONS.includes(ext) || FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT === path.basename(file, ext)) {
24
- return true;
25
- }
26
-
27
- return false;
28
- };
29
-
30
- const replaceWithAlias = (base, filePath, alias) => normalizeToPosixPath(path.join(alias, path.relative(base, filePath)));
8
+ import { fs } from '@modern-js/utils';
9
+ import { makeLegalIdentifier } from "../makeLegalIdentifier";
10
+ import { FILE_SYSTEM_ROUTES_COMPONENTS_DIR, FILE_SYSTEM_ROUTES_DYNAMIC_REGEXP, FILE_SYSTEM_ROUTES_INDEX, FILE_SYSTEM_ROUTES_LAYOUT } from "../constants";
11
+ import { replaceWithAlias } from "../utils";
12
+ import { debug, findLayout, shouldSkip, getRouteWeight } from "./utils";
31
13
 
32
14
  const compName = (srcDirectory, filePath) => {
33
15
  const legalCompName = makeLegalIdentifier(path.relative(srcDirectory, filePath));
@@ -43,7 +25,7 @@ const layoutNameAbbr = filePath => {
43
25
  const parents = [];
44
26
  /* eslint-disable no-param-reassign */
45
27
 
46
- const recursiveReadDir = ({
28
+ const recursiveReadDirLegacy = ({
47
29
  dir,
48
30
  routes,
49
31
  basePath: _basePath = '/',
@@ -103,7 +85,7 @@ const recursiveReadDir = ({
103
85
  };
104
86
 
105
87
  if (fs.statSync(filePath).isDirectory()) {
106
- recursiveReadDir({
88
+ recursiveReadDirLegacy({
107
89
  dir: filePath,
108
90
  routes,
109
91
  basePath: `${route.path}/`,
@@ -170,8 +152,6 @@ const normalizeNestedRoutes = (nested, internalComponentsDir, internalDirectory,
170
152
  return normalized;
171
153
  };
172
154
 
173
- const getRouteWeight = route => route === '*' ? 999 : route.split(':').length - 1;
174
-
175
155
  export const getClientRoutes = ({
176
156
  entrypoint,
177
157
  srcDirectory,
@@ -193,7 +173,7 @@ export const getClientRoutes = ({
193
173
  }
194
174
 
195
175
  let routes = [];
196
- recursiveReadDir({
176
+ recursiveReadDirLegacy({
197
177
  dir: entry,
198
178
  routes,
199
179
  basePath: '/',
@@ -0,0 +1,2 @@
1
+ export { getClientRoutes } from "./getRoutes";
2
+ export { getClientRoutes as getClientRoutesLegacy } from "./getRoutesLegacy";
@@ -0,0 +1,21 @@
1
+ import path from 'path';
2
+ import { createDebugger, findExists, fs } from '@modern-js/utils';
3
+ import { JS_EXTENSIONS, FILE_SYSTEM_ROUTES_LAYOUT, FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT, FILE_SYSTEM_ROUTES_IGNORED_REGEX } from "../constants";
4
+ const debug = createDebugger('get-client-routes');
5
+ export { debug };
6
+ export const findLayout = dir => findExists(JS_EXTENSIONS.map(ext => path.resolve(dir, `${FILE_SYSTEM_ROUTES_LAYOUT}${ext}`)));
7
+ export const getRouteWeight = route => route === '*' ? 999 : route.split(':').length - 1;
8
+ export const shouldSkip = file => {
9
+ // should not skip directory.
10
+ if (fs.statSync(file).isDirectory()) {
11
+ return false;
12
+ }
13
+
14
+ const ext = path.extname(file);
15
+
16
+ if (FILE_SYSTEM_ROUTES_IGNORED_REGEX.test(file) || !JS_EXTENSIONS.includes(ext) || FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT === path.basename(file, ext)) {
17
+ return true;
18
+ }
19
+
20
+ return false;
21
+ };