@modern-js/server 1.3.2 → 1.4.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.
Files changed (74) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/js/modern/dev-tools/babel/register.js +1 -0
  3. package/dist/js/modern/dev-tools/dev-server-plugin.js +1 -2
  4. package/dist/js/modern/dev-tools/mock/getMockData.js +24 -1
  5. package/dist/js/modern/dev-tools/mock/index.js +1 -26
  6. package/dist/js/modern/dev-tools/socket-server.js +65 -46
  7. package/dist/js/modern/dev-tools/watcher/index.js +3 -4
  8. package/dist/js/modern/dev-tools/watcher/stats-cache.js +32 -20
  9. package/dist/js/modern/libs/context/context.js +6 -0
  10. package/dist/js/modern/libs/hook-api/route.js +6 -4
  11. package/dist/js/modern/libs/render/index.js +1 -0
  12. package/dist/js/modern/libs/render/reader.js +1 -2
  13. package/dist/js/modern/libs/render/ssr.js +7 -2
  14. package/dist/js/modern/libs/route/index.js +0 -1
  15. package/dist/js/modern/libs/route/matcher.js +15 -3
  16. package/dist/js/modern/libs/route/route.js +1 -0
  17. package/dist/js/modern/server/dev-server/dev-server.js +7 -0
  18. package/dist/js/modern/server/index.js +5 -4
  19. package/dist/js/modern/server/modern-server-split.js +1 -1
  20. package/dist/js/modern/server/modern-server.js +13 -34
  21. package/dist/js/modern/utils.js +39 -0
  22. package/dist/js/node/dev-tools/babel/register.js +1 -0
  23. package/dist/js/node/dev-tools/dev-server-plugin.js +1 -2
  24. package/dist/js/node/dev-tools/mock/getMockData.js +29 -2
  25. package/dist/js/node/dev-tools/mock/index.js +5 -26
  26. package/dist/js/node/dev-tools/socket-server.js +65 -46
  27. package/dist/js/node/dev-tools/watcher/index.js +6 -2
  28. package/dist/js/node/dev-tools/watcher/stats-cache.js +33 -20
  29. package/dist/js/node/libs/context/context.js +6 -0
  30. package/dist/js/node/libs/hook-api/route.js +6 -4
  31. package/dist/js/node/libs/render/index.js +1 -0
  32. package/dist/js/node/libs/render/reader.js +2 -1
  33. package/dist/js/node/libs/render/ssr.js +8 -2
  34. package/dist/js/node/libs/route/index.js +0 -1
  35. package/dist/js/node/libs/route/matcher.js +16 -3
  36. package/dist/js/node/libs/route/route.js +1 -0
  37. package/dist/js/node/server/dev-server/dev-server.js +7 -0
  38. package/dist/js/node/server/index.js +9 -6
  39. package/dist/js/node/server/modern-server-split.js +1 -1
  40. package/dist/js/node/server/modern-server.js +12 -33
  41. package/dist/js/node/utils.js +51 -2
  42. package/dist/types/dev-tools/mock/getMockData.d.ts +2 -1
  43. package/dist/types/dev-tools/socket-server.d.ts +4 -1
  44. package/dist/types/dev-tools/watcher/index.d.ts +2 -1
  45. package/dist/types/dev-tools/watcher/stats-cache.d.ts +3 -2
  46. package/dist/types/libs/context/context.d.ts +2 -0
  47. package/dist/types/libs/hook-api/route.d.ts +3 -2
  48. package/dist/types/libs/render/reader.d.ts +13 -0
  49. package/dist/types/libs/render/ssr.d.ts +1 -0
  50. package/dist/types/libs/route/matcher.d.ts +1 -1
  51. package/dist/types/libs/route/route.d.ts +1 -0
  52. package/dist/types/server/dev-server/dev-server-split.d.ts +3 -3
  53. package/dist/types/server/modern-server-split.d.ts +3 -3
  54. package/dist/types/server/modern-server.d.ts +1 -2
  55. package/dist/types/type.d.ts +5 -3
  56. package/dist/types/utils.d.ts +5 -1
  57. package/package.json +9 -8
  58. package/tests/context.test.ts +12 -1
  59. package/tests/dev.test.ts +316 -5
  60. package/tests/fixtures/mock/exist/config/mock/index.ts +11 -0
  61. package/tests/fixtures/mock/zero/config/mock/index.ts +1 -0
  62. package/tests/fixtures/reader/index.ts +3 -0
  63. package/tests/fixtures/route-spec/dynamic.json +13 -0
  64. package/tests/fixtures/ssr/bundle.js +5 -0
  65. package/tests/fixtures/static-dir/bar.html +11 -0
  66. package/tests/fixtures/static-dir/baz/index.html +11 -0
  67. package/tests/fixtures/static-dir/foo/index.html +11 -0
  68. package/tests/fixtures/watch/a.ts +3 -0
  69. package/tests/fixtures/watch/index.ts +5 -0
  70. package/tests/fixtures/watch/stats.txt +1 -0
  71. package/tests/hook.test.ts +1 -1
  72. package/tests/render.test.ts +102 -0
  73. package/tests/route.test.ts +26 -3
  74. package/tests/utils.test.ts +35 -0
@@ -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
@@ -353,7 +348,7 @@ export class ModernServer {
353
348
  return;
354
349
  }
355
350
 
356
- const routeAPI = createRouteAPI(matched, this.router);
351
+ const routeAPI = createRouteAPI(matched, this.router, context.url);
357
352
  await this.emitRouteHook('afterMatch', {
358
353
  context,
359
354
  routeAPI
@@ -366,12 +361,15 @@ export class ModernServer {
366
361
  const {
367
362
  current
368
363
  } = routeAPI;
369
- const route = current.generate();
370
- const params = current.parseURLParams(context.url);
371
- context.setParams(params); // route is api service
364
+ const route = current.generate(context.url);
365
+ context.setParams(route.params);
366
+ context.setServerData('router', {
367
+ baseUrl: route.urlPath,
368
+ params: route.params
369
+ }); // route is api service
372
370
 
373
371
  if (route.isApi) {
374
- this.handleAPI(context);
372
+ await this.handleAPI(context);
375
373
  return;
376
374
  }
377
375
 
@@ -413,6 +411,7 @@ export class ModernServer {
413
411
  templateAPI
414
412
  });
415
413
  await this.injectMicroFE(context, templateAPI);
414
+ templateAPI.appendHead(`<script>window._SERVER_DATA=${JSON.stringify(context.serverData)}</script>`);
416
415
  response = templateAPI.get();
417
416
  }
418
417
 
@@ -555,7 +554,7 @@ export class ModernServer {
555
554
  const matched = this.router.match(statusPage) || this.router.match(customErrorPage); // if no custom status page find
556
555
 
557
556
  if (matched) {
558
- const route = matched.generate();
557
+ const route = matched.generate(context.url);
559
558
  const {
560
559
  entryName
561
560
  } = route; // check entryName, aviod matched '/' route
@@ -581,25 +580,5 @@ export class ModernServer {
581
580
  res.end(createErrorDocument(status, text));
582
581
  }
583
582
 
584
- prepareFavicons(favicon, faviconByEntries) {
585
- const faviconNames = [];
586
-
587
- if (favicon) {
588
- faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
589
- }
590
-
591
- if (faviconByEntries) {
592
- Object.keys(faviconByEntries).forEach(f => {
593
- const curFavicon = faviconByEntries[f];
594
-
595
- if (curFavicon) {
596
- faviconNames.push(curFavicon.substring(curFavicon.lastIndexOf('/') + 1));
597
- }
598
- });
599
- }
600
-
601
- return faviconNames;
602
- }
603
-
604
583
  }
605
584
  /* eslint-enable max-lines */
@@ -1,3 +1,4 @@
1
+ import { compile } from 'path-to-regexp';
1
2
  export const mergeExtension = users => {
2
3
  const output = [];
3
4
  return {
@@ -70,4 +71,42 @@ export const createMiddlewareCollecter = () => {
70
71
  addWebMiddleware,
71
72
  addAPIMiddleware
72
73
  };
74
+ };
75
+ export const toPath = (reg, params) => {
76
+ const fn = compile(reg, {
77
+ encode: encodeURIComponent
78
+ });
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;
73
112
  };
@@ -32,6 +32,7 @@ const enableRegister = (projectRoot, config) => {
32
32
  return require('@babel/register')(_objectSpread(_objectSpread({}, babelConfig), {}, {
33
33
  only: [function (filePath) {
34
34
  // TODO: wait params
35
+ // FIXME: 删除hardcode,根据 AppContext 中的 metaName 设置路径
35
36
  if (filePath.includes(`node_modules${_path.default.sep}.modern-js`)) {
36
37
  return true;
37
38
  }
@@ -25,8 +25,7 @@ class DevServerPlugin {
25
25
  } = this;
26
26
  const host = `&host=${options.client.host || 'localhost'}`;
27
27
  const path = `&path=${options.client.path}`;
28
- const port = `&port=${options.client.port}`; // Todo @songzhenwei
29
-
28
+ const port = `&port=${options.client.port}`;
30
29
  const clientEntry = `${require.resolve('@modern-js/hmr-client')}?${host}${path}${port}`;
31
30
 
32
31
  const hotEntry = require.resolve('webpack/hot/dev-server');
@@ -3,10 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.getMatched = exports.default = void 0;
7
7
 
8
8
  var _utils = require("@modern-js/utils");
9
9
 
10
+ var _pathToRegexp = require("path-to-regexp");
11
+
10
12
  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; }
11
13
 
12
14
  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; }
@@ -91,4 +93,29 @@ var _default = filepath => {
91
93
  return data;
92
94
  };
93
95
 
94
- exports.default = _default;
96
+ exports.default = _default;
97
+
98
+ const getMatched = (context, mockApiList) => {
99
+ const {
100
+ path: targetPathname,
101
+ method: targetMethod
102
+ } = context;
103
+ const matched = mockApiList.find(mockApi => {
104
+ const {
105
+ method,
106
+ path: pathname
107
+ } = mockApi;
108
+
109
+ if (method.toLowerCase() === targetMethod.toLowerCase()) {
110
+ return (0, _pathToRegexp.match)(pathname, {
111
+ encode: encodeURI,
112
+ decode: decodeURIComponent
113
+ })(targetPathname);
114
+ }
115
+
116
+ return false;
117
+ });
118
+ return matched;
119
+ };
120
+
121
+ exports.getMatched = getMatched;
@@ -9,36 +9,15 @@ var _path = _interopRequireDefault(require("path"));
9
9
 
10
10
  var _utils = require("@modern-js/utils");
11
11
 
12
- var _pathToRegexp = require("path-to-regexp");
13
-
14
12
  var _constants = require("../../constants");
15
13
 
16
- var _getMockData = _interopRequireDefault(require("./getMockData"));
14
+ var _getMockData = _interopRequireWildcard(require("./getMockData"));
17
15
 
18
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+ 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
17
 
20
- const getMatched = (context, mockApiList) => {
21
- const {
22
- path: targetPathname,
23
- method: targetMethod
24
- } = context;
25
- const matched = mockApiList.find(mockApi => {
26
- const {
27
- method,
28
- path: pathname
29
- } = mockApi;
30
-
31
- if (method.toLowerCase() === targetMethod.toLowerCase()) {
32
- return (0, _pathToRegexp.match)(pathname, {
33
- encode: encodeURI,
34
- decode: decodeURIComponent
35
- })(targetPathname);
36
- }
18
+ 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; }
37
19
 
38
- return false;
39
- });
40
- return matched;
41
- };
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
42
21
 
43
22
  const createMockHandler = ({
44
23
  pwd
@@ -69,7 +48,7 @@ const createMockHandler = ({
69
48
  const {
70
49
  res
71
50
  } = context;
72
- const matched = getMatched(context, apiList);
51
+ const matched = (0, _getMockData.getMatched)(context, apiList);
73
52
 
74
53
  if (!matched) {
75
54
  return next();
@@ -20,6 +20,7 @@ class SocketServer {
20
20
  this.options = void 0;
21
21
  this.app = void 0;
22
22
  this.stats = void 0;
23
+ this.timer = null;
23
24
  this.options = options;
24
25
  } // create socket, install socket handler, bind socket event
25
26
 
@@ -44,7 +45,7 @@ class SocketServer {
44
45
  // only dev server, use default logger
45
46
  _utils.logger.error(err);
46
47
  });
47
- setInterval(() => {
48
+ this.timer = setInterval(() => {
48
49
  this.wsServer.clients.forEach(socket => {
49
50
  const extWs = socket;
50
51
 
@@ -57,49 +58,7 @@ class SocketServer {
57
58
  });
58
59
  }, 30000);
59
60
  this.wsServer.on('connection', socket => {
60
- const connection = socket;
61
- connection.isAlive = true;
62
- connection.on('pong', () => {
63
- connection.isAlive = true;
64
- });
65
-
66
- if (!connection) {
67
- return;
68
- }
69
-
70
- this.sockets.push(connection);
71
- connection.on('close', () => {
72
- const idx = this.sockets.indexOf(connection);
73
-
74
- if (idx >= 0) {
75
- this.sockets.splice(idx, 1);
76
- }
77
- });
78
-
79
- if (this.options.client.logging) {
80
- this.sockWrite('logging', this.options.client.logging);
81
- }
82
-
83
- if (this.options.hot || this.options.hot === 'only') {
84
- this.sockWrite('hot');
85
- }
86
-
87
- if (this.options.liveReload) {
88
- this.sockWrite('liveReload');
89
- }
90
-
91
- if (this.options.client.progress) {
92
- this.sockWrite('progress', this.options.client.progress);
93
- }
94
-
95
- if (this.options.client.overlay) {
96
- this.sockWrite('overlay', this.options.client.overlay);
97
- } // send first stats to active client sock if stats exist
98
-
99
-
100
- if (this.stats) {
101
- this.sendStats(true);
102
- }
61
+ this.onConnect(socket);
103
62
  });
104
63
  }
105
64
 
@@ -118,8 +77,68 @@ class SocketServer {
118
77
  });
119
78
  }
120
79
 
121
- close(connection) {
122
- connection.close();
80
+ singleWrite(socket, type, data) {
81
+ this.send(socket, JSON.stringify({
82
+ type,
83
+ data
84
+ }));
85
+ }
86
+
87
+ close() {
88
+ this.sockets.forEach(socket => {
89
+ socket.close();
90
+ });
91
+
92
+ if (this.timer) {
93
+ clearInterval(this.timer);
94
+ this.timer = null;
95
+ }
96
+ }
97
+
98
+ onConnect(socket) {
99
+ const connection = socket;
100
+ connection.isAlive = true;
101
+ connection.on('pong', () => {
102
+ connection.isAlive = true;
103
+ });
104
+
105
+ if (!connection) {
106
+ return;
107
+ }
108
+
109
+ this.sockets.push(connection);
110
+ connection.on('close', () => {
111
+ const idx = this.sockets.indexOf(connection);
112
+
113
+ if (idx >= 0) {
114
+ this.sockets.splice(idx, 1);
115
+ }
116
+ });
117
+
118
+ if (this.options.client.logging) {
119
+ this.singleWrite(connection, 'logging', this.options.client.logging);
120
+ }
121
+
122
+ if (this.options.hot || this.options.hot === 'only') {
123
+ this.singleWrite(connection, 'hot');
124
+ }
125
+
126
+ if (this.options.liveReload) {
127
+ this.singleWrite(connection, 'liveReload');
128
+ }
129
+
130
+ if (this.options.client.progress) {
131
+ this.singleWrite(connection, 'progress', this.options.client.progress);
132
+ }
133
+
134
+ if (this.options.client.overlay) {
135
+ this.singleWrite(connection, 'overlay', this.options.client.overlay);
136
+ } // send first stats to active client sock if stats exist
137
+
138
+
139
+ if (this.stats) {
140
+ this.sendStats(true);
141
+ }
123
142
  } // get standard stats
124
143
 
125
144
 
@@ -3,7 +3,9 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.getWatchedFiles = exports.default = void 0;
7
+
8
+ var _path = _interopRequireDefault(require("path"));
7
9
 
8
10
  var _chokidar = _interopRequireDefault(require("chokidar"));
9
11
 
@@ -18,12 +20,14 @@ const getWatchedFiles = watcher => {
18
20
  const files = [];
19
21
  Object.keys(watched).forEach(dir => {
20
22
  watched[dir].forEach(fileName => {
21
- files.push(`${dir}/${fileName}`);
23
+ files.push(_path.default.join(dir, fileName));
22
24
  });
23
25
  });
24
26
  return files;
25
27
  };
26
28
 
29
+ exports.getWatchedFiles = getWatchedFiles;
30
+
27
31
  class Watcher {
28
32
  constructor() {
29
33
  this.dependencyTree = null;
@@ -7,24 +7,29 @@ exports.StatsCache = void 0;
7
7
 
8
8
  var _fs = _interopRequireDefault(require("fs"));
9
9
 
10
+ var _crypto = _interopRequireDefault(require("crypto"));
11
+
10
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
13
 
12
14
  class StatsCache {
13
15
  constructor() {
14
- this.cachedStats = {};
16
+ this.cachedHash = {};
17
+ this.cachedSize = {};
15
18
  }
16
19
 
17
20
  add(files) {
18
21
  const {
19
- cachedStats
22
+ cachedHash,
23
+ cachedSize
20
24
  } = this;
21
25
 
22
26
  for (const filename of files) {
23
27
  if (_fs.default.existsSync(filename)) {
24
- const stat = _fs.default.statSync(filename);
28
+ const stats = _fs.default.statSync(filename);
25
29
 
26
- if (stat.isFile() && !cachedStats[filename]) {
27
- cachedStats[filename] = this.sign(stat);
30
+ if (stats.isFile() && !cachedHash[filename]) {
31
+ cachedHash[filename] = this.hash(stats, filename);
32
+ cachedSize[filename] = stats.size;
28
33
  }
29
34
  }
30
35
  }
@@ -32,34 +37,43 @@ class StatsCache {
32
37
 
33
38
  refresh(filename) {
34
39
  const {
35
- cachedStats
40
+ cachedHash,
41
+ cachedSize
36
42
  } = this;
37
43
 
38
44
  if (_fs.default.existsSync(filename)) {
39
- const stat = _fs.default.statSync(filename);
45
+ const stats = _fs.default.statSync(filename);
40
46
 
41
- if (stat.isFile()) {
42
- cachedStats[filename] = this.sign(stat);
47
+ if (stats.isFile()) {
48
+ cachedHash[filename] = this.hash(stats, filename);
49
+ cachedSize[filename] = stats.size;
43
50
  }
44
51
  }
45
52
  }
46
53
 
47
54
  del(filename) {
48
- if (this.cachedStats[filename]) {
49
- delete this.cachedStats[filename];
55
+ if (this.cachedHash[filename]) {
56
+ delete this.cachedHash[filename];
57
+ delete this.cachedSize[filename];
50
58
  }
51
59
  }
52
60
 
53
61
  isDiff(filename) {
54
62
  const {
55
- cachedStats
63
+ cachedHash,
64
+ cachedSize
56
65
  } = this;
57
66
 
58
- const stat = _fs.default.statSync(filename);
67
+ const stats = _fs.default.statSync(filename);
68
+
69
+ const hash = cachedHash[filename];
70
+ const size = cachedSize[filename];
59
71
 
60
- const cachedStat = cachedStats[filename];
72
+ if (stats.size !== size) {
73
+ return true;
74
+ }
61
75
 
62
- if (this.sign(stat) !== cachedStat) {
76
+ if (this.hash(stats, filename) !== hash) {
63
77
  return true;
64
78
  }
65
79
 
@@ -67,12 +81,11 @@ class StatsCache {
67
81
  }
68
82
 
69
83
  has(filename) {
70
- return Boolean(this.cachedStats[filename]);
71
- } // Todo size 其实有点问题,修改单个字符会导致触发不了 change
72
-
84
+ return Boolean(this.cachedHash[filename]);
85
+ }
73
86
 
74
- sign(stat) {
75
- return stat.size;
87
+ hash(stats, filename) {
88
+ return _crypto.default.createHash('md5').update(_fs.default.readFileSync(filename)).digest('hex');
76
89
  }
77
90
 
78
91
  }
@@ -31,10 +31,12 @@ class ModernServerContext {
31
31
  this.params = {};
32
32
  this.logger = void 0;
33
33
  this.metrics = void 0;
34
+ this.serverData = void 0;
34
35
  this.req = req;
35
36
  this.res = res;
36
37
  this.logger = req.logger;
37
38
  this.metrics = req.metrics;
39
+ this.serverData = {};
38
40
  this.bind();
39
41
  }
40
42
 
@@ -53,6 +55,10 @@ class ModernServerContext {
53
55
  this.params = params;
54
56
  }
55
57
 
58
+ setServerData(key, value) {
59
+ this.serverData[key] = value;
60
+ }
61
+
56
62
  getReqHeader(key) {
57
63
  const {
58
64
  req
@@ -6,15 +6,17 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.createRouteAPI = void 0;
7
7
 
8
8
  class RouteAPI {
9
- constructor(matched, router) {
9
+ constructor(matched, router, url) {
10
10
  this.router = void 0;
11
11
  this.current = void 0;
12
+ this.url = void 0;
12
13
  this.current = matched;
13
14
  this.router = router;
15
+ this.url = url;
14
16
  }
15
17
 
16
18
  cur() {
17
- return this.current.generate();
19
+ return this.current.generate(this.url);
18
20
  }
19
21
 
20
22
  get(entryName) {
@@ -22,7 +24,7 @@ class RouteAPI {
22
24
  router
23
25
  } = this;
24
26
  const matched = router.matchEntry(entryName);
25
- return matched ? matched.generate() : null;
27
+ return matched ? matched.generate(this.url) : null;
26
28
  }
27
29
 
28
30
  use(entryName) {
@@ -41,6 +43,6 @@ class RouteAPI {
41
43
 
42
44
  }
43
45
 
44
- const createRouteAPI = (matched, router) => new RouteAPI(matched, router);
46
+ const createRouteAPI = (matched, router, url) => new RouteAPI(matched, router, url);
45
47
 
46
48
  exports.createRouteAPI = createRouteAPI;
@@ -64,6 +64,7 @@ const createRenderHandler = ({
64
64
  const result = await ssr.render(ctx, {
65
65
  distDir,
66
66
  entryName: route.entryName,
67
+ urlPath: route.urlPath,
67
68
  bundle: route.bundle,
68
69
  template: templateHTML,
69
70
  staticGenerate
@@ -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 => {
@@ -11,12 +11,15 @@ var _utils = require("@modern-js/utils");
11
11
 
12
12
  var _mimeTypes = _interopRequireDefault(require("mime-types"));
13
13
 
14
+ var _cookie = _interopRequireDefault(require("cookie"));
15
+
14
16
  var _cache = _interopRequireDefault(require("./cache"));
15
17
 
16
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
19
 
18
20
  const render = async (ctx, renderOptions, runner) => {
19
21
  const {
22
+ urlPath,
20
23
  bundle,
21
24
  distDir,
22
25
  template,
@@ -28,11 +31,14 @@ const render = async (ctx, renderOptions, runner) => {
28
31
 
29
32
  const context = {
30
33
  request: {
34
+ baseUrl: urlPath,
31
35
  params: ctx.params,
32
36
  pathname: ctx.path,
37
+ host: ctx.host,
33
38
  query: ctx.query,
34
- headers: ctx.headers,
35
- cookie: ctx.headers.cookie
39
+ url: ctx.href,
40
+ cookieMap: _cookie.default.parse(ctx.headers.cookie || ''),
41
+ headers: ctx.headers
36
42
  },
37
43
  redirection: {},
38
44
  template,
@@ -23,7 +23,6 @@ class RouteMatchManager {
23
23
 
24
24
  filter(pathname) {
25
25
  return this.matchers.reduce((matches, matcher) => {
26
- // 非网关来的,或网关匹配上之后,内部再进行一次自己的匹配
27
26
  if (matcher.matchUrlPath(pathname)) {
28
27
  matches.push(matcher);
29
28
  }