插件
NuxtCMS 的插件分两类,都在「后台 → 插件」统一管理:
| 运行时插件 | 代码包插件 | |
|---|---|---|
| 形态 | 一个 JSON 清单 nuxtcms.plugin.json | 一个 Nuxt Layer(npm 包 / Git 仓库) |
| 能力 | 设置项、注入代码、CSP 白名单、事件 Webhook、定时任务 | 以上全部 + 页面、组件、API、数据库表 |
| 安装 | 后台在线安装,无需重新构建,所有部署形态通用 | plugin.mjs add 后重新构建部署 |
| 典型 | 统计代码、在线客服、群机器人通知、搜索推送 | 会员、商城、表单设计器 |
官方插件中心
官网(https://insightme.top,NUXT_PLUGIN_HUB_URL 可改)就是插件中心,提供一条龙服务:
- 注册账号:官网
/account/register。 - 绑定站点:官网「账号 → API 令牌」创建令牌,粘贴到站点「后台 → 插件 → 账号与授权」。令牌只保存在服务端。
- 在线下载安装:插件市场里点「安装」,免费插件直接装好;有新版本时显示「更新到 vX」。
- 积分购买:付费插件标价为积分,点「N 积分购买」即扣积分并为当前域名签发授权。积分暂不支持在线支付,联系管理员充值。
- 联系授权:需要多站点授权、试用或报价,点「联系授权」,留言连同域名提交到官网后台,由管理员处理并发放授权码。
- 授权关联:授权绑定域名(
NUXT_PUBLIC_SITE_URL的 host)。也可以在插件设置里手动填写授权码。授权每天由 cron 复核一次;插件中心暂时连不上时保留上次结果,不会让正常运行的站点突然失效。
未授权的付费插件可以先安装和配置,但不会生效(不注入代码、不触发 Webhook)。
插件中心不可达时(内网、离线),市场自动切换为框架内置的官方插件(plugins/official/*.json),免费插件照常安装。
运行时插件清单
{
"id": "my-plugin",
"name": { "zh": "我的插件", "us": "My plugin" },
"version": "1.0.0",
"description": { "zh": "做什么用的", "us": "What it does" },
"requires": ">=1.3.0",
"category": "analytics",
"icon": "i-lucide-bar-chart-3",
"license": "free",
"settings": [
{ "key": "siteId", "label": "站点 ID", "type": "text", "required": true }
],
"inject": [
{ "position": "head", "when": "siteId", "html": "<script src=\"https://cdn.example.com/a.js?id={{settings.siteId}}\" async></script>" }
],
"csp": { "script-src": ["https://cdn.example.com"] },
"webhooks": [
{ "event": "contact.created", "url": "https://hooks.example.com/x", "body": { "text": "{{event.name}}:{{event.message}}" } }
],
"tasks": [
{ "name": "每日同步", "cron": "0 3 * * *", "url": "{{site.url}}/api/cron/xxx", "headers": { "Authorization": "Bearer {{cronSecret}}" } }
]
}
| 字段 | 说明 |
|---|---|
id | 小写字母、数字、短横线,全局唯一 |
name / description / label / help | 字符串或 { "zh": "...", "us": "..." } |
version | semver;市场据此提示更新 |
requires | 需要的最低 NuxtCMS 版本 |
license / priceCredits | free 或 paid(付费插件只能从插件中心安装) |
settings[].type | text textarea number boolean select secret url;secret 不回显给浏览器 |
inject[] | position: head / body;scope: public(默认,只在前台)/ all;when: 某个设置为真时才注入;raw: true 表示设置值本身就是 HTML(不转义) |
csp | 注入代码需要的外部域名。只有真正注入了代码的页面才会放开,没装插件的站点保持严格策略 |
webhooks[] | event 见下表;url / headers / body 都可以用模板 |
tasks[] | 安装时写入「定时任务」,由 cron 调度器执行;插件停用时任务一起停用,卸载时删除 |
模板变量
{{settings.xxx}}、{{site.url}}、{{site.name}}、{{event.xxx}}(Webhook)、{{cronSecret}}(任务)。注入 HTML 时变量会做 HTML 转义,防止设置值破坏页面。
事件
| 事件 | 时机 | 载荷 |
|---|---|---|
contact.created | 前台提交联系表单 | name email phone message createdAt |
content.published | 文章 / 页面 / 产品发布(含定时发布到点) | kind id title slug locale status url |
content.updated | 内容被修改 | 同上 |
content.deleted | 内容被删除 | 同上 |
plugin.installed | 插件安装或更新 | id version updated |
Webhook 在响应之后执行(Cloudflare 上用 waitUntil),失败只记日志,不影响用户操作。
本地调试
「后台 → 插件 → 开发者」可粘贴或上传清单直接安装,修改后再次导入即覆盖(设置保留)。
代码包插件
一个普通的 Nuxt Layer,根目录放 nuxtcms.plugin.json("kind": "package"),在 Nitro 插件里注册:
// server/plugins/my-plugin.ts
import manifest from '../../nuxtcms.plugin.json'
export default defineNitroPlugin(() => {
defineCmsPlugin(manifest, ({ on }) => {
on('content.published', async (payload) => {
// 插件停用或未授权时不会被调用
})
})
})
代码包插件给后台加菜单(app.config.ts):
export default defineAppConfig({
nuxtcms: { adminNav: [{ label: '我的插件', icon: 'i-lucide-puzzle', to: '/admin/my-plugin', adminOnly: true, after: 'plugins' }] },
})
在 API 里判断是否可用、读取设置:
export default defineEventHandler(async (event) => {
if (!(await isPluginActive(event, 'my-plugin'))) throw createError({ statusCode: 404 })
const settings = await getPluginSettings(event, 'my-plugin')
// ...
})
安装 / 卸载(在站点项目目录执行,然后重新构建部署):
node node_modules/nuxtcms/scripts/plugin.mjs list
node node_modules/nuxtcms/scripts/plugin.mjs add my-plugin --license NCMS-XXXX # 从插件中心按 id 安装
node node_modules/nuxtcms/scripts/plugin.mjs add github:you/nuxtcms-plugin-x#v1.0.0
node node_modules/nuxtcms/scripts/plugin.mjs remove my-plugin
CLI 会用项目的包管理器安装依赖,并记录到 nuxtcms.plugins.json;基座的 nuxt.config.ts 自动 extends 其中的包。带 --license 时授权码随构建下发,首次访问后台或 cron 运行时自动绑定并校验。
发布到官方插件中心
把清单(运行时插件)或包地址(代码包插件)提交给管理员,在官网后台「插件中心 → 插件」上架、定价(积分)。站点下次打开插件市场即可看到。