代码语法高亮(Shiki)
本教程共 56 篇 · 第 19 篇 · 更新于 2026-08-07 · 约 8 分钟阅读
本节目标:学会让 Astro 里的代码块自动上色,知道默认用的是什么、怎么换主题,以及怎么在组件里手动高亮代码。
写技术教程离不开贴代码。一堆黑底白字看着累,关键字、字符串、注释若是不同颜色,读起来就轻松多了。这个给代码「上色」的活,行话叫「语法高亮」(syntax highlighting)。
Astro 把这事内置了,开箱就能用,不用你装额外插件。它背后有两套引擎可选:Shiki 和 Prism。默认用的是 Shiki。
默认就高亮,不用配置
在 Markdown 或 MDX 里写代码块,用三个反引号包起来,后面跟上语言名,Astro 自动帮你上色。
```js
// 一段带语法高亮的 JavaScript
var fun = function lang(l) {
dateformat.i18n = require('./lang/' + l);
return true;
};
```
你什么都不用配,Astro 默认用 Shiki,配的是 github-dark 主题。生成的代码已经带着行内 style 颜色,没有多余的 CSS 类、没有样式表、也没有任何浏览器端 JS。换句话说,高亮是在构建时算好的,对网页性能很友好。
Note语言名写在开头反引号后面(如
```js、```ts、```astro)。写对了,上色才准确。Astro 自己的语法也能高亮,语言名用astro。
Shiki 背后是 TextMate 语法,支持的语言上百种,常见的前端、后端语言基本都覆盖。万一写了个它不认的语言名,代码不会报错,只是不给你上色,退回普通文本。所以上色不对劲时,先检查语言名有没有拼错。
换成自己喜欢的主题
默认 github-dark 未必合你口味。改主题在 astro.config.mjs 里动 markdown.shikiConfig。
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
markdown: {
shikiConfig: {
theme: 'dracula',
},
},
});
Shiki 自带一大堆主题,比如 dracula、github-light、one-dark-pro、nord 等等,名字直接填字符串就行。想要哪个,去 Shiki 官网的主题列表里挑。
明暗双主题
现在很多人喜欢网站跟着系统切深色、浅色。Shiki 支持同时给代码块配「亮色主题」和「暗色主题」,由 CSS 决定显示哪一个。
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
markdown: {
shikiConfig: {
themes: {
light: 'github-light',
dark: 'github-dark',
},
},
},
});
光配这个还不够,得加一段 CSS,让浏览器按系统偏好切换颜色变量。注意 Astro 给代码块加的类名是 .astro-code,不是 Shiki 文档里常见的 .shiki:
@media (prefers-color-scheme: dark) {
.astro-code,
.astro-code span {
color: var(--shiki-dark) !important;
background-color: var(--shiki-dark-bg) !important;
}
}
这段 Media Query 的意思是:系统处于深色模式时,用 --shiki-dark 那组颜色。浅色模式自然就用默认的亮色变量。
用自己的主题文件
如果现成主题都不称心,你可以从本地文件导入一个自定义主题:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import customTheme from './my-shiki-theme.json';
export default defineConfig({
markdown: {
shikiConfig: {
theme: customTheme,
},
},
});
my-shiki-theme.json 得是符合 Shiki 格式的主题文件。一般人不折腾这个,用内置主题就够了。
用 <Code /> 组件高亮
上面讲的都是 Markdown 里的代码块。如果你在 .astro 或 .mdx 文件里,想手写一段被高亮的代码,用 Astro 自带的 <Code /> 组件。它底层就是 Shiki 驱动的。
---
import { Code } from 'astro:components';
---
<!-- 高亮一段 JavaScript -->
<Code code={`const foo = 'bar';`} lang="js" />
<!-- 可选:换个主题 -->
<Code code={`const foo = 'bar';`} lang="js" theme="dark-plus" />
<!-- 可选:开启自动换行 -->
<Code code={`const foo = 'bar';`} lang="js" wrap />
<!-- 可选:渲染成行内代码 -->
<p><Code code={`const foo = 'bar';`} lang="js" inline /> 会显示成行内。</p>
几个常用属性:
code:要高亮的代码字符串,必填。lang:语言,比如js、ts、astro。theme:单独指定主题,覆盖默认。wrap:代码过长时自动换行。inline:渲染成行内代码,而不是一整块。
Tip
<Code />不会继承你在shikiConfig里给 Markdown 设的主题,得自己用theme属性指定。这是它和 Markdown 代码块的一个小区别。
想要更细的控制,embeddedLangs 可以补上嵌入式语言(比如 Vue 里嵌 TSX),transformers 能加聚焦高亮、行号标注等效果。这些属于进阶玩法,遇到再查官方文档即可。
用 <Prism /> 组件(Prism 引擎)
除了 Shiki,Astro 也支持 Prism 这套老牌高亮引擎。和 <Code /> 不同,<Prism /> 给元素加的是 CSS 类名,样式得你自己提供样式表。
先用 npm 装上包:
npm install @astrojs/prism
然后像普通组件一样用:
---
import { Prism } from '@astrojs/prism';
---
<Prism lang="js" code={`const foo = 'bar';`} />
除了 Prism 支持的语言,还能用 lang="astro" 高亮 Astro 代码。
想换成 Prism 作为 Markdown 的默认高亮,把配置改成:
// astro.config.mjs
export default defineConfig({
markdown: {
syntaxHighlight: 'prism',
},
});
一旦选了 Prism,你得自己准备一份 Prism 的 CSS 样式表(比如从 Prism Themes 仓库挑一份),放进 public/ 目录,再用 <link> 在页面头部加载,高亮颜色才会出现。
高亮是什么时候算好的
这点对性能敏感的人很重要。Astro 默认在「构建时」就把代码高亮算完,生成的是带颜色的静态 HTML。浏览器拿到就能直接显示,不需要下载高亮库、不需要运行时再算一遍。
这跟某些框架「页面加载后用 JS 现高亮」完全不同。Astro 的默认做法零客户端 JS、首屏即所见,这也是它主打「快」的一个小体现。
Prism 那条路稍不同:<Prism /> 只给元素加类名,真正的颜色靠你提供的 CSS 样式表在浏览器里生效。所以它依赖一份样式表,但不依赖高亮 JS。
给代码加聚焦高亮
想强调代码里的某一行,比如「看这里这行是关键」,可以用 Shiki 的 transformers(转换器)。它给代码行加 class,你再用自己的 CSS 控制样式。
---
import { transformerMetaHighlight } from '@shikijs/transformers';
import { Code } from 'astro:components';
const code = `const foo = 'hello'
const bar = ' world'
console.log(foo + bar) // [!code focus]
`;
---
<Code
code={code}
lang="js"
transformers={[transformerMetaHighlight()]}
meta="{1,3}"
/>
[!code focus] 是写在代码里的标记,配合 transformers 就能让那行「聚焦」。CSS 得你自己写,比如让没聚焦的行稍微模糊:
pre.has-focused .line:not(.focused) {
filter: blur(1px);
}
这种细节属于进阶,先知道有这个能力即可,用的时候再查官方文档照着配。
给某一行加高亮底色
比聚焦模糊更常用的,是「把某一行标黄,提醒读者重点看」。Shiki 的 transformerNotationHighlight 配合代码里的 [!code highlight] 标记就能做到:
---
import { transformerNotationHighlight } from '@shikijs/transformers';
import { Code } from 'astro:components';
const code = `const foo = 'hello'
const bar = ' world' // [!code highlight]
console.log(foo + bar)
`;
---
<Code
code={code}
lang="js"
transformers={[transformerNotationHighlight()]}
/>
被标了 [!code highlight] 的那一行会带上 highlighted 这个类名。你再写几行 CSS 给它上底色:
.line.highlighted {
background: rgba(255, 230, 0, 0.15);
display: block;
}
这套「在代码里写标记、用 transformers 渲染」的玩法,Shiki 还支持 [!code warning]、[!code error] 等标记,能做出黄、橙、红三色提示行。用到时照官方文档挑对应的 transformer 即可,思路都和聚焦高亮一致。
想关掉高亮怎么办
极少情况你可能不想要高亮,比如贴一段本就不该上色的文本。在配置里把 syntaxHighlight 设成 false 即可,整站代码块都回到纯文本。
// astro.config.mjs
export default defineConfig({
markdown: {
syntaxHighlight: false,
},
});
这个开关有三个可选值:shiki(默认)、prism、false。通常保持 shiki 不动就好,知道有得关就够了。
小结
语法高亮让代码好读,Astro 内置支持,默认走 Shiki,零配置就能用。要点就这些:Markdown 代码块默认上色,主题用 shikiConfig.theme 改;想要明暗切换用 themes 配双主题加一段 CSS;在组件里手写高亮用 <Code />;怀旧或特殊需求可以切到 Prism 用 <Prism />。
高亮在构建时算好,所以页面又快又稳。聚焦高亮这类花活靠 transformers 实现,按需取用。不想要高亮时把 syntaxHighlight 设成 false 即可。代码块上完色,内容页的观感就到位了。下一章开始进入内容集合,讲 Astro 管理大批结构化内容的现代做法。