@modern-js/prod-server 1.0.2 → 1.0.4

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @modern-js/prod-server
2
2
 
3
+ ## 1.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - d95f28c3: should enable babel register before server plugin require
8
+ - d95f28c3: remove server hook when api only
9
+ - 0923c182: fix static handler when static file not exist
10
+ - 2008fdbd: convert two packages server part, support server load plugin itself
11
+ - ca0bcf13: publish prod-server local
12
+ - Updated dependencies [5bf5868d]
13
+ - Updated dependencies [d95f28c3]
14
+ - Updated dependencies [2e8dec93]
15
+ - Updated dependencies [2008fdbd]
16
+ - Updated dependencies [2e8dec93]
17
+ - @modern-js/utils@1.3.5
18
+ - @modern-js/server-core@1.2.3
19
+
3
20
  ## 1.0.2
4
21
 
5
22
  ### Patch Changes
@@ -5,9 +5,8 @@ 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 { serverManager, AppContext, ConfigContext } from '@modern-js/server-core';
9
- import { compatRequire, logger as defaultLogger } from '@modern-js/utils';
10
- import { initAppContext } from '@modern-js/core';
8
+ import { serverManager, AppContext, ConfigContext, loadPlugins } from '@modern-js/server-core';
9
+ import { logger as defaultLogger, SHARED_DIR } from '@modern-js/utils';
11
10
  import { metrics as defaultMetrics } from "../libs/metrics";
12
11
  import { createProdServer } from "./modern-server-split";
13
12
  export class Server {
@@ -25,13 +24,13 @@ export class Server {
25
24
  async init() {
26
25
  const {
27
26
  options
28
- } = this; // initialize server runner
29
-
30
- this.runner = await this.createHookRunner(); // initialize server
27
+ } = this; // initialize server
31
28
 
32
29
  this.server = this.serverImpl(options); // create http-server
33
30
 
34
- this.app = await this.server.createHTTPServer(this.getRequestHandler()); // runner can only be used after server init
31
+ this.app = await this.server.createHTTPServer(this.getRequestHandler()); // initialize server runner
32
+
33
+ this.runner = await this.createHookRunner(); // runner can only be used after server init
35
34
 
36
35
  await this.server.onInit(this.runner);
37
36
  return this;
@@ -68,26 +67,47 @@ export class Server {
68
67
  options
69
68
  } = this;
70
69
  const {
71
- pwd: appDirectory,
72
- plugins = []
70
+ plugins = [],
71
+ pwd,
72
+ config
73
73
  } = options; // server app context for serve plugin
74
74
 
75
- const serverPlugins = plugins.map(p => {
76
- serverManager.usePlugin(compatRequire(p.pluginPath));
77
- return {
78
- server: p
79
- };
75
+ const loadedPlugins = loadPlugins(plugins, pwd);
76
+ loadedPlugins.forEach(p => {
77
+ serverManager.usePlugin(p);
80
78
  });
81
- const appContext = initAppContext(appDirectory, serverPlugins, '');
79
+ const appContext = this.initAppContext();
82
80
  serverManager.run(() => {
83
- var _options$config$outpu;
81
+ var _config$output;
84
82
 
85
- ConfigContext.set(this.options.config);
83
+ ConfigContext.set(config);
86
84
  AppContext.set(_objectSpread(_objectSpread({}, appContext), {}, {
87
- distDirectory: path.join(options.pwd, ((_options$config$outpu = options.config.output) === null || _options$config$outpu === void 0 ? void 0 : _options$config$outpu.path) || 'dist')
85
+ distDirectory: path.join(pwd, ((_config$output = config.output) === null || _config$output === void 0 ? void 0 : _config$output.path) || 'dist')
88
86
  }));
89
87
  });
90
88
  return serverManager.init({});
91
89
  }
92
90
 
91
+ initAppContext() {
92
+ var _config$output2;
93
+
94
+ const {
95
+ options
96
+ } = this;
97
+ const {
98
+ pwd: appDirectory,
99
+ plugins = [],
100
+ config
101
+ } = options;
102
+ const serverPlugins = plugins.map(p => ({
103
+ server: p
104
+ }));
105
+ return {
106
+ appDirectory,
107
+ distDirectory: path.join(appDirectory, ((_config$output2 = config.output) === null || _config$output2 === void 0 ? void 0 : _config$output2.path) || 'dist'),
108
+ sharedDirectory: path.resolve(appDirectory, SHARED_DIR),
109
+ plugins: serverPlugins
110
+ };
111
+ }
112
+
93
113
  }
@@ -576,7 +576,7 @@ export class ModernServer {
576
576
  }
577
577
 
578
578
  const text = ERROR_PAGE_TEXT[status] || ERROR_PAGE_TEXT[500];
579
- res.end(createErrorDocument(status, text));
579
+ context.res.end(createErrorDocument(status, text));
580
580
  }
581
581
 
582
582
  }
@@ -88,7 +88,7 @@ export const getStaticReg = (output = {}) => {
88
88
  } = output;
89
89
  const favicons = prepareFavicons(favicon, faviconByEntries);
90
90
  const staticFiles = [cssPath, jsPath, mediaPath].filter(v => Boolean(v));
91
- const staticPathRegExp = new RegExp(`^/(static/|upload/|favicon.ico|icon.png${favicons.length > 0 ? `|${favicons.join('|')}` : ''}|${staticFiles.join('|')})`);
91
+ const staticPathRegExp = new RegExp(`^/(static/|upload/|favicon.ico|icon.png${favicons.length > 0 ? `|${favicons.join('|')}` : ''}${staticFiles.length > 0 ? `|${staticFiles.join('|')}` : ''})`);
92
92
  return staticPathRegExp;
93
93
  };
94
94
  export const prepareFavicons = (favicon, faviconByEntries) => {
@@ -11,8 +11,6 @@ var _serverCore = require("@modern-js/server-core");
11
11
 
12
12
  var _utils = require("@modern-js/utils");
13
13
 
14
- var _core = require("@modern-js/core");
15
-
16
14
  var _metrics = require("../libs/metrics");
17
15
 
18
16
  var _modernServerSplit = require("./modern-server-split");
@@ -40,13 +38,13 @@ class Server {
40
38
  async init() {
41
39
  const {
42
40
  options
43
- } = this; // initialize server runner
44
-
45
- this.runner = await this.createHookRunner(); // initialize server
41
+ } = this; // initialize server
46
42
 
47
43
  this.server = this.serverImpl(options); // create http-server
48
44
 
49
- this.app = await this.server.createHTTPServer(this.getRequestHandler()); // runner can only be used after server init
45
+ this.app = await this.server.createHTTPServer(this.getRequestHandler()); // initialize server runner
46
+
47
+ this.runner = await this.createHookRunner(); // runner can only be used after server init
50
48
 
51
49
  await this.server.onInit(this.runner);
52
50
  return this;
@@ -84,32 +82,52 @@ class Server {
84
82
  options
85
83
  } = this;
86
84
  const {
87
- pwd: appDirectory,
88
- plugins = []
85
+ plugins = [],
86
+ pwd,
87
+ config
89
88
  } = options; // server app context for serve plugin
90
89
 
91
- const serverPlugins = plugins.map(p => {
92
- _serverCore.serverManager.usePlugin((0, _utils.compatRequire)(p.pluginPath));
93
-
94
- return {
95
- server: p
96
- };
90
+ const loadedPlugins = (0, _serverCore.loadPlugins)(plugins, pwd);
91
+ loadedPlugins.forEach(p => {
92
+ _serverCore.serverManager.usePlugin(p);
97
93
  });
98
- const appContext = (0, _core.initAppContext)(appDirectory, serverPlugins, '');
94
+ const appContext = this.initAppContext();
99
95
 
100
96
  _serverCore.serverManager.run(() => {
101
- var _options$config$outpu;
97
+ var _config$output;
102
98
 
103
- _serverCore.ConfigContext.set(this.options.config);
99
+ _serverCore.ConfigContext.set(config);
104
100
 
105
101
  _serverCore.AppContext.set(_objectSpread(_objectSpread({}, appContext), {}, {
106
- distDirectory: _path.default.join(options.pwd, ((_options$config$outpu = options.config.output) === null || _options$config$outpu === void 0 ? void 0 : _options$config$outpu.path) || 'dist')
102
+ distDirectory: _path.default.join(pwd, ((_config$output = config.output) === null || _config$output === void 0 ? void 0 : _config$output.path) || 'dist')
107
103
  }));
108
104
  });
109
105
 
110
106
  return _serverCore.serverManager.init({});
111
107
  }
112
108
 
109
+ initAppContext() {
110
+ var _config$output2;
111
+
112
+ const {
113
+ options
114
+ } = this;
115
+ const {
116
+ pwd: appDirectory,
117
+ plugins = [],
118
+ config
119
+ } = options;
120
+ const serverPlugins = plugins.map(p => ({
121
+ server: p
122
+ }));
123
+ return {
124
+ appDirectory,
125
+ distDirectory: _path.default.join(appDirectory, ((_config$output2 = config.output) === null || _config$output2 === void 0 ? void 0 : _config$output2.path) || 'dist'),
126
+ sharedDirectory: _path.default.resolve(appDirectory, _utils.SHARED_DIR),
127
+ plugins: serverPlugins
128
+ };
129
+ }
130
+
113
131
  }
114
132
 
115
133
  exports.Server = Server;
@@ -611,7 +611,7 @@ class ModernServer {
611
611
  }
612
612
 
613
613
  const text = _constants.ERROR_PAGE_TEXT[status] || _constants.ERROR_PAGE_TEXT[500];
614
- res.end((0, _utils2.createErrorDocument)(status, text));
614
+ context.res.end((0, _utils2.createErrorDocument)(status, text));
615
615
  }
616
616
 
617
617
  }
@@ -114,7 +114,7 @@ const getStaticReg = (output = {}) => {
114
114
  } = output;
115
115
  const favicons = prepareFavicons(favicon, faviconByEntries);
116
116
  const staticFiles = [cssPath, jsPath, mediaPath].filter(v => Boolean(v));
117
- const staticPathRegExp = new RegExp(`^/(static/|upload/|favicon.ico|icon.png${favicons.length > 0 ? `|${favicons.join('|')}` : ''}|${staticFiles.join('|')})`);
117
+ const staticPathRegExp = new RegExp(`^/(static/|upload/|favicon.ico|icon.png${favicons.length > 0 ? `|${favicons.join('|')}` : ''}${staticFiles.length > 0 ? `|${staticFiles.join('|')}` : ''})`);
118
118
  return staticPathRegExp;
119
119
  };
120
120
 
@@ -12,4 +12,5 @@ export declare class Server {
12
12
  listen(port: number | undefined, listener: any): void;
13
13
  getRequestHandler(): (req: IncomingMessage, res: ServerResponse, next?: (() => void) | undefined) => void;
14
14
  private createHookRunner;
15
+ private initAppContext;
15
16
  }
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { IncomingMessage, Server, ServerResponse } from 'http';
3
- import { serverManager } from '@modern-js/server-core';
3
+ import { serverManager, ServerPlugin } from '@modern-js/server-core';
4
4
  import type { NormalizedConfig } from '@modern-js/core';
5
5
  import type { Metrics, Logger, NextFunction } from '@modern-js/types/server';
6
6
  import { ModernRouteInterface } from './libs/route';
@@ -17,12 +17,11 @@ declare module '@modern-js/core' {
17
17
  };
18
18
  }
19
19
  }
20
+ declare type Plugin = string | [string, any] | ServerPlugin;
20
21
  export declare type ModernServerOptions = {
21
22
  pwd: string;
22
23
  config: NormalizedConfig;
23
- plugins?: {
24
- pluginPath: string;
25
- }[];
24
+ plugins?: Plugin[];
26
25
  routes?: ModernRouteInterface[];
27
26
  staticGenerate?: boolean;
28
27
  loggerOptions?: Record<string, string>;
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "1.0.2",
14
+ "version": "1.0.4",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -28,10 +28,9 @@
28
28
  }
29
29
  },
30
30
  "dependencies": {
31
- "@modern-js/core": "^1.4.6",
32
- "@modern-js/utils": "^1.3.4",
31
+ "@modern-js/utils": "^1.3.5",
33
32
  "@babel/compat-data": "^7.17.0",
34
- "@modern-js/server-core": "^1.2.2",
33
+ "@modern-js/server-core": "^1.2.3",
35
34
  "axios": "^0.24.0",
36
35
  "compare-versions": "^3.6.0",
37
36
  "http-proxy-middleware": "^2.0.1",
@@ -45,7 +44,8 @@
45
44
  "cookie": "^0.4.2"
46
45
  },
47
46
  "devDependencies": {
48
- "@modern-js/types": "^1.3.4",
47
+ "@modern-js/types": "^1.3.5",
48
+ "@modern-js/core": "^1.5.0",
49
49
  "@scripts/jest-config": "0.0.0",
50
50
  "@scripts/build": "0.0.0",
51
51
  "del-cli": "^4.0.1",
@@ -4,9 +4,11 @@ import {
4
4
  serverManager,
5
5
  AppContext,
6
6
  ConfigContext,
7
+ loadPlugins,
7
8
  } from '@modern-js/server-core';
8
- import { compatRequire, logger as defaultLogger } from '@modern-js/utils';
9
- import { initAppContext, UserConfig } from '@modern-js/core';
9
+ import { logger as defaultLogger, SHARED_DIR } from '@modern-js/utils';
10
+ import type { UserConfig } from '@modern-js/core';
11
+ import { ISAppContext } from '@modern-js/types';
10
12
  import {
11
13
  ModernServerOptions,
12
14
  ServerHookRunner,
@@ -37,15 +39,15 @@ export class Server {
37
39
  public async init() {
38
40
  const { options } = this;
39
41
 
40
- // initialize server runner
41
- this.runner = await this.createHookRunner();
42
-
43
42
  // initialize server
44
43
  this.server = this.serverImpl(options);
45
44
 
46
45
  // create http-server
47
46
  this.app = await this.server.createHTTPServer(this.getRequestHandler());
48
47
 
48
+ // initialize server runner
49
+ this.runner = await this.createHookRunner();
50
+
49
51
  // runner can only be used after server init
50
52
  await this.server.onInit(this.runner);
51
53
 
@@ -83,27 +85,38 @@ export class Server {
83
85
  serverManager.clear();
84
86
 
85
87
  const { options } = this;
86
- const { pwd: appDirectory, plugins = [] } = options;
88
+ const { plugins = [], pwd, config } = options;
87
89
 
88
90
  // server app context for serve plugin
89
- const serverPlugins = plugins.map(p => {
90
- serverManager.usePlugin(compatRequire(p.pluginPath));
91
- return {
92
- server: p,
93
- };
91
+ const loadedPlugins = loadPlugins(plugins, pwd);
92
+ loadedPlugins.forEach(p => {
93
+ serverManager.usePlugin(p);
94
94
  });
95
- const appContext = initAppContext(appDirectory, serverPlugins, '');
95
+
96
+ const appContext = this.initAppContext();
96
97
  serverManager.run(() => {
97
- ConfigContext.set(this.options.config as UserConfig);
98
+ ConfigContext.set(config as UserConfig);
98
99
  AppContext.set({
99
100
  ...appContext,
100
- distDirectory: path.join(
101
- options.pwd,
102
- options.config.output?.path || 'dist',
103
- ),
101
+ distDirectory: path.join(pwd, config.output?.path || 'dist'),
104
102
  });
105
103
  });
106
104
 
107
105
  return serverManager.init({});
108
106
  }
107
+
108
+ private initAppContext(): ISAppContext {
109
+ const { options } = this;
110
+ const { pwd: appDirectory, plugins = [], config } = options;
111
+ const serverPlugins = plugins.map(p => ({
112
+ server: p,
113
+ }));
114
+
115
+ return {
116
+ appDirectory,
117
+ distDirectory: path.join(appDirectory, config.output?.path || 'dist'),
118
+ sharedDirectory: path.resolve(appDirectory, SHARED_DIR),
119
+ plugins: serverPlugins,
120
+ };
121
+ }
109
122
  }
@@ -593,6 +593,7 @@ export class ModernServer implements ModernServerInterface {
593
593
  const matched =
594
594
  this.router.match(statusPage) || this.router.match(customErrorPage);
595
595
  // if no custom status page find
596
+
596
597
  if (matched) {
597
598
  const route = matched.generate(context.url);
598
599
  const { entryName } = route;
@@ -613,9 +614,8 @@ export class ModernServer implements ModernServerInterface {
613
614
  }
614
615
  }
615
616
  }
616
-
617
617
  const text = ERROR_PAGE_TEXT[status] || ERROR_PAGE_TEXT[500];
618
- res.end(createErrorDocument(status, text));
618
+ context.res.end(createErrorDocument(status, text));
619
619
  }
620
620
  }
621
621
  /* eslint-enable max-lines */
package/src/type.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Buffer } from 'buffer';
2
2
  import { IncomingMessage, Server, ServerResponse } from 'http';
3
- import { serverManager } from '@modern-js/server-core';
3
+ import { serverManager, ServerPlugin } from '@modern-js/server-core';
4
4
  import type { NormalizedConfig } from '@modern-js/core';
5
5
  import type { Metrics, Logger, NextFunction } from '@modern-js/types/server';
6
6
  import { ModernRouteInterface } from './libs/route';
@@ -20,10 +20,11 @@ declare module '@modern-js/core' {
20
20
  }
21
21
  }
22
22
 
23
+ type Plugin = string | [string, any] | ServerPlugin;
23
24
  export type ModernServerOptions = {
24
25
  pwd: string;
25
26
  config: NormalizedConfig;
26
- plugins?: { pluginPath: string }[];
27
+ plugins?: Plugin[];
27
28
  routes?: ModernRouteInterface[];
28
29
  staticGenerate?: boolean;
29
30
  loggerOptions?: Record<string, string>;
package/src/utils.ts CHANGED
@@ -94,7 +94,7 @@ export const getStaticReg = (output: NormalizedConfig['output'] = {}) => {
94
94
  const staticPathRegExp = new RegExp(
95
95
  `^/(static/|upload/|favicon.ico|icon.png${
96
96
  favicons.length > 0 ? `|${favicons.join('|')}` : ''
97
- }|${staticFiles.join('|')})`,
97
+ }${staticFiles.length > 0 ? `|${staticFiles.join('|')}` : ''})`,
98
98
  );
99
99
 
100
100
  return staticPathRegExp;
@@ -8,6 +8,24 @@
8
8
  "isSSR": true,
9
9
  "enableModernMode": false,
10
10
  "bundle": "bundles/main.js"
11
+ },
12
+ {
13
+ "urlPath": "/500",
14
+ "entryName": "500",
15
+ "entryPath": "html/main/index.html",
16
+ "isSPA": true,
17
+ "isSSR": true,
18
+ "enableModernMode": false,
19
+ "bundle": "bundles/main.js"
20
+ },
21
+ {
22
+ "urlPath": "/404",
23
+ "entryName": "500",
24
+ "entryPath": "html/main/index.html",
25
+ "isSPA": true,
26
+ "isSSR": true,
27
+ "enableModernMode": false,
28
+ "bundle": "bundles/main.js"
11
29
  }
12
30
  ]
13
31
  }
@@ -130,6 +130,80 @@ describe('test server', () => {
130
130
 
131
131
  expect(html).toMatch('<div>Modern.js</div>');
132
132
  });
133
+
134
+ test('should error handler correctly with custom entry', async () => {
135
+ const server = await createServer({
136
+ config: {
137
+ ...(defaultsConfig as NormalizedConfig),
138
+ output: {
139
+ path: 'test-dist',
140
+ },
141
+ },
142
+ pwd: appDirectory,
143
+ });
144
+
145
+ const modernServer: ModernServer = (server as any).server;
146
+ const req = httpMocks.createRequest({
147
+ url: '/',
148
+ headers: {
149
+ host: 'modernjs.com',
150
+ },
151
+ eventEmitter: Readable,
152
+ method: 'GET',
153
+ });
154
+ const res = httpMocks.createResponse({ eventEmitter: EventEmitter });
155
+ const ctx = createContext(req, res);
156
+ ctx.error = () => {
157
+ // empty
158
+ };
159
+
160
+ setTimeout(() => {
161
+ (modernServer as any).onError(ctx, new Error('test error'));
162
+ }, 100);
163
+ const html = await new Promise((resolve, _reject) => {
164
+ res.on('finish', () => {
165
+ resolve(res._getData());
166
+ });
167
+ });
168
+ expect(html).toMatch('<div>Modern.js</div>');
169
+ });
170
+
171
+ test('should error handler correctly with fallback doc', async () => {
172
+ const server = await createServer({
173
+ config: {
174
+ ...(defaultsConfig as NormalizedConfig),
175
+ output: {
176
+ path: 'test-dist',
177
+ },
178
+ },
179
+ pwd: appDirectory,
180
+ });
181
+
182
+ const modernServer: ModernServer = (server as any).server;
183
+ const req = httpMocks.createRequest({
184
+ url: '/',
185
+ headers: {
186
+ host: 'modernjs.com',
187
+ },
188
+ eventEmitter: Readable,
189
+ method: 'GET',
190
+ });
191
+ const res = httpMocks.createResponse({ eventEmitter: EventEmitter });
192
+ const ctx = createContext(req, res);
193
+ ctx.error = () => {
194
+ // empty
195
+ };
196
+
197
+ setTimeout(() => {
198
+ (modernServer as any).renderErrorPage(ctx, 404);
199
+ }, 100);
200
+ const html = await new Promise((resolve, _reject) => {
201
+ res.on('finish', () => {
202
+ resolve(res._getData());
203
+ });
204
+ });
205
+ expect(html).toMatch('This page could not be found.');
206
+ });
133
207
  });
134
208
 
135
209
  describe('should split server work correctly', () => {
@@ -79,8 +79,8 @@ describe('test server utils', () => {
79
79
  describe('test create static reg', () => {
80
80
  test('should test static path correctly', () => {
81
81
  const reg = getStaticReg();
82
- expect(reg.test('/static')).toBeTruthy();
83
- expect(reg.test('/upload')).toBeTruthy();
82
+ expect(reg.test('/static/')).toBeTruthy();
83
+ expect(reg.test('/upload/')).toBeTruthy();
84
84
  });
85
85
 
86
86
  test('should test custom static path correctly', () => {