博客制作总结
前言
这是对这个博客整个制作流程的一篇总结文章,用于记录遇到的bug与解决方案
pages 分页
这个说起来有点困难,大概是我按照之前的一些个人习惯,会把一些页面内的公用方法放在 pages 下的页面文件夹中,当时以为 ts 扩展名的文件不会被识别为组件,但是打包测试的时候发现一直在报错,检查的时候才发现打包器把页面下所有的 ts 文件都尝试转换为路由了,就挺离谱的,后面就把一些不是路由的组件放在了 components 文件夹下,把一些方法给转移到全局 utils 文件夹下了
总结一下就是 pages 文件夹下只放跟路由有关的页面,组件也要分离到其他地方去
Astro.glob 与 Content Collection
最初做内容处理的时候只有一个获取内容的 api: Astro.glob()
文档:https://docs.astro.build/en/reference/api-reference/#astroglob
他用于获取 markdown 文件或 mdx 文件,不过可惜的是只能获取一种类型的文件,不能同时限定范围获取两种文件
当时想着是需要获取的地方写两行代码,一行获取 md,一行获取 mdx
后面做测试的时候又发现一个问题:如果找不到对应的文件就会直接抛出错误,用了 trycatch 也不能解决
当时博客已经是有一些成型的了,后面就去文档找有没有专门的内容相关特性
运气还是很好的,当时 astro 版本好像是 1.8 还是 1.9,里面已经有了 content collection 这个实验性功能
对于当时的我来说算是一门急救药,反正都写在文档里了不用白不用
在这个功能里,规定了 src/content
目录为内容集合目录
文档:https://docs.astro.build/en/guides/content-collections/
很可惜的是目前文档是全英文,看懂基本使用方法还是需要花点力气的
不过好在英文表达都是比较基础的,连我这个四级都没过的人都看懂了要做什么,至于有没有翻译想法还是看未来有没有大佬翻译吧(
现在我的博客都是用 content collection 去实现了,包括关于页面,好友页面都是这样处理
当然这样有个麻烦点就是:md 文件引用的图片不能通过相对目录去引用,必须放到 public 文件夹下才可以保证生产环境文件也可以使用
当然也有办法去实现相对目录引用,这个会放到下一节去讨论
不知道未来旧的 API 会不会变成不推荐使用,毕竟引用范围有限定
这个 content collection 还有一个很方便的点就是会自动处理头部信息,并转换为 js 内的对象,而不是扔给你一个字符串去判断
可以通过他的 config 去决定可选用的头部,astro 会根据预先决定的格式去尝试转换头部,而且也有对内容做出限定
文档:https://docs.astro.build/en/guides/content-collections/#defining-datatypes-with-zod
markdown 与 markdown react
当初引入 mdx 是为了处理 markdown 图片引入的问题和图片居中的问题
当时在 markdown 里面处理图片路径问题花了挺长时间的,因为在开发环境下引入的图片能展示,但是一打包就消失了
这个问题还是比较容易处理的,但是对于我一个在 hexo 写博客,经常通过相对目录引入图片的人来说还是挺痛苦的
于是后面就去看了一下官方,发现有 mdx 这个玩意,想着拿来试一下看看能不能用
mdx 全称 markdown react,是一种比较新的 markdown 格式,除了保留基本的 markdown 功能,还加入了 jsx 语法,这样子就可以在markdown 内使用一些组件,具体实现原理不是很清楚,但是 astro 官方有一个实例,就是在 mdx 内引入官方的 images 组件
文档:https://docs.astro.build/en/guides/images/#using-in-mdx
通过这个组件似乎可以对图片做出一些压缩与处理,减少流量使用
当然原生引入图片的方式也是可以用的,通过内联的 import 语句处理即可
<img src={import('./logo.png')} />
图片居中的方式我采用了一种比较简单粗暴的方法:直接在外面套 div 标签
<div style="text-align: center;">
<img />
</div>
当然未来可能会使用图片插件通过注入的方式处理,到时候图片应该也会有自动居中的功能
Search 的搜索模式
当时想着是分两种:静态搜索与前后端分离搜索
静态搜索就是打包生成的时候生成一份索引,然后在组件中编写特定的匹配规则展示搜索结果
本博客可以自定义生成的搜索索引,也可以自定义匹配规则,在 博客配置 文件中设置即可
本博客的搜索索引处理思路很简单:通过 astro 内置的集成 api 来处理,位于 src/_intergration/BuildSearchIndex.ts
下
输入输出的话也是用 fs 模块来生成文件
构建环节会默认部署到 public 下的位置方便访问
本博客内置的搜索索引是一个 json 文件,转换后是一个对象,对应关心为:文章标题
-> 文章原 markdown 内容
没有经过处理,所以很简单,当然你也可以编写自己的集成来替代原来的集成,你甚至可以将其转成其他格式的索引文件,然后在配置中编写自己的匹配规则
另一种就是前后端分离搜索,这种搜索模式用来处理文章内容过多的情况,现在本博客有 27 篇文章,生成的索引大小是 183 kb,还在接受范围内,毕竟原来的博客的 xml 搜索索引能有近 600 kb,我的想法是当超过 1.5MB 的索引可能就不适合静态搜索了,于是开发了这种前后端分离的搜索模式
这种搜索模式我认为可以用在本博客的服务端渲染-中间件模式,在中间件模式下就可以自己编写接口,然后将 node 架设为服务端处理接口,当然这种模式就可能要注意一些安全问题和性能问题,要是有人闲的来对这个接口发起大量访问,可能就需要做出拒绝访问的处理
还有一个很有意思的小点,就是 search 的设计模式,当时只想着面向过程,然后代码写了一堆屎山
后面洗澡的时候觉得不能这样,太乱了,不方便维护,不如用一下代理模式
简单说一下代理模式:代理模式就是通过设置一个代理服务器,使得原本无法直接访问的数据能被访问到
vue 和 react 脚手架中的 proxy 就是这样一个代理服务器设置。
而在本博客的想法是设置一个虚拟的服务器实例,他会根据预先设置的搜索模式来匹配不同的内容
组件层面则是调用这个虚拟服务器的获取内容的方法来获取要展示的数据,并专注于展示,这样就分离了逻辑层与视图层
这样体验下来感觉设计模式还是在业务处理方面会用的较多,专门处理渲染的页面可能会用的少
Astro 内置的端点
这个也是可以作为静态搜索的端点处理,当然这玩意我是在做完了搜索部分才发现的
文档:https://docs.astro.build/zh-cn/core-concepts/endpoints/
看着是可以作为一个静态接口和重定向工具,未来会想想哪里用它更好
全局注入与页面注入 js css
注入方式分全局注入和页面注入
通过 astro 内置的集成 api 进行注入的,接下来一下难受的点
如何区分页面注入
这里采用的是一个很简单粗暴的方法引入的
window.location.pathname
通过判断这个路径位置来处理
一开始想着是设置根据文件夹路径来处理,但是这一部分的技术没有调研好,做的非常难受
目前的解决方案是这样
switch (window.location.pathname){
case "/":
await import('./inject.js')
break;
}
这种引入方式有个问题就是可能兼容不了那么多的插件,毕竟是作为模块异步引入
之前做的 petite-vue 播放器就不能通过这种方式引入,因为他是在全局挂载对象的,必须得是同步过程
当时的解决方案是通过动态插入 script 标签来限制加载,但是这样又会出现新问题:cdn 卡了的话就直接白屏,体验下降一大截,总之就是很难受就对了
这个注入会持续改进,寄
css 引入
分全局注入和页面注入
页面注入跟上面思路一样,都是直接 import 注入
全局注入则是用了 page-ssr 的模式
文档:https://docs.astro.build/en/reference/integrations-reference/#injectscript-option
命令行处理博客
本博客是在 package.json 将 blog
作为了起步的命令行占位符,之前还想着是搞一个接受输入输出的简单 node 应用来生成博客,但是有个缺点就是这种方法要生成一篇博客模板效率可能太低了,不如直接生成文件来处理
命令行启动参数 npx blog
获取命令行参数就是通过 process.argv
,他返回一个字符串数组,里面前两项是 node 的路径和脚本路径,第三项开始就是传入的参数
有一个挺特殊的地方就是以 -
开头的参数不会被传入,就挺神奇
获取完参数了就是根据参数匹配对应的指令,通过 fs 模块做标准的文件处理
技术含量不是很高,所以就不详细展开说了
Astro PR #6088
一个很小的 pr,解决了请求链接带有中文路径时请求错误的问题