Bundles
The main shiki entries bundles all supported themes and languages via lazy dynamic imports. The efficiency shouldn't be a concern to most of the scenarios as the grammar would only be imported/downloaded when it is used. However, when you bundle Shiki into browsers runtime or web workers, even those files are not imported, they still add up to your dist size. We provide the fine-grained bundle to help you compose languages and themes one-by-one as you need.
INFO
If you are building a web application, or in a performance-sensitive environment, it's always better to use the fine-grained bundles to reduce the bundle size and memory usage. Learn more about Best Performance Practices.
Bundle Presets
To make it easier, we also provide some pre-composed bundles for you to use:
shiki/bundle/full
Bundle Size: 6.4 MB (minified), 1.2 MB (gzip), async chunks included
The full bundle includes all themes and languages, same as the main shiki entry.
shiki/bundle/web
Bundle Size: 3.8 MB (minified), 695 KB (gzip), async chunks included
The bundle includes all themes and common web languages like (HTML, CSS, JS, TS, JSON, Markdown, etc.) and some web frameworks (Vue, JSX, Svelte, etc.).
Use as normal, all functions from shiki are also available in the bundle:
import {
BundledLanguage,
BundledTheme,
codeToHtml,
createHighlighter
} from 'shiki/bundle/web'
const highlighter = await createHighlighter({
langs: ['html', 'css', 'js'],
themes: ['github-dark', 'github-light'],
})Fine-grained Bundle
When importing shiki, all the themes and languages are bundled as async chunks. Normally it won't be a concern to you as they are not being loaded if you don't use them. In some cases, if you want to control what to bundle, you can use the core and compose your own bundle.
// directly import the theme and language modules, only the ones you imported will be bundled.
import nord from '@shikijs/themes/nord'
// `shiki/core` entry does not include any themes or languages or the wasm binary.
import { createHighlighterCore } from 'shiki/core'
import { createOnigurumaEngine } from 'shiki/engine/oniguruma'
const highlighter = await createHighlighterCore({
themes: [
// instead of strings, you need to pass the imported module
nord,
// or a dynamic import if you want to do chunk splitting
import('@shikijs/themes/material-theme-ocean')
],
langs: [
import('@shikijs/langs/javascript'),
// shiki will try to interop the module with the default export
() => import('@shikijs/langs/css'),
// or a getter that returns custom grammar
async () => JSON.parse(await fs.readFile('my-grammar.json', 'utf-8'))
],
// `shiki/wasm` contains the wasm binary inlined as base64 string.
engine: createOnigurumaEngine(import('shiki/wasm'))
})
// optionally, load themes and languages after creation
await highlighter.loadTheme(import('@shikijs/themes/vitesse-light'))
const code = highlighter.codeToHtml('const a = 1', {
lang: 'javascript',
theme: 'material-theme-ocean'
})INFO
Shorthands are only avaliable in bundle presets. For a fine-grained bundle, you can create your own shorthands using createSingletonShorthands or port it yourself.
Handling Embedded Languages
Some languages like markdown, vue, svelte, mdx, etc. contain embedded languages (e.g., code blocks in markdown can contain JavaScript, Python, HTML, etc.). When using fine-grained bundles, these embedded languages are not loaded automatically to keep the bundle size small and give you full control.
If you want to highlight embedded languages in your code, you have several options:
Option 1: Manually Load Embedded Languages
You can manually load all the languages you expect to use:
import { createHighlighterCore } from 'shiki/core'
const highlighter = await createHighlighterCore({
themes: [import('@shikijs/themes/nord')],
langs: [
import('@shikijs/langs/markdown'),
import('@shikijs/langs/javascript'),
import('@shikijs/langs/typescript'),
import('@shikijs/langs/python'),
// ...add other languages you need
],
engine: createOnigurumaEngine(import('shiki/wasm')),
})Option 2: Dynamically Load Based on Content
Use the guessEmbeddedLanguages utility to detect and load embedded languages dynamically:
import { createHighlighterCore, guessEmbeddedLanguages } from 'shiki/core'
const highlighter = await createHighlighterCore({
themes: [import('@shikijs/themes/nord')],
langs: [import('@shikijs/langs/markdown')],
engine: createOnigurumaEngine(import('shiki/wasm')),
})
// Get your markdown content
const markdownCode = '```js\nconsole.log("hello")\n```'
// Detect embedded languages
const embeddedLangs = guessEmbeddedLanguages(markdownCode, 'markdown', highlighter)
// Load them dynamically
await Promise.all(
embeddedLangs.map(lang =>
highlighter.loadLanguage(import(`@shikijs/langs/${lang}`)),
),
)
// Now highlight with all required languages loaded
const html = highlighter.codeToHtml(markdownCode, {
lang: 'markdown',
theme: 'nord',
})Option 3: Create Custom Shorthands with Auto-Loading ⭐ RECOMMENDED
For the best user experience similar to the bundle presets, create custom shorthands with automatic embedded language detection:
import {
createdBundledHighlighter,
createSingletonShorthands,
guessEmbeddedLanguages,
} from 'shiki/core'
import { createOnigurumaEngine } from 'shiki/engine/oniguruma'
// Define your bundled languages
const bundledLanguages = {
javascript: () => import('@shikijs/langs/javascript'),
typescript: () => import('@shikijs/langs/typescript'),
python: () => import('@shikijs/langs/python'),
markdown: () => import('@shikijs/langs/markdown'),
// ... add more languages as needed
}
const bundledThemes = {
nord: () => import('@shikijs/themes/nord'),
// ... add more themes as needed
}
// Create a custom highlighter factory
const createHighlighter = createdBundledHighlighter({
langs: bundledLanguages,
themes: bundledThemes,
engine: () => createOnigurumaEngine(import('shiki/wasm')),
})
// Create shorthands with auto-loading embedded languages
export const { codeToHtml, codeToHast, getSingletonHighlighter }
= createSingletonShorthands(createHighlighter, {
guessEmbeddedLanguages,
})
// Now you can use it like the bundle presets
const html = await codeToHtml(markdownCode, {
lang: 'markdown',
theme: 'nord',
})
// Embedded languages in the markdown will be automatically detected and loaded!TIP
The guessEmbeddedLanguages function detects languages from:
- Markdown fenced code blocks:
```langor~~~lang - HTML/Vue language attributes:
lang="javascript" - LaTeX environments:
\begin{language}