PenpotのSVGメタデータ完全クレンジング:デザインシステムを最速でプロダクションへ直結させる技術
テックリードの皆さん、日々のデザインハンドオフに疲弊していないか?
「デザイナーがPenpotで完璧なコンポーネントを作った。しかし、いざコードに落とし込もうとエクスポートしたSVGを見ると、謎の自動生成ID(`id=”rect-42-a”`)、意味のないネストの `
この悪夢のような冗長性を手作業で削ぎ落とす時間は、エンジニアにとってもデザイナーにとっても1秒の価値もない。
オープンソースの強力なデザインツール「Penpot」は、SVGをネイティブの共通言語として扱う。だからこそ、デザインデータからプロダクションコードに至るパイプラインを完全自動化することで、パフォーマンスと開発体験(DX)を極限まで高めることができる。
今回は、Penpotから吐き出されるSVGを極限までクレンジングし、CI/CDパイプラインやビルドプロセスに組み込んで完全自動化するための実践的アプローチを、設定ファイルとスクリプトの全貌とともに解説する。
—
1. 開発スピードを劇的に高めるPenpotのショートカット&エコシステム
まず、大前提として「ゴミのないSVG」はPenpot上のクリーンなレイヤー構造から始まる。無駄なグループ化を防ぎ、効率的にコンポーネントを切るための実践知を共有しよう。
デザイナー・エンジニア共通で覚えるべき神ショートカット
- `Ctrl + G` / `Ctrl + Shift + G`: グループ化とグループ解除。無駄なネストを防ぐため、常にフラットな構造を意識する。
- `Alt + 2`: コンポーネントのアウトライン(ワイヤーフレーム)表示。不要なパスが隠れていないか瞬時に検知する。
- `Ctrl + /`: クイックサーチ。コマンドラインのようにレイヤーやアクションにアクセスし、マウス操作のコンテキストスイッチをゼロにする。
チーム開発で絶対に揃えるべき設定ルール
Penpotをチームで運用する際、以下のルールをデザインシステムのリポジトリ(`README.md`)に明記し、全員の共通認識とする。
1. レイヤー名のセマンティクス規約:
- エクスポート時にIDとして残るレイヤー名は、必ずケバブケース(例:`icon-user-check`)で命名する。スペースや日本語のレイヤー名は厳禁。
2. 不必要なグループ(`
- 単一の子要素を持つグループは作成しない(Penpot上で自動生成された場合も、エクスポート前にフラット化する)。
3. ストロークのパス化:
- アイコンなどのベクターは、ストローク(線)のままではなく必ずアウトライン化(`Ctrl + Shift + O`相当の処理)を行い、異なるスケールでも破綻しないようにする。
—
2. SVGクレンジングの核心:なぜ「そのまま」使ってはいけないのか?
PenpotからエクスポートしたSVGには、Webのプロダクション環境において以下の「毒」が含まれている。
- エディタ固有のメタデータ: `xmlns:xlink` や不要な `version` 属性。
- 冗長な `id` 属性: 全コンポーネントで衝突(コリジョン)の原因になる自動生成ID。
- 無駄なグループタグ(`
`) : CSSセレクタの深さを無駄に増やし、DOMの肥大化を招く。 - ハードコードされたカラー: デザインシステムの色変え(CSS変数による制御)を阻害する `fill=”#000000″` などの記述。
これらを人力で修正するのではなく、SVGO(SVG Optimizer)をカスタム設定し、ビルドプロセスに組み込むことで完全自動化する。
—
3. 実践:SVGクレンジング・ビルドパイプラインの構築
プロジェクトのルートディレクトリに、PenpotからエクスポートしたSVGを自動で最適化するスクリプトと設定ファイルを配置する。
① SVGO設定ファイル (`svgo.config.js`)
プロダクション環境で完全にクリーンかつ安全なSVGを出力するための設定だ。デザインシステムの色制御を可能にするため、不要な `fill` 属性の削除や、IDの難読化(または完全削除)を行う。
// svgo.config.js
module.exports = {
multipass: true, // 複数回最適化処理を走らせて極限まで軽量化
plugins: [
{
name: ‘preset-default’,
params: {
overrides: {
// viewBoxはレスポンシブデザインに必須なので絶対に残す
removeViewBox: false,
// デフォルトで消えない隠し要素やコメントを確実に削除
removeComments: true,
removeMetadata: true,
removeTitle: true,
removeDesc: true,
},
},
},
// プロダクションでのID衝突を防ぐため、すべてのIDを削除(必要な場合は ‘prefixIds’ に変更)
‘removeUnusedNS’,
‘removeUselessStrokeAndFill’,
{
name: ‘removeAttrs’,
params: {
// Penpot特有の不要な属性や、CSSで制御したいハードコードカラーをターゲットに指定
attrs: ‘(data-name|fill-rule|clip-rule)’,
},
},
// 単一のパスを持つ不要なグループタグを自動的に直下の要素に統合
‘collapseGroups’,
],
};
② 自動クレンジング・スクリプト (`scripts/clean-svgs.js`)
Node.js環境で動作し、指定したディレクトリ内のPenpot製SVGを一括スキャンして最適化をかけるスクリプト。
/
- @file clean-svgs.js
- @description PenpotからエクスポートされたSVGアセットを自動クレンジングするスクリプト
/
const fs = require(‘fs’);
const path = require(‘path’);
const { optimize } = require(‘svgo’);
const INPUT_DIR = path.resolve(__dirname, ‘../src/assets/svg/raw’);
const OUTPUT_DIR = path.resolve(__dirname, ‘../src/assets/svg/optimized’);
// 出力先ディレクトリが存在しない場合は自動生成
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
}
// ディレクトリ内のSVGファイルを処理
fs.readdir(INPUT_DIR, (err, files) => {
if (err) {
console.error(‘❌ 入力ディレクトリの読み込みに失敗しました:’, err);
process.exit(1);
}
const svgFiles = files.filter(file => path.extname(file).toLowerCase() === ‘.svg’);
if (svgFiles.length === 0) {
console.log(‘⚠️ 処理対象のSVGファイルが見つかりません。’);
return;
}
console.log(`🚀 ${svgFiles.length}件のSVGファイルのクレンジングを開始します…`);
svgFiles.forEach(file => {
const filePath = path.join(INPUT_DIR, file);
const svgString = fs.readFileSync(filePath, ‘utf8’);
// SVGOによる最適化の実行
const result = optimize(svgString, {
path: filePath,
// 設定ファイルを外部読み込み
config: require(‘../svgo.config.js’),
});
const outputPath = path.join(OUTPUT_DIR, file);
fs.writeFileSync(outputPath, result.data, ‘utf8’);
console.log(`✨ Optimized: ${file}`);
});
console.log(‘🎉 すべてのSVGのクレンジングが完了しました!’);
});
③ `package.json` への組み込み
日々の開発フロー(ビルドやコミットフック)にこのスクリプトを組み込む。これで、エンジニアは何も意識せずとも常に最新かつ軽量なSVGを手に入れることができる。
{
“scripts”: {
“svg:clean”: “node scripts/clean-svgs.js”,
“prebuild”: “npm run svg:clean”,
“dev”: “npm run svg:clean && vite”
}
}
—
4. チーム開発におけるワークフローの極意
この仕組みを導入したチームのワークフローはこう変わる。
1. Design: デザイナーがPenpotでコンポーネントをアップデートし、SVGとして一括エクスポート。
2. Commit: エクスポートした生データを `src/assets/svg/raw/` にドロップしてGitコミット。
3. Build / CI: デプロイメントまたはローカルビルドのトリガー(`prebuild`)により、自動的に `svgo` が走り、最適化されたSVGが `src/assets/svg/optimized/` に生成される。コードベースには常に「人間が書いたかのような美しいSVG」だけが取り込まれる。
テックリードからの提言
ツールに人間が合わせるな。ツールに雑務を肩代わりさせろ。
Penpotというオープンで強力なデザイン基盤を手にいれた我々は、デザインからコードへのトランスレーションコストを限りなくゼロに近づける義務がある。
このSVGクレンジングの自動化パイプラインを取り入れ、無駄なメタデータに別れを告げよう。プロダクションの軽量化と、エンジニア・デザイナー間の心理的安全性の向上を同時に達成できるはずだ。