惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
A
About on SuperTechFans
D
DataBreaches.Net
量子位
云风的 BLOG
云风的 BLOG
T
The Blog of Author Tim Ferriss
U
Unit 42
M
MIT News - Artificial intelligence
小众软件
小众软件
博客园 - Franky
GbyAI
GbyAI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Help Net Security
Help Net Security
Recorded Future
Recorded Future
The Last Watchdog
The Last Watchdog
S
Secure Thoughts
S
Security @ Cisco Blogs
MongoDB | Blog
MongoDB | Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
IT之家
IT之家
L
LINUX DO - 热门话题
H
Hacker News: Front Page
V
Vulnerabilities – Threatpost
Security Latest
Security Latest
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 叶小钗
J
Java Code Geeks
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
PCI Perspectives
PCI Perspectives
Cyberwarzone
Cyberwarzone
S
Schneier on Security
Scott Helme
Scott Helme
Microsoft Security Blog
Microsoft Security Blog
Attack and Defense Labs
Attack and Defense Labs
T
The Exploit Database - CXSecurity.com
C
Cisco Blogs
Y
Y Combinator Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tenable Blog
Google DeepMind News
Google DeepMind News
T
Threat Research - Cisco Blogs
H
Hackread – Cybersecurity News, Data Breaches, AI and More
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V
V2EX
美团技术团队
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Know Your Adversary
Know Your Adversary

姓王者的博客

Linux用户Secure Boot自主维护指南 | 姓王者的博客 MAD Bugs 已经开始——关于信息安全的军备竞赛 | 姓王者的博客 解决钉钉Dingtalk无法在Linux新版内核上启动问题-修复可执行栈错误 | 姓王者的博客 突发:GitHub 正遭受大规模 Issue 赌博广告轰炸 | 姓王者的博客 Ubuntu26.04-beta体验:坚毅浣熊! | 姓王者的博客 fakeclaw装作龙虾发贴吧 | 姓王者的博客 找回12年前的QQ记忆 | 姓王者的博客 在Linux上玩Flash网页游戏-洛克王国 | 姓王者的博客 Copilot将使用交互数据来训练 | 姓王者的博客 重要通知-请更新我的GPG公钥 | 姓王者的博客 为了自由Android | 姓王者的博客 GPL"2,3"事 | 姓王者的博客 短文-对VitePlus的一点🤏小贡献 | 姓王者的博客 Bing收录没了?亲测有效的快速恢复指南 | 姓王者的博客 解决桌面设备二维码快速识别的工具-ClipQR | 姓王者的博客 解决 Nautilus 自定义终端插件安装依赖问题 | 姓王者的博客 OpenClaw 该熄火了 | 姓王者的博客 Vite8 - 统一的基建开始 | 姓王者的博客 Astro 6 推出啦 | 姓王者的博客 ubuntu的openvpn异常暂停推送更新 | 姓王者的博客 Ubuntu 24.04 安装 Win10 虚拟机 | 姓王者的博客 ESA-后记:热爱阿里云 | 姓王者的博客 Moonbit 0.8.0 重大发布,我也要改一下我的包 | 姓王者的博客 ESA Pages 边缘开发大赛获奖 | 姓王者的博客 Astro: 优化katex,mermaid和灯箱使用 | 姓王者的博客 从edgeone迁移到esa | 姓王者的博客 出租人类:AI时代的荒诞与真实 | 姓王者的博客 Astro 5.17构建性能优化实践:从18s到13s | 姓王者的博客 Moonbit License Checker 开发使用 | 姓王者的博客 Stalux Astro博客主题自荐 | 姓王者的博客 把Hexo永久链接迁移到Astro | 姓王者的博客 再见👋 LeanCloud | 姓王者的博客 2025年终总结 | 姓王者的博客 许可合规-fancybox | 姓王者的博客 博客主题的软著下来了 | 姓王者的博客 友链图谱 - 汇聚千丝万缕的联系 | 姓王者的博客 chen-er 专为Chen式ER图打造的npm包 | 姓王者的博客 为什么我推荐你使用GPG来加密你的邮件 | 姓王者的博客 2025第三方客户端登录东北大学邮箱 | 姓王者的博客 好久没更新了,过去与未来 | 姓王者的博客 1024 重要的日子 | 姓王者的博客 再也不见Windows10 | 姓王者的博客 偷梁换柱,解决Ubuntu24.04安装Packet Tracer缺失依赖问题 | 姓王者的博客 中秋-来试试Moonbit吧 | 姓王者的博客 Obsidian使用体验 | 姓王者的博客 猪猪侠·一只老猪的逆袭 | 姓王者的博客 国庆日纪念 | 姓王者的博客 GNU 42周年,AI时代的自由精神 | 姓王者的博客 解决Linux上启动游戏总是默认English的情况 | 姓王者的博客 7x24:运维使命 | 姓王者的博客 Tauri2.x实现系统菜单导航Vue路由 | 姓王者的博客 计算机图形学-基本图形生成算法 | 姓王者的博客 数据库原理-关系数据 | 姓王者的博客 数据库原理-设计技巧 | 姓王者的博客 数据库原理E-R模型 | 姓王者的博客 旧忆 - 我曾玩过的游戏 | 姓王者的博客 再谈自由软件 | 姓王者的博客 可能解决Tauri多窗口应用阻塞问题 | 姓王者的博客 Xingwangzhe! Z-Library We miss you and we need your help | 姓王者的博客 计算机组成原理第二章 - 定点数与浮点数 | 姓王者的博客 计算机组成原理第一章 | 姓王者的博客 不小心写死循环窗口弹出了 | 姓王者的博客 美化Grub界面 | 姓王者的博客 计算机图形学-图形的表示与数据结构 | 姓王者的博客 计算机图形学绪论 | 姓王者的博客 为什么说,大学教育与社会脱节 | 姓王者的博客 VSCode Remote 远程连接服务器记录 | 姓王者的博客 解决Tauri2.x拖拽事件问题 | 姓王者的博客 新学期第一课《计算机图形学》报告 | 姓王者的博客 Tauri在GNOME46+上通知无效的临时解决方法 | 姓王者的博客 窃文者:未经授权转载我文章 | 姓王者的博客 GPG公钥分享文化 | 姓王者的博客 解决在ubuntu上,打包vscode插件问题 | 姓王者的博客 伪造squaremap的玩家显示 | 姓王者的博客 爆,沉浸式翻译泄露敏感信息 | 姓王者的博客 读书:《Free as in Freedom》——若为自由故 | 姓王者的博客 首页文章列表懒加载优化 | 姓王者的博客 Ubuntu 24.04 安装 Vivado 2018.3 | 姓王者的博客 腾讯Edgeone免费版体验 | 姓王者的博客 在 Ubuntu 上实现 Thetis FIDO U2F 密钥登录 | 姓王者的博客 Thetis物理密钥,为什么我们应该使用物理密钥 | 姓王者的博客 高考生过来看!教你精准转换录取位次! | 姓王者的博客 ubuntu无法访问windows磁盘问题 | 姓王者的博客 收信有感,防范钓鱼邮件 | 姓王者的博客 自由不止软件-记录一次zlib上传书籍 | 姓王者的博客 时隔两年,通关夺命邮差2 | 姓王者的博客 博客一周年了,竟然坚持了下来 | 姓王者的博客 Minecraft大电影:不建不散! | 姓王者的博客 是时候了解docker了! | 姓王者的博客 编译原理:LL(1)文法 | 姓王者的博客 编译原理:文法转换 | 姓王者的博客 离散数学:子群的陪集及拉格朗日定理 | 姓王者的博客 离散数学:半群,独异点 | 姓王者的博客 《人工智能生成合成内容标识办法》与个人博客--我们应该做什么? | 姓王者的博客 通识学习:形式语言与自动机,布尔代数与数进制 | 姓王者的博客 Webmapview:一个我的世界内置网页地图浏览Fabric模组 | 姓王者的博客 海岛机器人农场试玩 | 姓王者的博客 正则表达式学习 | 姓王者的博客 抓取个人博客文章目录到github主页 | 姓王者的博客 制作github贪吃蛇贡献图 | 姓王者的博客
学习开发astro博客后台(一)钩子文学 | 姓王者的博客
作者:xingwangzhe · 2025-07-04 · via 姓王者的博客

🕒 阅读时间:3 分钟 📝 字数:906 👀 阅读量: Loading...

前端会点,后端不怎么会,想着 Astro 默认作为 SSG 前端框架,得需要一个伪后台。我看了官方文档,有很多后台,但都不是我想要的那种 dev 开发环境下的后台,所以我准备手搓一个解耦的后台实现,也就是作为 npm 包来分发。

当然回过头来,我还什么都不会,所以从官方文档,从头开始。

钩子

很详细啊,难得官方有中文文档,赞👍,虽然我不太懂钩子,但是不懂就学嘛,还是挺有意思的。

创建项目

创建 package.json 文件。

安装必要的依赖

安装前置,相关依赖,配置一下命令,方便编译成 JS:

...

"exports": {

".": {

"import": "./dist/index.js",

"types": "./dist/index.d.ts"

},

"./src/pages/admin.astro": "./src/pages/admin.astro"

},

"files": [

"dist",

"src/pages",

"README.md"

],

"scripts": {

"build": "tsc",

"dev": "tsc --watch",

"clean": "rimraf dist",

"prebuild": "npm run clean",

"prepublishOnly": "npm run build"

},

"devDependencies": {

"typescript": "^5.8.3"

},

"peerDependencies": {

"astro": "^5.8.0"

},

...

基本构建:

D:\test\locastrol> bun run build

$ bun run clean

$ rimraf dist

$ tsc

测试

import { AstroIntegration } from "astro";

interface Options {

collections: String;

}

export function locastrol(config: Options = { collections: "" }): AstroIntegration {

const { collections } = config;

return {

name: "locastrol",

hooks: {

"astro:config:setup": ({ injectRoute, updateConfig, command }) => {

if (command == "dev") {

// 通过 Vite 环境变量传递 collections 参数

updateConfig({

vite: {

define: {

"import.meta.env.LOCASTROL_COLLECTIONS":

JSON.stringify(collections),

},

},

}); // 后台首页

// 编辑器路由 - 使用动态路由

injectRoute({

pattern: "/locastrol/editor",

entrypoint: "locastrol/src/pages/index.astro",

});

injectRoute({

pattern: "/locastrol/editor/[slug]",

entrypoint: "locastrol/src/pages/[slug].astro",

});

// API 路由

injectRoute({

pattern: "/api/locastrol/posts/[slug]",

entrypoint: "locastrol/src/api/posts/[slug].ts",

});

injectRoute({

pattern: "/api/locastrol/posts",

entrypoint: "locastrol/src/api/posts.ts",

});

}

},

"astro:server:start": ({ address }) => {

console.log(

"\x1b[43m\x1b[30m%s\x1b[0m \x1b[36m%s\x1b[0m",

"✅Locastrol后台已经启动",

`http://localhost:${address.port}/locastrol/editor`,

);

},

},

};

}

export type { Options };

cd d:\test\astrotest && New-Item -ItemType SymbolicLink -Path "node_modules\locastrol" -Target "d:\test\locastrol"

把本地依赖软链接上,这样方便随改随测

软链接截图

奇异搞笑 astro: content 导入

我当时不明白,为什么我不能导入来获取这个方法,问了一下 Copilot:

import { getCollection } from "astro:content";

Copilot 回答说:astro:content 是 Astro 的虚拟模块,只在 Astro 项目运行时可用,于是它推荐了各种疯狂的高超技巧来实现获取内容合集,我照做了,但是总是感觉别扭。问另一个 AI,让我另辟蹊径,直接写 Astro 组件?

欸,果然只问一个 AI,这个 AI 就会犯轴,转不过弯,好多时间浪费在那了…

---

import { getCollection } from "astro:content";

const POSTS = 'blog';

const posts = await getCollection(POSTS);

---

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Document</title>

</head>

<body>

<div>hello world</div>

<ul><!-- 列出所有文章,具体类型先any,我喜欢anyscript :) -->

{posts.map((post: { slug: any; data: { title: unknown; }; }) => (

<li>

<a href={`/blog/${post.slug}`}>{post.data.title}</a>

</li>

))}

</ul>

</body>

</html>

直接通过组件来实现的内容集合查询

具体讲讲钩子这块

插件得先注入

这块主要是看官方的文档,首先我得配置一下我这个插件的注入方式,

import { AstroIntegration } from 'astro';

interface Options{

collections: String;

}

export function IntergrationName(config: Options = { }): AstroIntegration {...}

这个应该是默认插件导出,导出名就是Intergration,然后在astro.config.mjs中配置一下

import { defineConfig } from 'astro/config';

import { IntergrationName } from 'locastrol';

export default defineConfig({

integrations: [IntergrationName({...})],

});

钩子,对事件的响应,或者说回调?

很明显,钩子总是与事件有关 astro:config:setup这个钩子,在配置阶段触发,可以用来修改配置,比如说我想要在开发环境下,注入一些路由,或者是修改一些配置

我就注入了一些路由,比如说/locastrol/editor这个路由,它会指向src/pages/index.astro,也就是我的后台首页

:::tip

值得注意的是,以locastrol这个包名作为entrypoint的开头是因为我这个是npm包,得包名开头才能被识别为npm包的路径,不会导致astro混淆

而且还要确保包导出了这些文件

:::

hooks: {

'astro:config:setup': ({ injectRoute, updateConfig, command }) => {

if (command == 'dev') {

// 通过 Vite 环境变量传递 collections 参数

updateConfig({

vite: {

define: {

'import.meta.env.LOCASTROL_COLLECTIONS': JSON.stringify(collections)

}

}

});

// 后台首页

injectRoute({

pattern: '/locastrol/editor',

entrypoint: 'locastrol/src/pages/index.astro'

});

injectRoute({

pattern: '/locastrol/editor/[slug]',

entrypoint: 'locastrol/src/pages/[slug].astro'

});

}

},

}

:::warning 加上if (command == 'dev')条件判断很重要,不然ssg会把后台页面也渲染出来

到时候一些私密内存变量就会不小心暴露出来了 :::

'astro:server:start': ({ address }) => {

console.log('\x1b[43m\x1b[30m%s\x1b[0m \x1b[36m%s\x1b[0m', '✅Locastrol后台已经启动', `http://localhost:${address.port}/locastrol/editor`);

},

这个钩子在服务器启动时触发,我在这里打印了一条日志,告诉用户后台已经启动,并给出访问地址,不过我好奇,为什么ai给我这么邪乎的颜色代码,就没有更好的实现吗?

roadmap ^ ^

看了一眼官方文档,暂时先俩这些钩子,先列个表单列出所有文章,后续查询可以使用官方的内容集合来做到,用nodejs api来做到增删改,也许可以再加个中间件来实现身份验证?

不过那倒是有点背离dev local后台的初心了,而且我还有好多功能没实现呢!