SVG設計: Satori + SVGO
2026年10月確認: satori 0.63、@resvg/resvg-js 2.6、svgo 4.1。
Satori — マークアップ → SVG
npm i satori @resvg/resvg-js
import satori from 'satori'
import { Resvg } from '@resvg/resvg-js'
import { readFile, writeFile } from 'node:fs/promises'
const font = await readFile('./Inter-Bold.ttf') // TTF、OTF、WOFF、WOFF2
const svg = await satori(
<div style={{ display: 'flex', width: '100%', height: '100%', alignItems: 'center',
justifyContent: 'center', background: '#0b1020', color: 'white', fontSize: 96 }}>
Đủ 20/20
</div>,
{ width: 1920, height: 1080, fonts: [{ name: 'Inter', data: font, weight: 700, style: 'normal' }] },
)
const png = new Resvg(svg, { fitTo: { mode: 'width', value: 1920 } }).render().asPng()
await writeFile('title.png', png)
- JSX/Reactなしの場合、プレーンオブジェクトを渡す:
{ type: 'div', props: { style: {...}, children: '...' } }。 - テキストがある場合はフォントが必須。ベトナム語にはグリフを持つフォント(Inter、Be Vietnam Pro、Noto Sans)が必要。
- レイアウト: Flexbox、Grid(サブグリッド/メイソンリーなし)、ブロック。CSSのサブセット — JSなし、アニメーションなし、外部スタイルシートなし。スタイルはインライン。
- 画像:
<img src>は絶対URLまたはデータURI、さらに明示的なwidth/heightが必要。 - テキストはデフォルトで
<path>になります(移植性が高く、選択不可)。embedFont: falseで<text>を維持します。 - 絵文字:
graphemeImagesまたはloadAdditionalAssetを使用して、不足しているセグメントに画像/フォントを供給します。 - PNGの代替:
sharp(Buffer.from(svg)).png()。
SVGO v4 — 最適化
npx svgo in.svg -o out.svg
npx svgo -f ./icons -o ./icons-min
// svgo.config.mjs
export default {
multipass: true,
plugins: [
{ name: 'preset-default', params: { overrides: {
// SVGがアニメーション化されるか、id/classでスタイルされる場合、これらを保持:
cleanupIds: false, // コードがターゲットとするidをリネーム/削除する
collapseGroups: false, // アニメーションの単位として使用する<g>をフラット化する
mergePaths: false, // 個別にアニメーションするパスをマージする
convertShapeToPath: false, // <circle>/<rect>を<path>に変換する(r、cx、widthがなくなる)
} } },
'prefixIds', // 複数のSVGが1ページにインライン化される場合に一意のIDを付与
],
}
- v4の変更点:
removeViewBoxとremoveTitleはpreset-defaultに含まれなくなりました(必要に応じて名前で追加してください。スケーリングのためにviewBoxは保持してください)。removeScriptElement→removeScripts。名前付きエクスポートのみ:import { optimize } from 'svgo'。ブラウザビルドはsvgo/browser。 - Node API:
const { data } = optimize(svgString, { multipass: true, plugins: [...] })。 - 静的なアイコンには、通常の
preset-defaultで十分です。上記のオーバーライドは、アニメーション化またはスクリプト化されたSVGにのみ重要です。 - アニメーション用にSVGを最適化した後、アニメーションコードが使用するすべてのセレクターが出力にまだ存在することを確認してください。