Edy's Hub

プログラミングやライフスタイルについて書き綴っています

M1 Macbook air でherokuを使う

方法

brew で heroku をインストール

公式のCLImacOSにあるコマンドを実行します。

devcenter.heroku.com

brew tap heroku/brew && brew install heroku

command not found になった場合

自分の場合はbrew実行時に以下のエラーが発生しました。

% brew tap heroku/brew && brew install heroku      
zsh: command not found: brew

以下の記事を参考にトラブルシューティングしていきます。 【M1 Mac】zsh: command not foundと出た時の解決策。 - Qiita

zenn.dev

まずはbrewのインストールを行います。

% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 

完了後、パスを通していきます。

~/.zshrc に以下を追加。

export PATH=/opt/homebrew/bin:$PATH
source ~/.zshrc

再びチャレンジ

brew tap heroku/brew && brew install heroku

その後、 heroku login ができるか検証します。

% heroku login         
 ›   Warning: Our terms of service have changed: 
 ›   https://dashboard.heroku.com/terms-of-service
heroku: Press any key to open up the browser to login or q to exit:

任意のキーを押すとブラウザが立ち上がり、以下の画面に遷移します。

heroku login

後はサインイン or サインアップすれば使用可能になります。

ログイン完了後

Typescript学習〜『プロを目指す人のためのTypeScript入門』を読んでみて第2章〜

はじめに

業務で使うことのあるTypeScriptを本格的に勉強し始めたところです。

現在絶賛『プロを目指す人のためのTypeScript入門』を読み進めており、その際のメモを備忘録として残しております。

前回の記事 www.edyhub.com

書籍はこちら

第2章

第2章は「基本的な文法・基本的な型」について。

変数宣言

変数宣言の際の型注釈の構文は以下になります。

const 変数: 型 = 式;

例として書くと、

const greeting: string = "Hello, world"

書籍には以下のTipsが書かれていました。

  • 極力 let を避けてconst を使用すべき
  • 変数への再代入は基本的に不要な実装にする
  • letを使用すると読み手の負荷が増す(再代入の可能性を考慮してコードリーディングが必要になるため)

プリミティブ型

TypeScriptには基本的な型が存在します。

それらはプリミティブと呼ばれます。

現時点では文字列、数値、真偽値、BigInt、null、undefined、シンボルの7種類がある様です。

数値

数値はTypeScriptにおけるプリミティブの一つです。 実は10進数以外を扱っても実行結果を見ると適切に数値として認識されます。

2進数/8進数/16進数を扱った場合は下記の様なアウトプットになります。

const binary = 0b1010;
const octal = 0o755;
const hexadecimal = 0xff;

console.log(binary, octal, hexadecimal);

コンパイル結果

% node dist/index.js                                                                                                                                   
10 493 255

またTypeScriptの数値はIEEE754倍精度浮動小数点数です。 何やら難しく感じられますが、整数の精度が53ビットであることを覚えておくと良いと思います。 (正直覚えなくても良い気もします)

そのため、53ビットに収まらない大きさの整数や小数を扱う際には注意が必要です。 例えば以下の出力は直感と異なる計算誤差が生まれます。

console.log(9007199254740993);
console.log(0.1 + 0.2);
9007199254740992
0.30000000000000004

計算誤差を受け入れられない場合は、任意精度計算に対応したライブラリを導入するなど対応が必要になります。

Number型 - TypeScript Deep Dive 日本語版

一方で、最近(ES2020)になってBigInt型が登場しました。 古いブラウザでは利用できない制約がありつつも、誤差なく表すことが可能な型です。 通常の数値(number)よりは計算速度が遅いものの、今後利用シーンが増加する見込みがあるようです。

null と undefined

  • TypeScriptの型で挙げた null と undefined は、それ自体が値の名前
  • どちらも「データがない」状況を示している
  • その状況を示す概念が2種類あるのはJavaScriptやTypeScriptに特有の特徴

著者はサポートが厚いundefinedを推していました。

一致判定

  • ===== の2つを比較したとき、基本的に === のみ使う(同じく !=!== も後者)
  • 後者の方がより厳密な一致判定が行われるから

もう少し具体的に言うと、

== は暗黙的に型変換を行ってから比較を行うため型が異なってもtrueになることがあり、 === は型が異なる場合は常に結果をfalseとなります。

const str: any = "3";

// true 
console.log(str == 3);

// false
console.log(str === 3);

短絡評価

ES2020で追加された論理演算子 ??

例えば

x ?? y

のような場合は「xがnullまたはundefinedのときのみyを返し、それ以外のときはxを返す」というロジックに。

例えば、データがない場合は代替値を返したい場合に活用できますね。

まとめ

第2章も内容は基本的な文法の説明でした。

  • 部分的な差異はあれどプリミティブ型は他の言語との類似点が多い
  • 演算子や制御構文も基本的に一つ言語に慣れていればすんなり理解できた
  • for文の省略記法は初見殺しかも(気になる方は書籍を読んでみてください)

Typescript学習〜『プロを目指す人のためのTypeScript入門』を読んでみて第1章〜

はじめに

普段はバックエンドの開発がメインですが時たまフロントエンドの開発に着手することがあります。 今まではRails内でjQueryによる開発が多かったのですが去年あたりから Next.js × TypeScript の環境に移行し始めたので良い機会と思いTypeScriptを勉強し始めました。

会社の同僚が紹介してくれた入門書を読んでいきがてら備忘録を残しておこうと思います。

メモ

  • TypeScriptには静的型システムが備わっている
  • コンパイルエラーが出たら大喜び
  • 型安全性とドキュメント化のメリットがある
  • TypeScriptは "Javascript + 型" という様相の言語である
  • Node.js は偶数のメジャーバージョン(14, 16, ...)が安定版とされている(←確かに、と思いつつ知らなかった)

作業に移る前の準備

nvmのインストール

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash

インストールが終わると .zshrc に以下が追加されます。

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

バージョンが表示されれば成功です。

% nvm -v
0.37.2

nodeのインストール

nvmに続けてnodeをインストールします。

% nvm install --lts
Installing latest LTS version.
Downloading and installing node v16.15.1...
Downloading https://nodejs.org/dist/v16.15.1/node-v16.15.1-darwin-arm64.tar.xz...
########################################################################################################################################################### 100.0%
Computing checksum with shasum -a 256
Checksums matched!
Now using node v16.15.1 (npm v8.11.0)
Creating default alias: default -> lts/* (-> v16.15.1)

バージョンが表示されれば成功です。

% node -v
v16.15.1

package.jsonを作成

% npm init --yes

※ --yes は対話形式でのコマンド入力をスキップして、すべての質問をデフォルト値で答える。

TypeScriptをインストール

% npm install --save-dev typescript @types/node                                                                                                          

added 2 packages, and audited 3 packages in 2s

found 0 vulnerabilities

tsconfig.jsonの準備

コンパイラオプションとしてコマンドライン引数ではなく tsconfig.json を採用

% npx tsc --init                                                                                                                                         

Created a new tsconfig.json with:                                                                                       
                                                                                                                     TS 
  target: es2016
  module: commonjs
  strict: true
  esModuleInterop: true
  skipLibCheck: true
  forceConsistentCasingInFileNames: true


You can learn more at https://aka.ms/tsconfig

基本的な進め方

個人開発しているRailsプロジェクトにCircleCIを導入する

はじめに

職場でCircleCIによるRspec及びrubocopの自動実行をしているので個人開発しているサービスにも導入してみようと思いました。

CircleCIのファイル編集とかは職場でもやったことが無かったので調査から始めてみます。

CircleCIの本家を当たってみる

作っているサービスは Ruby on Rails で運用しているため、CircleCiのRubyのガイドを読み進めてみます。

言語ガイド:Ruby - CircleCI

version: 2 # CircleCI 2.0 を使用します
jobs: # ステップの集合
  build: # Workflows を使用しない実行では、エントリポイントとして `build` ジョブが必要
    parallelism: 3 # このジョブのインスタンスを 3つ並列実行します
    docker: # Docker でステップを実行します
      - image: circleci/ruby:2.4.2-jessie-node # このイメージをすべての `steps` が実行されるプライマリコンテナとして使用します
        environment: # プライマリコンテナの環境変数
          BUNDLE_JOBS: 3
          BUNDLE_RETRY: 3
          BUNDLE_PATH: vendor/bundle
          PGHOST: 127.0.0.1
          PGUSER: circleci-demo-ruby
          RAILS_ENV: test
      - image: circleci/postgres:9.5-alpine # データベースイメージ
        environment: # データベースの環境変数
          POSTGRES_USER: circleci-demo-ruby
          POSTGRES_DB: rails_blog
          POSTGRES_PASSWORD: ""
    steps: # 実行可能コマンドの集合
      - checkout # ソースコードを作業ディレクトリにチェックアウトする特別なステップ

      # Bundler のバージョンを指定します

      - run:
          name: Bundler を指定
          command: bundle -v

      # バンドルキャッシュを復元します
      # 依存関係キャッシュについては https://circleci.com/docs/ja/2.0/caching/ をお読みください

      - restore_cache:
          keys:
            - rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
            - rails-demo-bundle-v2-

      - run: # Ruby の依存関係をインストールします
          name: バンドルインストール
          command: bundle check || bundle install

      # Ruby の依存関係のバンドルキャッシュを保存します

      - save_cache:
          key: rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle

      # アプリケーションで Webpacker または Yarn を他の何らかの方法で使用する場合にのみ必要です

      - restore_cache:
          keys:
            - rails-demo-yarn-{{ checksum "yarn.lock" }}
            - rails-demo-yarn-

      - run:
          name: Yarn をインストール
          command: yarn install --cache-folder ~/.cache/yarn

      # Yarn または Webpacker のキャッシュを保存します

      - save_cache:
          key: rails-demo-yarn-{{ checksum "yarn.lock" }}
          paths:
            - ~/.cache/yarn

      - run:
          name: DB を待機
          command: dockerize -wait tcp://localhost:5432 -timeout 1m

      - run:
          name: データベースをセットアップ
          command: bin/rails db:schema:load --trace

      - run:
          name: RSpec を並列実行
          command: |
            bundle exec rspec --profile 10 \
                              --format RspecJunitFormatter \
                              --out test_results/rspec.xml \
                              --format progress \
                              $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)

      # タイミング解析のテスト結果を保存します

      - store_test_results: # テストサマリー (https://circleci.com/docs/ja/2.0/collect-test-data/) に表示するテスト結果をアップロードします
          path: test_results
      # デプロイコンフィグの例については https://circleci.com/docs/ja/2.0/deployment-integrations/ を参照してください

現状、開発しているプロダクトの構成は下記のとおりです。 - Dockerでweb, webpacker, dbコンテナをビルドする仕組み - ruby 2.6.6 - rails 6.0.0 - mysql 5.7

それぞれ対応するように修正していきます。

実際にファイルを作成してみた

version: 2
jobs:
  build:
    working_directory: ~/Hookah
    docker:
      - image: circleci/ruby:2.6.6-node-browsers
        environment:
          RAILS_ENV: test
          DATABASE_HOST: 127.0.0.1
      - image: mysql:5.7
        environment:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes

    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            - v1-dependencies-

      - run:
          name: Install bundle dependencies
          command: bundle install --path=vendor/bundle --jobs 4 --retry 3

      - run:
          name: Install yarn
          command: |
            yarn install

      - save_cache:
          paths:
            - ./vendor/bundle
            - ./node_modules
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}

      - run:
          name: Database Setup
          command: |
            bundle exec rake db:create db:schema:load

これでリモートリポジトリにプッシュしてみると、、 bundle exec rake db:create db:schema:load

の段階でエラーに。

bundle exec rake db:create db:schema:load
2020-05-23 16:22:30 WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path= is deprecated. Use Selenium::WebDriver::Chrome::Service#driver_path= instead.
DEPRECATION WARNING: Single arity template handlers are deprecated. Template handlers must
now accept two parameters, the view object and the source for the view object.
Change:
  >> Coffee::Rails::TemplateHandler.call(template)
To:
  >> Coffee::Rails::TemplateHandler.call(template, source)
 (called from <top (required)> at /home/circleci/Hookah/Rakefile:6)
Unknown MySQL server host 'db' (-2)
Couldn't create 'hookah_test' database. Please check your configuration.
rake aborted!
Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)

bundle update slim を実行

エラーメッセージでググってみると、どうやら gem 'slim' が原因になっていそうな。

qiita.com

ただ、bundle update をしても既に最新バージョンになっていた。

別のクエリでググってみると、 coffee-rails が怪しそうに。

github.com

coffee-rails のバージョンを 5.0.0 に上げるのが良さそうだったので変更。

すると、エラーが一つ消えたがさらにMySQL周りでエラーに...(面倒くさそうw)

2020-05-23 16:36:15 WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path= is deprecated. Use Selenium::WebDriver::Chrome::Service#driver_path= instead.
Unknown MySQL server host 'db' (-2)
Couldn't create 'hookah_test' database. Please check your configuration.
rake aborted!
Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)

省略

この記事を見て、

CircleCIのmysqlイメージを用いるように変更を加えました。

teratail.com

しかし、結果は変わらず。

データベース名を削除

Unknown MySQL server host 'db' (-2)
Couldn't create 'hookah_test' database. Please check your configuration.

ここにある Unknown MySQL server host 'db' (-2) というのが気になったので調べてみると、config/database.ymlhost: db と定義していることを確認しました。 (1年以上前に記述していたので忘れていた・・・)

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  database: <%= ENV['DATABASE_NAME'] %>
  username: <%= ENV['DATABASE_USERNAME'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>

development:
  <<: *default
  database: hookah_development
  host: db

test:
  <<: *default
  database: hookah_test
  host: db

production:
  <<: *default
  database: hookah_production
  username: root
  socket: /var/lib/mysql/mysql.sock

そこで、こちらの記事を参考に、hostには localhost を割り当てるように変更しました。 こちらは環境変数DATABASE_HOST として 127.0.0.1 になるようにしました。

qiita.com

変更後

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  database: <%= ENV['DATABASE_NAME'] %>
  username: <%= ENV['DATABASE_USERNAME'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>
  host: <%= ENV['DATABASE_HOST'] %>

development:
  <<: *default
  database: hookah_development

test:
  <<: *default
  database: hookah_test

production:
  <<: *default
  database: hookah_production
  username: root
  socket: /var/lib/mysql/mysql.sock

完成版

こちらが初期段階として導入に成功したCircleCIのファイルです。 Ruby on Rails による開発を行うので、rubocopやRspecのjobを今後追加していこうと思います。

version: 2
jobs:
  build:
    working_directory: ~/Hookah
    docker:
      - image: circleci/ruby:2.6.6-node-browsers
        environment:
          RAILS_ENV: test
          MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
          DATABASE_HOST: 127.0.0.1
          DATABASE_USERNAME: root
      - image: circleci/mysql:5.7

    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            - v1-dependencies-

      - run:
          name: Install bundle dependencies
          command: bundle install --path=vendor/bundle --jobs 4 --retry 3

      - run:
          name: Install yarn
          command: |
            yarn install

      - save_cache:
          paths:
            - ./vendor/bundle
            - ./node_modules
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}

      - run:
          name: Database Setup
          command: |
            bundle exec rake db:create db:schema:load

以上で導入を終了します。 当初予定していたrubocopやRspecは未対応ですが、基盤ができたので一旦これにて完了とします。

Reactを動かしてみる【準備編】

概要

社内でReactを用いた新規事業がスタートしたので、これを機に今までちゃんと勉強してなかったツケを回収する。

学習教材

Boothで購入したPDFをもとにサクッと進めていく。 すべて含めて200ページ弱なので週末で終わるかな。

booth.pm

作業手順

  • node, npm, yarnのインストール
  • React Appの作成

node, npm, yarnのインストール

npm と node をインストールしておきます。 筆者はすでに導入済みでした。

Nodeのバージョン管理に anyenv を用いるのでインストールを推奨します。

qiita.com

シェルは bash を使用しています。

$ brew install anyenv
$ echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l
$ anyenv install --init
...
Completed!
$ node -v
v13.12.0
$ npm -v
6.14.4

この後は、yarn をインストールします

$brew install yarn
$yarn -v
1.22.4

React Appの作成

ここからは実際にアプリケーションの作成に移ります。 適当なワーキングディレクトリで下記コマンドを打ち込みましょう。

$ npx create-react-app hello-world --typescript

npx は npm のパッケージをいちいちインストールしなくてもそのバイナリが実行できるコマンドです。

完了したら作成したプロジェクトに移動して yarn start と入力します。

$ cd hello-world
$ yarn start

Chromeのブラウザ上にアプリが表示されれば成功です。

f:id:yuki-eda0629:20200415224131p:plain
ブラウザに表示されたアプリケーション

今回は一旦ここまでにしておきます。

続きは別記事で書いていこうと思います。

コーディングトレースにチャレンジ

背景

普段は業務でサーバサイドエンジニアとして従事しているため、マークアップを0から行うことがほとんどありません。

ただ、Web開発に関わる人間としてフロントエンドの知見も多少なりとも保持しておきたいと思い、HTML/CSSを復習してみようと思いました。

前提として、HTMLのタグ、CSSのプロパティについての知識はあります。

何をやるか?

世に公開されているWebサイトをトレース(= 模写)しようと思います。

そして、ただデザインをトレースするのではなく、HTML/CSSを書いてマークアップをしてみます。

コーディングトレースを経て、そのサイトがどんなデザイン・構造のもと作成されているのかを理解していきます。

下準備

事前に過去にコーディングトレースをしてきた方々がどんな方法を用いて、コーディングをされてきたのかを調べておきます

※ 本記事は実際にコーディングはせず、調査のみになります。

やること

必要なファイルを用意します
  • index.html
  • main.css
フォントがわかる拡張機能を追加

フォントもこだわるべきではあるのですが、文字を睨めっこしてフォントを探り当てるのは本質的ではないので、一旦今回はGoogle Chrome拡張機能「WhatFont」に頼ることにします。

WhatFont - Chrome ウェブストア

画像の一括ダウンロードツールを追加

フォントに加え、画像のダウンロードも時間短縮したいものです。 今回は、サイト上の画像を一括保存できるGoogle Chrome拡張機能「Image Downloader」で画像を一気にダウンロードします。

ただし、この拡張機能は背景として用いられている画像については保存が出来ないようになっています。

その際は、デベロッパーツールなどでコードを確認して保存する必要があります。

Image Downloader - Chrome ウェブストア

色の抽出ツールを追加

さらに色の判別もGoogle Chrome拡張機能におまかせします。

用いるのは、「ColorPick Eyedropper」です。

ColorPick Eyedropper - Chrome ウェブストア

参考サイト

shibaken.org

haniwaman.com

新卒2年目エンジニア記事Pick【4月上旬編】

働き方

転職エントリ①

dev.classmethod.jp

  • リリースサイクルが速い
    • 1週間に1度のアプリリリース...
    • 開発速度の視座が上がる
  • 在籍中は約640本の記事を書きました、というコメントがさらっと書かれてある
  • 総じてアウトプット量によって社内外でのポジションを確立した感じがある

転職エントリ②

yoshiyuki-kato.hatenablog.com

  • 4年働いたリクルートを退職した振り返り
  • 入社早々、アサインされるはずだった開発プロジェクトが吹き飛ぶ
    • 入社早々社内ニートになるというスタート
  • 2年目まではフロントエンド→バックエンド→パフォーマンス・チューニング
  • その後、組織と技術の関係性に興味を持つ
  • 最後に社内の新規事業にアサインされる
  • しかし、ご自身も含め、チームの「熱量」の不足がネックになる
  • 2020年4月からリクルート同期が立ち上げた会社に転職した
  • 人間の営みに即した仕組みを伴う良いシステムを今後も追求していく予定

技術

フロントエンド①

note.com

  • jQueryやDOMを知っていればいいという世界観ではなくなっている
    • それは自分も感じる(肌感覚で2019年はVueがプロジェクトに採用されることに驚きを感じなくなった)
    • モダンウェブ技術を知っていれば、静的ページの生成にも応用が効く
  • Reactが提供した最大の功績は概念でありソフトウェア世界観
  • 文字数多めだったのでちゃんと読むと15分くらい掛かる
  • フロントエンドに関わる人もソフトウェア設計論をガッツリ理解して運用できることが求められる世界が到来している
    • フロントエンドでは The Clean Architecture よりも派生形である VIPER の方が馴染みやすいかも
  • 記事末尾のおすすめ記事が良質

記事中で登場したprismaはこちら

www.prisma.io

フロントエンド②

blog.cybozu.io

  • レガシなフロント技術をモダンな技術に移行していくチャレンジのお話
  • すべてを一気に最新技術に置き換えるのは現実的ではない
  • デグレを起こすことなく、問題を解決して開発体験の向上が図れるかを重要視

ブログ運用

ブログに対してのスタンス

www.specializedblog.com

  • ブログだけに依存するのは危険
    • プラットフォームに関係なくファンがついている状態を作ろう
  • ブログを収入媒体と捉えるのではなく、集客媒体とみなす
  • フロントエンド(集客媒体)とバックエンド(収入媒体)は別々で用意する