NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

注目のタグ

    VuePress × AWS で始めるモダンなブログサイト入門

    はじめに

    こんにちは、NRI ネットコムに新しくキャリアで入社しました永川です。普段はインフラエンジニアとして様々なシステムの開発・運用を担当しています。

    今回は、VuePress と AWS を活用してブログサイトを構築する方法についてお話ししたいと思います。最近、VuePress を使ってシンプルでモダンなブログサイトを作成したので、その過程を題材に共有します。

    VuePress とは

    VuePress とはドキュメントやブログ向けの静的なウェブサイトを生成するオープンソースのフレームワークです。

    Vue.js の生みの親である Evan You 氏により、コンテンツを主軸に置いた静的サイトの作成にフォーカスしたフレームワークとして開発されました。

    いわゆる静的サイトジェネレーター (SSG) の一つで、ドキュメントやブログといった静的コンテンツに特化したツールとなっています。

    動的コンテンツや更新の激しいコンテンツには向きませんが、静的な HTML ファイルをビルド時に事前に生成するので、デバイスやサーバーに負荷がかからず、ページの表示速度が非常に速いです。

    また CDN (Contents Delivery Network) とも非常に相性がよく、スケーラビリティに優れているといった特徴があります。

    SSG 関する詳しい説明はこちら↓ aws.amazon.com

    主な機能

    VuePress の主要な機能としては下記のものがあります。

    • Markdown から HTML を生成

    • 自動目次生成、全文検索、多言語に対応

    • Vue コンポーネントを埋め込み

    • 拡張性の高い様々なプラグイン

    メリット

    個人的に VuePress を使って嬉しいポイントは、

    • Markdown に対応している

    • VSCode などの使い慣れたツールを使ってドキュメントを記載可能

    • GitHub でドキュメントの管理をしたり、GitHub Actions を使用して CI/CD の仕組みを組みこむことが可能

    のようなところだと思います。

    普段開発で使用しているツールやプロセスをドキュメント作成にも適用できるところが非常に良いですね!

    VuePress でブログを作る

    今回作成したサイトでは VuePress のテーマの一つである VuePress Theme Hope を使用しました。VuePress 標準のテーマでも良いのですが、こういったテーマを使用することにより、さらに簡単に多機能なサイトを作成することができます。

    実行環境

    下記の手順は以下の実行環境で実施しています。

    • OS:MacOS Sonoma
      MacOS, LinuxOS で動作確認をしています。

    • Node.js:v18.17.1
      v18.0以上が必要です。VuePress の環境構築に使います。

    • npm:v9.6.7
      v.8.0以上が必要です。パッケージマネージャーとして使用します。

    • VuePress:v2.0.0-rc.9
      v2.0以上が必要です。ブログのフレームワークとして使用します。

    ブログ構築の手順

    ここからは VuePress を使ったブログサイトの構築方法を解説したいと思います。

    まず、下記のコマンドでプロジェクトを作成します。

    npm init vuepress-theme-hope@latest sample-blog

    その後、表示されるプロンプトに従って、言語やパッケージマネージャーなどの設定を行います。

    ? Select a language to display / 选择显示语言 english (US)
    ? Choose package manager npm
    ? Which bundler do you want to use? vite
    Generating package.json...
    ? Your project name sample-blog
    ? Your project version 2.0.0
    ? Your project description A project of vuepress-theme-hope
    ? Your project license MIT
    Generating tsconfig.json...
    ? Does the project need multiple languages? No
    ? Do you need a GitHub workflow to deploy docs on GitHub pages? Yes
    ? What type of project do you want to create? blog
    Generating Template...
    ? Initialize a git repository? Yes
    Installing Deps...
    This may take a few minutes, please be patient.
    We can not correctly output progress bar from child process, so the process may look stuck.
    
    
    Successful Generated!
    

    プロジェクトの作成に成功したら、以下のコマンドで開発サーバーを起動してみましょう。

    npm run docs:dev

    実行すると、以下のような出力が表示されます。

    > sample-blog@2.0.0 docs:dev
    > vuepress-vite dev src
    
    ✔ Initializing and preparing data - done in 113ms
    
      vite v5.2.14 dev server running at:
    
      ➜  Local:   http://localhost:8080/
      ➜  Network: http://192.168.0.100:8080/
      ➜  Network: http://192.168.64.1:8080/

    これで、初期設定済みのブログサイトが立ち上がりました!ブラウザで http://localhost:8080/ にアクセスをすると確認をすることができます。

    ブログのカスタマイズ

    一部省略をしてますが初期で作成される Vuepress Theme Hope のプロジェクトは下記のフォルダ構成になっています。

    .
    ├── .github
    │   └── workflows
    │       └── deploy-docs.yml
    ├── package.json
    └── src
        ├── .vuepress
        │   ├── config.ts
        │   ├── navbar.ts
        │   ├── public
        │   │   └── assets
        │   │       ├── icon
        │   │       └── images
        │   ├── sidebar.ts
        │   └── theme.ts
        ├── README.md
        └── posts
            ├── apple
            │   ├── 1.md
            │   ├── 2.md
            │   └── 3.md
            ├── cherry.md
            └── strawberry.md

    このうち下記の4つほどを押さえていればブログサイトをカスタマイズして作り替えることができます。

    1. .src/.vuepress/config.ts, .src/.vuepress/theme.ts
      ブログ・著者の名前や説明、言語などのブログの基本設定を記載するファイル。
      ここでブログサイトのタイトルを変更したり、自身のプロフィールなどに書き換えたりすることができます。

    2. ./src/README.md
      トップページの md ファイル。
      ここでトップページに表示されるタイトルやコンテンツ、背景画像を変更することができます。

    3. ./src/posts/
      ブログ記事を管理するディレクトリ。
      このディレクトリ配下に md ファイルを追加していくことで記事を投稿することができます。
      (ナビゲーションバーやサイドバーも合わせて修正する必要がありますが、postsという名前を変えたり、同じ階層に別のカテゴリでmdファイルをまとめることも可能です。)

    4. .src/.vuepress/navbar.ts , .src/.vuepress/sidebar.ts
      上部に表示されるナビゲーションバーや、サイドバーの設定ファイル。
      ここでナビゲーションバーやサイドバーに表示される内容をカスタマイズすることができます。

      ぜひ色々いじって試してみてください!

    AWS でブログをホスティングする

    ここからは、ブログを AWS で公開する手順を解説します。

    VuePress の公式サイトでは GitHub Pages や Heroku, Netlify などの静的コンテンツのホスティングサービスへデプロイする方法が紹介されていますが、今回は AWS と Github Actions で同じ仕組みを作成しました。

    ホスティングサービスを利用しても良いのですが、コスト面やカスタマイズ性、学習目的を考慮して AWS を選択しました。

    必要な準備

    • AWS CLI のインストール

    • GitHub リポジトリへ VuePress のプロジェクトをプッシュ

    Amazon S3 とAmazon CloudFront の作成

    AWS のアーキテクチャは Amazon S3 ( 以下 S3 ) で静的ファイルをホスティングし、Amazon CloudFront ( 以下 CloudFront ) で配信を行うシンプルかつ一般的な構成にしています。

    また CloudFront 経由のアクセスのみを許可し、S3 への直接アクセスを防ぐため以下の設定を有効化しました。

    • S3 のブロックパブリックアクセスの有効化

    • CloudFront で Origin Access Control (OAC) を使用

    • OAC を利用し、CloudFront 経由のアクセスだけを許可する S3 バケットポリシーを実装

    こちらの設定を活用すると、バケットの非公開や最小特権アクセスの実装といった S3 のセキュリティベストプラクティス に則りつつ、より安全にブログを公開できます。

    AWS CloudFormation テンプレート

    上記の S3 と CloudFront の作成・設定には AWS CloudFormation テンプレートを使用しました。

    このテンプレートでは以下の4つのリソースを作成しています。

    • ブロックパブリックアクセスを有効化したS3 バケット

    • CloudFront からのみアクセスを許可するバケットポリシー

    • S3 へのセキュアなアクセスを実現する Origin Access Control (OAC)

    • S3 と連携する CloudFront ディストリビューション

    AWSTemplateFormatVersion: 2010-09-09
    Description: Template for S3 static site with CloudFront
    
    Resources:
      S3StaticSiteBucket:
        Type: AWS::S3::Bucket
        Properties:
          PublicAccessBlockConfiguration:
            BlockPublicAcls: True
            BlockPublicPolicy: True
            IgnorePublicAcls: True
            RestrictPublicBuckets: True
    
      S3StaticSiteBucketPolicy:
        Type: AWS::S3::BucketPolicy
        DependsOn:
          - CloudFrontDistribution
        Properties:
          Bucket: !Ref S3StaticSiteBucket
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: "AllowCloudFrontAccess"
                Effect: "Allow"
                Principal:
                  Service: "cloudfront.amazonaws.com"
                Action: "s3:GetObject"
                Resource: !Sub "arn:${AWS::Partition}:s3:::${S3StaticSiteBucket}/*"
                Condition:
                  StringEquals:
                    AWS:SourceArn: !Sub "arn:${AWS::Partition}:cloudfront::${AWS::AccountId}:distribution/${CloudFrontDistribution}"
    
      OAC:
        Type: AWS::CloudFront::OriginAccessControl
        Properties:
          OriginAccessControlConfig:
            Description: Access Control
            Name: StaticSiteOAC
            OriginAccessControlOriginType: s3
            SigningBehavior: always
            SigningProtocol: sigv4
    
      CloudFrontDistribution:
        Type: AWS::CloudFront::Distribution
        DependsOn:
          - S3StaticSiteBucket
          - OAC
        Properties:
          DistributionConfig:
            DefaultCacheBehavior:
              AllowedMethods:
                - GET
                - HEAD
              CachedMethods:
                - GET
                - HEAD
              CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6
              TargetOriginId: S3StaticSiteBucket
              ViewerProtocolPolicy: redirect-to-https
              Compress: true
            Enabled: true
            Origins:
              - DomainName: !GetAtt S3StaticSiteBucket.DomainName
                Id: S3StaticSiteBucket
                OriginAccessControlId: !GetAtt OAC.Id
                S3OriginConfig:
                  OriginAccessIdentity: ""
            DefaultRootObject: index.html
            PriceClass: PriceClass_200
            ViewerCertificate:
              CloudFrontDefaultCertificate: true

    静的ファイルのビルドとS3へのアップロード

    S3 と CloudFront の作成が完了したら、VuePress のプロジェクトをビルドして、生成されたファイルを S3 バケットにアップロードします。

    npm run build
    aws s3 sync ./src/.vuepress/dist s3://<your-bucket-name> --delete
    

    アップロードが完了後、作成したCloudFrontのURLにアクセスするとデプロイが成功していることを確認することができます!

    ※ 作成直後だと、バケットポリシーの反映に時間がかかるためか Access Denied のエラーが出ることがあります。その場合は時間をおいて再度アクセスしてみてください。

    GitHub Actions で運用を自動化する

    最後に GitHub Actions の設定を行い、main ブランチにマージされたら自動的に新しい記事が配信される仕組みを作成します。

    VuePress Theme Hope でプロジェクトを作成した時点で .github/workflows 配下にデフォルトの YMAL ファイルが準備されているため、そこに AWS にデプロイするための下記の設定を追記します。

    • AWS のクレデンシャルの設定

    • S3 バケットへのコンテンツのアップロード処理

    • CloudFront のキャッシュ削除処理

    使用した Github Actions の YAML ファイルは下記です。

    name: Deploy Docs
    
    on:
      push:
        branches:
          - main
    
    env:
      BUCKET_NAME: "<your-bucket-name>"
      CF_DISTRIBUTION_ID: "<your-cloudfront-distridution-id>"
      AWS_REGION: "<your-region>"
    
    permissions:
      id-token: write
      contents: read
    
    jobs:
      deploy-gh-pages:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout
            uses: actions/checkout@v3
            with:
              fetch-depth: 0
    
          - name: Setup Node.js
            uses: actions/setup-node@v3
            with:
              node-version: 18
              cache: npm
    
          - name: Install Deps
            run: npm ci
    
          - name: Build Docs
            env:
              NODE_OPTIONS: --max_old_space_size=8192
            run: npm run docs:build
            working-directory: ./src
    
          - name: configure aws credentials
            uses: aws-actions/configure-aws-credentials@v3
            with:
              role-to-assume: ${{ secrets.IAM_ROLE_ARN }}
              role-session-name: deploy-static-site
              aws-region: ${{ env.AWS_REGION }}
    
          - name: Deploy Docs
            run: |
              aws s3 sync --exact-timestamps --delete src/.vuepress/dist s3://${{ env.BUCKET_NAME }}/
              aws cloudfront create-invalidation --distribution-id ${{ env.CF_DISTRIBUTION_ID }} --paths "/*"
            working-directory: ./src

    これで記事を作成し、その更新を mainブランチ へマージすることで自動的に公開される仕組みを作ることができました。

    使い慣れたツールでブログ記事を執筆し、GitHubで管理しつつ自動で公開という一連の流れが完成したことになります!

    まとめ

    今回は VuePress を使ってブログサイトを作成し、AWS で公開する方法を紹介しました。

    基盤を S3とCloudFrontで構築しましたが、これぐらいの小規模かつシンプルな静的サイトであれば、 CI/CD の環境の含めてまとめて作成してくれる AWS Amplify を使用してもよかったかもしれません。

    また機会があれば次は Amplify を使って構築してみようと思います。

    VuePress を使えばブログ以外でも簡単に静的サイトを作成することができるので、興味のある方はぜひこの記事を参考に作ってみてください!

    参考URL

    VuePress

    AWS関連

    GitHub Actions