Skip to content

Commit 07e9277

Browse files
killaguclaude
andcommitted
feat(egg): skip loadRouter in metadataOnly mode
AppWorkerLoader.load() now gates loadRouter() behind !metadataOnly, allowing manifest-only startup to skip route registration entirely. This serves the egg-bin manifest generate command. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent aa1c3b2 commit 07e9277

File tree

6 files changed

+104
-63
lines changed

6 files changed

+104
-63
lines changed

packages/egg/src/lib/loader/AppWorkerLoader.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ export class AppWorkerLoader extends EggApplicationLoader {
3737
// app
3838
await this.loadController();
3939
// app
40-
await this.loadRouter(); // Depend on controllers
40+
if (!this.options.metadataOnly) {
41+
await this.loadRouter(); // Depend on controllers
42+
}
4143
}
4244
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
module.exports = class MetadataOnlyBoot {
2+
constructor(app) {
3+
this.app = app;
4+
app.bootLog = [];
5+
}
6+
7+
configWillLoad() {
8+
this.app.bootLog.push('configWillLoad');
9+
}
10+
11+
configDidLoad() {
12+
this.app.bootLog.push('configDidLoad');
13+
}
14+
15+
async didLoad() {
16+
this.app.bootLog.push('didLoad');
17+
}
18+
19+
async willReady() {
20+
this.app.bootLog.push('willReady');
21+
}
22+
23+
async didReady() {
24+
this.app.bootLog.push('didReady');
25+
}
26+
27+
async serverDidReady() {
28+
this.app.bootLog.push('serverDidReady');
29+
}
30+
31+
async beforeClose() {
32+
this.app.bootLog.push('beforeClose');
33+
}
34+
35+
async loadMetadata() {
36+
this.app.bootLog.push('loadMetadata');
37+
}
38+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = async function () {
2+
this.body = 'hello';
3+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = (app) => {
2+
app.get('/', app.controller.home);
3+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"name": "metadata-only-app"
3+
}

packages/egg/test/start.test.ts

Lines changed: 54 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,58 @@
1-
import { describe } from 'vitest';
1+
import { strict as assert } from 'node:assert';
22

3-
// import utils from '../utils';
4-
// import assert from 'assert';
5-
// import path from 'path';
3+
import { describe, it, afterAll, beforeAll } from 'vitest';
64

7-
// let app;
5+
import { singleProcessApp, type SingleModeApplication } from './utils.ts';
86

9-
describe.skip('test/lib/start.test.js', () => {
10-
// afterEach(() => app.close());
11-
// describe('start', () => {
12-
// it('should dump config and plugins', async () => {
13-
// app = await utils.singleProcessApp('apps/demo');
14-
// const baseDir = utils.getFilepath('apps/demo');
15-
// let json = require(path.join(baseDir, 'run/agent_config.json'));
16-
// assert(/\d+\.\d+\.\d+/.test(json.plugins.onerror.version));
17-
// assert(json.config.name === 'demo');
18-
// assert(json.config.tips === 'hello egg');
19-
// json = require(path.join(baseDir, 'run/application_config.json'));
20-
// checkApp(json);
21-
// const dumpped = app.dumpConfigToObject();
22-
// checkApp(dumpped.config);
23-
// function checkApp(json) {
24-
// assert(/\d+\.\d+\.\d+/.test(json.plugins.onerror.version));
25-
// assert(json.config.name === 'demo');
26-
// // should dump dynamic config
27-
// assert(json.config.tips === 'hello egg started');
28-
// }
29-
// });
30-
// it('should request work', async () => {
31-
// app = await utils.singleProcessApp('apps/demo');
32-
// await app.httpRequest().get('/protocol')
33-
// .expect(200)
34-
// .expect('http');
35-
// await app.httpRequest().get('/class-controller')
36-
// .expect(200)
37-
// .expect('this is bar!');
38-
// });
39-
// it('should env work', async () => {
40-
// app = await utils.singleProcessApp('apps/demo', { env: 'prod' });
41-
// assert(app.config.env === 'prod');
42-
// });
43-
// });
44-
// describe('custom framework work', () => {
45-
// it('should work with options.framework', async () => {
46-
// app = await utils.singleProcessApp('apps/demo', { framework: path.join(__dirname, '../fixtures/custom-egg') });
47-
// assert(app.customEgg);
48-
// await app.httpRequest().get('/protocol')
49-
// .expect(200)
50-
// .expect('http');
51-
// await app.httpRequest().get('/class-controller')
52-
// .expect(200)
53-
// .expect('this is bar!');
54-
// });
55-
// it('should work with package.egg.framework', async () => {
56-
// app = await utils.singleProcessApp('apps/custom-framework-demo');
57-
// assert(app.customEgg);
58-
// await app.httpRequest().get('/protocol')
59-
// .expect(200)
60-
// .expect('http');
61-
// await app.httpRequest().get('/class-controller')
62-
// .expect(200)
63-
// .expect('this is bar!');
64-
// });
65-
// });
7+
describe('test/start.test.ts', () => {
8+
describe('metadataOnly mode', () => {
9+
let app: SingleModeApplication;
10+
11+
beforeAll(async () => {
12+
app = await singleProcessApp('apps/metadata-only-app', { metadataOnly: true });
13+
});
14+
15+
afterAll(async () => {
16+
await app.close();
17+
});
18+
19+
it('should only call loadMetadata, not normal lifecycle hooks', () => {
20+
assert.deepStrictEqual(app.bootLog, ['loadMetadata']);
21+
});
22+
23+
it('should skip loadRouter — no routes registered', () => {
24+
assert.strictEqual(app.router.stack.length, 0);
25+
});
26+
27+
it('should not create agent', () => {
28+
assert.strictEqual(app.agent, undefined);
29+
});
30+
});
31+
32+
describe('normal mode (baseline)', () => {
33+
let app: SingleModeApplication;
34+
35+
beforeAll(async () => {
36+
app = await singleProcessApp('apps/metadata-only-app');
37+
});
38+
39+
afterAll(async () => {
40+
await app.close();
41+
});
42+
43+
it('should call normal lifecycle hooks, not loadMetadata', () => {
44+
assert(app.bootLog.includes('configDidLoad'));
45+
assert(app.bootLog.includes('didLoad'));
46+
assert(app.bootLog.includes('willReady'));
47+
assert(!app.bootLog.includes('loadMetadata'));
48+
});
49+
50+
it('should register routes', () => {
51+
assert(app.router.stack.length > 0);
52+
});
53+
54+
it('should create agent', () => {
55+
assert(app.agent);
56+
});
57+
});
6658
});

0 commit comments

Comments
 (0)