函数
¥Functions
Page summary:
src/indexhosts global register, bootstrap, and destroy functions to run logic during application lifecycle.
可用模式
¥Available modes
生命周期函数支持 3 种执行模式,因此你可以根据它们管理的依赖进行调整。Strapi 会等待每个函数完成,无论它是正常返回、解析 async 函数还是解析 Promise,然后再继续执行启动或关闭操作。
¥Lifecycle functions support 3 execution patterns/modes so you can align them with the dependencies they manage. Strapi waits for each function to finish, whether it returns normally, resolves an async function, or resolves a promise, before moving on with startup or shutdown.
Strapi 不使用返回值,因此函数应仅在设置或清理完成后才解析(或返回),并在失败时抛出异常或拒绝。
¥Return values aren't used by Strapi, so the functions should resolve (or return) only when their setup or cleanup is complete and throw or reject to signal a failure.
同步
¥Synchronous
同步函数运行的逻辑会立即完成,无需等待其他异步任务。
¥Synchronous functions run logic that completes immediately without awaiting other asynchronous tasks.
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
strapi.log.info('Registering static configuration');
},
bootstrap({ strapi }) {
strapi.log.info('Bootstrap finished without awaiting tasks');
},
destroy({ strapi }) {
strapi.log.info('Server shutdown started');
}
};
export default {
register({ strapi }) {
strapi.log.info('Registering static configuration');
},
bootstrap({ strapi }) {
strapi.log.info('Bootstrap finished without awaiting tasks');
},
destroy({ strapi }) {
strapi.log.info('Server shutdown started');
}
};
异步
¥Asynchronous
异步函数使用 async 关键字在 Strapi 继续执行之前调用 await 任务,例如 API 调用或数据库查询。
¥Asynchronous functions use the async keyword to await tasks such as API calls or database queries before Strapi continues.
- JavaScript
- TypeScript
module.exports = {
async register({ strapi }) {
await new Promise((resolve) => setTimeout(resolve, 200));
strapi.log.info('Async register finished after a short delay');
},
async bootstrap({ strapi }) {
const { results: articles } = await strapi
.documents('api::article.article')
.findMany({
filters: { publishedAt: { $notNull: true } },
fields: ['id'],
});
strapi.log.info(`Indexed ${articles.length} published articles`);
},
async destroy({ strapi }) {
await strapi.documents('api::temporary-cache.temporary-cache').deleteMany({
filters: {},
});
}
};
export default {
async register({ strapi }) {
await new Promise((resolve) => setTimeout(resolve, 200));
strapi.log.info('Async register finished after a short delay');
},
async bootstrap({ strapi }) {
const { results: articles } = await strapi
.documents('api::article.article')
.findMany({
filters: { publishedAt: { $notNull: true } },
fields: ['id'],
});
strapi.log.info(`Indexed ${articles.length} published articles`);
},
async destroy({ strapi }) {
await strapi.documents('api::temporary-cache.temporary-cache').deleteMany({
filters: {},
});
}
};
返回 Promise
¥Returning a promise
返回 Promise 的函数会返回一个 Promise,以便 Strapi 可以等待其解析后再继续执行。
¥Promise-returning functions hand back a promise so Strapi can wait for its resolution before continuing.
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
return new Promise((resolve) => {
strapi.log.info('Registering with a delayed startup task');
setTimeout(resolve, 200);
});
},
bootstrap({ strapi }) {
return new Promise((resolve, reject) => {
strapi
.documents('api::category.category')
.findMany({ filters: { slug: 'general' }, pageSize: 1 })
.then(({ results }) => {
if (results.length === 0) {
return strapi.documents('api::category.category').create({
data: { name: 'General', slug: 'general' },
});
}
return results[0];
})
.then(() => {
strapi.log.info('Ensured default category exists');
resolve();
})
.catch(reject);
});
},
destroy({ strapi }) {
return new Promise((resolve, reject) => {
strapi
.documents('api::temporary-cache.temporary-cache')
.deleteMany({ filters: {} })
.then(() => {
strapi.log.info('Cleared temporary cache before shutdown');
resolve();
})
.catch(reject);
});
}
};
export default {
register({ strapi }) {
return new Promise((resolve) => {
strapi.log.info('Registering with a delayed startup task');
setTimeout(resolve, 200);
});
},
bootstrap({ strapi }) {
return new Promise((resolve, reject) => {
strapi
.documents('api::category.category')
.findMany({ filters: { slug: 'general' }, pageSize: 1 })
.then(({ results }) => {
if (results.length === 0) {
return strapi.documents('api::category.category').create({
data: { name: 'General', slug: 'general' },
});
}
return results[0];
})
.then(() => {
strapi.log.info('Ensured default category exists');
resolve();
})
.catch(reject);
});
},
destroy({ strapi }) {
return new Promise((resolve, reject) => {
strapi
.documents('api::temporary-cache.temporary-cache')
.deleteMany({ filters: {} })
.then(() => {
strapi.log.info('Cleared temporary cache before shutdown');
resolve();
})
.catch(reject);
});
}
};
生命周期函数
¥Lifecycle functions
生命周期函数允许你在 Strapi 启动和关闭的特定阶段放置代码。
¥Lifecycle functions let you place code at specific phases of Strapi's startup and shutdown.
-
register()函数用于服务启动前的配置时设置。¥The
register()function is for configuration-time setup before services start. -
bootstrap()函数用于需要 Strapi API 的初始化。¥The
bootstrap()function is for initialization that needs Strapi's APIs. -
destroy()函数用于应用停止时的清理工作。¥The
destroy()function is for teardown when the application stops.
注册
¥Register
register 生命周期函数可在 ./src/index.js(或 ./src/index.ts)中找到,是一个在应用初始化之前运行的异步函数。
¥The register lifecycle function, found in ./src/index.js (or in ./src/index.ts), is an asynchronous function that runs before the application is initialized.
register() 是 Strapi 应用启动时发生的第一件事。这发生在任何设置过程之前,并且你无权访问 register() 函数中的数据库、路由、策略或任何其他后端服务器元素。
¥register() is the very first thing that happens when a Strapi application is starting. This happens before any setup process and you don't have any access to database, routes, policies, or any other backend server elements within the register() function.
register() 函数可用于:
¥The register() function can be used to:
-
以编程方式扩展 content-types
¥extend content-types programmatically
-
加载一些 环境变量
¥load some environment variables
-
注册仅由当前 Strapi 应用使用的 自定义字段,
¥register a custom field that would be used only by the current Strapi application,
-
注册 用户和权限插件的自定义提供程序。
¥register a custom provider for the Users & Permissions plugin.
更具体地说,register() 的一个典型用例包括预先加载安全任务,例如在应用完成初始化之前加载密钥、轮换 API 密钥或注册身份验证提供程序。
¥More specifically, typical use-cases for register() include front-load security tasks such as loading secrets, rotating API keys, or registering authentication providers before the app finishes initializing.
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
strapi.customFields.register({
name: 'color',
plugin: 'my-color-picker',
type: 'string',
});
},
};
export default {
register({ strapi }) {
strapi.customFields.register({
name: 'color',
plugin: 'my-color-picker',
type: 'string',
});
},
};
引导程序
¥Bootstrap
在 ./src/index.js(或 ./src/index.ts)中找到的 bootstrap 生命周期函数在每次服务器启动时都会被调用。
¥The bootstrap lifecycle function, found in ./src/index.js (or in ./src/index.ts), is called at every server start.
bootstrap() 在后端服务器启动之前、Strapi 应用设置完成后运行,因此你可以访问 strapi 对象中的任何内容。
¥bootstrap() is run before the back-end server starts but after the Strapi application has setup, so you have access to anything from the strapi object.
bootstrap 函数可用于:
¥The bootstrap function can be used to:
-
如果没有管理员用户,请创建一个
¥create an admin user if there isn't one
-
用一些必要的数据填充数据库
¥fill the database with some necessary data
-
声明 基于角色的访问控制 (RBAC) 功能的自定义条件
¥declare custom conditions for the Role-Based Access Control (RBAC) feature
更具体地说,bootstrap() 的一个典型用例是支持编辑工作流程。例如,通过填充初始内容、附加 Webhook 或在启动时安排 cron 作业。
¥More specifically, a typical use-case for bootstrap() is supporting editorial workflows. For example by seeding starter content, attaching webhooks, or scheduling cron jobs at startup.
你可以在终端中运行 yarn strapi console(或 npm run strapi console)并与 strapi 对象进行交互。
¥You can run yarn strapi console (or npm run strapi console) in the terminal and interact with the strapi object.
- JavaScript
- TypeScript
module.exports = {
async bootstrap({ strapi }) {
const { results } = await strapi
.documents('api::category.category')
.findMany({ filters: { slug: 'general' }, pageSize: 1 });
if (results.length === 0) {
await strapi.documents('api::category.category').create({
data: { name: 'General', slug: 'general' },
});
strapi.log.info('Created default category');
}
},
};
export default {
async bootstrap({ strapi }) {
const { results } = await strapi
.documents('api::category.category')
.findMany({ filters: { slug: 'general' }, pageSize: 1 });
if (results.length === 0) {
await strapi.documents('api::category.category').create({
data: { name: 'General', slug: 'general' },
});
strapi.log.info('Created default category');
}
},
};
销毁
¥Destroy
destroy 函数位于 ./src/index.js(或 ./src/index.ts)中,是一个异步函数,在应用关闭之前运行。
¥The destroy function, found in ./src/index.js (or in ./src/index.ts), is an asynchronous function that runs before the application gets shut down.
destroy 函数可用于优雅地:
¥The destroy function can be used to gracefully:
-
停止正在运行的 services
¥stop services that are running
-
清理插件操作(例如关闭连接、删除监听器等)
¥clean up plugin actions (e.g. close connections, remove listeners, etc.)
更具体地说,destroy() 的一个典型用例是处理操作清理,例如关闭数据库或队列连接以及移除监听器,以便应用可以正常关闭。
¥More specifically, a typical use-case for destroy() is to handle operational clean-up, such as closing database or queue connections and removing listeners so the application can shut down cleanly.
- JavaScript
- TypeScript
let heartbeat;
module.exports = {
async bootstrap({ strapi }) {
heartbeat = setInterval(() => {
strapi.log.debug('Heartbeat interval running');
}, 60_000);
},
async destroy() {
clearInterval(heartbeat);
},
};
let heartbeat: ReturnType<typeof setInterval>;
export default {
async bootstrap({ strapi }) {
heartbeat = setInterval(() => {
strapi.log.debug('Heartbeat interval running');
}, 60_000);
},
async destroy() {
clearInterval(heartbeat);
},
};
用法
¥Usage
组合使用
¥Combined usage
所有 3 个生命周期函数可以组合使用,以配置应用启动和关闭期间的自定义行为。
¥All 3 lifecycle functions can be put together to configure custom behavior during application startup and shutdown.
-
确定逻辑的运行时间。
¥Decide when your logic should run.
-
在
register()中添加仅初始化任务(例如,注册自定义字段或提供程序)。¥Add initialization-only tasks (e.g. registering a custom field or provider) in
register(). -
在
bootstrap()中添加需要完全访问 Strapi 的启动任务(例如,填充数据或附加 Webhook)。¥Add startup tasks that need full Strapi access (e.g. seeding or attaching webhooks) in
bootstrap(). -
在
destroy()中添加清理逻辑(例如,关闭外部连接)。¥Add cleanup logic (e.g. closing external connections) in
destroy().
-
-
将代码放置在
src/index.js|ts中。保持register()代码简洁,因为它在 Strapi 完全设置之前运行。¥Place the code in
src/index.js|ts. Keepregister()lean because it runs before Strapi is fully set up. -
重启 Strapi 以确认每个生命周期按顺序执行。
¥Restart Strapi to confirm each lifecycle executes in sequence.
let cronJobKey: string | undefined;
export default {
register({ strapi }) {
strapi.customFields.register({
name: 'color',
type: 'string',
plugin: 'color-picker',
});
},
async bootstrap({ strapi }) {
cronJobKey = 'log-reminders';
strapi.cron.add({
[cronJobKey]: {
rule: '0 */6 * * *', // every 6 hours
job: async () => {
strapi.log.info('Remember to review new content in the admin panel.');
},
},
});
},
async destroy({ strapi }) {
if (cronJobKey) {
strapi.cron.remove(cronJobKey);
}
},
};
你可能会在 这篇博客文章 中找到有关注册生命周期函数的其他信息。
¥You might find additional information in this blog article about registering lifecycle functions.