ポートフォリオサイト作成と開発環境

Pocket

最近は情シス的な業務やサイト制作でもサーバー廻りを担当することが多くなりました。
そのためフロント部分をキャッチアップする目的をかねて、自分のポートフォリオサイトを作成しています。

開発環境を備忘録としてまとめます。

サイト

hiroshi-sawai.com

サイトの内容

  • 静的サイト
    勉強のために静的サイトジェネレーターやCSSフレームワークを使わない
  • GitHubのリポジトリにマークダウンでまとめてきた内容を取得してHTMLとして公開
  • GitHub Actionsを使ってAWS EC2にデプロイ

以下に開発環境をまとめます。

開発環境 目次

フロントエンド

タスクランナー

  • npm-scripts

CSS

概要

Sass/PostCSSなどをインストール

  • npmでnode-sassをインストール:$ npm install -D node-sass
  • npmでpostcss-cliをインストール:$ npm install -D postcss-cli
  • npmでautoprefixerをインストール:$ npm install -D autoprefixer
  • npmでcssnanoをインストール:$ npm install -D cssnano
  • npmでwatchをインストール:$ npm install -D watch
  • npmでnpm-run-allをインストール:$ npm install -D npm-run-all

postcss-cliは、v7系は単体で動作します。v8系はpostcssと一緒にインストールする必要があります。

ビルド

  • node-sassscssファイルをコンパイル
    • "css:sass": "node-sass src/sass/style.scss -o dist/css/ --output-style expanded"
  • autoprefixerでベンダープレフィックスを付与
    • "css:prefixer": "postcss --no-map dist/css/style.css --use autoprefixer --replace"
    • package.jsonbrowserslistプロパティーに対象ブラウザを設定
  • cssnanoでCSSをminify
    • "css:nano": "postcss public/css/style.css --use cssnano --replace"
    • mapファイルを出力(no-mapは付与しない)
  • 上記をまとめてbuildを定義
    • "css:build": "run-s css:sass css:prefixer css:nano"

watchscssを監視して変更があった場合にcss:buildを実行。

"css:build": "run-s css:sass css:prefixer css:nano"

package.jsonのcss関連のnpm scriptsは以下のとおり。

  "scripts": {
    "css:sass": "node-sass src/sass/style.scss -o public/css/ --output-style expanded",
    "css:prefixer": "postcss --no-map public/css/style.css --use autoprefixer --replace",
    "css:nano": "postcss public/css/style.css --use cssnano --replace",
    "css:build": "run-s css:sass css:prefixer css:nano",
    "css:watch": "watch 'npm run css:build' ./src/sass"
  }

lint

  • npmでprettierをインストール:$ npm install -D prettier
  • npmでstylelintをインストール:$ npm install -D stylelint
  • npmでstylelint-prettierをインストール:$ npm install -D stylelint-prettier
  • npmでstylelint-config-prettierをインストール: $ npm install --save-dev stylelint-config-prettier

stylelint-config-prettierprettierと衝突するルールを全て削除。
.stylelintrcを作成して以下を記載。

{
  "plugins": ["stylelint-prettier"],
  "rules": {
    "prettier/prettier": true
  },
  "extends": ["stylelint-prettier/recommended"]
}
lint実行
  "scripts": {
    "css:sass": "node-sass src/sass/style.scss -o public/css/ --output-style expanded",
    "css:prefixer": "postcss --no-map public/css/style.css --use autoprefixer --replace",
    "css:nano": "postcss public/css/style.css --use cssnano --replace",
+    "css:lint": "stylelint 'src/sass/*.scss' --fix",
    "css:build": "run-s css:sass css:prefixer css:nano",
    "css:watch": "watch 'npm run css:build' ./src/sass",
  }
  • +がCSS lint実行のために追加したnpm scripts
huskyでcommitのときにlint実行
  • npmでhuskyをインストール: $ npm install husky --save-dev
  • package.jsonに以下の記述を追加
"husky": {
   "hooks": {
     "pre-commit": "npm run css:lint"
   }
}

JavaScript

  • ES6(ES2015〜ES2020)をBabelでES5にトランスパイル
  • Webpackでバンドル
  • コードフォーマッターはPrettierESLintの組み合わせ

Babel/Webpackをインストール

  • npmでbabel-loader @babel/core @babel/preset-envをインストール
    • $ npm install babel-loader @babel/core @babel/preset-env
  • npmでwebpack/webpack-cliをインストール
    • $ npm install -D webpack webpack-cli
    • webpack.config.jsを作成して設定

webpack.config.js

module.exports = {
    mode: 'development', // or production
    entry: {
        index: './src/js/index.js',
        foo: './src/js/foo.js',
        bar: './src/js/bar.js
    },
    output: {
        filename: '[name].js',
        path: __dirname + '/public/js'
    },
     optimization: {
        minimize: true,
    },
    devtool: "source-map",
    module: {
        rules: [
            {
                test: /\.js$/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets:  [["@babel/preset-env", { "targets": "defaults" }]]
                        }
                    }
                ]
            }
        ]
    }
};
  • mode
    • https://webpack.js.org/configuration/mode/
  • @babel/preset-env
    • https://babeljs.io/docs/en/babel-preset-env
    • https://aloerina01.github.io/blog/2019-06-21-1
package.json
  "scripts": {
    "docs": "node ./src/js/docs/app.js --gfm",
    "css:sass": "node-sass src/sass/style.scss -o public/css/ --output-style expanded",
    "css:prefixer": "postcss --no-map public/css/style.css --use autoprefixer --replace",
    "css:nano": "postcss public/css/style.css --use cssnano --replace",
    "css:lint": "stylelint 'src/sass/*.scss' --fix",
    "css:build": "run-s css:sass css:prefixer css:nano",
    "css:watch": "watch 'npm run css:build' ./src/sass",
+    "js:build": "webpack",
+    "js:watch": "watch 'npm run js:build' ./src/js",
+    "watch": "run-p css:watch js:watch",
  }
  • +がJavaScriptビルド関連で追加したnpm scripts
  • npm run watchでscss&jsファイルを監視してそれぞれビルド

Prettier/ESLintをインストール

ref. Prettierの導入方法 フロントエンド開発で必須のコード整形ツール

  • Prettier
    • npmでprettierをインストール:$ npm install -D prettier
    • npmでprettier-eslintをインストール
    • $ npm install -D prettier-eslint prettier-eslint-cli eslint-config-google
    • .eslintrc.jsonを作成して初期設定
.eslintrc.json
{
  "extends": ["google"],
  "parserOptions": {
    "ecmaVersion": 2018
  }
}
npm-scripts

npm-scriptsに以下を記載。

  "scripts": {
    "docs": "node ./src/js/docs/app.js --gfm",
    "css:sass": "node-sass src/sass/style.scss -o public/css/ --output-style expanded",
    "css:prefixer": "postcss --no-map public/css/style.css --use autoprefixer --replace",
    "css:nano": "postcss public/css/style.css --use cssnano --replace",
    "css:lint": "stylelint 'src/sass/*.scss' --fix",
    "css:build": "run-s css:sass css:prefixer css:nano",
    "css:watch": "watch 'npm run css:build' ./src/sass",
    "js:build": "webpack",
    "js:watch": "watch 'npm run js:build' ./src/js",
+    "js:lint": "prettier-eslint --write $PWD/'src/**/*.js'",
    "watch": "run-p css:watch js:watch"
  },

+がJavaScript lint関連で追加したnpm scripts

$PWD/を付与しないとgitpodではエラーが発生。
ref. https://github.com/prettier/prettier-eslint-cli/issues/208

huskyでcommitのときにlint実行

package.jsonに以下を追加

"husky": {
   "hooks": {
     "pre-commit": "npm run js:lint && npm run css:lint"
   }
},

サーバーサイド

AWS EC2 Ubuntu18.04にデプロイします。

パッケージインストール

Ubuntuバージョン確認

$ cat /etc/os-release

リポジトリ&パッケージ更新

$ sudo apt update
$ sudo apt upgrade

利用可能パッケージを検索

$ apt search {{keywork}} | grep {{keyword}} | less

{{keywork}}の例:apache2php

Apacheをインストール

$ sudo apt install apache2

PHPをインストール

20200829時点ではphp7.2が使用デフォルトで使用可能だった。

$ sudo apt install php7.2

一緒にインストールされたモジュールを確認。

$ php -m
// インストール済モジュール一覧が表示
php-mbstringをインストール

$ php -mphp-mbstringがインストールされていなかったのでインストール。

$ sudo apt install php-mbstring

SSL化 Lets Encrypt

  • https://certbot.eff.org/lets-encrypt/ubuntubionic-apache

mailgunと連携

  1. maigunコントロールパネルでドメインを追加
    • mg.hiroshi-sawai.com
  2. ドメイン(hiroshi-sawai.com)を認証
    • ドメイン認証が完了していないと、後述するスクリプトでエラーが発生して送信できない
    • https://documentation.mailgun.com/en/latest/quickstart-sending.html#add-sending-tracking-dns-records
  3. 公式 Mailgun PHP clientをComposerで導入
    • https://github.com/mailgun/mailgun-php
    • 使用方法はmailgun公式のドキュメントよりもリポジトリの情報が新しい

ドメイン(hiroshi-sawai.com)を認証

ドメイン認証はDNSにレコードを追加する。
追加する設定値はmailgunコントロールパネルのDomainで確認。

Mailgun PHP clientをComposerで導入

  1. Composerをインストール
  2. Mailgun PHP clientをインストール

Composerをインストール

$ cd /path/to/project
$ curl -sS https://getcomposer.org/installer | php

Mailgun PHP clientをインストール

$ cd /path/to/project
$ ./composer.phar require mailgun/mailgun-php kriswallsmith/buzz nyholm/psr7
// composer.pharでは駄目(パスが通っていないため)

送信API

  • https://documentation.mailgun.com/en/latest/user_manual.html#sending-via-api

CI

GitHub Action

  • https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions#about-yaml-syntax-for-workflows

AWS EC2 Ubuntu18.04を前提として記載。

  1. EC2でSSH鍵をパスフレーズなしで作成
    sh-keygen -m PEM -t rsa -C "info@example.com"
  2. 公開鍵をログインユーザー(ubuntu)の~/.ssh/authorized_keys に追記
    $ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
  3. 公開先ディレクトリを作成
    $ mkdir -p /var/www/html
  4. GitHubからクローンするために、公開鍵をGitHubのSSHに登録
  5. リポジトリをクローン
    $ git clone git@github.com:xxxxx/example.git
  6. GitHubからAWS EC2にアクセスするために、GitHubのリポジトリsettings > secretにSSH接続情報を登録(変数名は任意)
    変数は後述するGitHub Action設定ファイル(例:.github/workflows/deploy.yml)で使用

    • EC2_SECRET_KEY:秘密鍵を登録
    • EC2_HOST:EC2のIP
    • EC2_USER:ubuntu(AWSのEC2インスタンスがUbuntuの場合)
  7. プロジェクトルートの直下にGitHub Action設定ファイル.github/workflows/deploy.ymltを作成

SSHの鍵作成はCircleCIの以下のドキュメントを参照
ref. https://circleci.com/docs/ja/2.0/add-ssh-key/

手順
ターミナルから、ssh-keygen -m PEM -t rsa -C “your_email@example.com” コマンドを入力して鍵を生成します。 詳細については、Secure Shell (SSH) のドキュメントを参照してください。

メモ: CircleCI が SSH 鍵を復号化できるよう、鍵には常に空のパスフレーズを設定してください。 また、CircleCI は OpenSSH のデフォルトのファイル形式をサポートしていません。OpenSSH を使用して鍵を生成する場合は、ssh-keygen -m pem コマンドを使用します。

メモ: 最近 ssh-keygen は、デフォルトで PEM 形式の鍵を生成しないように更新されました。 非公開鍵が —–BEGIN RSA PRIVATE KEY—– で始まらない場合、ssh-keygen -m PEM -t rsa -C “your_email@example.com” コマンドで鍵を生成すると、強制的に PEM 形式で生成できます。

deploy.yml

name: Deploy to EC2
on:
  push:
    branches: [ master ]

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    steps:
      - name: deploy to ec2
        env:
          EC2_SECRET_KEY: ${{ secrets.EC2_SECRET_KEY }}
          EC2_USER: ${{ secrets.EC2_USER }}
          EC2_HOST: ${{ secrets.EC2_HOST }}
        run: |
          echo "$EC2_SECRET_KEY" > secret_key
          chmod 600 secret_key
          ssh -oStrictHostKeyChecking=no ${EC2_USER}@${EC2_HOST} -i secret_key "cd /var/www/html/hiroshi-sawai.com/current && git fetch origin master && git reset --hard origin/master"

コメント

No comments yet.

コメントの投稿

改行と段落タグは自動で挿入されます。
メールアドレスは表示されません。