@modern-js/server 1.4.0 → 1.4.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @modern-js/server
2
2
 
3
+ ## 1.4.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 2cfc4235: support cssPath/jsPath/mediaPath in production mode
8
+ - 8d55e234: fix: catch api error
9
+ - Updated dependencies [53aca274]
10
+ - Updated dependencies [78279953]
11
+ - Updated dependencies [e116ace5]
12
+ - Updated dependencies [4d72edea]
13
+ - @modern-js/core@1.4.1
14
+ - @modern-js/utils@1.3.1
15
+
3
16
  ## 1.4.0
4
17
 
5
18
  ### Minor Changes
@@ -14,7 +14,7 @@ const createCacheItem = async (filepath, mtime) => {
14
14
  };
15
15
  };
16
16
 
17
- class LruReader {
17
+ export class LruReader {
18
18
  // private timer?: NodeJS.Timeout;
19
19
  constructor() {
20
20
  this.cache = void 0;
@@ -96,7 +96,6 @@ class LruReader {
96
96
 
97
97
 
98
98
  }
99
-
100
99
  const reader = new LruReader();
101
100
  export const readFile = async filepath => {
102
101
  const file = await reader.read(filepath);
@@ -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, mergeExtension, noop } from "../utils";
24
+ import { createErrorDocument, createMiddlewareCollecter, getStaticReg, mergeExtension, noop } 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";
@@ -126,15 +126,10 @@ export class ModernServer {
126
126
  this.warmupSSRBundle();
127
127
  }
128
128
 
129
- await this.prepareFrameHandler();
130
- const {
131
- favicon,
132
- faviconByEntries
133
- } = this.conf.output || {};
134
- const favicons = this.prepareFavicons(favicon, faviconByEntries); // Only work when without setting `assetPrefix`.
129
+ await this.prepareFrameHandler(); // Only work when without setting `assetPrefix`.
135
130
  // Setting `assetPrefix` means these resources should be uploaded to CDN.
136
131
 
137
- const staticPathRegExp = new RegExp(`^/(static/|upload/|favicon.ico|icon.png${favicons.length > 0 ? `|${favicons.join('|')}` : ''})`);
132
+ const staticPathRegExp = getStaticReg(this.conf.output || {});
138
133
  this.staticFileHandler = createStaticFileHandler([{
139
134
  path: staticPathRegExp,
140
135
  target: distDir
@@ -374,7 +369,7 @@ export class ModernServer {
374
369
  }); // route is api service
375
370
 
376
371
  if (route.isApi) {
377
- this.handleAPI(context);
372
+ await this.handleAPI(context);
378
373
  return;
379
374
  }
380
375
 
@@ -585,25 +580,5 @@ export class ModernServer {
585
580
  res.end(createErrorDocument(status, text));
586
581
  }
587
582
 
588
- prepareFavicons(favicon, faviconByEntries) {
589
- const faviconNames = [];
590
-
591
- if (favicon) {
592
- faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
593
- }
594
-
595
- if (faviconByEntries) {
596
- Object.keys(faviconByEntries).forEach(f => {
597
- const curFavicon = faviconByEntries[f];
598
-
599
- if (curFavicon) {
600
- faviconNames.push(curFavicon.substring(curFavicon.lastIndexOf('/') + 1));
601
- }
602
- });
603
- }
604
-
605
- return faviconNames;
606
- }
607
-
608
583
  }
609
584
  /* eslint-enable max-lines */
@@ -77,4 +77,36 @@ export const toPath = (reg, params) => {
77
77
  encode: encodeURIComponent
78
78
  });
79
79
  return fn(params);
80
+ };
81
+ export const getStaticReg = (output = {}) => {
82
+ const {
83
+ favicon,
84
+ faviconByEntries,
85
+ cssPath,
86
+ jsPath,
87
+ mediaPath
88
+ } = output;
89
+ const favicons = prepareFavicons(favicon, faviconByEntries);
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('|')})`);
92
+ return staticPathRegExp;
93
+ };
94
+ export const prepareFavicons = (favicon, faviconByEntries) => {
95
+ const faviconNames = [];
96
+
97
+ if (favicon) {
98
+ faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
99
+ }
100
+
101
+ if (faviconByEntries) {
102
+ Object.keys(faviconByEntries).forEach(f => {
103
+ const curFavicon = faviconByEntries[f];
104
+
105
+ if (curFavicon) {
106
+ faviconNames.push(curFavicon.substring(curFavicon.lastIndexOf('/') + 1));
107
+ }
108
+ });
109
+ }
110
+
111
+ return faviconNames;
80
112
  };
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.updateFile = exports.readFile = exports.init = exports.close = void 0;
6
+ exports.updateFile = exports.readFile = exports.init = exports.close = exports.LruReader = void 0;
7
7
 
8
8
  var _utils = require("@modern-js/utils");
9
9
 
@@ -110,6 +110,7 @@ class LruReader {
110
110
 
111
111
  }
112
112
 
113
+ exports.LruReader = LruReader;
113
114
  const reader = new LruReader();
114
115
 
115
116
  const readFile = async filepath => {
@@ -156,15 +156,10 @@ class ModernServer {
156
156
  this.warmupSSRBundle();
157
157
  }
158
158
 
159
- await this.prepareFrameHandler();
160
- const {
161
- favicon,
162
- faviconByEntries
163
- } = this.conf.output || {};
164
- const favicons = this.prepareFavicons(favicon, faviconByEntries); // Only work when without setting `assetPrefix`.
159
+ await this.prepareFrameHandler(); // Only work when without setting `assetPrefix`.
165
160
  // Setting `assetPrefix` means these resources should be uploaded to CDN.
166
161
 
167
- const staticPathRegExp = new RegExp(`^/(static/|upload/|favicon.ico|icon.png${favicons.length > 0 ? `|${favicons.join('|')}` : ''})`);
162
+ const staticPathRegExp = (0, _utils2.getStaticReg)(this.conf.output || {});
168
163
  this.staticFileHandler = (0, _serveFile.createStaticFileHandler)([{
169
164
  path: staticPathRegExp,
170
165
  target: distDir
@@ -409,7 +404,7 @@ class ModernServer {
409
404
  }); // route is api service
410
405
 
411
406
  if (route.isApi) {
412
- this.handleAPI(context);
407
+ await this.handleAPI(context);
413
408
  return;
414
409
  }
415
410
 
@@ -620,26 +615,6 @@ class ModernServer {
620
615
  res.end((0, _utils2.createErrorDocument)(status, text));
621
616
  }
622
617
 
623
- prepareFavicons(favicon, faviconByEntries) {
624
- const faviconNames = [];
625
-
626
- if (favicon) {
627
- faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
628
- }
629
-
630
- if (faviconByEntries) {
631
- Object.keys(faviconByEntries).forEach(f => {
632
- const curFavicon = faviconByEntries[f];
633
-
634
- if (curFavicon) {
635
- faviconNames.push(curFavicon.substring(curFavicon.lastIndexOf('/') + 1));
636
- }
637
- });
638
- }
639
-
640
- return faviconNames;
641
- }
642
-
643
618
  }
644
619
  /* eslint-enable max-lines */
645
620
 
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.toPath = exports.toMessage = exports.noop = exports.mergeExtension = exports.createMiddlewareCollecter = exports.createErrorDocument = void 0;
6
+ exports.toPath = exports.toMessage = exports.prepareFavicons = exports.noop = exports.mergeExtension = exports.getStaticReg = exports.createMiddlewareCollecter = exports.createErrorDocument = void 0;
7
7
 
8
8
  var _pathToRegexp = require("path-to-regexp");
9
9
 
@@ -102,4 +102,42 @@ const toPath = (reg, params) => {
102
102
  return fn(params);
103
103
  };
104
104
 
105
- exports.toPath = toPath;
105
+ exports.toPath = toPath;
106
+
107
+ const getStaticReg = (output = {}) => {
108
+ const {
109
+ favicon,
110
+ faviconByEntries,
111
+ cssPath,
112
+ jsPath,
113
+ mediaPath
114
+ } = output;
115
+ const favicons = prepareFavicons(favicon, faviconByEntries);
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('|')})`);
118
+ return staticPathRegExp;
119
+ };
120
+
121
+ exports.getStaticReg = getStaticReg;
122
+
123
+ const prepareFavicons = (favicon, faviconByEntries) => {
124
+ const faviconNames = [];
125
+
126
+ if (favicon) {
127
+ faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
128
+ }
129
+
130
+ if (faviconByEntries) {
131
+ Object.keys(faviconByEntries).forEach(f => {
132
+ const curFavicon = faviconByEntries[f];
133
+
134
+ if (curFavicon) {
135
+ faviconNames.push(curFavicon.substring(curFavicon.lastIndexOf('/') + 1));
136
+ }
137
+ });
138
+ }
139
+
140
+ return faviconNames;
141
+ };
142
+
143
+ exports.prepareFavicons = prepareFavicons;
@@ -1,4 +1,17 @@
1
1
  /// <reference types="node" />
2
+ export declare class LruReader {
3
+ private readonly cache;
4
+ constructor();
5
+ init(): void;
6
+ close(): void;
7
+ read(filepath: string): Promise<{
8
+ content: Buffer;
9
+ mtime: Date;
10
+ } | {
11
+ content: Buffer;
12
+ } | null>;
13
+ update(): void;
14
+ }
2
15
  export declare const readFile: (filepath: string) => Promise<Buffer | undefined>;
3
16
  export declare const updateFile: () => void;
4
17
  export declare const init: () => void;
@@ -68,6 +68,5 @@ export declare class ModernServer {
68
68
  private requestHandler;
69
69
  private onError;
70
70
  private renderErrorPage;
71
- private prepareFavicons;
72
71
  }
73
72
  export {};
@@ -1,3 +1,4 @@
1
+ import type { NormalizedConfig } from '@modern-js/core';
1
2
  export declare const mergeExtension: (users: any[]) => {
2
3
  middleware: any[];
3
4
  };
@@ -13,4 +14,6 @@ export declare const createMiddlewareCollecter: () => {
13
14
  addWebMiddleware: (input: any) => void;
14
15
  addAPIMiddleware: (input: any) => void;
15
16
  };
16
- export declare const toPath: (reg: string, params: Record<string, any>) => string;
17
+ export declare const toPath: (reg: string, params: Record<string, any>) => string;
18
+ export declare const getStaticReg: (output?: NormalizedConfig['output']) => RegExp;
19
+ export declare const prepareFavicons: (favicon: string | undefined, faviconByEntries?: Record<string, string | undefined> | undefined) => string[];
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "1.4.0",
14
+ "version": "1.4.1",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -34,12 +34,12 @@
34
34
  "@babel/preset-typescript": "^7.15.0",
35
35
  "@babel/register": "^7.15.3",
36
36
  "@babel/runtime": "^7",
37
- "@modern-js/core": "^1.4.0",
37
+ "@modern-js/core": "^1.4.1",
38
38
  "@modern-js/hmr-client": "^1.2.1",
39
39
  "@modern-js/server-core": "^1.2.2",
40
40
  "@modern-js/server-utils": "^1.2.1",
41
41
  "@modern-js/bff-utils": "^1.2.2",
42
- "@modern-js/utils": "^1.3.0",
42
+ "@modern-js/utils": "^1.3.1",
43
43
  "axios": "^0.24.0",
44
44
  "babel-plugin-module-resolver": "^4.1.0",
45
45
  "chokidar": "^3.5.2",
@@ -65,7 +65,7 @@
65
65
  },
66
66
  "devDependencies": {
67
67
  "@scripts/build": "0.0.0",
68
- "@modern-js/types": "^1.3.0",
68
+ "@modern-js/types": "^1.3.1",
69
69
  "@types/jest": "^26",
70
70
  "@types/lru-cache": "^5.1.1",
71
71
  "@types/mime-types": "^2.1.0",
@@ -100,8 +100,7 @@
100
100
  },
101
101
  "publishConfig": {
102
102
  "registry": "https://registry.npmjs.org/",
103
- "access": "public",
104
- "types": "./dist/types/index.d.ts"
103
+ "access": "public"
105
104
  },
106
105
  "scripts": {
107
106
  "new": "modern new",
@@ -0,0 +1,3 @@
1
+ export default {
2
+ name: 'modern',
3
+ };
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>bar</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>baz</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>foo</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,102 @@
1
+ import path from 'path';
2
+ import { render } from '../src/libs/render/ssr';
3
+ import { handleDirectory } from '../src/libs/render/static';
4
+ import { LruReader } from '../src/libs/render/reader';
5
+
6
+ describe('test render function', () => {
7
+ test('should return content correctly ', async () => {
8
+ const renderResult = await render(
9
+ {
10
+ params: {},
11
+ pathname: '/foo',
12
+ host: 'localhost:8080',
13
+ query: {},
14
+ url: 'localhost:8080/foo',
15
+ cookieMap: {},
16
+ headers: {},
17
+ } as any,
18
+ {
19
+ urlPath: '/foo',
20
+ bundle: 'bundle.js',
21
+ distDir: path.join(__dirname, 'fixtures', 'ssr'),
22
+ template: 'tpl.html',
23
+ entryName: 'foo',
24
+ staticGenerate: false,
25
+ } as any,
26
+ {
27
+ extendSSRContext: () => {
28
+ // empty
29
+ },
30
+ } as any,
31
+ );
32
+
33
+ expect(renderResult.content).toMatch('Modern.js');
34
+ expect(renderResult.contentType).toMatch('text/html; charset=utf-8');
35
+ });
36
+
37
+ test('should handle directory for .html correctly', async () => {
38
+ const entryPath = path.join(__dirname, 'fixtures', 'static-dir');
39
+
40
+ const res1 = await handleDirectory(
41
+ {
42
+ path: '/modern/bar',
43
+ } as any,
44
+ entryPath,
45
+ '/modern',
46
+ );
47
+
48
+ expect(res1?.content.toString()).toMatch('bar');
49
+ });
50
+
51
+ test('should handle directory for index.html correctly', async () => {
52
+ const entryPath = path.join(__dirname, 'fixtures', 'static-dir');
53
+
54
+ const res1 = await handleDirectory(
55
+ {
56
+ path: '/modern/foo',
57
+ } as any,
58
+ entryPath,
59
+ '/modern',
60
+ );
61
+
62
+ expect(res1?.content.toString()).toMatch('foo');
63
+ });
64
+
65
+ test('should handle directory for /index.html correctly', async () => {
66
+ const entryPath = path.join(__dirname, 'fixtures', 'static-dir');
67
+
68
+ const res1 = await handleDirectory(
69
+ {
70
+ path: '/modern/baz/',
71
+ } as any,
72
+ entryPath,
73
+ '/modern',
74
+ );
75
+
76
+ expect(res1?.content.toString()).toMatch('baz');
77
+ });
78
+
79
+ test('should reader work correctly', async () => {
80
+ const reader = new LruReader();
81
+ const dir = path.join(__dirname, 'fixtures', 'reader');
82
+
83
+ const nullRes = await reader.read(path.join(dir, 'foo.ts'));
84
+ expect(nullRes).toBeNull();
85
+
86
+ const dirRes = await reader.read(path.join(dir, 'test-dir'));
87
+ expect(dirRes).toBeNull();
88
+
89
+ const res = await reader.read(path.join(dir, 'index.ts'));
90
+ expect(res).not.toBeNull();
91
+ expect(res?.content.toString()).toMatch('modern');
92
+
93
+ const res1 = await reader.read(path.join(dir, 'index.ts'));
94
+ expect(res1).not.toBeNull();
95
+ expect(res1?.content.toString()).toMatch('modern');
96
+
97
+ reader.update();
98
+ const res2 = await reader.read(path.join(dir, 'index.ts'));
99
+ expect(res2).not.toBeNull();
100
+ expect(res2?.content.toString()).toMatch('modern');
101
+ });
102
+ });
@@ -5,6 +5,7 @@ import {
5
5
  toMessage,
6
6
  createErrorDocument,
7
7
  createMiddlewareCollecter,
8
+ getStaticReg,
8
9
  } from '../src/utils';
9
10
 
10
11
  describe('test server utils', () => {
@@ -74,4 +75,32 @@ describe('test server utils', () => {
74
75
  const fn = compile('/home/:id', { encode: encodeURIComponent });
75
76
  expect(fn({ id: 2 })).toBe('/home/2');
76
77
  });
78
+
79
+ describe('test create static reg', () => {
80
+ test('should test static path correctly', () => {
81
+ const reg = getStaticReg();
82
+ expect(reg.test('/static')).toBeTruthy();
83
+ expect(reg.test('/upload')).toBeTruthy();
84
+ });
85
+
86
+ test('should test custom static path correctly', () => {
87
+ const reg = getStaticReg({
88
+ cssPath: 'static-css',
89
+ });
90
+ expect(reg.test('/static-css')).toBeTruthy();
91
+ });
92
+
93
+ test('should test favicon path correctly', () => {
94
+ const reg = getStaticReg({
95
+ favicon: 'index.icon',
96
+ faviconByEntries: {
97
+ foo: 'foo.icon',
98
+ baz: 'baz.icon',
99
+ },
100
+ });
101
+ expect(reg.test('/index.icon')).toBeTruthy();
102
+ expect(reg.test('/foo.icon')).toBeTruthy();
103
+ expect(reg.test('/baz.icon')).toBeTruthy();
104
+ });
105
+ });
77
106
  });
package/tests/ssr.test.ts DELETED
@@ -1,34 +0,0 @@
1
- import path from 'path';
2
- import { render } from '../src/libs/render/ssr';
3
-
4
- describe('test ssr render function', () => {
5
- test('should return content correctly ', async () => {
6
- const renderResult = await render(
7
- {
8
- params: {},
9
- pathname: '/foo',
10
- host: 'localhost:8080',
11
- query: {},
12
- url: 'localhost:8080/foo',
13
- cookieMap: {},
14
- headers: {},
15
- } as any,
16
- {
17
- urlPath: '/foo',
18
- bundle: 'bundle.js',
19
- distDir: path.join(__dirname, 'fixtures', 'ssr'),
20
- template: 'tpl.html',
21
- entryName: 'foo',
22
- staticGenerate: false,
23
- } as any,
24
- {
25
- extendSSRContext: () => {
26
- // empty
27
- },
28
- } as any,
29
- );
30
-
31
- expect(renderResult.content).toMatch('Modern.js');
32
- expect(renderResult.contentType).toMatch('text/html; charset=utf-8');
33
- });
34
- });