初めて「Nuxt.jsにTypeScriptを導入してCircleCIでGitHub Pagesへデプロイ」してみたところ、欲張りすぎたため、いろんなところにハマった記録です。
ちなみに、わたしのスキル感はこんな感じ。初心者が頑張ってみた感じです。
- Nuxt.js: Vue.jsは使っているが、Nuxt.jsは初めて使ってみる
- TypeScript: 難しい型は分からない。。勉強し始めたばかり。
- CircleCI(CI/CD): 業務ではjenkinsを使用してビルド、デプロイしている。
- GitHub Pages: 存在は知っているが、使ったことはない。
概要
- Nuxt.jsのプロジェクトを作成
- TypeScriptも勉強中のため、ついでに組み込んでみる
- CircleCIを使ってビルド、GitHub Pagesへデプロイ
開発環境
node v10.13.0
yarn v1.21.1
教科書
基本的には、こちらの記事の手順に従ってやってみました。
CircleCIを使ってNuxt.jsをGitHub Pagesへデプロイする
https://qiita.com/yagi_suke/items/03a2411fdc3137ce657a
Nuxt.jsへのTypeScriptの導入は、こちらの記事に沿って進めました。
Nuxt.js PWA(Progressive Web Apps) のベースアプリをTypeScript対応する
https://riotz.works/articles/lulzneko/2019/05/10/typescripting-base-app-of-nuxtjs-pwa/
公式
CircleCI
https://circleci.com/docs/ja/2.0/getting-started/
バージョン 2.0
Nuxt.js
https://ja.nuxtjs.org/guide/
バージョン 2.11.x
Nuxt TypeScript
https://typescript.nuxtjs.org/guide/
完成したもの
Github
https://github.com/harada-k/nuxt-typescript
デプロイしたページ
https://harada-k.github.io/nuxt-typescript/
実装
STEP1:Nuxt.jsのプロジェクトの用意
まずは、Nuxtのインストール。
https://ja.nuxtjs.org/guide/installation
create-nuxt-app を利用してインストールしました(yarnを使用しました)。
$ yarn create nuxt-app <project-name>
TypeScriptの導入でハマったポイント
次に、TypeScriptを使ってみたいので、こちらの記事を参考にTypeScriptを導入します。
https://riotz.works/articles/lulzneko/2019/05/10/typescripting-base-app-of-nuxtjs-pwa/
Nuxt.jsもTypeScriptも初心者ですが、手順に従ってやってみます。
ところが、うまくいかない・・・(早すぎる躓き)。
Nuxt.jsのバージョンが、記事はv2.6.3、自分はv2.11.0だったのが原因でした。
Nuxt.js、バージョン2.9からTypeScriptのサポートが大幅に変更になったんですね・・・。
https://typescript.nuxtjs.org/guide/
公式の手順に従って進め、なんとか導入完了。
公式のドキュメント、大事!!
vueファイルをTypeScriptに書き換える際は、スクリプトベース(Vue.extend)で実装。
eslintの導入でハマったポイント
tsconfig.json、eslintの導入、設定などは、以下の記事を参考に実装しました。
https://qiita.com/tomopict/items/ced60c44203852faca0a
当初はnodeのバージョンを11.10.0にしていたのですが、、、
yarn add -D @typescript-eslint/eslint-plugin
上記のこちらのコマンドでエラー発生。。
error @typescript-eslint/eslint-plugin@2.22.0: The engine "node" is incompatible with this module. Expected version "^8.10.0 || ^10.13.0 || >=11.10.1". Got "11.10.0"
error Found incompatible module.
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
nodeバージョンは、"^8.10.0 || ^10.13.0 || >=11.10.1"でやっておくれ、ということのようです。
10.13.0に変更したところ、無事にインストールできました。
ESLint公式にも書いてありますね。。
https://eslint.org/docs/user-guide/getting-started
余談
yarn install に --ignore-engines オプションを付けると、エラーを無視できるようになるそうです。
もしくは、configにセット。
yarn config set ignore-engines true
ただし、エラーを無視するだけなので、packageが指定するnodeバージョンで実行したほうが良いと思います。
ちなみに、package.jsonにenginesを指定すると、nodeなどのバージョンを固定できます。
{
"engines": {
"node": ">=10.14",
"npm": ">=6",
"yarn": ">=1"
}
}
逆に言うと、typescript-eslintのpackege.jsonに、enginesの指定が入っていた、ということになりますね。
https://github.com/typescript-eslint/typescript-eslint/blob/master/package.json#L51
STEP2:CircleCIの設定
CircleCIへの登録は、Githubアカウントとの連携のみなので、問題なくクリア。
続いて、CircleCIの実行ファイル.circleci/config.ymlを作成してみます。
version: 2
jobs:
lint:
docker:
- image: circleci/node:10.13.0
steps:
- checkout
- restore_cache:
keys:
- yarn-{{ checksum "package.json" }}
- run: yarn install
- save_cache:
paths:
- node_modules
key: yarn-{{ checksum "package.json" }}
- run: yarn run lint
deploy:
docker:
- image: circleci/node:10.13.0
steps:
- checkout
- restore_cache:
keys:
- yarn-{{ checksum "package.json" }}
- run: yarn install
- run: git config user.name $GITHUB_NAME
- run: git config user.email $GITHUB_EMAIL
- run: yarn run generate:gh-pages
- run: yarn run deploy:gh-pages
workflows:
version: 2
build-deploy:
jobs:
- lint
- deploy:
requires:
- lint
filters:
branches:
only: master
Docker Images
jenkinsでのビルド、デプロイは日常的に行なっているので、大体のイメージは掴めたのですが、Docker Imageは初めての遭遇。
Dockerとは?から学ぼうと思ったのですが、ぼんやりしたイメージしか掴めませんでした。。
https://www.ogis-ri.co.jp/otc/hiroba/technical/docker/part1.html
https://qiita.com/kotaro-dr/items/b1024c7d200a75b992fc
実際にDockerをインストールして動かしてみると良いとは思いますが、今回の主軸はそこではないので、一旦スキップ。。
開発環境(node.js v10.13.0)と同じimageを使えば良いのではないか?と理解し、CircleCIが提供しているビルド済みイメージから選びました。
https://circleci.com/docs/ja/2.0/circleci-images/#nodejs
Nuxt.jsのrouterの設定
run: yarn run generate:gh-pages
Nuxt.jsのrouterの設定は、公式の「GitHub Pagesへデプロイするには?」に詳しく書かれています。
https://ja.nuxtjs.org/faq/github-pages/
package.jsonのscriptsに、Github Pages向けにrouter設定してビルドを行うコマンドを追加します。
"generate:gh-pages": "DEPLOY_ENV=GH_PAGES nuxt-ts generate",
このコマンドを、CircleCIのYAMLファイル内で呼び出して実行します。
- run: yarn run generate:gh-pages
gh-pagesパッケージの導入
gh-pagesブランチは、デプロイするものだけ(generate:gh-pagesコマンドで作成した、distフォルダの中身のみ)が入った状態にしたいので、gh-pagesパッケージを導入します。
https://www.npmjs.com/package/gh-pages
package.jsonのscriptsに、デプロイジョブを追加します。
"deploy:gh-pages": "gh-pages -d dist -m 'chore: update [skip ci]' -t",
このコマンドを、CircleCIのYAMLファイル内で呼び出して実行します。
- run: yarn run deploy:gh-pages
config.ymlの記述については、こちらの記事で理解を深めました。
https://qiita.com/gold-kou/items/4c7e62434af455e977c2#configyml
秘密鍵と公開鍵を登録する
「CircleCIのプロジェクトに追加する」「CircleCIに環境変数を設定する」は、手順通りでクリア。
次のハマりポイントは、「CircleCIに秘密鍵を登録する」でした。。
$ ssh-keygen -t rsa -b 4096 -C 任意の文字列 -f ./id_rsa # パスワードは空にすること
Githubに登録する公開鍵はすんなりクリアできたのですが、CircleCIに登録する秘密鍵が、エラーで登録できない!!
原因は、OpenSSH 7.8から、秘密鍵のヘッダの形式が変更になったことにあるようでした。
それ以前の秘密鍵は、OpenSSLのPEM形式で作成されていましたが、本バージョンからOpenSSHの形式がデフォルトとなり、秘密鍵のヘッダの形式が大きく変わっています。
PEM形式で作成するには、-m PEMオプションをつければOK。
ssh-keygen -t rsa -b 4096 -C "任意の文字列" -f ./id_rsa -m PEM
これで無事に秘密鍵が登録できました。。
よく見ると、CircleCIのドキュメントにも書いてありました。。。公式ドキュメント大事。。
https://circleci.com/docs/ja/2.0/gh-bb-integration/#github-%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%AD%E3%83%BC%E3%81%AE%E4%BD%9C%E6%88%90
注意:最近 ssh-keygen は、デフォルトで PEM 形式のキーを生成しないようにアップデートされました。 プライベートキーが -----BEGIN RSA PRIVATE KEY----- で始まらない場合、ssh-keygen -m PEM -t rsa -C "your_email@example.com" でキーを生成すると、強制的に PEM 形式で生成できます。
まとめ
これで、masterブランチに変更をpushすると、自動でLint、build、deployが行われるようになりました。
Github
https://github.com/harada-k/nuxt-typescript
デプロイしたページ
https://harada-k.github.io/nuxt-typescript/
Lintジョブはmasterに限定していないので、featureブランチを切って修正を行い、リモートにpushした場合も、Lintジョブが走ります。
featureブランチからmasterブランチへPull requestを作成、masterにマージされると、自動的にビルド、Github pagesにデプロイされます。
フロー的にもわかりやすいし、便利です。
ハマりどころが他にもあるとは思いますが、何かのお役に立てたら幸いです。
今回の教訓は、「ハマったら公式!」
参考
いまさらだけどCircleCIに入門したので分かりやすくまとめてみた
https://qiita.com/gold-kou/items/4c7e62434af455e977c2
Nuxt v2.9.2でTypeScript, eslint, Prettier環境構築 + VSCodeの設定
https://qiita.com/tomopict/items/ced60c44203852faca0a
デコレータ使わない Vue.js + TypeScript で進んだ「LINEのお年玉」キャンペーン
https://engineering.linecorp.com/ja/blog/vue-js-typescript-otoshidama/
3分でつくる2019年版 Nuxt.js TypeScript 開発環境設定
https://qiita.com/hiropy0123/items/4ee85fdb9b19bc89056f
package.json の engine について npm と yarn の挙動の違い
https://blog.yukung.org/difference-between-the-behavior-of-yarn-and-npm-for-engine/
package.jsonに"engines"を設定すると「このバージョンのNode.jsでしか動かない」を表明できる
https://qiita.com/suin/items/994458418c737cc9c3e8