@modern-js/prod-server 1.0.6 → 1.1.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 (54) hide show
  1. package/.eslintrc.js +8 -0
  2. package/CHANGELOG.md +34 -0
  3. package/dist/js/modern/libs/loadConfig.js +54 -0
  4. package/dist/js/modern/libs/proxy.js +3 -0
  5. package/dist/js/modern/server/index.js +102 -14
  6. package/dist/js/modern/server/modern-server.js +7 -6
  7. package/dist/js/modern/utils.js +2 -0
  8. package/dist/js/node/libs/loadConfig.js +79 -0
  9. package/dist/js/node/libs/proxy.js +4 -0
  10. package/dist/js/node/server/index.js +107 -14
  11. package/dist/js/node/server/modern-server.js +6 -5
  12. package/dist/js/node/utils.js +6 -1
  13. package/dist/types/index.d.ts +1 -0
  14. package/dist/types/libs/loadConfig.d.ts +19 -0
  15. package/dist/types/server/index.d.ts +31 -0
  16. package/dist/types/type.d.ts +2 -1
  17. package/dist/types/utils.d.ts +1 -0
  18. package/package.json +19 -17
  19. package/src/index.ts +1 -0
  20. package/src/libs/loadConfig.ts +65 -0
  21. package/src/libs/proxy.ts +2 -0
  22. package/src/server/index.ts +112 -7
  23. package/src/server/modern-server.ts +4 -3
  24. package/src/type.ts +2 -1
  25. package/src/utils.ts +3 -0
  26. package/tests/.eslintrc.js +0 -6
  27. package/tests/context.test.ts +0 -52
  28. package/tests/fixtures/hosting-files/static/index.js +0 -1
  29. package/tests/fixtures/pure/modern.config.js +0 -5
  30. package/tests/fixtures/pure/package.json +0 -21
  31. package/tests/fixtures/pure/src/App.css +0 -119
  32. package/tests/fixtures/pure/src/App.tsx +0 -43
  33. package/tests/fixtures/pure/test-dist/bundles/main.js +0 -5
  34. package/tests/fixtures/pure/test-dist/html/main/index.html +0 -36
  35. package/tests/fixtures/pure/test-dist/route.json +0 -31
  36. package/tests/fixtures/pure/tsconfig.json +0 -12
  37. package/tests/fixtures/reader/index.ts +0 -3
  38. package/tests/fixtures/route-spec/dynamic.json +0 -13
  39. package/tests/fixtures/route-spec/index.json +0 -29
  40. package/tests/fixtures/ssr/bundle-error.js +0 -3
  41. package/tests/fixtures/ssr/bundle.js +0 -5
  42. package/tests/fixtures/ssr/tpl.html +0 -11
  43. package/tests/fixtures/static-dir/bar.html +0 -11
  44. package/tests/fixtures/static-dir/baz/index.html +0 -11
  45. package/tests/fixtures/static-dir/foo/index.html +0 -11
  46. package/tests/helper.ts +0 -8
  47. package/tests/hook.test.ts +0 -44
  48. package/tests/middleware.test.ts +0 -179
  49. package/tests/render.test.ts +0 -206
  50. package/tests/route.test.ts +0 -77
  51. package/tests/server.test.ts +0 -288
  52. package/tests/spr.test.ts +0 -38
  53. package/tests/tsconfig.json +0 -12
  54. package/tests/utils.test.ts +0 -106
package/.eslintrc.js ADDED
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: ['@modern-js'],
4
+ parserOptions: {
5
+ tsconfigRootDir: __dirname,
6
+ project: ['./tsconfig.json'],
7
+ },
8
+ };
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @modern-js/prod-server
2
2
 
3
+ ## 1.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 6cffe99d: chore:
8
+ remove react eslint rules for `modern-js` rule set.
9
+ add .eslintrc for each package to speed up linting
10
+ - 04ae5262: chore: bump @modern-js/utils to v1.4.1 in dependencies
11
+ - 60f7d8bf: feat: add tests dir to npmignore
12
+ - Updated dependencies [b8599d09]
13
+ - Updated dependencies [04ae5262]
14
+ - Updated dependencies [60f7d8bf]
15
+ - Updated dependencies [3bf4f8b0]
16
+ - @modern-js/utils@1.5.0
17
+ - @modern-js/server-core@1.3.1
18
+
19
+ ## 1.1.0
20
+
21
+ ### Minor Changes
22
+
23
+ - d2d1d6b2: feat: support server config
24
+
25
+ ### Patch Changes
26
+
27
+ - 17d0cc46: feat: prebundle lodash to @modern-js/utils/lodash
28
+ - Updated dependencies [77ff9754]
29
+ - Updated dependencies [d2d1d6b2]
30
+ - Updated dependencies [07a4887e]
31
+ - Updated dependencies [ea2ae711]
32
+ - Updated dependencies [17d0cc46]
33
+ - Updated dependencies [d2d1d6b2]
34
+ - @modern-js/utils@1.4.0
35
+ - @modern-js/server-core@1.3.0
36
+
3
37
  ## 1.0.6
4
38
 
5
39
  ### Patch Changes
@@ -0,0 +1,54 @@
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 * as path from 'path';
8
+ import { compatRequire, fs, DEFAULT_SERVER_CONFIG } from '@modern-js/utils';
9
+ import mergeDeep from 'merge-deep';
10
+ import { debug } from "../utils";
11
+ export const getServerConfigPath = (distDirectory, serverConfigFile = DEFAULT_SERVER_CONFIG) => {
12
+ const serverConfigPath = path.join(distDirectory, serverConfigFile);
13
+ return `${serverConfigPath}.js`;
14
+ };
15
+ export const requireConfig = serverConfigPath => {
16
+ if (fs.pathExistsSync(serverConfigPath)) {
17
+ try {
18
+ return compatRequire(serverConfigPath);
19
+ } catch (error) {
20
+ debug(error);
21
+ return {};
22
+ }
23
+ }
24
+
25
+ return {};
26
+ };
27
+ /**
28
+ * 对配置进行合并,开发环境下,cliConfig 与 serverConfig 进行深合并
29
+ * 生产环境下,resolvedConfig 与 serverConfig 进行深合并
30
+ * resolvedConfigPath: 构建序列化后的 modern.config.js 文件路径
31
+ */
32
+
33
+ export const loadConfig = ({
34
+ cliConfig,
35
+ serverConfig,
36
+ resolvedConfigPath
37
+ }) => {
38
+ let config = null;
39
+
40
+ if (process.env.NODE_ENV === 'production') {
41
+ const resolvedConfig = requireConfig(resolvedConfigPath); // cli config has a higher priority,because it's an argument passed in.
42
+
43
+ config = mergeDeep(_objectSpread(_objectSpread({}, resolvedConfig), {}, {
44
+ plugins: [] // filter cli plugins
45
+
46
+ }), serverConfig, cliConfig);
47
+ } else {
48
+ config = mergeDeep(_objectSpread(_objectSpread({}, cliConfig), {}, {
49
+ plugins: []
50
+ }), serverConfig);
51
+ }
52
+
53
+ return config;
54
+ };
@@ -1,6 +1,9 @@
1
1
  import { createProxyMiddleware } from 'http-proxy-middleware';
2
2
  import { formatProxyOptions } from '@modern-js/utils';
3
+ import { debug } from "../utils";
3
4
  export const createProxyHandler = proxyOptions => {
5
+ debug('createProxyHandler', proxyOptions);
6
+
4
7
  if (!proxyOptions) {
5
8
  return null;
6
9
  } // If it is not an array, it may be an object that uses the context attribute
@@ -6,8 +6,10 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
6
6
 
7
7
  import path from 'path';
8
8
  import { serverManager, AppContext, ConfigContext, loadPlugins } from '@modern-js/server-core';
9
- import { logger as defaultLogger, SHARED_DIR } from '@modern-js/utils';
9
+ import { logger as defaultLogger, SHARED_DIR, OUTPUT_CONFIG_FILE } from '@modern-js/utils';
10
10
  import { metrics as defaultMetrics } from "../libs/metrics";
11
+ import { loadConfig, getServerConfigPath, requireConfig } from "../libs/loadConfig";
12
+ import { debug } from "../utils";
11
13
  import { createProdServer } from "./modern-server-split";
12
14
  export class Server {
13
15
  constructor(options) {
@@ -16,25 +18,99 @@ export class Server {
16
18
  this.server = void 0;
17
19
  this.app = void 0;
18
20
  this.runner = void 0;
21
+ this.serverConfig = void 0;
19
22
  options.logger = options.logger || defaultLogger;
20
23
  options.metrics = options.metrics || defaultMetrics;
21
24
  this.options = options;
25
+ this.serverConfig = {};
22
26
  }
27
+ /**
28
+ * 初始化顺序
29
+ * - 获取 server runtime config
30
+ * - 设置 context
31
+ * - 创建 hooksRunner
32
+ * - 合并插件,内置插件和 serverConfig 中配置的插件
33
+ * - 执行 config hook
34
+ * - 获取最终的配置
35
+ * - 设置配置到 context
36
+ * - 初始化 server
37
+ * - 执行 prepare hook
38
+ * - 执行 server init
39
+ */
40
+
23
41
 
24
42
  async init() {
25
43
  const {
26
44
  options
27
- } = this; // initialize server
45
+ } = this;
46
+ this.initServerConfig(options);
47
+ await this.injectContext(this.runner, options); // initialize server runner
48
+
49
+ this.runner = await this.createHookRunner(); // init config and execute config hook
28
50
 
29
- this.server = this.serverImpl(options); // create http-server
51
+ await this.initConfig(this.runner, options);
52
+ await this.injectContext(this.runner, options); // initialize server
30
53
 
31
- this.app = await this.server.createHTTPServer(this.getRequestHandler()); // initialize server runner
54
+ this.server = this.serverImpl(options);
55
+ await this.runPrepareHook(this.runner); // create http-server
32
56
 
33
- this.runner = await this.createHookRunner(); // runner can only be used after server init
57
+ this.app = await this.server.createHTTPServer(this.getRequestHandler()); // runner can only be used after server init
34
58
 
35
59
  await this.server.onInit(this.runner);
36
60
  return this;
37
61
  }
62
+ /**
63
+ * Execute config hooks
64
+ * @param runner
65
+ * @param options
66
+ */
67
+
68
+
69
+ runConfigHook(runner, serverConfig) {
70
+ const newServerConfig = runner.config(serverConfig || {});
71
+ return newServerConfig;
72
+ }
73
+
74
+ async runPrepareHook(runner) {
75
+ runner.prepare();
76
+ }
77
+
78
+ initServerConfig(options) {
79
+ var _options$config$outpu;
80
+
81
+ const {
82
+ pwd,
83
+ serverConfigFile
84
+ } = options;
85
+ const distDirectory = path.join(pwd, ((_options$config$outpu = options.config.output) === null || _options$config$outpu === void 0 ? void 0 : _options$config$outpu.path) || 'dist');
86
+ const serverConfigPath = getServerConfigPath(distDirectory, serverConfigFile);
87
+ const serverConfig = requireConfig(serverConfigPath);
88
+ this.serverConfig = serverConfig;
89
+ }
90
+ /**
91
+ *
92
+ * merge cliConfig and serverConfig
93
+ */
94
+
95
+
96
+ async initConfig(runner, options) {
97
+ var _config$output;
98
+
99
+ const {
100
+ pwd,
101
+ config
102
+ } = options;
103
+ const {
104
+ serverConfig
105
+ } = this;
106
+ const finalServerConfig = this.runConfigHook(runner, serverConfig);
107
+ const resolvedConfigPath = path.join(pwd, (config === null || config === void 0 ? void 0 : (_config$output = config.output) === null || _config$output === void 0 ? void 0 : _config$output.path) || 'dist', OUTPUT_CONFIG_FILE);
108
+ options.config = loadConfig({
109
+ cliConfig: config,
110
+ serverConfig: finalServerConfig,
111
+ resolvedConfigPath
112
+ });
113
+ }
38
114
 
39
115
  async close() {
40
116
  await this.server.onClose();
@@ -65,31 +141,43 @@ export class Server {
65
141
  serverManager.clear();
66
142
  const {
67
143
  options
68
- } = this;
144
+ } = this; // TODO: 确认下这里是不是可以不从 options 中取插件,而是从 config 中取和过滤
145
+
69
146
  const {
70
147
  plugins = [],
71
148
  pwd,
72
149
  config
73
- } = options; // server app context for serve plugin
150
+ } = options;
151
+ const serverPlugins = this.serverConfig.plugins || []; // server app context for serve plugin
74
152
 
75
- const loadedPlugins = loadPlugins(plugins, pwd);
153
+ const loadedPlugins = loadPlugins(plugins.concat(serverPlugins), pwd);
154
+ debug('plugins', config.plugins, loadedPlugins);
76
155
  loadedPlugins.forEach(p => {
77
156
  serverManager.usePlugin(p);
78
- });
157
+ }); // create runner
158
+
159
+ const hooksRunner = await serverManager.init({});
160
+ return hooksRunner;
161
+ }
162
+
163
+ async injectContext(runner, options) {
79
164
  const appContext = this.initAppContext();
165
+ const {
166
+ config,
167
+ pwd
168
+ } = options;
80
169
  serverManager.run(() => {
81
- var _config$output;
170
+ var _config$output2;
82
171
 
83
172
  ConfigContext.set(config);
84
173
  AppContext.set(_objectSpread(_objectSpread({}, appContext), {}, {
85
- distDirectory: path.join(pwd, ((_config$output = config.output) === null || _config$output === void 0 ? void 0 : _config$output.path) || 'dist')
174
+ distDirectory: path.join(pwd, ((_config$output2 = config.output) === null || _config$output2 === void 0 ? void 0 : _config$output2.path) || 'dist')
86
175
  }));
87
176
  });
88
- return serverManager.init({});
89
177
  }
90
178
 
91
179
  initAppContext() {
92
- var _config$output2;
180
+ var _config$output3;
93
181
 
94
182
  const {
95
183
  options
@@ -104,7 +192,7 @@ export class Server {
104
192
  }));
105
193
  return {
106
194
  appDirectory,
107
- distDirectory: path.join(appDirectory, ((_config$output2 = config.output) === null || _config$output2 === void 0 ? void 0 : _config$output2.path) || 'dist'),
195
+ distDirectory: path.join(appDirectory, ((_config$output3 = config.output) === null || _config$output3 === void 0 ? void 0 : _config$output3.path) || 'dist'),
108
196
  sharedDirectory: path.resolve(appDirectory, SHARED_DIR),
109
197
  plugins: serverPlugins
110
198
  };
@@ -21,7 +21,7 @@ import clone from 'lodash.clone';
21
21
  import { RouteMatchManager } from "../libs/route";
22
22
  import { createRenderHandler } from "../libs/render";
23
23
  import { createStaticFileHandler } from "../libs/serve-file";
24
- import { createErrorDocument, createMiddlewareCollecter, getStaticReg, mergeExtension, noop } from "../utils";
24
+ import { createErrorDocument, createMiddlewareCollecter, getStaticReg, mergeExtension, noop, debug } from "../utils";
25
25
  import * as reader from "../libs/render/reader";
26
26
  import { createProxyHandler } from "../libs/proxy";
27
27
  import { createContext } from "../libs/context";
@@ -73,6 +73,7 @@ export class ModernServer {
73
73
  this.distDir = path.join(pwd, ((_config$output = config.output) === null || _config$output === void 0 ? void 0 : _config$output.path) || 'dist');
74
74
  this.workDir = this.distDir;
75
75
  this.conf = config;
76
+ debug('server conf', this.conf);
76
77
  this.logger = logger;
77
78
  this.metrics = metrics;
78
79
  this.router = new RouteMatchManager();
@@ -98,7 +99,8 @@ export class ModernServer {
98
99
  ctx.res.setHeader('Access-Control-Allow-Origin', '*');
99
100
  ctx.res.setHeader('Access-Control-Allow-Credentials', 'false');
100
101
  next();
101
- }); // proxy handler, each proxy has own handler
102
+ });
103
+ debug('final server conf', this.conf); // proxy handler, each proxy has own handler
102
104
 
103
105
  this.proxyHandler = createProxyHandler((_conf$bff = conf.bff) === null || _conf$bff === void 0 ? void 0 : _conf$bff.proxy);
104
106
 
@@ -223,7 +225,8 @@ export class ModernServer {
223
225
  }
224
226
 
225
227
  if (fs.existsSync(apiDir)) {
226
- const mode = fs.existsSync(path.join(apiDir, AGGRED_DIR.lambda)) ? ApiServerMode.frame : ApiServerMode.func; // if use lambda/, mean framework style of writing, then discard user extension
228
+ const mode = fs.existsSync(path.join(apiDir, AGGRED_DIR.lambda)) ? ApiServerMode.frame : ApiServerMode.func;
229
+ debug('exists api dir', mode); // if use lambda/, mean framework style of writing, then discard user extension
227
230
 
228
231
  const apiExtension = mergeExtension(pluginAPIExt);
229
232
  this.frameAPIHandler = await this.prepareAPIHandler(mode, apiExtension);
@@ -324,7 +327,6 @@ export class ModernServer {
324
327
  }
325
328
  /* —————————————————————— private function —————————————————————— */
326
329
  // handler route.json, include api / csr / ssr
327
- // eslint-disable-next-line max-statements
328
330
 
329
331
 
330
332
  async routeHandler(context) {
@@ -416,8 +418,7 @@ export class ModernServer {
416
418
 
417
419
  res.setHeader('content-type', file.contentType);
418
420
  res.end(response);
419
- } // eslint-disable-next-line max-statements
420
-
421
+ }
421
422
 
422
423
  async injectMicroFE(context, templateAPI) {
423
424
  var _conf$runtime, _conf$server;
@@ -1,4 +1,6 @@
1
1
  import { compile } from 'path-to-regexp';
2
+ import { createDebugger } from '@modern-js/utils';
3
+ export const debug = createDebugger('prod-server');
2
4
  export const mergeExtension = users => {
3
5
  const output = [];
4
6
  return {
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.requireConfig = exports.loadConfig = exports.getServerConfigPath = void 0;
7
+
8
+ var path = _interopRequireWildcard(require("path"));
9
+
10
+ var _utils = require("@modern-js/utils");
11
+
12
+ var _mergeDeep = _interopRequireDefault(require("merge-deep"));
13
+
14
+ var _utils2 = require("../utils");
15
+
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+
18
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
+
20
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
21
+
22
+ 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; }
23
+
24
+ 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; }
25
+
26
+ 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; }
27
+
28
+ const getServerConfigPath = (distDirectory, serverConfigFile = _utils.DEFAULT_SERVER_CONFIG) => {
29
+ const serverConfigPath = path.join(distDirectory, serverConfigFile);
30
+ return `${serverConfigPath}.js`;
31
+ };
32
+
33
+ exports.getServerConfigPath = getServerConfigPath;
34
+
35
+ const requireConfig = serverConfigPath => {
36
+ if (_utils.fs.pathExistsSync(serverConfigPath)) {
37
+ try {
38
+ return (0, _utils.compatRequire)(serverConfigPath);
39
+ } catch (error) {
40
+ (0, _utils2.debug)(error);
41
+ return {};
42
+ }
43
+ }
44
+
45
+ return {};
46
+ };
47
+ /**
48
+ * 对配置进行合并,开发环境下,cliConfig 与 serverConfig 进行深合并
49
+ * 生产环境下,resolvedConfig 与 serverConfig 进行深合并
50
+ * resolvedConfigPath: 构建序列化后的 modern.config.js 文件路径
51
+ */
52
+
53
+
54
+ exports.requireConfig = requireConfig;
55
+
56
+ const loadConfig = ({
57
+ cliConfig,
58
+ serverConfig,
59
+ resolvedConfigPath
60
+ }) => {
61
+ let config = null;
62
+
63
+ if (process.env.NODE_ENV === 'production') {
64
+ const resolvedConfig = requireConfig(resolvedConfigPath); // cli config has a higher priority,because it's an argument passed in.
65
+
66
+ config = (0, _mergeDeep.default)(_objectSpread(_objectSpread({}, resolvedConfig), {}, {
67
+ plugins: [] // filter cli plugins
68
+
69
+ }), serverConfig, cliConfig);
70
+ } else {
71
+ config = (0, _mergeDeep.default)(_objectSpread(_objectSpread({}, cliConfig), {}, {
72
+ plugins: []
73
+ }), serverConfig);
74
+ }
75
+
76
+ return config;
77
+ };
78
+
79
+ exports.loadConfig = loadConfig;
@@ -9,7 +9,11 @@ var _httpProxyMiddleware = require("http-proxy-middleware");
9
9
 
10
10
  var _utils = require("@modern-js/utils");
11
11
 
12
+ var _utils2 = require("../utils");
13
+
12
14
  const createProxyHandler = proxyOptions => {
15
+ (0, _utils2.debug)('createProxyHandler', proxyOptions);
16
+
13
17
  if (!proxyOptions) {
14
18
  return null;
15
19
  } // If it is not an array, it may be an object that uses the context attribute
@@ -13,6 +13,10 @@ var _utils = require("@modern-js/utils");
13
13
 
14
14
  var _metrics = require("../libs/metrics");
15
15
 
16
+ var _loadConfig = require("../libs/loadConfig");
17
+
18
+ var _utils2 = require("../utils");
19
+
16
20
  var _modernServerSplit = require("./modern-server-split");
17
21
 
18
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -30,25 +34,103 @@ class Server {
30
34
  this.server = void 0;
31
35
  this.app = void 0;
32
36
  this.runner = void 0;
37
+ this.serverConfig = void 0;
33
38
  options.logger = options.logger || _utils.logger;
34
39
  options.metrics = options.metrics || _metrics.metrics;
35
40
  this.options = options;
41
+ this.serverConfig = {};
36
42
  }
43
+ /**
44
+ * 初始化顺序
45
+ * - 获取 server runtime config
46
+ * - 设置 context
47
+ * - 创建 hooksRunner
48
+ * - 合并插件,内置插件和 serverConfig 中配置的插件
49
+ * - 执行 config hook
50
+ * - 获取最终的配置
51
+ * - 设置配置到 context
52
+ * - 初始化 server
53
+ * - 执行 prepare hook
54
+ * - 执行 server init
55
+ */
56
+
37
57
 
38
58
  async init() {
39
59
  const {
40
60
  options
41
- } = this; // initialize server
61
+ } = this;
62
+ this.initServerConfig(options);
63
+ await this.injectContext(this.runner, options); // initialize server runner
64
+
65
+ this.runner = await this.createHookRunner(); // init config and execute config hook
42
66
 
43
- this.server = this.serverImpl(options); // create http-server
67
+ await this.initConfig(this.runner, options);
68
+ await this.injectContext(this.runner, options); // initialize server
44
69
 
45
- this.app = await this.server.createHTTPServer(this.getRequestHandler()); // initialize server runner
70
+ this.server = this.serverImpl(options);
71
+ await this.runPrepareHook(this.runner); // create http-server
46
72
 
47
- this.runner = await this.createHookRunner(); // runner can only be used after server init
73
+ this.app = await this.server.createHTTPServer(this.getRequestHandler()); // runner can only be used after server init
48
74
 
49
75
  await this.server.onInit(this.runner);
50
76
  return this;
51
77
  }
78
+ /**
79
+ * Execute config hooks
80
+ * @param runner
81
+ * @param options
82
+ */
83
+
84
+
85
+ runConfigHook(runner, serverConfig) {
86
+ const newServerConfig = runner.config(serverConfig || {});
87
+ return newServerConfig;
88
+ }
89
+
90
+ async runPrepareHook(runner) {
91
+ runner.prepare();
92
+ }
93
+
94
+ initServerConfig(options) {
95
+ var _options$config$outpu;
96
+
97
+ const {
98
+ pwd,
99
+ serverConfigFile
100
+ } = options;
101
+
102
+ const distDirectory = _path.default.join(pwd, ((_options$config$outpu = options.config.output) === null || _options$config$outpu === void 0 ? void 0 : _options$config$outpu.path) || 'dist');
103
+
104
+ const serverConfigPath = (0, _loadConfig.getServerConfigPath)(distDirectory, serverConfigFile);
105
+ const serverConfig = (0, _loadConfig.requireConfig)(serverConfigPath);
106
+ this.serverConfig = serverConfig;
107
+ }
108
+ /**
109
+ *
110
+ * merge cliConfig and serverConfig
111
+ */
112
+
113
+
114
+ async initConfig(runner, options) {
115
+ var _config$output;
116
+
117
+ const {
118
+ pwd,
119
+ config
120
+ } = options;
121
+ const {
122
+ serverConfig
123
+ } = this;
124
+ const finalServerConfig = this.runConfigHook(runner, serverConfig);
125
+
126
+ const resolvedConfigPath = _path.default.join(pwd, (config === null || config === void 0 ? void 0 : (_config$output = config.output) === null || _config$output === void 0 ? void 0 : _config$output.path) || 'dist', _utils.OUTPUT_CONFIG_FILE);
127
+
128
+ options.config = (0, _loadConfig.loadConfig)({
129
+ cliConfig: config,
130
+ serverConfig: finalServerConfig,
131
+ resolvedConfigPath
132
+ });
133
+ }
52
134
 
53
135
  async close() {
54
136
  await this.server.onClose();
@@ -80,34 +162,45 @@ class Server {
80
162
 
81
163
  const {
82
164
  options
83
- } = this;
165
+ } = this; // TODO: 确认下这里是不是可以不从 options 中取插件,而是从 config 中取和过滤
166
+
84
167
  const {
85
168
  plugins = [],
86
169
  pwd,
87
170
  config
88
- } = options; // server app context for serve plugin
171
+ } = options;
172
+ const serverPlugins = this.serverConfig.plugins || []; // server app context for serve plugin
89
173
 
90
- const loadedPlugins = (0, _serverCore.loadPlugins)(plugins, pwd);
174
+ const loadedPlugins = (0, _serverCore.loadPlugins)(plugins.concat(serverPlugins), pwd);
175
+ (0, _utils2.debug)('plugins', config.plugins, loadedPlugins);
91
176
  loadedPlugins.forEach(p => {
92
177
  _serverCore.serverManager.usePlugin(p);
93
- });
178
+ }); // create runner
179
+
180
+ const hooksRunner = await _serverCore.serverManager.init({});
181
+ return hooksRunner;
182
+ }
183
+
184
+ async injectContext(runner, options) {
94
185
  const appContext = this.initAppContext();
186
+ const {
187
+ config,
188
+ pwd
189
+ } = options;
95
190
 
96
191
  _serverCore.serverManager.run(() => {
97
- var _config$output;
192
+ var _config$output2;
98
193
 
99
194
  _serverCore.ConfigContext.set(config);
100
195
 
101
196
  _serverCore.AppContext.set(_objectSpread(_objectSpread({}, appContext), {}, {
102
- distDirectory: _path.default.join(pwd, ((_config$output = config.output) === null || _config$output === void 0 ? void 0 : _config$output.path) || 'dist')
197
+ distDirectory: _path.default.join(pwd, ((_config$output2 = config.output) === null || _config$output2 === void 0 ? void 0 : _config$output2.path) || 'dist')
103
198
  }));
104
199
  });
105
-
106
- return _serverCore.serverManager.init({});
107
200
  }
108
201
 
109
202
  initAppContext() {
110
- var _config$output2;
203
+ var _config$output3;
111
204
 
112
205
  const {
113
206
  options
@@ -122,7 +215,7 @@ class Server {
122
215
  }));
123
216
  return {
124
217
  appDirectory,
125
- distDirectory: _path.default.join(appDirectory, ((_config$output2 = config.output) === null || _config$output2 === void 0 ? void 0 : _config$output2.path) || 'dist'),
218
+ distDirectory: _path.default.join(appDirectory, ((_config$output3 = config.output) === null || _config$output3 === void 0 ? void 0 : _config$output3.path) || 'dist'),
126
219
  sharedDirectory: _path.default.resolve(appDirectory, _utils.SHARED_DIR),
127
220
  plugins: serverPlugins
128
221
  };
@@ -103,6 +103,7 @@ class ModernServer {
103
103
  this.distDir = _path.default.join(pwd, ((_config$output = config.output) === null || _config$output === void 0 ? void 0 : _config$output.path) || 'dist');
104
104
  this.workDir = this.distDir;
105
105
  this.conf = config;
106
+ (0, _utils2.debug)('server conf', this.conf);
106
107
  this.logger = logger;
107
108
  this.metrics = metrics;
108
109
  this.router = new _route.RouteMatchManager();
@@ -128,7 +129,8 @@ class ModernServer {
128
129
  ctx.res.setHeader('Access-Control-Allow-Origin', '*');
129
130
  ctx.res.setHeader('Access-Control-Allow-Credentials', 'false');
130
131
  next();
131
- }); // proxy handler, each proxy has own handler
132
+ });
133
+ (0, _utils2.debug)('final server conf', this.conf); // proxy handler, each proxy has own handler
132
134
 
133
135
  this.proxyHandler = (0, _proxy.createProxyHandler)((_conf$bff = conf.bff) === null || _conf$bff === void 0 ? void 0 : _conf$bff.proxy);
134
136
 
@@ -257,7 +259,8 @@ class ModernServer {
257
259
  }
258
260
 
259
261
  if (_utils.fs.existsSync(apiDir)) {
260
- const mode = _utils.fs.existsSync(_path.default.join(apiDir, _constants.AGGRED_DIR.lambda)) ? _constants.ApiServerMode.frame : _constants.ApiServerMode.func; // if use lambda/, mean framework style of writing, then discard user extension
262
+ const mode = _utils.fs.existsSync(_path.default.join(apiDir, _constants.AGGRED_DIR.lambda)) ? _constants.ApiServerMode.frame : _constants.ApiServerMode.func;
263
+ (0, _utils2.debug)('exists api dir', mode); // if use lambda/, mean framework style of writing, then discard user extension
261
264
 
262
265
  const apiExtension = (0, _utils2.mergeExtension)(pluginAPIExt);
263
266
  this.frameAPIHandler = await this.prepareAPIHandler(mode, apiExtension);
@@ -359,7 +362,6 @@ class ModernServer {
359
362
  }
360
363
  /* —————————————————————— private function —————————————————————— */
361
364
  // handler route.json, include api / csr / ssr
362
- // eslint-disable-next-line max-statements
363
365
 
364
366
 
365
367
  async routeHandler(context) {
@@ -451,8 +453,7 @@ class ModernServer {
451
453
 
452
454
  res.setHeader('content-type', file.contentType);
453
455
  res.end(response);
454
- } // eslint-disable-next-line max-statements
455
-
456
+ }
456
457
 
457
458
  async injectMicroFE(context, templateAPI) {
458
459
  var _conf$runtime, _conf$server;