Astro 是一款现代化的前端框架,由开发团队 Snowpack 创建,旨在提供一种简单而强大的方式来构建快速、可靠且易于维护的 Web 应用程序。 Astro 支持静态站点生成,这意味着在构建时生成 HTML 文件,从而提高网站的加载速度和性能。
今天我们主要讲述如何使用 Astro 快速搭建自己的博客系统。
1. 环境准备 需要先安装 nodejs v18.17.1 或 v20.3.0 更高版本 文本编辑器——推荐使用带有官方 Astro 扩展的 VS Code。 命令行终端- 通过 Astro 的命令行界面 (CLI) 访问。 2. 创建一个 Astro 项目 这里推荐使用 pnpm 作为 node 包管理工具,如果您习惯 npm or yarn 可自行调整命令行指令及参数。
2.1. 使用命令行向导创建项目 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 $ pnpm create astro@latest .../191d395dcd8-40343 | +59 ++++++ .../191d395dcd8-40343 | Progress: resolved 59, reused 27, downloaded 32, added 59, done astro Launch sequence initiated. dir Where should we create your new project? ./density-dwarf tmpl How would you like to start your new project? Use blog template ts Do you plan to write TypeScript? Yes use How strict should TypeScript be? Strict deps Install dependencies? Yes git Initialize a new git repository? Yes ✔ Project initialized! ■ Template copied ■ TypeScript customized ■ Dependencies installed ■ Git initialized next Liftoff confirmed. Explore your project! Enter your project directory using cd ./density-dwarf Run pnpm dev to start the dev server. CTRL+C to stop. Add frameworks like react or tailwind using astro add. Stuck? Join us at https://astro.build/chat ╭─────╮ Houston: │ ◠ ◡ ◠ Good luck out there, astronaut! 🚀 ╰─────╯
2.2. 使用模板创建项目 官方 templates 可以在这里找到 astro examples
1 2 3 4 5 6 7 8 9 pnpm create astro@latest --template <example-name> pnpm create astro@latest --template <github-username>/<github-repo> git clone https://github.com/<github-username>/<github-repo> myProjectName
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 $pnpm create astro@latest --template surjithctly/astroship astro Launch sequence initiated. dir Where should we create your new project? ./purple-plasma ◼ tmpl Using surjithctly/astroship as project template ts Do you plan to write TypeScript? Yes use How strict should TypeScript be? Strict deps Install dependencies? Yes git Initialize a new git repository? Yes ✔ Project initialized! ■ Template copied ■ TypeScript customized ■ Dependencies installed ■ Git initialized next Liftoff confirmed. Explore your project! Enter your project directory using cd ./purple-plasma Run pnpm dev to start the dev server. CTRL+C to stop. Add frameworks like react or tailwind using astro add. Stuck? Join us at https://astro.build/chat ╭─────╮ Houston: │ ◠ ◡ ◠ Good luck out there, astronaut! 🚀 ╰─────╯
3. 开发环境启动 Astro Astro 带有内置开发服务器,其中包含项目开发所需的一切。astro dev
命令将启动本地开发服务器,以便您首次看到新网站的运行情况。
每个入门模板都附带一个可astro dev
为您运行的预配置脚本。导航到您的项目目录后,使用您最喜欢的包管理器运行此命令并启动 Astro 开发服务器。
1 2 3 4 5 6 7 8 9 10 11 12 $ pnpm dev > [email protected] dev /path-to-astro-project > astro dev astro v4.8.7 ready in 395 ms ┃ Local http://localhost:4321/ ┃ Network use --host to expose
然后浏览器打开http://localhost:4321/
4. 项目结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 / ├── public/ │ └── ... ├── src/ │ ├── components/ │ │ └── ... │ ├── layouts/ │ │ └── ... │ └── pages/ │ └── ... │ ├── content │ │ ├── blog │ │ │ ├── example-page-a.md │ │ ├── config.ts │ │ └── team │ │ ├── example-page-b.md │ │ ├── example-page-c.mdx └── package.json
Astro 会在在 src/pages/ 目录中查找 .astro 或 .md 文件, 在编译期间将其渲染称 html 页面。每个页面都根据其文件名显示为一个路由。
任何静态文件(如图像)都可以放在 public/ 目录中。
5. 创建第一篇博文 通常情况下在 src/content 下有一些预设的目录,如果将 markdown 格式的博客文章,放置在预设的目录下, 并配置好合适的 front-matter,
在开发模式下使用, 例如https://localhost:4321/blog/example-page-a 就能访问。
5.1. create a new content Collection 如果你想在 src/content 添加新的目录结构用于分门别类的放置自己的博客文章, 此时需要创建新的content collection ,此时就需要修改配置 config.ts,然后在 src/pages 下创建新的页面。
例如我想在 src/content 在创建一个 ansible 的目录用于存放 ansible 相关的文章。
首先我需要在 src/content 下创建 ansible 目录; 然后我需要修改 config.ts,添加 ansible 相关的配置;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 const ansibleCollection = defineCollection ({ schema : z.object ({ draft : z.boolean (), title : z.string (), snippet : z.string (), image : z.object ({ src : z.string (), alt : z.string (), }), publishDate : z.string ().transform ((str ) => new Date (str)), author : z.string ().default ("Astroship" ), category : z.string (), tags : z.array (z.string ()), }), }); export const collections = { blog : blogCollection, team : teamCollection, ansible : ansibleCollection, };
然后要创建 ansible 的主页面 src/pages/ansible.astro,这样当用户访问https://localhost:4321/ansible 就不会是空白页面或者出现 404 页面找不到的问题
内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 --- import { getCollection } from "astro:content" ;import { Picture } from "astro:assets" ;import Layout from "@layouts/Layout.astro" ;import Container from "@components/container.astro" ;import Sectionhead from "@components/sectionhead.astro" ;const publishedAnsibleEntries = await getCollection ("ansible" , ({ data } ) => { return !data.draft && data.publishDate < new Date (); }); publishedAnsibleEntries.sort (function (a, b ) { return b.data .publishDate .valueOf () - a.data .publishDate .valueOf (); }); --- <Layout title ="Ansible" > <Container > <Sectionhead > <Fragment slot ="title" > Ansible</Fragment > <Fragment slot ="desc" > We write about building startups and thoughts going on our mind. </Fragment > </Sectionhead > <main class ="mt-16" > <ul class ="grid gap-16 max-w-4xl mx-auto" > { publishedAnsibleEntries.map((ansiblePostEntry, index) => ( <li > <a href ={ `/ansible /${ansiblePostEntry.slug }`}> <div class ="grid md:grid-cols-2 gap-5 md:gap-10 items-center" > <Picture src ={ansiblePostEntry.data.image.src} alt ={ansiblePostEntry.data.image.alt} sizes ="(max-width: 800px) 100vw, 800px" width ={800} height ={600} loading ={index <= 2 ? "eager " : "lazy "} decoding ={index <= 2 ? "sync " : "async "} class ="w-full rounded-md object-cover object-center bg-white" /> <div > <span class ="text-blue-400 uppercase tracking-wider text-sm font-medium" > {ansiblePostEntry.data.category} </span > <h2 class ="text-3xl font-semibold leading-snug tracking-tight mt-1 " > {ansiblePostEntry.data.title} </h2 > <div class ="flex gap-2 mt-3" > <span class ="text-gray-400" > {ansiblePostEntry.data.author} </span > <span class ="text-gray-400" > • </span > <time class ="text-gray-400" datetime ={ansiblePostEntry.data.publishDate.toISOString()} > {ansiblePostEntry.data.publishDate.toDateString()} </time > </div > </div > </div > </a > </li > )) } </ul > </main > </Container > </Layout >
最后要创建一个博客文章的渲染页面 例如: src/pages/ansible/[slug].astro
内容可以参考下面的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 --- import { getCollection } from "astro:content" ;import Layout from "@layouts/Layout.astro" ;import Container from "@components/container.astro" ;export async function getStaticPaths ( ) { const ansibleEntries = await getCollection ("ansible" ); return ansibleEntries.map ((entry ) => ({ params : { slug : entry.slug }, props : { entry }, })); } const { entry } = Astro .props ;const { Content } = await entry.render ();--- <Layout title ={entry.data.title} > <Container > <div class ="mx-auto max-w-3xl mt-14" > <span class ="text-blue-400 uppercase tracking-wider text-sm font-medium" > {entry.data.category} </span > <h1 class ="text-4xl lg:text-5xl font-bold lg:tracking-tight mt-1 lg:leading-tight" > {entry.data.title} </h1 > <div class ="flex gap-2 mt-3 items-center flex-wrap md:flex-nowrap" > <span class ="text-gray-400" > {entry.data.author} </span > <span class ="text-gray-400" > •</span > <time class ="text-gray-400" datetime ={entry.data.publishDate.toISOString()} > {entry.data.publishDate.toDateString()} </time > <span class ="text-gray-400 hidden md:block" > •</span > <div class ="w-full md:w-auto flex flex-wrap gap-3" > { entry.data.tags.map((tag) => ( <span class ="text-sm text-gray-500" > #{tag}</span > )) } </div > </div > </div > <div class ="mx-auto prose prose-lg mt-6 max-w-3xl" > <Content /> </div > <div class ="text-center mt-8" > <a href ="/ansible" class ="bg-gray-100 px-5 py-3 rounded-md hover:bg-gray-200 transition" > ← Back to ansible</a > </div > </Container > </Layout >
最终,我们放置一篇文章在 src/content/ansible 下面,内容如下,当我们打开https://localhost:4321/ansible/first-page 就可以正常访问了。
vi src/content/ansible/first-page.md
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 --- title: 运维自动化之Ansible snippet: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti." draft: false toc: true name: "Robert Palmer" avatar: { src: "https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?&fit=crop&w=280", alt: "Robert Palmer", } image: { src: "https://images.unsplash.com/photo-1593720213428-28a5b9e94613?&fit=crop&w=430&h=240", alt: "full stack web development", } publishDate: "2022-11-08 11:39" category: "Tutorials" tags: - linux - Ansible categories: - devops - ansible reward: true --- 我的第一篇博客
6. 如何发布博客 astro 支持的发布平台有很多,例如:Netlify, Vercel, Github pages, gitlab pages, Cloudflare pages, Heroku, AWS, Google cloud 等等。
今天我们以 github pages 为例,讲解如何将自己的博客发布到 github pages。
6.1. 配置站点 修改配置
astro.config.mjs
1 2 3 4 5 6 export default defineConfig({ site: "https://your_website_domain" , base: 'your-repo', } );
site:
站点的值必须为以下值之一:
以下 URL 基于您的用户名:https://.github.io 为 GitHub 组织的私人页面自动生成的随机 URL:https://.pages.GitHub.io/
base: 可能需要一个 base 值,以便 Astro 将您的存储库名称(例如/your-repo)视为您网站的 base。
设置自定义域
您可以通过添加以下内容来设置自定义域/将 public/CNAME 文件添加到您的项目:
public/CNAME sub.mydomain.com
这将在您的自定义域而不是 user.github.io 部署您的网站。别忘了为您的域提供商配置 DNS。
6.2. 发布站点 发布之前,先编译
编译后将在 dist 目录生成网站所有静态资源文件。然后将其发布到 github 上。
1 2 3 4 5 6 7 8 9 10 git init git add . git commit -m "initial commit" git remote add origin <https://github.com/><username>/<repository>.git npx angular-cli-ghpages --dir =dist/
7. 配置 Astro 编辑器 对于 vscode 编辑器, 可以安装插件 astro-build.astro-vscode
1 2 3 code --install-extension astro-build.astro-vscode
其他编辑器,可以参考:
Astro Editor Setup
7.1. 自动格式化 astro 文档 首先安装 prettier 和 prettier astro 插件
1 2 pnpm i --save-dev prettier prettier-plugin-astro
修改 vscode settings.json
1 2 3 "[astro]" : { "editor.defaultFormatter" : "esbenp.prettier-vscode" } ,
修改配置 .prettierrc 覆盖 prettier 默认的 parser 为 astro
1 2 3 4 5 6 7 8 9 10 11 12 13 { "plugins" : [ "prettier-plugin-astro" ] , "overrides" : [ { "files" : "*.astro" , "options" : { "parser" : "astro" } } ] , .... }
参考How to automatically format Astro files in VS Code using Prettier
8. 参考文档 Start a new Astro project
Astro deploy
Astro Editor Setup
Astro Introduction