ゆとり日記

心にゆとりを持って生きたいプログラマーの雑記です。気が向いたら書きます。

GitHub Actionsを使って、Next.jsを静的にデプロイする

「Next.jsを静的サイトにホスティングできるんだっけ・・?」

Deployment | Next.js

公式にStatic HTML Exportと書かれているので出来るはずですが、自分で試さないと安心できなかったのでやってみました。

実現したいこと

Next.jsで作成したアプリケーションを静的サイトとしてデプロイするが目的です。 今回はデプロイ先として、GitHub Pagesを選択しました。

実際に動いているURLはこちらです。 Next.js Sample Website

デプロイまでの手順

  • GitHub Pagesとして使うリポジトリを用意する。
  • Next.jsのnext buildでビルドしたソースコードnext exportで静的サイトとしてエクスポートできるようにする。
  • GitHub ActionsでGitHub Pagesにデプロイできるようにする。
  • masterブランチへのpushをトリガーにして、 GitHub Actionsが動くようにする。

必要な手順はこのようになります。一つずつ見ていきましょう。

GitHub Pagesとして使うリポジトリを用意

https://help.github.com/ja/github/working-with-github-pages/about-github-pages

公式のドキュメントを一読しましょう。日本語のページが用意されているので、実際に手を動かしてやってみるのがおすすめです。

静的サイトとしてエクスポートする

"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start",
  "export": "next export"
}

package.jsonの抜粋です。next exportがエクスポートのコマンドなので、npm run exportで実行できるようにしておきましょう。 yarnでも同様の進め方が可能ですが、今回はnpmで進めていきます。

GitHub Actionsでデプロイ

github.com

今回はこちらを使っていきます。

help.github.com

Actions上でNode.jsを扱いたいので、こちらを参考にしつつ以下のようなymlファイルを用意します。

name: Node.js CI

on:
  push:
    branches: [ master ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Use Node.js
        uses: actions/setup-node@v1
        with:
          node-version: '12.x'
      - name: Install dependencies
        run: npm ci
      - name: build
        run: npm run build
      - name: export static html
        run: npm run export
      - name: jekyll
        run: touch ./.nojekyll
      - name: Deploy
        uses: JamesIves/github-pages-deploy-action@releases/v3
        with:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          BRANCH: master
          FOLDER: out

masterブランチへのpushをトリガーにして、GitHub Pagesへのデプロイまでを実行できるようになりました。 見れば分かる箇所は飛ばしつつ、補足をしていきます。

yamlのファイル名

今回はGitHub Actionsを1つ試すだけなので、適当な名前でOKです。作成したyaml.github/workflows配下に配置しましょう。

jekyllの無効化

- name: jekyll
  run: touch ./.nojekyll

GitHub Pagesではデフォルトでjekyllの変換機能が入っていますが、今回はNext.jsの静的ホスティングを試すために変換を無効にする必要が出てきます。

.nojekyllをルートディレクトリに配置することで無効にできるので、忘れずに入れておきましょう。

デプロイ指定の落とし穴

- name: Deploy
  uses: JamesIves/github-pages-deploy-action@releases/v3
  with:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    BRANCH: master
    FOLDER: out

BRANCHの指定はGitHub Actionsのトリガーに選んでいるブランチと同じにしましょう。master以外のブランチでGitHub Actionsが動くように設定している場合はBRANCHの変更も忘れないでください。

FOLDERに指定しているoutディレクトリは、next exportソースコードがエクスポートされるディレクトリです。指定があっていないと「CIは正常に通ってるけど、ページが見れない」状態になってハマるので注意してください。

まとめ

同じことを試されている方が多くいたのですんなり行くかと思っていましたが、意外とハマりどころがありました。GitHub Actionsの練習にもなるので、これから入門する人はやってみるのがオススメです。

React Hooksを使ってJavaScriptを動的に取得する

「Next.js、全然分からない」「Reactやるのが久しぶりで何もわからない」

このようにボヤきながらReactと向き合う中で、しばらくハマっていたことが解決したのでブログに纏めておきます。

何が解決したのか

独立したJavaScriptファイルを取得Custom Hookを作ることができました。

自前のソースコードを書くだけなら要らぬ心配ですが、サードパーティスクリプトGoogle Analyticsなど)をSPAでそのまま使いたい場合があると思います。そういう時に使えるかもしれない裏技です。

動作サンプル

https://codepen.io/rukiadia/pen/JjYadOL

画面表示後にjQueryのコードをCDNから取得しています。あくまでサンプルなので、jQuery云々は気にしないでください。

  • react v16.13.1
  • react-dom v16.13.1

Reactのバージョンはこちらで動作させています。

コードの説明

const { useEffect, useState } = React;
// 手元で試す場合は以下
// import React, { useEffect, useState } from "react";

const useScript = (src) => {
   // 「取得の完了」「取得時のエラー判定」をLocal Stateとして扱う
   const [state, setState] = useState({
     loaded: false,
     hasError: false
   });

  useEffect(() => {
    const scriptElement = document.createElement('script');
    scriptElement.src = src;

    const onLoadFunction = () => {
      setState({
        loaded: true,
        hasError: false
      });
    };

    const onErrorFunction = () => {
      // 取得失敗時、コンポーネント側でエラーハンドリングするフラグを立てる
      setState({
        loaded: true,
        hasError: true
      });
    };

    scriptElement.addEventListener('load', onLoadFunction);
    scriptElement.addEventListener('error', onErrorFunction);
    const wrapper = document.getElementById('wrapper');
    wrapper.appendChild(scriptElement);

    return () => {
      // load、error時の処理を関数化しておけば、ここでremoveEventListenerできる
      scriptElement.removeEventListener('load', onLoadFunction);
      scriptElement.removeEventListener('error', onErrorFunction);
    }
  }, []);

  return [state.loaded, state.hasError];
};
  • 動的にscript要素を生成してJavaScriptを取得する。
  • 「取得の完了」か「取得の成否」をLocal Stateとして管理し、結果をuseScriptを使っているコンポーネント側に返す。

やっていることを箇条書きにすると、このようになります。

実装時に気をつけること

動的に生成したscriptで取得したJavaScriptからはdocument.writeを呼び出せないので、document.writeが含まれている場合はこの手法が使えません。非同期取得を試す前に取得相手の中身は軽く見ておくようにしましょう。

Custom Hookの命名はuseで始める

ja.reactjs.org

カスタムフックとは、名前が ”use” で始まり、ほかのフックを呼び出せる JavaScript の関数のことです。

自作する場合は自由な命名をしないように意識しましょう。

ja.reactjs.org

"use"で始めなくても動かせてしまうので、公式で提供されているESLintを使っておくのが安全です。

参考資料

WebRTCを効率的にキャッチアップする

仕事でWebRTCを使うことになり、この一週間くらいはキャッチアップに勤しんでました。 ベースとなる知識の習得と、最新動向を知るためのアプローチについてブログに書いておきます。

まず大事なこと

最初のうちは、古い情報を見ないようにしましょう。 WebRTCは変化が早い技術なので、ブラウザの対応状況や最新仕様は頻繁に変わっていきます。前提知識がない状態で古い情報にアクセスすると、その情報が今も使える知識なのか判断できずに混乱してしまいます。

WebRTCで有名な人や企業を探す

WebRTCに限った話ではないが、業界の最先端でいる人や企業を探して最新動向を入手しやすくしよう。

すぐに思い浮かんだ企業はこちらの2社。

個人単位ではこの辺りの方達をフォローした。

参考に出来る資料を探す

W3Cの資料読めばいいっちゃいいんですが、網羅的に書かれた説明を読んだり聞いたりもしたいところです。 なので、udemyで動画講座を探したり、O'Reillyで参考書籍を探してみましょう。

動画

Udemyは講座がそもそもあまり無かったり、最終更新日が古いものも混ざっていて参考にできそうなものはなかった。 Youtubeで過去に開催された「HTML5 Conference」や「WebRTC Meetup Tokyo」の録画を見ることは可能だった。

youtu.be

youtu.be

書籍

色々漁ってみたが、参考にできたのはReal World HTTPハイパフォーマンス・ブラウザネットワーキングの2冊。

「Real World HTTP」で大まかな概論とユースケースを理解して、「ハイパフォーマンス・ブラウザネットワーキング」でWebRTCのプロトコルの詳細を理解するようにすれば、学習がスムーズに進むかもしれません。

「ハイパフォーマンス・ブラウザネットワーキング」ではWebRTCを支えるプロトコルであるUDPについても詳しく解説されているので、予備知識に不安がある人は知識を補っておくとベター。

実際に作って練習する

概論を読んだだけだとイメージが湧かないので、チュートリアル的なものをこなしてみると良い。

SkyWayは有料のプラットフォームだが、開発用アカウントを作ると無料枠があるので、そちらで動きを試すのがオススメ。 WebRTCに必要なサーバ(シグナリングサーバーやTURNサーバー)も用意されているので、手早く試せる。

まとめ

簡単ですが、自分が調べたりやってみたことを纏めてみました。 僕と同じく、これからWebRTCに入門しようとしている人の道標になってくれれば幸いです。

WEB+DB PRESS Vol.116「はじめてのトラブルシューティング」特集に寄稿しました #wdpress

04/24(金)発売のWEB+DB PRESSの「はじめてのトラブルシューティング」特集に寄稿しました!

WEB+DB PRESS Vol.116の表紙
WEB+DB PRESS Vol.116

@soudai1025さん、@yutailang0119さん、@maeponさんとの共著で、僕は@maeponとフロントエンドのトラブルシューティングを担当しました。フロントエンドの基礎知識から、パフォーマンス、アクセシビリティにも触れた内容になっています。

4/16頃から大型書店ではテスト販売があるそうなので、見かけたら手にとって頂けると嬉しいです。

書いた経緯

昨年末、@soudai1025に誘ってもらったのがきっかけです。一人でやり切れるかどうかの不安が少しあったので、執筆経験のある同僚の@maeponに共著という形式でサポートしてもらう形で受けることにしました。

初めての原稿を書いてみてどうだったか

僕の担当は4ページ弱でしたが、正直とても大変でした。

初めての原稿に張り切りすぎて、文章のボリュームが膨らんでしまったのが最初の失敗です。 書いている途中に書きたいことが新たに出てきてしまい、結果的に規定ページの1.5倍近いボリュームになってしまいました。

膨らんだ文章を削っていくのもなかなかに大変でした。 どこを削るかも悩みました。また、削る過程で文章の構成がおかしくなってしまい、結果的に大部分を書き直したこともありました。 編集の稲尾さんや、レビューをしてくれた共著メンバーには負担をかけてしまったなと反省しています。

謝辞

重ねてになりますが、編集の稲尾さんをはじめ、原稿のレビューや校正をしてくれた共著メンバーにはとても感謝しています。 フロントエンドの章を分担していた@maeponには執筆の過程で大きなサポートをしてもらいました。

お疲れ様でした!

まとめ

修正の大変さに心が折れそうになる時期もありましたが、挑戦してみて本当によかったなと今では思っています! 2020/04/24 (金) 発売予定のWEB+DB PRESS Vol.116をよろしくお願いします!!

リモートワークをしばらくやったので振り返る

タイトルのままです。リモートワークで働くようになって、今週で三週目に入ったので振り返りをしてみようと思います。

  • 良かったこと
  • 改善したいこと
  • 抱えているモヤモヤ

この辺りを触れていきます。

リモートワークの良かったこと

まずは良かったことから挙げてみます。

可処分時間が増えた

通勤時間が無くなったので、浮いた時間を使う選択肢が増えました。

電車通勤していた時は基本的に読書に時間を使っていましたが、電車が混雑して読書に時間を使えない場合もあります。また、通勤に使っている電車が事故で止まることもしばしばあったので、それが地味にストレスになっていました。

在宅であれば電車の運行状況や混雑状況は関係なくなるので、合間の勉強時間を安定して確保できるのはメリットだと感じます。

集中の時間が増えた

自分のタスクに没頭する時間は増えた気がします。

オフィスだと同僚とちょいちょい雑談をしたくなってしまうので、これをやらなくなったのが主な要因だと思っています。 雑談自体は数分で終わりますが、その後に集中状態に戻るまでにある程度の時間が必要です。これらの積み重ねでロスしていた時間が大きかったのでしょう。

しかし、雑談自体は良いことなので、雑談しすぎないようにするコントロールが重要だと考えています。「雑談は時間の無駄」と極端に考えず、適度にやっていけるのが最良でしょう。

現状共有を頻繁にするようになった

リモートワークだと個々の状況が見えづらくなりがちなので、自分の作業状況は意識的に共有するようにしました。

弊社には分報の文化があります。従業員は個々のチャンネルを作っていて、そこで勤怠報告をしたり、面白かった記事をカジュアルに共有したりしています。

僕の場合はタスクが順調に進んだ時は「秒で終わった」と言ってみたり、行き詰まった時は「完全に詰んだ」と言ってみたりして、自分の状況が他の人から見えやすいように意識するようになりました。

改善したいこと

良いこともありますが、もちろん上手くいってないこともあります。

早起きをするようにはならない

「通勤していた頃と同じ時間に起きて、早く仕事を始めて早く終わろう!」

リモートワークする前はこう考えていたんですが、実際は通勤時間の分だけ余分に寝るようになっただけに終わりました。 「遅く寝て遅く起きる生活」に脳がシフトしつつあり、早めの改善が必要なことをようやく自覚し始めました。

リモートワークになったからといって生活リズムを崩してしまうと、その影響がメンタルにも来るので一層の注意が必要です。

運動不足になった

これはリモートワークにしたことが原因ではなく、コロナが原因です。

2年近く日常的に通っていたジムに行けなくなってしまったので、運動や筋トレの時間を新規に作る必要が出てきました。 運動は外をランニングすれば済む話ですが、筋トレはそうもいきません。自宅でジムと同じトレーニングマシンを用意するのはスペース的に不可能なので、筋肉を落とさないためのトレーニングをしなければいけません。

現状では良い感じの習慣は作れていないので、今後数週間の課題として残しています。

抱えているモヤモヤ

ここからは改善すべき課題に近い、なんとなく思っていることです。

距離の遠い人がより遠く感じる

オフラインでコミュニケーション取れてなかった人達をより遠くに感じるようになった感覚を最近感じます。

仕事で関わることが少ない人と話す機会が少なくなりがちという課題は自分の中であったのですが、それを解決できないまま全社リモートワークに突入してしまったのが悩みになっています。また、4月に新たなに入社した人とも全然会話が出来てないのも良くないポイントだなと思っています。

組織の体制や方針の変更、新たに会社に入ってくる人とのコミュニケーション不足、リモートワークに慣れきれていない自分の精神状態。こういった起因による漠然とした不安の膨らみとどう向き合うかを考える毎日です。

余談

リモート飲み会は終電やトイレを気にする必要がなって便利な半面、延々と深酒出来てしまうリスクもあることがわかりました。 手の届くところにウイスキーのボトルとか置かないようにしましょう・・。

来年の抱負

「DEATH STRANDING」やってたら大晦日になってました。

以前書いた入社1年ブログで2019年の振り返りは大体やっているので、2020年の目標とか抱負を中心に考えていきます。

rukiadia.hatenablog.jp

来年の目標

大きく分けて2つです。

  • コンピューターサイエンスの学士を取得するためにUniversity of the Peopleに入学する。
  • アウトプットの機会を増やす。

University of the Peopleに入学する

ちょうど今日、記事にされている方がいました。Twitterで話題になっていますね。

tmkk.hatenablog.com

僕は今年の秋頃にこのオンライン大学の存在を知り、入学資格に足りうるTOEFLでの得点を取るために勉強を継続しています。年明けに初めての試験を受ける予定です。

コンピューターサイエンス(CS)の学士を取ろうと思った理由

  • 海外で働きたくなった時に学歴が足枷にならないようにしたい。
  • ソフトウェアの世界で戦っていくための土台を作りたい。

この辺りが主だった理由です。

僕は専門の大学も行かずに独学でこれまでプログラマーを続けてきました。それなりの勉強はやってきたつもりではありますが、足りない部分はまだまだ多いとも感じています。感覚的な物言いになってしまうのですが・・「実戦で必要になったから勉強した知識」の積み重ねをした結果、基礎により近い土台が盤石になっていないイメージを自分の中で抱えています。

「このままじゃ不味いでしょ」ということで、夏頃に通信で通える大学を調べ始めました。

通信にこだわる理由

仕事を辞めてフルタイムで通える程の余裕はないし、仕事を辞めたくもなかった。理由は至って単純です。

英語圏の大学にした理由

英語を使わざるをえない環境に身を置かないと、日常的に使えるレベルの英語は身につかないと考えたためです。

CSと英語の勉強を一緒に進めるのはそれなりに大変だと自覚してはいますが、やらずに後悔したくはないので頑張っていきます。

アウトプットの機会を増やす

2019年はアウトプットをあまりせずにサボってました。

登壇でいうと、フロントエンドカンファレンス福岡の前夜祭と、会社で開催している高円寺devで話したくらいです。ブログに至っては、今年の前半は一行も書いてません。

アウトプットの目標

闇雲に頑張るだけでは意味がないので、一応目標を定めておきます。

  • ブログは月一で書く。
  • 1Q(三ヶ月毎)に一回は登壇をする。

「ノルマ軽くない??」と思われるかもしれません。

人類は年末年始になると無茶な目標を立てがちな生き物です、しかし、僕はそこまで無謀な事はしません。少し頑張れば達成可能な目標を達成し、次の目標を少しだけハードにすることで、徐々に体を慣らしていく作戦でいきます。

PHPカンファレンスやBuildersconのような規模のイベントでCFPを通すことがもう一つの目標でもあるので、そこを目指して地道にやっていこうと思います。

まとめ

ということで、2020年は2019年の1.05倍くらいの頑張りでやっていこうと思います。

では皆さん、良いお年を。