個人的フロントエンド開発環境の締めくくり:2019年編


この記事は勤労をしていない高校生が書いているということを念頭に置いて参考にして下さい

この記事は 2019 年の個人的な締めくくりです、時間がないので何が何なのかという解説はしません、利用しているパッケージはできるだけ数を載せるのでハブ空港として利用して下さい

2020 年になっても更新はする

いまはNuxt.js x firebaseで日報アプリを作っていたり CLI ツールを作っていて、多分以下のリポジトリ内の内容が最新になっています

開発環境

Windows で、VSCode から WSL の Ubuntu にリモート接続してやっている、zsh を使っています

anyenvnodenvを管理して、Node.js のバージョン管理を nodenv でやっているので、ローカルに.node-versionというファイルを作り(下記)、nodenv localと打つとそのバージョンが利用出来ます

|.node-version
12.13.1

nvmだと.node-version.nvmrcという名前に置き換わるだけだと思う

Yarnを使っていますが正直好みだと思います(インストールのときに進捗バーが見れてうれしいです)

フロントエンド:ツール

原則@sno2wman/*の形で共用ファイルとして配布する形をとっている

Github Actions で自動でテスト、場合によっては配布が行われるようにしている(後述)

ESLint

@sno2wman/eslint-config

eslint-config-airnbnb-baseを継承した上で、以下のものが全載せされている

@sno2wman/eslint-config/+avaAVAの為の設定ファイルを追加できる

(この書き方は@teppeis 氏のeslint-config-teppeisを参考にしている)

Typescript 連携

@sno2wman/eslint-config-typescript

設定ファイル原本

@sno2wman/eslint-configを継承している

plugin:@typescript-eslint/recommended以下公式推奨のやつは全部のルールをカバーしてないからほとんど色々自分で設定する必要がある

(大多数のコンフィグ部分を@akameco 氏のeslint-config-precure/typescriptから引っ張ってきた覚えがある)

eslint-import-resolver-typescript

tsconfig.json以下compilerOptions.pathsで張ったエイリアスを解決する

eslint-import-resolver-alias.eslintrcに直接書くという手もある

配布時に行っているテスト

eslint-find-rulesで未設定のルールがないかをチェックしている

参考:akameco / eslint-find-rules を使い ESlint の全ての項目を設定する

Prettier

@sno2wman/prettier-config

v1.17 から共用ファイルが使えるようになっているので、

.prettierrcにただ"@sno2wman/prettier-config"とだけ書けばそれで設定が終了する

Editorconfig

ファイルやエディター間でできるだけフォーマットを同じにしようというやつです

.editorconfigというファイルを作って、開発環境毎に随時書き換えたりはしますがおおよそこうです

|.editorconfig
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.yml]
indent_style = space

[.node-version]
insert_final_newline = false

Prettier の設定と矛盾しないように設定して下さい

YAML についてはあまり詳しくないですがタブを使うと壊れたのでこう設定しています

.node-versionの部分は末尾に新しい空白行があると Netlify などで初期設定がうまく行かない現象があったのでこうしています

Stylelint

@sno2wman/stylelint-config

SASS/SCSS を使うのでこうなっている、no-descending-specificityはズボラなので切っています

module.exports = {
  plugins: ['stylelint-scss'],
  extends: [
    'stylelint-config-standard',
    'stylelint-config-recommended-scss',
    'stylelint-config-prettier'
  ],
  rules: {
    'no-descending-specificity': null
  }
}

lint-staged / husky

.lintstagedrc.huskyrcでそれぞれ設定ファイルを作ることが出来る

.huskyrcは余程なければ以下の内容でいいんじゃないでしょうか

{
  "hooks": {
    "pre-commit": "lint-staged"
  }
}

.lintstagedrcこのあたりを見て下さい

gitmoji

Conventional Commit でコミットメッセージを書いていたんですが CLI で色々やろうとするとメチャクチャ複雑になった覚えがあったので、gitmoji を採用しています、

本家の gitmoji-cli を使わずに拙作のcz-gitmoji-cliを利用しています(この記事からちょっと書き直して設定ファイル別物になったので参考にしないで下さい)

Vue.js w/ Nuxt.js

この辺は後で別の記事でまた書いておきたい

Typescript 周り

ここを参考にしてください

自分は Typescript と相性が良いような気がするので@vue/composition-apiを採用しています

setupメソッドの第 2 引数で Nuxt 関連のコンテキストに触れたりするのはかなり便利です

参考

Vuex

nuxt-typed-vuexがかなりいいんじゃないかと思っています

Composition API と相性が多分よく、先程のsetupメソッドで、第 2 引数(contextとしましょう)、context.root.$accessorで楽に Vuex ストアを参照できるのが本当に嬉しい

あと型推測を特に設定無しでやってくれるので書き心地がよいです

i18n

<template/>内に日本語を持ち込みたくなかった

yarn add yaml-loader nuxt-i18n @kazupon/vue-i18n-loader

nuxt.config.ts

{
  modules: [
    [
      'nuxt-i18n',
      {
        locales: [{ code: 'ja', iso: 'ja-JP' }],
        defaultLocale: 'ja',
        vueI18n: {fallbackLocale: 'ja'},
        vueI18nLoader: true
      }
    ]
  ],
  build: {
    transpile: [/nuxt-typed-vuex/],
    extend(config) {
      config.module!.rules.push({
        resourceQuery: /blockType=i18n/,
        type: 'javascript/auto',
        loader: ['@kazupon/vue-i18n-loader', 'yaml-loader']
      })
    }
  }
}

の用に設定すると

<i18n locale="ja" lang="yml">
submit: "投稿する"
</i18n>

<template>
  <div>
    <p>{{ $t('submit') }}</p>
  </div>
</template>

のようにできます

インフラテクチャー

Github Actions

個人プロジェクトとかで Travis CI、Circle CI 以外の選択肢が出来たのは本当に嬉しい

設定ファイルをテストする方法は現状ないと思うので、プライベートリポジトリなどを作ってコミット駆動開発をすると良いと思います

参考

今使っているものを全文載せる

name: Node CI

on: [push]

jobs:
  default:
    runs-on: ubuntu-latest
    env:
      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
    steps:
      - uses: actions/checkout@v1
      - name: Get Node.js version
        id: node-version
        run: echo "::set-output name=version::$(cat .node-version)"
      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node-version: ${{ steps.node-version.version }}
      - name: Setup yarn
        run: |
          curl -o- -L https://yarnpkg.com/install.sh | bash
          export PATH="$HOME/.yarn/bin:$PATH"
      - name: Get yarn cache dir
        id: yarn-cache
        run: echo "::set-output name=dir::$(yarn cache dir)"
      - name: Cache
        uses: actions/cache@v1
        with:
          path: ${{ steps.yarn-cache.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - name: Install dependencies
        run: yarn --frozen-lockfile
      - name: Lint
        run: npm run lint
        env:
          CI: true
      - name: Test
        run: npm run test
        env:
          CI: true
      - name: Build
        run: npm run build
        env:
          CI: true
      - name: Codecov
        run: npx codecov
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
      - name: Publish
        run: npm publish
        if: contains(github.ref, 'tags/v')

jobs.steps.[name].envCI: trueを設定するとどこでコケたのか分かりやすくなるので適当につけてください

Get Node.js version, Setup Node.js

Node.js のバージョンはできるだけ一箇所に纏めておきたかったので、.node-versionファイルからバージョンを取得して、それを使用するようにしています

(CLI ツールのようないろんな環境で使われる場合は matrix などで色々指定すると良いと思います)

Setup yarn, Get yarn cache dir, Cache, Install dependencies

yarn をインストールして、キャッシュをあれしておきます、キャッシュ関連は公式で配布されているのでここを見るといいでしょう

yarn を使ってない場合はyarn --frozen-lockfileの部分はnpm ciになったりすると思います

参考:

Codecov

気休めでCodecovでカバレッジを測ったりしている、Github App として Codecov を設定しても競合して崩壊するということはなかったです

Publish

v1.2.3みたいなタグがついたコミットが行われるときにこの job が実行され、自動で publish が行われるようになります

参考:@KamataRyo / Travis CI を使って npm を継続的に公開・メンテナンスするよ

Renovate

Renovate Bot、依存関係のバージョンを自動で更新をやってくれます

参考

SnO2WMaN/renovate-config

renovate.json

{
  "extends": [
    "github>sno2wman/renovate-config",
    ":timezone(Asia/Tokyo)",
    "schedule:daily"
  ]
}

その他

fossa

アプリ / サービス配布のときにライセンス周りで怒られが発生しないようにfossaというサービスで解析するようにはしてありますが、詳しいことはよく分かっていません

FontAwesome 5

アイコン周りは全部FontAwesome 5及び、vue-fontawesomeを使用しています

利用するときには、以下の用に書くと Tree Shaking が働いて出力ファイルのサイズが減るはずです

import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { faPenNib, faCircleNotch } from '@fortawesome/pro-solid-svg-icons'

Pro ライセンスについて

トークンが手に入るはずなので、NPM_FONTAWESOME_TOKENという名前で各々サービスや.envで設定しておくとして、

以下の内容の.npmrcを作成する

@fortawesome:registry=https://npm.fontawesome.com/
//npm.fontawesome.com/:_authToken=${NPM_FONTAWESOME_TOKEN}

renovate.jsonは、トークンをここで暗号化したうえで、encrypted.npmTokenに入れると上手くいく

{
  "encrypted": {
    "npmToken": "<ENCRYPTED>"
  },
  "npmrc": "@fortawesome:registry=https://npm.fontawesome.com/\n//npm.fontawesome.com/:_authToken=${NPM_TOKEN}",
  "npm": {
    "packageRules": [
      {
        "groupName": "FontAwesome Icons Pack",
        "packagePatterns": ["^@fortawesome/pro-", "^@fortawesome/free-"],
        "automerge": true,
        "updateTypes": ["minor"]
      }
    ]
  }
}

参考:Renovate Docs - Private npm module support

あとがき

クリスマスの深夜に書くものではない、2019 年 12 月 31 日 にはもっとまともな感じの記事になっていると思います

共用ファイルとして色々配布するのは色々楽しいです、皆さんもやってみてはどうでしょうか