Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,8 @@
"engines": {
"node": ">=22.18.0"
},
"optionalDependencies": {
"@utoo/utoo-mingw64_nt-10.0-26100-x64": "npm:@utoo/utoo-win32-x64@1.0.28"
},
Comment thread
killagu marked this conversation as resolved.
"packageManager": "pnpm@10.28.0"
}
20 changes: 13 additions & 7 deletions packages/core/src/lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,14 +254,20 @@ export class Lifecycle extends EventEmitter {
}

async close(): Promise<void> {
// close in reverse order: first created, last closed
const closeFns = Array.from(this.#closeFunctionSet);
debug('%s start trigger %d beforeClose functions', this.app.type, closeFns.length);
for (const fn of closeFns.reverse()) {
debug('%s trigger beforeClose at %o', this.app.type, fn.fullPath);
await utils.callFn(fn);
this.#closeFunctionSet.delete(fn);
if (this.#metadataOnly || this.#snapshotBuilding) {
debug('%s skip beforeClose functions in early-exit lifecycle mode', this.app.type);
this.#closeFunctionSet.clear();
} else {
// close in reverse order: first created, last closed
const closeFns = Array.from(this.#closeFunctionSet);
debug('%s start trigger %d beforeClose functions', this.app.type, closeFns.length);
for (const fn of closeFns.reverse()) {
debug('%s trigger beforeClose at %o', this.app.type, fn.fullPath);
await utils.callFn(fn);
this.#closeFunctionSet.delete(fn);
}
}

// Be called after other close callbacks
this.app.emit('close');
this.removeAllListeners();
Expand Down
29 changes: 29 additions & 0 deletions packages/core/test/snapshot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,35 @@ describe('test/snapshot.test.ts', () => {
// beforeClose is registered during configDidLoad iteration, which is skipped
assert.ok(!beforeCloseCalled, 'beforeClose should NOT be called since configDidLoad is skipped');
});

it('should skip app.beforeClose callbacks when closing during snapshot build', async () => {
let beforeCloseCalled = false;
app = new EggCore({ snapshot: true });

app.lifecycle.addBootHook(
class Boot {
app: EggCore;

constructor(app: EggCore) {
this.app = app;
}

configWillLoad(): void {
this.app.beforeClose(() => {
beforeCloseCalled = true;
});
}
},
);

app.lifecycle.init();
app.lifecycle.triggerConfigWillLoad();
await app.ready();
await app.close();
app = undefined;

assert.ok(!beforeCloseCalled, 'app.beforeClose should NOT be called during snapshot build close');
});
});

describe('snapshotWillSerialize / snapshotDidDeserialize lifecycle hooks', () => {
Expand Down
3 changes: 3 additions & 0 deletions packages/egg/test/fixtures/apps/metadata-only-app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ module.exports = class MetadataOnlyBoot {
constructor(app) {
this.app = app;
app.bootLog = [];
app.beforeClose(() => {
app.bootLog.push('app.beforeClose');
});
}

configWillLoad() {
Expand Down
6 changes: 6 additions & 0 deletions packages/egg/test/start.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ describe('test/start.test.ts', () => {
});
});

it('should skip beforeClose callbacks when closing a metadataOnly app', async () => {
const app = await singleProcessApp('apps/metadata-only-app', { metadataOnly: true });
await app.close();
assert.deepStrictEqual(app.bootLog, ['loadMetadata']);
});

describe('normal mode (baseline)', () => {
let app: SingleModeApplication;

Expand Down
34 changes: 17 additions & 17 deletions tools/egg-bundler/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,28 @@ path is `<baseDir>/.egg/manifest.json`.

## Options

| Option | Description |
| --- | --- |
| `baseDir` | Application root directory. Required. |
| `outputDir` | Output directory for the bundled artifact. Required. |
| `manifestPath` | Path to `manifest.json`. Defaults to `<baseDir>/.egg/manifest.json`. |
| `framework` | Framework name or absolute path. Defaults to `egg`. |
| `mode` | Build mode, `production` or `development`. Defaults to `production`. |
| `tegg` | Accepted by `BundlerConfig`, but not applied by the current implementation yet. |
| `externals.force` | Package names to always keep external. |
| `externals.inline` | Package names to force inline even if auto-detected as external. |
| `pack.buildFunc` | Test hook for replacing the real `@utoo/pack` build entry. |
| `pack.rootPath` | Override the monorepo workspace root used by `@utoo/pack`. |
| Option | Description |
| ------------------ | ------------------------------------------------------------------------------- |
| `baseDir` | Application root directory. Required. |
| `outputDir` | Output directory for the bundled artifact. Required. |
| `manifestPath` | Path to `manifest.json`. Defaults to `<baseDir>/.egg/manifest.json`. |
| `framework` | Framework name or absolute path. Defaults to `egg`. |
| `mode` | Build mode, `production` or `development`. Defaults to `production`. |
| `tegg` | Accepted by `BundlerConfig`, but not applied by the current implementation yet. |
| `externals.force` | Package names to always keep external. |
| `externals.inline` | Package names to force inline even if auto-detected as external. |
| `pack.buildFunc` | Test hook for replacing the real `@utoo/pack` build entry. |
| `pack.rootPath` | Override the monorepo workspace root used by `@utoo/pack`. |
Comment thread
killagu marked this conversation as resolved.

## Result

`bundle()` resolves with:

| Field | Description |
| --- | --- |
| `outputDir` | Absolute output directory. |
| `files` | Sorted absolute paths for files written into the artifact. |
| `manifestPath` | Absolute path to `bundle-manifest.json`. |
| Field | Description |
| -------------- | ---------------------------------------------------------- |
| `outputDir` | Absolute output directory. |
| `files` | Sorted absolute paths for files written into the artifact. |
| `manifestPath` | Absolute path to `bundle-manifest.json`. |

## Running The Bundle

Expand Down
Loading