学习开发astro博客后台(一)钩子文学
前端会点,后端不怎么会,想着 Astro 默认作为 SSG 前端框架,得需要一个伪后台。我看了官方文档,有很多后台,但都不是我想要的那种 dev 开发环境下的后台,所以我准备手搓一个解耦的后台实现,也就是作为 npm 包来分发。
当然回过头来,我还什么都不会,所以从官方文档,从头开始。
很详细啊,难得官方有中文文档,赞👍,虽然我不太懂钩子,但是不懂就学嘛,还是挺有意思的。
创建项目
npm init
创建 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
,也就是我的后台首页
值得注意的是,以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' }); } },}
加上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后台的初心了,而且我还有好多功能没实现呢!
学习开发astro博客后台(一)钩子文学
本文链接: https://xingwangzhe.fun/posts/f023e0e0
本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
留言评论