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
40 changes: 38 additions & 2 deletions docs/guide/essentials/config/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

WXT includes a system that lets you hook into the build process and make changes.

Here's an example hook that modifies the `manifest.json` file before it is written to the output directory:
## Adding Hooks

The easiest way to add a hook is via the `wxt.config.ts`. Here's an example hook that modifies the `manifest.json` file before it is written to the output directory:

```ts
// wxt.config.ts
Expand All @@ -17,6 +19,40 @@ export default defineConfig({
});
```

> Most hooks provide the `wxt` object as the first argument. It contains the resolved config and other info about the current build.
Most hooks provide the `wxt` object as the first argument. It contains the resolved config and other info about the current build. The other arguments can be modified by reference to change different parts of the build system.

Putting one-off hooks like this in your config file is simple, but if you find yourself writing lots of hooks, you should extract them into [WXT Modules](/guide/essentials/wxt-modules) instead.

## Execution Order

Because hooks can be defined in multiple places, including [WXT Modules](/guide/essentials/wxt-modules), the order which they're executed can matter. Hooks are executed in the following order:

1. NPM modules in the order listed in the [`modules` config](/api/reference/wxt/interfaces/InlineConfig#modules)
2. User modules in [`/modules` folder](/guide/essentials/project-structure), loaded alphabetically
3. Hooks listed in your `wxt.config.ts`

To see the order for your project, run `wxt prepare --debug` flag and search for the "Hook execution order":

```
⚙ Hook execution order:
⚙ 1. wxt:built-in:unimport
⚙ 2. src/modules/auto-icons.ts
⚙ 3. src/modules/example.ts
⚙ 4. src/modules/i18n.ts
⚙ 5. wxt.config.ts > hooks
```

Changing execution order is simple:

- Prefix your user modules with a number (lower numbers are loaded first):
<!-- prettier-ignore -->
```html
📁 modules/
📄 0.my-module.ts
📄 1.another-module.ts
```
- If you need to run an NPM module after user modules, just make it a user module and prefix the filename with a number!
```ts
// modules/2.i18n.ts
export { default } from '@wxt-dev/i18n/module';
```
4 changes: 4 additions & 0 deletions docs/guide/essentials/wxt-modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ Build-time options are placed in your `wxt.config.ts`, while runtime options is

If you use TypeScript, modules augment WXT's types so you will get type errors if options are missing or incorrect.

## Execution Order

Modules are loaded in the same order as hooks are executed. Refer to the [Hooks documentation](/guide/essentials/config/hooks#execution-order) for more details.

## Writing Modules

Here's what a basic WXT module looks like:
Expand Down
2 changes: 2 additions & 0 deletions packages/wxt/src/core/resolve-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,8 @@ export async function resolveWxtUserModules(
cwd: modulesDir,
onlyFiles: true,
}).catch(() => []);
// Sort modules to ensure a consistent execution order
localModulePaths.sort();
const localModules = await Promise.all<WxtModuleWithMetadata<any>>(
localModulePaths.map(async (file) => {
const absolutePath = normalizePath(path.resolve(modulesDir, file));
Expand Down
15 changes: 15 additions & 0 deletions packages/wxt/src/core/wxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { createHooks } from 'hookable';
import { createWxtPackageManager } from './package-managers';
import { createViteBuilder } from './builders/vite';
import { builtinModules } from '../builtin-modules';
import { relative } from 'path';

/**
* Global variable set once `createWxt` is called once. Since this variable is used everywhere, this
Expand Down Expand Up @@ -66,6 +67,20 @@ export async function registerWxt(

// Initialize hooks
wxt.hooks.addHooks(config.hooks);
if (wxt.config.debug) {
const order = [
...builtinModules.map((module) => module.name),
...config.userModules.map((module) =>
relative(wxt.config.root, module.id),
),
'wxt.config.ts > hooks',
];
wxt.logger.debug('Hook execution order:');
order.forEach((name, i) => {
wxt.logger.debug(` ${i + 1}. ${name}`);
});
}

await wxt.hooks.callHook('ready', wxt);
}

Expand Down