@modern-js/server 1.1.1 → 1.1.2

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,23 @@
1
1
  # @modern-js/server
2
2
 
3
+ ## 1.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 0fa83663: support more .env files
8
+ - f594fbc8: fix apple icon and favicon support
9
+ - d1fde77a: fix public/ file in windows
10
+ - Updated dependencies [6f7fe574]
11
+ - Updated dependencies [b011e0c5]
12
+ - Updated dependencies [0fa83663]
13
+ - Updated dependencies [f594fbc8]
14
+ - @modern-js/core@1.1.2
15
+ - @modern-js/server-utils@1.1.1
16
+ - @modern-js/bff-utils@1.1.1
17
+ - @modern-js/hmr-client@1.1.1
18
+ - @modern-js/server-plugin@1.1.1
19
+ - @modern-js/utils@1.1.2
20
+
3
21
  ## 1.1.1
4
22
 
5
23
  ### Patch Changes
@@ -2,7 +2,7 @@ import { removeTailSlash } from '@modern-js/utils';
2
2
  import { match, pathToRegexp } from 'path-to-regexp';
3
3
  import { ModernRoute } from "./route"; // eslint-disable-next-line no-useless-escape
4
4
 
5
- const regCharsDetector = /[^a-zA-Z\-_0-9\/]/;
5
+ const regCharsDetector = /[^a-zA-Z\-_0-9\/\.]/;
6
6
  export class RouteMatcher {
7
7
  constructor(spec) {
8
8
  this.spec = void 0;
@@ -1,30 +1,28 @@
1
1
  // Todo 看看是不是能 fork 一份,即使命中也返回
2
2
  import serve from 'serve-static';
3
- export const createStaticFileHandler = rules => {
4
- const middlewares = rules.reduce((map, rule) => {
5
- map[rule.path] = serve(rule.target);
6
- return map;
7
- }, {}); // eslint-disable-next-line consistent-return
3
+ import { isString, isRegExp } from '@modern-js/utils';
4
+ export const createStaticFileHandler = rules => // eslint-disable-next-line consistent-return
5
+ async (context, next) => {
6
+ const {
7
+ url: requestUrl,
8
+ req,
9
+ res
10
+ } = context;
11
+ const hitRule = rules.find(item => {
12
+ if (isString(item.path) && requestUrl.startsWith(item.path)) {
13
+ return true;
14
+ } else if (isRegExp(item.path) && item.path.test(requestUrl)) {
15
+ return true;
16
+ }
8
17
 
9
- return async (context, next) => {
10
- const {
11
- url: requestUrl,
12
- req,
13
- res
14
- } = context;
15
- const hit = Object.keys(middlewares).find(u => requestUrl.startsWith(u));
18
+ return false;
19
+ });
16
20
 
17
- if (hit) {
18
- // when matches static resources, delete the first layer of req.url
19
- const removed = hit;
20
- context.url = requestUrl.slice(removed.length - 1);
21
- middlewares[hit](req, res, () => {
22
- // will invok next, recover req.url
23
- context.url = removed + context.url;
24
- next();
25
- });
26
- } else {
27
- return next();
28
- }
29
- };
21
+ if (hitRule) {
22
+ serve(hitRule.target)(req, res, () => {
23
+ next();
24
+ });
25
+ } else {
26
+ return next();
27
+ }
30
28
  };
@@ -120,12 +120,17 @@ export class ModernServer {
120
120
  }
121
121
 
122
122
  await this.prepareFrameHandler();
123
+ const {
124
+ favicon,
125
+ faviconByEntries
126
+ } = this.conf.output;
127
+ const favicons = this.prepareFavicons(favicon, faviconByEntries); // Only work when without setting `assetPrefix`.
128
+ // Setting `assetPrefix` means these resources should be uploaded to CDN.
129
+
130
+ const staticPathRegExp = new RegExp(`^/(static/|upload/|favicon.ico|icon.png${favicons.length > 0 ? `|${favicons.join('|')}` : ''})`);
123
131
  this.staticFileHandler = createStaticFileHandler([{
124
- path: '/static/',
125
- target: path.join(distDir, 'static')
126
- }, {
127
- path: '/upload/',
128
- target: path.join(distDir, 'upload')
132
+ path: staticPathRegExp,
133
+ target: distDir
129
134
  }]);
130
135
  this.routeRenderHandler = createRenderHandler({
131
136
  distDir,
@@ -277,6 +282,26 @@ export class ModernServer {
277
282
  this.addHandler(mid);
278
283
  });
279
284
  }
285
+
286
+ prepareFavicons(favicon, faviconByEntries) {
287
+ const faviconNames = [];
288
+
289
+ if (favicon) {
290
+ faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
291
+ }
292
+
293
+ if (faviconByEntries) {
294
+ Object.keys(faviconByEntries).forEach(f => {
295
+ const curFavicon = faviconByEntries[f];
296
+
297
+ if (curFavicon) {
298
+ faviconNames.push(curFavicon.substring(curFavicon.lastIndexOf('/') + 1));
299
+ }
300
+ });
301
+ }
302
+
303
+ return faviconNames;
304
+ }
280
305
  /* —————————————————————— private function —————————————————————— */
281
306
  // handler route.json, include api / csr / ssr
282
307
  // eslint-disable-next-line max-statements
@@ -12,7 +12,7 @@ var _pathToRegexp = require("path-to-regexp");
12
12
  var _route = require("./route");
13
13
 
14
14
  // eslint-disable-next-line no-useless-escape
15
- const regCharsDetector = /[^a-zA-Z\-_0-9\/]/;
15
+ const regCharsDetector = /[^a-zA-Z\-_0-9\/\.]/;
16
16
 
17
17
  class RouteMatcher {
18
18
  constructor(spec) {
@@ -7,36 +7,35 @@ exports.createStaticFileHandler = void 0;
7
7
 
8
8
  var _serveStatic = _interopRequireDefault(require("serve-static"));
9
9
 
10
+ var _utils = require("@modern-js/utils");
11
+
10
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
13
 
12
14
  // Todo 看看是不是能 fork 一份,即使命中也返回
13
- const createStaticFileHandler = rules => {
14
- const middlewares = rules.reduce((map, rule) => {
15
- map[rule.path] = (0, _serveStatic.default)(rule.target);
16
- return map;
17
- }, {}); // eslint-disable-next-line consistent-return
18
-
19
- return async (context, next) => {
20
- const {
21
- url: requestUrl,
22
- req,
23
- res
24
- } = context;
25
- const hit = Object.keys(middlewares).find(u => requestUrl.startsWith(u));
26
-
27
- if (hit) {
28
- // when matches static resources, delete the first layer of req.url
29
- const removed = hit;
30
- context.url = requestUrl.slice(removed.length - 1);
31
- middlewares[hit](req, res, () => {
32
- // will invok next, recover req.url
33
- context.url = removed + context.url;
34
- next();
35
- });
36
- } else {
37
- return next();
15
+ const createStaticFileHandler = rules => // eslint-disable-next-line consistent-return
16
+ async (context, next) => {
17
+ const {
18
+ url: requestUrl,
19
+ req,
20
+ res
21
+ } = context;
22
+ const hitRule = rules.find(item => {
23
+ if ((0, _utils.isString)(item.path) && requestUrl.startsWith(item.path)) {
24
+ return true;
25
+ } else if ((0, _utils.isRegExp)(item.path) && item.path.test(requestUrl)) {
26
+ return true;
38
27
  }
39
- };
28
+
29
+ return false;
30
+ });
31
+
32
+ if (hitRule) {
33
+ (0, _serveStatic.default)(hitRule.target)(req, res, () => {
34
+ next();
35
+ });
36
+ } else {
37
+ return next();
38
+ }
40
39
  };
41
40
 
42
41
  exports.createStaticFileHandler = createStaticFileHandler;
@@ -148,12 +148,17 @@ class ModernServer {
148
148
  }
149
149
 
150
150
  await this.prepareFrameHandler();
151
+ const {
152
+ favicon,
153
+ faviconByEntries
154
+ } = this.conf.output;
155
+ const favicons = this.prepareFavicons(favicon, faviconByEntries); // Only work when without setting `assetPrefix`.
156
+ // Setting `assetPrefix` means these resources should be uploaded to CDN.
157
+
158
+ const staticPathRegExp = new RegExp(`^/(static/|upload/|favicon.ico|icon.png${favicons.length > 0 ? `|${favicons.join('|')}` : ''})`);
151
159
  this.staticFileHandler = (0, _serveFile.createStaticFileHandler)([{
152
- path: '/static/',
153
- target: _path.default.join(distDir, 'static')
154
- }, {
155
- path: '/upload/',
156
- target: _path.default.join(distDir, 'upload')
160
+ path: staticPathRegExp,
161
+ target: distDir
157
162
  }]);
158
163
  this.routeRenderHandler = (0, _render.createRenderHandler)({
159
164
  distDir,
@@ -310,6 +315,26 @@ class ModernServer {
310
315
  this.addHandler(mid);
311
316
  });
312
317
  }
318
+
319
+ prepareFavicons(favicon, faviconByEntries) {
320
+ const faviconNames = [];
321
+
322
+ if (favicon) {
323
+ faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
324
+ }
325
+
326
+ if (faviconByEntries) {
327
+ Object.keys(faviconByEntries).forEach(f => {
328
+ const curFavicon = faviconByEntries[f];
329
+
330
+ if (curFavicon) {
331
+ faviconNames.push(curFavicon.substring(curFavicon.lastIndexOf('/') + 1));
332
+ }
333
+ });
334
+ }
335
+
336
+ return faviconNames;
337
+ }
313
338
  /* —————————————————————— private function —————————————————————— */
314
339
  // handler route.json, include api / csr / ssr
315
340
  // eslint-disable-next-line max-statements
@@ -1,7 +1,7 @@
1
1
  import { NextFunction } from '../type';
2
2
  import { ModernServerContext } from './context';
3
3
  declare type Rule = {
4
- path: string;
4
+ path: string | RegExp;
5
5
  target: string;
6
6
  };
7
7
  export declare const createStaticFileHandler: (rules: Rule[]) => (context: ModernServerContext, next: NextFunction) => Promise<void>;
@@ -51,6 +51,7 @@ export declare class ModernServer {
51
51
  protected prepareAPIHandler(mode: ApiServerMode, extension: ReturnType<typeof mergeExtension>): Promise<Adapter>;
52
52
  protected filterRoutes(routes: ModernRouteInterface[]): ModernRouteInterface[];
53
53
  protected preServerInit(): Promise<void>;
54
+ private prepareFavicons;
54
55
  private routeHandler;
55
56
  private injectMicroFE;
56
57
  private compose;
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "1.1.1",
14
+ "version": "1.1.2",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -33,12 +33,12 @@
33
33
  "@babel/preset-typescript": "^7.15.0",
34
34
  "@babel/register": "^7.15.3",
35
35
  "@babel/runtime": "^7",
36
- "@modern-js/core": "^1.1.1",
37
- "@modern-js/hmr-client": "^1.1.0",
38
- "@modern-js/server-plugin": "^1.1.0",
39
- "@modern-js/server-utils": "^1.1.0",
40
- "@modern-js/bff-utils": "^1.1.0",
41
- "@modern-js/utils": "^1.1.1",
36
+ "@modern-js/core": "^1.1.2",
37
+ "@modern-js/hmr-client": "^1.1.1",
38
+ "@modern-js/server-plugin": "^1.1.1",
39
+ "@modern-js/server-utils": "^1.1.1",
40
+ "@modern-js/bff-utils": "^1.1.1",
41
+ "@modern-js/utils": "^1.1.2",
42
42
  "axios": "^0.21.4",
43
43
  "babel-plugin-module-resolver": "^4.1.0",
44
44
  "chokidar": "^3.5.2",
@@ -63,7 +63,7 @@
63
63
  "devDependencies": {
64
64
  "@modern-js/module-tools": "^1.1.0",
65
65
  "@modern-js/plugin-testing": "^1.1.0",
66
- "@modern-js/types": "^1.1.1",
66
+ "@modern-js/types": "^1.1.2",
67
67
  "@types/jest": "^26",
68
68
  "@types/lru-cache": "^5.1.1",
69
69
  "@types/mime-types": "^2.1.0",
@@ -8,7 +8,7 @@ import {
8
8
  import { ModernRoute, ModernRouteInterface } from './route';
9
9
 
10
10
  // eslint-disable-next-line no-useless-escape
11
- const regCharsDetector = /[^a-zA-Z\-_0-9\/]/;
11
+ const regCharsDetector = /[^a-zA-Z\-_0-9\/\.]/;
12
12
  export class RouteMatcher {
13
13
  public spec: ModernRouteInterface;
14
14
 
@@ -1,38 +1,34 @@
1
1
  // Todo 看看是不是能 fork 一份,即使命中也返回
2
2
  import serve from 'serve-static';
3
+ import { isString, isRegExp } from '@modern-js/utils';
3
4
  import { NextFunction } from '../type';
4
5
  import { ModernServerContext } from './context';
5
6
 
6
7
  type Rule = {
7
- path: string;
8
+ path: string | RegExp;
8
9
  target: string;
9
10
  };
10
11
 
11
- export const createStaticFileHandler = (rules: Rule[]) => {
12
- const middlewares = rules.reduce(
13
- (map: Record<string, ReturnType<typeof serve>>, rule) => {
14
- map[rule.path] = serve(rule.target);
15
- return map;
16
- },
17
- {},
18
- );
19
-
12
+ export const createStaticFileHandler =
13
+ (rules: Rule[]) =>
20
14
  // eslint-disable-next-line consistent-return
21
- return async (context: ModernServerContext, next: NextFunction) => {
15
+ async (context: ModernServerContext, next: NextFunction) => {
22
16
  const { url: requestUrl, req, res } = context;
23
- const hit = Object.keys(middlewares).find(u => requestUrl.startsWith(u));
24
17
 
25
- if (hit) {
26
- // when matches static resources, delete the first layer of req.url
27
- const removed = hit;
28
- context.url = requestUrl.slice(removed.length - 1);
29
- middlewares[hit](req, res, () => {
30
- // will invok next, recover req.url
31
- context.url = removed + context.url;
18
+ const hitRule = rules.find(item => {
19
+ if (isString(item.path) && requestUrl.startsWith(item.path)) {
20
+ return true;
21
+ } else if (isRegExp(item.path) && item.path.test(requestUrl)) {
22
+ return true;
23
+ }
24
+ return false;
25
+ });
26
+
27
+ if (hitRule) {
28
+ serve(hitRule.target)(req, res, () => {
32
29
  next();
33
30
  });
34
31
  } else {
35
32
  return next();
36
33
  }
37
34
  };
38
- };
@@ -154,14 +154,20 @@ export class ModernServer {
154
154
 
155
155
  await this.prepareFrameHandler();
156
156
 
157
+ const { favicon, faviconByEntries } = this.conf.output;
158
+ const favicons = this.prepareFavicons(favicon, faviconByEntries);
159
+ // Only work when without setting `assetPrefix`.
160
+ // Setting `assetPrefix` means these resources should be uploaded to CDN.
161
+ const staticPathRegExp = new RegExp(
162
+ `^/(static/|upload/|favicon.ico|icon.png${
163
+ favicons.length > 0 ? `|${favicons.join('|')}` : ''
164
+ })`,
165
+ );
166
+
157
167
  this.staticFileHandler = createStaticFileHandler([
158
168
  {
159
- path: '/static/',
160
- target: path.join(distDir, 'static'),
161
- },
162
- {
163
- path: '/upload/',
164
- target: path.join(distDir, 'upload'),
169
+ path: staticPathRegExp,
170
+ target: distDir,
165
171
  },
166
172
  ]);
167
173
 
@@ -315,6 +321,27 @@ export class ModernServer {
315
321
  });
316
322
  }
317
323
 
324
+ private prepareFavicons(
325
+ favicon: string | undefined,
326
+ faviconByEntries?: Record<string, string | undefined>,
327
+ ) {
328
+ const faviconNames = [];
329
+ if (favicon) {
330
+ faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
331
+ }
332
+ if (faviconByEntries) {
333
+ Object.keys(faviconByEntries).forEach(f => {
334
+ const curFavicon = faviconByEntries[f];
335
+ if (curFavicon) {
336
+ faviconNames.push(
337
+ curFavicon.substring(curFavicon.lastIndexOf('/') + 1),
338
+ );
339
+ }
340
+ });
341
+ }
342
+ return faviconNames;
343
+ }
344
+
318
345
  /* —————————————————————— private function —————————————————————— */
319
346
 
320
347
  // handler route.json, include api / csr / ssr