VuePress
GitHub概要
vuejs/vuepress
📝 Minimalistic Vue-powered static site generator
トピックス
スター履歴
ドキュメント作成ツール
VuePress
概要
VuePressはVue.jsを基盤とした静的サイトジェネレータです。マークダウンベースのコンテンツ作成とVue.jsの表現力を組み合わせ、高速で美しいドキュメントサイトを構築できます。
詳細
VuePress(ビュープレス)は2018年にEvan You(Vue.jsの作者)によって開発され、Vue.jsエコシステムの公式ドキュメントツールとして誕生しました。マークダウンファイルを基盤としながら、Vue.jsコンポーネントの強力な機能を活用できます。静的サイト生成(SSG)により高速な表示速度を実現し、同時にSPAとしてのリッチなユーザー体験を提供します。プラグインシステムにより、検索機能、PWA対応、ブログ機能、多言語対応など多彩な機能を追加できます。テーマシステムにより、デフォルトテーマの美しいデザインを使用するか、完全カスタムテーマを作成できます。Vue.jsエコシステムと密接に統合されており、VueコンポーネントをMarkdown内で直接使用できます。2025年現在、Vue.js、Element Plus、Ant Design Vue等の多くのVue.jsプロジェクトで公式ドキュメントツールとして採用されています。VuePress 2ではVite統合により開発体験が大幅に向上し、より高速なビルドと開発サーバーを実現しています。バージョン管理、多言語サイト構築、SEO最適化など、現代的なドキュメントサイトに必要な機能を標準装備しています。
メリット・デメリット
メリット
- Vue.js統合: MarkdownとVueコンポーネントのシームレスな組み合わせ
- 高速表示: 静的サイト生成による優れたパフォーマンスとSEO
- SPA体験: ページ遷移時のリッチなユーザー体験とナビゲーション
- 豊富なプラグイン: 検索、PWA、ブログ、多言語対応の公式プラグイン
- 美しいデフォルトテーマ: すぐに使える洗練されたデザイン
- Vue.jsエコシステム: 既存のVueコンポーネントライブラリとの統合
- 開発者体験: Vite統合による高速な開発サーバーとホットリロード
デメリット
- Vue.js依存: Vue.jsの知識が必要、学習コストの存在
- Node.js環境: 開発・ビルドにNode.js環境が必須
- ビルド時間: 大規模サイトでのビルド時間増加
- プラグイン制限: Vue.js生態系外のプラグイン選択肢の限定
- カスタマイズ複雑性: 高度なカスタマイズにはVue.jsとWebpack/Viteの理解が必要
- メモリ使用量: 大規模サイトでの開発時メモリ消費
主要リンク
書き方の例
プロジェクトの初期化
# VuePressプロジェクトの作成
yarn create vuepress-site my-docs
# または
npx create-vuepress-site my-docs
# プロジェクト構造
my-docs/
├── docs/ # ドキュメントディレクトリ
│ ├── .vuepress/ # VuePress設定ディレクトリ
│ │ ├── config.js # サイト設定ファイル
│ │ ├── components/ # カスタムVueコンポーネント
│ │ ├── theme/ # カスタムテーマ
│ │ └── public/ # 静的アセット
│ ├── guide/ # ガイドセクション
│ └── README.md # ホームページ
└── package.json
基本的な設定ファイル(config.js)
// docs/.vuepress/config.js
module.exports = {
// サイト基本情報
title: 'プロジェクトドキュメント',
description: 'Vue.jsベースのドキュメントサイト',
base: '/',
lang: 'ja-JP',
// ヘッド設定
head: [
['link', { rel: 'icon', href: '/favicon.ico' }],
['meta', { name: 'theme-color', content: '#3eaf7c' }],
['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }],
['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }]
],
// テーマ設定
themeConfig: {
// ナビゲーションバー
nav: [
{ text: 'ホーム', link: '/' },
{ text: 'ガイド', link: '/guide/' },
{ text: 'API', link: '/api/' },
{ text: 'GitHub', link: 'https://github.com/username/project' }
],
// サイドバー
sidebar: {
'/guide/': [
'',
'getting-started',
'installation',
'configuration',
'deployment'
],
'/api/': [
'',
'components',
'directives',
'utilities'
]
},
// Git リポジトリ設定
repo: 'username/project',
repoLabel: 'GitHub',
docsDir: 'docs',
docsBranch: 'main',
editLinks: true,
editLinkText: 'このページを編集',
// 最終更新日時表示
lastUpdated: '最終更新',
// 検索設定
search: true,
searchMaxSuggestions: 10,
// Algolia DocSearch設定
algolia: {
apiKey: 'your-api-key',
indexName: 'your-index-name'
}
},
// プラグイン設定
plugins: [
'@vuepress/back-to-top',
'@vuepress/medium-zoom',
['@vuepress/pwa', {
serviceWorker: true,
updatePopup: {
message: "新しいコンテンツが利用可能です。",
buttonText: "更新"
}
}],
['@vuepress/google-analytics', {
'ga': 'UA-XXXXXXXXX-X'
}]
],
// Markdown設定
markdown: {
lineNumbers: true,
anchor: { permalink: true },
toc: { includeLevel: [1, 2, 3] },
plugins: [
'markdown-it-container',
'markdown-it-footnote',
'markdown-it-deflist'
]
},
// ビルド設定
evergreen: true,
dest: 'dist',
// 多言語設定
locales: {
'/': {
lang: 'ja-JP',
title: 'プロジェクトドキュメント',
description: 'Vue.jsベースのドキュメントサイト'
},
'/en/': {
lang: 'en-US',
title: 'Project Documentation',
description: 'Vue.js-powered documentation site'
}
}
}
マークダウンと Vue.js コンポーネントの統合
# VuePressの活用ガイド
## 基本的なマークダウン
VuePressはマークダウンを拡張し、様々な機能を提供します。
### カスタムコンテナ
::: tip ヒント
これは便利なヒントです。
:::
::: warning 注意
注意が必要な内容です。
:::
::: danger 危険
危険な操作に関する警告です。
:::
::: details クリックして詳細を表示
詳細な説明がここに表示されます。
:::
### コードブロック
```javascript{2-4}
function example() {
// この部分がハイライトされます
const message = 'Hello VuePress!'
console.log(message)
return message
}
Vue.jsコンポーネントの使用
<CustomComponent :prop="value" @event="handler"> スロットコンテンツ
動的コンテンツ
現在の時刻: {{ new Date().toLocaleString() }}
カウンター: {{ counter }} <button @click="increment">クリック
### カスタムVueコンポーネントの作成
```vue
<!-- docs/.vuepress/components/FeatureCard.vue -->
<template>
<div class="feature-card">
<div class="feature-icon">
<slot name="icon"></slot>
</div>
<h3 class="feature-title">{{ title }}</h3>
<p class="feature-description">{{ description }}</p>
<div class="feature-actions">
<slot name="actions"></slot>
</div>
</div>
</template>
<script>
export default {
name: 'FeatureCard',
props: {
title: {
type: String,
required: true
},
description: {
type: String,
required: true
}
}
}
</script>
<style scoped>
.feature-card {
border: 1px solid #e0e6ed;
border-radius: 8px;
padding: 24px;
margin: 16px 0;
background: #ffffff;
transition: box-shadow 0.3s ease;
}
.feature-card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.feature-icon {
font-size: 2em;
margin-bottom: 16px;
color: #3eaf7c;
}
.feature-title {
margin: 0 0 12px 0;
font-size: 1.4em;
color: #2c3e50;
}
.feature-description {
margin: 0 0 16px 0;
color: #5e6d82;
line-height: 1.6;
}
.feature-actions {
display: flex;
gap: 12px;
}
</style>
プラグイン開発の例
// plugins/custom-plugin.js
module.exports = (options = {}, context) => ({
name: 'custom-plugin',
// プラグイン設定
async ready() {
// プラグイン初期化処理
console.log('Custom plugin is ready!')
},
// Markdown拡張
extendMarkdown(md) {
md.use(require('markdown-it-container'), 'custom', {
validate: function(params) {
return params.trim().match(/^custom\s+(.*)$/)
},
render: function(tokens, idx) {
const m = tokens[idx].info.trim().match(/^custom\s+(.*)$/)
if (tokens[idx].nesting === 1) {
return `<div class="custom-container">
<div class="custom-title">${m[1]}</div>
<div class="custom-content">`
} else {
return '</div></div>'
}
}
})
},
// ページ拡張
async additionalPages() {
return [
{
path: '/custom-page/',
frontmatter: {
title: 'カスタムページ',
layout: 'CustomLayout'
}
}
]
},
// クライアント側拡張
enhanceAppFiles: [
path.resolve(__dirname, 'enhanceApp.js')
],
// ビルド時処理
async generated(pagePaths) {
// 生成されたページの後処理
console.log('Generated pages:', pagePaths.length)
}
})
テーマカスタマイズ
// docs/.vuepress/theme/index.js
const path = require('path')
module.exports = {
// 親テーマを継承
extend: '@vuepress/theme-default',
// レイアウトのオーバーライド
layouts: {
Layout: path.resolve(__dirname, 'layouts/Layout.vue'),
404: path.resolve(__dirname, 'layouts/404.vue')
},
// グローバルコンポーネント
globalLayout: path.resolve(__dirname, 'layouts/GlobalLayout.vue'),
// プラグインの追加
plugins: [
'@vuepress/back-to-top',
'@vuepress/nprogress',
['@vuepress/search', {
searchMaxSuggestions: 10
}]
]
}
カスタムレイアウトコンポーネント
<!-- docs/.vuepress/theme/layouts/Layout.vue -->
<template>
<div class="custom-layout">
<!-- ヘッダー -->
<header class="custom-header">
<nav class="custom-nav">
<router-link to="/" class="custom-logo">
<img src="/logo.png" alt="Logo">
</router-link>
<ul class="custom-nav-links">
<li v-for="item in $themeConfig.nav" :key="item.text">
<NavLink :item="item"/>
</li>
</ul>
</nav>
</header>
<!-- メインコンテンツ -->
<main class="custom-main">
<aside class="custom-sidebar" v-if="shouldShowSidebar">
<Sidebar :items="sidebarItems"/>
</aside>
<div class="custom-content">
<div class="content-wrapper">
<!-- ページコンテンツ -->
<Content/>
<!-- ページナビゲーション -->
<PageNav v-bind="{ sidebarItems }"/>
<!-- 編集リンク -->
<PageEdit/>
</div>
</div>
</main>
<!-- フッター -->
<footer class="custom-footer">
<p>© {{ new Date().getFullYear() }} プロジェクト名</p>
</footer>
</div>
</template>
<script>
import Home from '@theme/components/Home.vue'
import Navbar from '@theme/components/Navbar.vue'
import Page from '@theme/components/Page.vue'
import Sidebar from '@theme/components/Sidebar.vue'
import { resolveSidebarItems } from '@theme/util'
export default {
name: 'Layout',
components: {
Home,
Page,
Sidebar,
Navbar
},
computed: {
shouldShowSidebar() {
const { frontmatter } = this.$page
return !frontmatter.home &&
frontmatter.sidebar !== false &&
this.sidebarItems.length
},
sidebarItems() {
return resolveSidebarItems(
this.$page,
this.$page.regularPath,
this.$site,
this.$localePath
)
}
}
}
</script>
<style lang="stylus">
.custom-layout
min-height 100vh
display flex
flex-direction column
.custom-header
background #ffffff
border-bottom 1px solid #eaecef
position sticky
top 0
z-index 20
.custom-nav
max-width 1200px
margin 0 auto
padding 0 2rem
display flex
align-items center
justify-content space-between
height 3.5rem
.custom-logo img
height 2rem
.custom-nav-links
display flex
list-style none
margin 0
padding 0
gap 2rem
.custom-main
flex 1
display flex
max-width 1200px
margin 0 auto
width 100%
.custom-sidebar
width 20rem
flex-shrink 0
.custom-content
flex 1
min-width 0
.content-wrapper
padding 2rem
max-width 740px
.custom-footer
background #f8f9fa
text-align center
padding 2rem
border-top 1px solid #eaecef
</style>
ビルドと自動デプロイ設定
# .github/workflows/deploy.yml
name: Build and Deploy VuePress
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18
cache: yarn
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Build VuePress
run: yarn docs:build
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/.vuepress/dist
cname: docs.example.com
高度な機能とワークフロー
// docs/.vuepress/enhanceApp.js
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
export default ({
Vue, // VuePressが使用しているVueコンストラクタ
options, // ルートインスタンスのオプション
router, // 現在のアプリのルーターインスタンス
siteData // サイトメタデータ
}) => {
// Element UIをグローバルに登録
Vue.use(ElementUI)
// グローバルコンポーネントの登録
Vue.component('demo-component', {
template: '<div class="demo">{{ message }}</div>',
data() {
return {
message: 'Hello from global component!'
}
}
})
// グローバルミックスインの追加
Vue.mixin({
computed: {
$title() {
return this.$page.title || this.$site.title
}
}
})
// ルーターガードの追加
router.beforeEach((to, from, next) => {
console.log('Navigating to:', to.path)
next()
})
// 開発環境でのホットリロード設定
if (process.env.NODE_ENV === 'development' && module.hot) {
module.hot.accept()
}
}
開発・ビルドコマンド
# 開発サーバー起動
yarn docs:dev
# または
npm run docs:dev
# 本番ビルド
yarn docs:build
# または
npm run docs:build
# 特定ポートでの起動
vuepress dev docs --port 8080
# デバッグモードでの起動
DEBUG=vuepress:* vuepress dev docs
# プラグインの詳細確認
vuepress info
# キャッシュクリア
rm -rf docs/.vuepress/.cache docs/.vuepress/dist
# カスタムテーマのejection(非推奨)
vuepress eject docs