高木のブログ

VirtualBox のバージョンを上げたら vagrant up ができなくなった

VirtualBox を 6.1.32 に上げたら vagrant up でコケるようになった(上げる前のバージョンは失念した)

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'centos/7' version '2004.01' is up to date...
==> default: Clearing any previously set network interfaces...
The IP address configured for the host-only network is not within the
allowed ranges. Please update the address used to be within the allowed
ranges and run the command again.

  Address: 192.168.30.93
  Ranges: 192.168.56.0/21

Valid ranges can be modified in the /etc/vbox/networks.conf file. For
more information including valid format see:

  https://www.virtualbox.org/manual/ch06.html#network_hostonly

原因 🔗

どこからかのバージョンから、Vagrantfileで設定する private_network のIPアドレスに範囲制限が入ったみたい

数値比較の絞り込みをするならgrepよりawkを使った方が良い

grepで数値比較(いいかた合ってるかわからないけど、〇〇以上とか〇〇以下)で絞り込みをしたかったので調べたら、どうやらawkでやった方が簡単だった

ランダムな数値が改行区切りで入ったファイルがある
ここから20以上の数値だけに絞り込みたい

$ cat random_number.txt
81
10
43
11
2
42
37
62
31
11
86
9
44
10
87
17
72
78
6
21

grepで絞り込み 🔗

grepだと文字列として正規表現で絞り込みをしないといけない
最大値がわからないとすると、20未満を除外する正規表現を書いたほうが良さそう
今回の例だと難しくはなかったけど、可読性が悪すぎる

$ grep -v '^1*[0-9]$' random_number.txt
81
43
42
37
62
31
86
44
87
72
78
21

awkで絞り込み 🔗

awkなら数値の比較ができるので、あら簡単

$ awk '{ if ($0 >= 20) print $0 }' random_number.txt
81
43
42
37
62
31
86
44
87
72
78
21

おわり 🔗

絞り込み = grep じゃなかったんだなあ

RubyでTOMLを扱うために使うGemはどれがいいか調べてみた

Tags: Ruby Gem

RubyでTOMLを扱うことになったので、どのGemを使えばいいか調べてみた

既に調べていた方がいたが、6年前の記事だった(https://keyamb.hatenablog.com/entry/2016/03/08/165648)

2022年現在では変わっているかもしれないので再調査

比較するGemは以下の3つ

結論 🔗

用途がパースだけならTOML v1.0.0に一番対応している tomlrb を使うのが良さそう(ダンプ機能がまだ実装されていない)
ダンプもするなら toml-rb を使うのが良さそう(複雑ではないパースなら問題なさそう)

比較項目 🔗

ダウンロード数 🔗

もちろんダウンロード数が正義ではない

  • toml: 16,157,541
  • toml-rb: 19,168,816
  • tomlrb: 24,803,130

スター数 🔗

もちろんスター数が正義ではない

  • toml: 139
  • toml-rb: 88
  • tomlrb: 51

アクティビティ 🔗

もちろん(以下略

最終リリース日 🔗

  • toml: 2021/06/01
  • toml-rb: 2022/01/27
  • tomlrb: 2020/12/20

最終コミット日 🔗

  • toml: 2021/12/02
  • toml-rb: 2022/01/27
  • tomlrb: 2022/01/02

テスト 🔗

これは大事かも

TOML v1.0.0 に準拠されているかのテストケースを306個作って確認してくれた方がいた https://github.com/gyfis/toml-comparison

これは通ったテストケースの数

  • toml: 217
  • toml-rb: 226
  • tomlrb: 283

Denoの使用すべきdeno_stdのバージョンを出力するワンライナー

Tags: Deno

Deno(本体)とdeno_stdは独立してバージョン管理されていて、使用すべきバージョンは https://github.com/denoland/dotland/blob/main/versions.json で確認することができる

頻繁にDenoを使うわけではないので、使うときはアップグレードから始める
その度に対応するdeno_stdバージョンを確認しにいくのは少し面倒なので、現在使おうとしているDenoのバージョンに対応するdeno_stdバージョンを出力するワンライナーを書いた
それをエイリアスに登録してすぐ確認できるようにした

成果物 🔗

ワンライナー 🔗

$ curl -s https://raw.githubusercontent.com/denoland/dotland/main/versions.json | jq -r '.["cli_to_std"]["v'`deno -V | awk '{print $2}'`'"]'
0.122.0

エイリアス登録 🔗

一部ダブルクォーテーションをエスケープして登録

alias deno-std-version="curl -s https://raw.githubusercontent.com/denoland/dotland/main/versions.json | jq -r '.[\"cli_to_std\"][\"v'`deno -V | awk '{print $2}'`'\"]'"
$ deno-std-version
0.122.0

Rails.env.production?の正体

Tags: Rails

環境によって処理を分ける時によく使う Rails.env.production? だったり、Rails.env.development? ってやつ

Rails.env.production?
#=> true

タイポしてもエラーにならないから、何事だ!と思い少し調べた

Rails.env.productio?
#=> false

そもそも String じゃなかった 🔗

Rails.env がただの Stirng かと思ったら、ActiveSupport::EnvironmentInquirer だった

Rails.env
#=> "production"
Rails.env.class
#=> ActiveSupport::EnvironmentInquirer

ActiveSupport::EnvironmentInquirer とは 🔗

ごにょごにょ書いてあるけど、一旦ここでは ActiveSupport::StringInquirer を継承しているとだけ

module ActiveSupport
  class EnvironmentInquirer < StringInquirer # :nodoc:
    DEFAULT_ENVIRONMENTS = ["development", "test", "production"]
    def initialize(env)
      super(env)

      DEFAULT_ENVIRONMENTS.each do |default|
        instance_variable_set :"@#{default}", env == default
      end
    end

    DEFAULT_ENVIRONMENTS.each do |env|
      class_eval "def #{env}?; @#{env}; end"
    end
  end
end

https://github.com/rails/rails/blob/18707ab17fa492eb25ad2e8f9818a320dc20b823/activesupport/lib/active_support/environment_inquirer.rb

ActiveSupport::StringInquirer とは 🔗

String を継承して、method_missing をオーバーライドしている

module ActiveSupport
  class StringInquirer < String
    private
      def respond_to_missing?(method_name, include_private = false)
        method_name.end_with?("?") || super
      end

      def method_missing(method_name, *arguments)
        if method_name.end_with?("?")
          self == method_name[0..-2]
        else
          super
        end
      end
  end
end

https://github.com/rails/rails/blob/18707ab17fa492eb25ad2e8f9818a320dc20b823/activesupport/lib/active_support/string_inquirer.rb#L19

Togglのデータがちゃんと同期されているかチェックする仕組みを作った

意識高い系エンジニアなので、自己研鑽に使った時間を Toggl で記録して、Pixela で可視化している
しかし、TogglのAPIで値が取れず、グラフの更新ができていないことがある
これはTogglのiPhoneアプリが、Togglのサーバーとデータ同期できていないことが原因になっている(同期がうまくいかない原因はわからない)

一旦ログアウトしてログインし直すと同期できるようになるんだけど、同期されていない分は消えてしまう
リカバリーは、ログアウトする前にスクショを取ってバックアップして、手動で入力し直すというアナログな方法を取っている

同期できてないことに気付くのが遅れれば遅れるほどリカバリーが大変になるので、早めに気付きたい
ということで、GitHub Actionsを使って気付ける仕組みを作った

実装 🔗

Rubyスクリプト 🔗

直近3日のデータを見て、何もなかったらコケるようにした雑実装
コケたらGitHub Actionsのメール通知機能で気が付ける仕組み

require 'dotenv/load'
require 'base64'
require 'faraday'
require 'json'

API_ENDPOINT = 'https://api.track.toggl.com/reports/api/v2'
USER_AGENT = 'toggl-sync-status-check (https://github.com/ytkg/toggl-sync-status-check)'

url = "#{API_ENDPOINT}/summary"
params = {
  user_agent: USER_AGENT,
  workspace_id: ENV['TOGGL_WORKSPACE_ID'],
  since: Date.today - 2,
  until: Date.today
}
headers = { 'Authorization' => "Basic #{Base64.encode64("#{ENV['TOGGL_API_TOKEN']}:api_token")}" }
response = Faraday.get(url, params, headers)

raise 'No data.' if JSON.parse(response.body, symbolize_names: true)[:data].empty?

p :ok

GitHub Actions ワークフロー 🔗

毎日0時0分に動くようにした
0時に実行すると当日分はデータがないので、チェックしてるのは実質2日分か

name: Ruby

on:
  workflow_dispatch:
  schedule:
    - cron:  '0 0 * * *'
jobs:
  ruby:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up Ruby
      uses: ruby/setup-ruby@v1
      with:
        ruby-version: 2.7
    - name: Install dependencies
      run: bundle install
    - name: Run script
      env:
        TOGGL_API_TOKEN: ${{ secrets.TOGGL_API_TOKEN }}
        TOGGL_WORKSPACE_ID: ${{ secrets.TOGGL_WORKSPACE_ID }}
      run: bundle exec ruby app.rb

リポジトリ 🔗

ytkg/toggl-sync-status-check - GitHub

Thorを使ってCLIを作る時に書くおまじない

Tags: Gem Ruby

Thor を使ってCLIを作る時に書かないといけないおまじないがある

以下のように引数が必要なサブコマンドを書いて、引数なしでコマンドを実行するとDeprecation warinigが出る

#!/usr/bin/env ruby

require 'thor'

module Sample
  class Cli < Thor
    desc 'hello NAME', 'say hello'
    def hello(name)
      puts "hello, #{name}"
    end
  end
end

Sample::Cli.start
$ bundle exec exe/sample hello
ERROR: "sample hello" was called with no arguments
Usage: "sample hello NAME"
Deprecation warning: Thor exit with status 0 on errors. To keep this behavior, you must define `exit_on_failure?` in `Sample::Cli`
You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.

おまじない 🔗

true を返す exit_on_failure? メソッドを定義する

Ruby3.1環境で出る thor の deprecation warning

Tags: Ruby Gem

Ruby3.1 + Railsで出てくる thor gem のdeprecation warning
Rails以外でもthorを使っていると出るっぽい

Calling `DidYouMean::SPELL_CHECKERS.merge!(error_name => spell_checker)' has been deprecated. Please call `DidYouMean.correct_error(error_name, spell_
checker)' instead.

PR: Support latest did_you_mean by deivid-rodriguez · Pull Request #761 · rails/thor

gem自体は v1.2.0 で修正されたけど、bundle -v でも出てくる

$ bundle -v
Calling `DidYouMean::SPELL_CHECKERS.merge!(error_name => spell_checker)' has been deprecated. Please call `DidYouMean.correct_error(error_name, spell_
checker)' instead.
Bundler version 2.2.28

これはbundlerのバージョンを上げればOK

$ bundle update --bundler
$ bundle -v
Bundler version 2.3.4

公開しているGemの rubygems_mfa_required を有効にした

Tags: Gem Ruby

公開しているGemで使っているRuboCopのバージョンを上げたら、以下の警告が出るようになった
v1.23.0 から Gemspec/RequireMFA が追加された警告みたい

switchbot.gemspec:5:1: C: [Correctable] Gemspec/RequireMFA: metadata['rubygems_mfa_required'] must be set to 'true'.
Gem::Specification.new do |spec| ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

gemspecに以下を追加することで、MFAを設定しているアカウントでないとGemの更新や削除ができなくなるので、安全性が高くなる

+  spec.metadata['rubygems_mfa_required'] = 'true'

リリースする時にOPTコードを求められるようになる

$ bundle exec rake release
Calling `DidYouMean::SPELL_CHECKERS.merge!(error_name => spell_checker)' has been deprecated. Please call `DidYouMean.correct_error(error_name, spell_checker)' instead.
switchbot 0.5.1 built to pkg/switchbot-0.5.1.gem.
Tagged v0.5.1.
Pushed git commits and release tag.
Pushing gem to https://rubygems.org...
You have enabled multi-factor authentication. Please enter OTP code.
Code:

rubygems_mfa_required を有効にしないとしても、アカウントのMFAは設定しておいた方がいい
MFAの設定は https://rubygems.org/settings/edit で出来る

参考 🔗

個人gemにrubygems_mfa_requiredをつけた - くりにっき

2021年を振り返る

Tags: 振り返り

書いている途中で力尽きたので一旦公開
1月31日までにはちゃんと書く


2021年を振り返る

Ruby/Rails 🔗

Ruby/Railsが絡む記事は40記事くらい書いた。小ネタ系が多かった。

Gemを2個リリースした。

Rails関連はAction Cableなどの不要な機能を外したり、6.0系から6.1系にアップグレードしたり。

Deno 🔗

去年v1.0.0が出た時に軽く触って、今年になってちゃんとDenoに入門した。
カンペなしで良さや特徴を人に説明できない状態なのでまだまだかなという感じ。
来年も引き続き触っていきたい。

React 🔗

やっとReactを触り始めた。(何年も前から触ろうとしていたけどなかなか着手できず)
ポートフォリオサイト (https://takagi.dev/ ) を作っている。

Cloudflare Workers 🔗

今年はCloudflareの勢いがすごかった印象

Google Cloud Platform 🔗

業務でGCPを使うことになったので触った。(実際に使ったのはBigQueryのみ)
とりあえずSecret ManagerとCloud Functionsを触りだけ。

Rails6.1からform_withで同期通信(local: true)がデフォルトになった

Tags: Rails

先日Rails7が出たが、仕事でもプライベートでも未だに6.0系を使っている
そろそろ上げないとまずいと思い、とりあえず個人アプリの1つをRails6.1系にあげた
そんな大きなアプリではないので、1カ所だけ仕様変更の対応をしてアップグレードは無事終わった

問題 🔗

非同期通信で更新している部分がエラーを吐いた

SettingsController#create is missing a template for this request format and variant.
request.formats: ["text/html"]
request.variant: []

原因 🔗

タイトル通りで、 form_with で同期通信がデフォルト(local: true)になったため
6.0系までは非同期通信がデフォルト(local: false)だったので、オプションの指定を省略していた

プルリクエスト 🔗

https://github.com/rails/rails/pull/40708

解決方法 🔗

form_with のオプションに local: false を指定する

-<%= form_with url: settings_path do |form| %>
+<%= form_with url: settings_path, local: false do |form| %>

生成されるHTMLタグ 🔗

data-remote="true" が付くようになり、今まで通り非同期で更新するようになった

-<form action="/settings" accept-charset="UTF-8" method="post">
+<form action="/settings" accept-charset="UTF-8" data-remote="true" method="post">

参考 🔗

【MySQL】JSON型のカラムを見やすい形式で表示する

Tags: MySQL

問題 🔗

MySQLでJSON型のカラムを普通にSELECT文で表示すると見づらい

> select body from response \G
*************************** 1. row ***************************
body: {"body": {"deviceList": [{"deviceId": "500291B269BE", "deviceName": "Living Room Humidifier", "deviceType": "Humidifier", "hubDeviceId": "000000000000", "enableCloudService": true}], "infraredRemoteList": [{"deviceId": "02-202008110034-13", "deviceName": "Living Room TV", "remoteType": "TV", "hubDeviceId": "FA7310762361"}]}, "message": "success", "statusCode": 100}

例でSwitchBotのAPIのレスポンスを使用した(https://github.com/OpenWonderLabs/SwitchBotAPI)
このくらいの量だったら読めなくもないけど、実際はもっと長いレスポンスを格納する時もある

解決方法 🔗

JSON_PRETTY というユーティリティ関数があるので、それを使うと見やすい形式で表示してくれる

select JSON_PRETTY(body) from response \G
*************************** 1. row ***************************
JSON_PRETTY(body): {
  "body": {
    "deviceList": [
      {
        "deviceId": "500291B269BE",
        "deviceName": "Living Room Humidifier",
        "deviceType": "Humidifier",
        "hubDeviceId": "000000000000",
        "enableCloudService": true
      }
    ],
    "infraredRemoteList": [
      {
        "deviceId": "02-202008110034-13",
        "deviceName": "Living Room TV",
        "remoteType": "TV",
        "hubDeviceId": "FA7310762361"
      }
    ]
  },
  "message": "success",
  "statusCode": 100
}

MySQL 5.7.8からJSON型をサポートしたので、おそらくそれ以降なら使えるはず
ちなみにJSON型のカラム以外でもJSON形式になっていれば使えた

補足 🔗

今回使ったテーブルのCREATE文とINSERT文

create table response (body json);
desc response;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| body  | json | YES  |     | NULL    |       |
+-------+------+------+-----+---------+-------+
1 row in set (0.002 sec)
insert into response values ('{"statusCode":100,"body":{"deviceList":[{"deviceId":"500291B269BE","deviceName":"Living Room Humidifier","deviceType":"Humidifier","enableCloudService":true,"hubDeviceId":"000000000000"}],"infraredRemoteList":[{"deviceId":"02-202008110034-13","deviceName":"Living Room TV","remoteType":"TV","hubDeviceId":"FA7310762361"}]},"message":"success"}');

参考 🔗

MySQLでJSON型を使う(JSON関数編) | スマートスタイル TECH BLOG

【Prezto】リダイレクトによる上書きを有効にする

Tags: Prezto Zsh

Prezto を導入してから、リダイレクトでの上書き(および追記)ができなくなった

$ echo "# sample" >> README.md
zsh: no such file or directory: README.md
$ echo "# sample" > README.md
zsh: file exists: README.md

GitHubにコードを上げる時にリポジトリを作ってコピーしてペッ!ってのが出来なくて不便
これの1行目からつまずく

echo "# sample" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin [email protected]:ytkg/sample.git
git push -u origin main

原因 🔗

Prezto の設定でリダイレクトによる上書きが無効にされていた(prezto/modules/directory/init.zsh

解決方法 🔗

.zshrc に リダイレクトによる上書きを有効する設定 を追記する

setopt CLOBBER

参考 🔗

既存のRailsアプリからAction CableやAction Mailerなどの不要な機能を取り除く

Tags: Rails

既存のRailsアプリからAction CableやAction Mailerなどの不要な機能を取り除いたのでその手順を記録として残す

初めから不要なのがわかっていれば、rails new をするタイミングでスキップするオプションを付ければ良い

不要な機能をスキップするオプション:

$ rails new -h | grep Skip
      [--skip-namespace], [--no-skip-namespace]              # Skip namespace (affects only isolated engines)
      [--skip-collision-check], [--no-skip-collision-check]  # Skip collision check
  -G, [--skip-git], [--no-skip-git]                          # Skip .gitignore file
      [--skip-keeps], [--no-skip-keeps]                      # Skip source control .keep files
  -M, [--skip-action-mailer], [--no-skip-action-mailer]      # Skip Action Mailer files
      [--skip-action-mailbox], [--no-skip-action-mailbox]    # Skip Action Mailbox gem
      [--skip-action-text], [--no-skip-action-text]          # Skip Action Text gem
  -O, [--skip-active-record], [--no-skip-active-record]      # Skip Active Record files
      [--skip-active-job], [--no-skip-active-job]            # Skip Active Job
      [--skip-active-storage], [--no-skip-active-storage]    # Skip Active Storage files
  -P, [--skip-puma], [--no-skip-puma]                        # Skip Puma related files
  -C, [--skip-action-cable], [--no-skip-action-cable]        # Skip Action Cable files
  -S, [--skip-sprockets], [--no-skip-sprockets]              # Skip Sprockets files
  -J, [--skip-javascript], [--no-skip-javascript]            # Skip JavaScript files
      [--skip-turbolinks], [--no-skip-turbolinks]            # Skip turbolinks gem
      [--skip-jbuilder], [--no-skip-jbuilder]                # Skip jbuilder gem
  -T, [--skip-test], [--no-skip-test]                        # Skip test files
      [--skip-system-test], [--no-skip-system-test]          # Skip system test files
      [--skip-bootsnap], [--no-skip-bootsnap]                # Skip bootsnap gem
      [--no-rc], [--no-no-rc]                                # Skip loading of extra configuration options from .railsrc file
  -s, [--skip], [--no-skip]        # Skip files that already exist

手順 🔗

正式な取り除き方がわからなかったので、スキップするオプションを付けるパターン、付けないパターンで rails new して、その差分を見て機能を削除した

wrangler2なら2行で、Cloudflare Workersにデプロイできる

cloudflare/wrangler2 - GitHub

いつの間にか、wrangler2が出ていた(まだBeta版)
たった2行で、アプリ作ってCloudflare Workersにデプロイするところまでもっていける(設定ファイルとか作らない)
もちろん実用性のあるアプリは流石に無理だけど

(wrangler2はたった2行でデプロイできるってのが売りではない)

手順 🔗

「hello world」を返すアプリ

$ echo -E "export default { fetch() { return new Response('hello world\n') } }" > index.js
$ npx wrangler@beta publish index.js --name hello
$ curl hello.ytkg.workers.dev
hello world

補足 🔗

開発サーバー 🔗

起動 🔗

$ npx wrangler@beta dev index.js
$ curl localhost:8787
hello world

ローカルモード 🔗

Lキーでローカルモードにできる

通常起動だと開発中も無料枠を消費してしまうので、ローカルモードは必須
miniflare を使わなくて済む(というよりminiflareが内包されたっぽい?)

起動時に --local をつけたらはじめからローカルモードで起動できる

$ npx wrangler@beta dev index.js --local

ローカルモードだとターミナルにログが出なくなったけど、Dキーで開発者ツールが開いてそこでログが見れる

(キーは表記上大文字だけど、実際はShiftなしの小文字の入力でOK)

リポジトリ 🔗

上げるほどでもないけど成果物をGitHubに上げといた ytkg/wrangler2-sample - GitHub

RubyでいうクラスメソッドとプライベートクラスメソッドをTypeScriptで実装する

最近はTypeScriptの勉強をしている

RubyでいうクラスメソッドとプライベートクラスメソッドをTypeScriptで実装してみた
ググってもなかなか出てこなくて、そもそもこういう使い方するのかどうかってところだけど、とりあえず目的の挙動するもができたので記録として残す

TypeScript以前にJavaScriptの勉強をした方が良さげだなあ

Ruby 🔗

クラスメソッドは self. を付けてメソッドを定義する
プライベートメソッドはクラスメソッドを定義したあと、 private_class_method でプライベートに指定する

class Foo
  def self.bar
    "bar, #{baz}"
  end

  def self.baz
    'baz'
  end

  private_class_method :baz
end

Foo.bar #=> "bar, baz"

Ruby 2.1以降から以下のような定義の仕方もできるようになっている

private_class_method def self.baz
  'baz'
end

TypeScript 🔗

static を付けるとクラスメソッドっぽいものになる
さらに private を付けるとプライベートなクラスメソッドっぽいものになる

class Foo {
  static bar() {
    return `bar, ${this.baz()}`;
  }

  private static baz() {
    return 'baz';
  }
}

Foo.bar() //=> "bar, baz"

GitHub ActionsからReactアプリをCloudflare Workers Sitesにデプロイする

前回、ローカルから「Create React Appで作ったReactアプリをCloudflare Workers Sitesにデプロイする 」をやったので、今回はGitHub Actionsから自動デプロイできるようにしてみる

Deploy to Cloudflare Workers with Wrangler

手順 🔗

APIトークンを取得する 🔗

APIトークンはここで取得できる
https://dash.cloudflare.com/profile/api-tokens

テンプレートは「Edit Cloudflare Workers」を選択

APIトークンをGitHubのSecretsに登録 🔗

Nameは「CF_API_TOKEN」で登録

ワークフローファイルを作成する 🔗

name: Deploy

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    name: Deploy
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: '14'
          cache: yarn
      - name: Install Dependencies
        run: yarn install
      - name: Build
        run: yarn build
      - name: Publish
        uses: cloudflare/[email protected]
        with:
          apiToken: ${{ secrets.CF_API_TOKEN }}

補足 🔗

キャッシュ 🔗

キャッシュは後回しする予定だったけど、いつの間にか actions/setup-node がキャッシュ機能をサポートしていたので簡単にできた

以下の4行を追加するだけ

- uses: actions/setup-node@v2
  with:
    node-version: '14'
    cache: yarn

今のところ依存パッケージが少ないから20秒ほどの短縮

Create React Appで作ったReactアプリをCloudflare Workers Sitesにデプロイする

Cloudflare WorkersはReactアプリも動かせるということでやってみた

ReactとTypeScriptの勉強のために、ポートフォリオ兼サンプル置き場のReactアプリを作った(この記事を公開した時点では全然できていないけど)ので、それをCloudflare Workersにデプロイする

https://takagi.dev/

ytkg/takagi-dev - GitHub

手順 🔗

Wranglerのインストールと認証は事前に済ませておく(Cloudflare Workersを試す を参照)

Workersの初期化 🔗

Reactアプリのルートディレクトリに移動して、以下コマンドを実行

$ wrangler init --site

wrangler.toml ファイルと workers-site ディレクトリが生成される

静的ファイル出力ディレクトリの設定を wrangler.toml に追記 🔗

Reactアプリをビルドすると、build ディレクトリに静的ファイルができるのでそれを指定する

 usage_model = ''
 compatibility_flags = []
 workers_dev = true
-site = {bucket = "",entry-point = "workers-site"}
+site = {bucket = "./build",entry-point = "workers-site"}
 compatibility_date = "2021-11-25"

SPAの設定を workers-site/index.js に追記(ルーティング機能付きの場合) 🔗

React Routerを利用した複数ページを持つReactアプリは設定が必要で、シングルページの場合はスキップでOK

-import { getAssetFromKV, mapRequestToAsset } from '@cloudflare/kv-asset-handler'
+import { getAssetFromKV, mapRequestToAsset, serveSinglePageApp } from '@cloudflare/kv-asset-handler'

 /**
  * The DEBUG flag will do two things that help during development:
@@ -41,8 +41,6 @@ async function handleEvent(event) {
         bypassCache: true,
       };
     }
+
+    options.mapRequestToAsset = serveSinglePageApp;
     const page = await getAssetFromKV(event, options);

この設定をしないとどうなるか 🔗

例えば https://example.net/about みたいなページに直接アクセスした時にエラーが返る

could not find about/index.html in your content namespace

Reactアプリをデプロイ 🔗

$ wrangler publish

Create React App + TypeScript + Tailwind CSSのボイラープレート

Create React AppでTypeScriptとTailwind CSSの導入まで 」で作ったReactアプリのボイラープレートを作った

ytkg/react-typescript-tailwind-boilerplate - GitHub

作ったといっても最低限動く状態なったものをGitHubに上げただけで、よくあるボイラーテンプレートにあるセットアップスクリプトとかもない
でもこれでReactの勉強のためにReactアプリを量産できるようになった

余力があれば、ちゃんとメンテしていきたいなという感じ

使い方 🔗

$ git clone --depth=1 https://github.com/ytkg/react-typescript-tailwind-boilerplate.git <YOUR_PROJECT_NAME>
$ cd <YOUR_PROJECT_NAME>
$ yarn install
$ yarn start

【Heroku】データベースの自動メンテナンスの記録

Tags: Heroku

いつも使っているHerokuでデータベースのメンテナンスがあった

しばらく待っていたら接続できるようになったんだけど、初めてのことでかなり焦ったので記録として残しておく

環境変数の変更まで終わってからメンテナンス完了のメールを送ってきて欲しいという感想

流れ 🔗

[2021/11/21 14:15] メンテナンスの告知メールが届く 🔗

Your database DATABASE_URL on [アプリ名] requires maintenance. During this period, your database will become read-only. Once maintenance has completed, your database credentials and hostname will have changed, but we will update your app’s config variables accordingly to reflect the new database connection string.

This automated maintenance is a necessary part of our Hobby tier plans, Dev and Basic. Should you need more control over maintenance windows, a production database (Standard tier or higher) offers more control over database maintenance, as we are able to schedule them in advance and provide better tools for self-served maintenance.

僕はShellスクリプトでDenoを手に入れた

Tags: Deno

Denoのバージョンを最新にしようとしたら、Denoなんでない!って怒られた

$ brew upgrade deno
Error: deno not installed

そうか、HomebrewじゃなくてShellスクリプトで入れたのか
忘れないようにここに記録しておく

そもそも何でインストールしたか確認できる方法とかってあるのかな

インストール 🔗

$ curl -fsSL https://deno.land/x/install/install.sh | sh
$ deno --version
deno 1.16.1 (release, x86_64-apple-darwin)
v8 9.7.106.2
typescript 4.4.2

バージョンを指定してインストール 🔗

curl -fsSL https://deno.land/x/install/install.sh | sh -s v1.0.0

バージョンアップ 🔗

$ deno upgrade
Looking up latest version
Found latest version 1.16.1
Checking https://github.com/denoland/deno/releases/download/v1.16.1/deno-x86_64-apple-darwin.zip
28.6 MiB / 28.6 MiB (100.0%)
Deno is upgrading to version 1.16.1
Archive:  /var/folders/pp/gt4jlrmj7cgg0xrdggtspylh0000gn/T/.tmpyleuc4/deno.zip
  inflating: deno
Upgraded successfully

バージョンを指定してバージョンアップ 🔗

$ deno upgrade --version 1.0.0

バージョンダウンもできる

Cloudflare Workersを試す

巷で話題の Cloudflare Workers をいつも通り、触りだけ試す

どういうワーカーをサンプルで作ろうかと悩んで、一時期話題になってた偶数かどうか教えてくれるネタAPI、 isEven API を作ることにした

手順 🔗

Wrangler のインストール 🔗

WranglerというCLIツールで開発やデプロイをする

$ yarn global add @cloudflare/wrangler
$ wrangler --version
wrangler 1.19.4

認証 🔗

$ wrangler login

ブラウザが開くので認証を済ませる

✨  Successfully configured. You can find your configuration file at: /Users/ytkg/.wrangler/config/default.toml

プロジェクト作成 🔗

テンプレート がいくつか用意されているので、今回はTypeScriptのテンプレートを使ってプロジェクトを作成する

wrangler generate is-even-api https://github.com/cloudflare/worker-typescript-template
$ cd is-even-api
$ yarn

サーバー起動 🔗

$ wrangler dev
$ curl http://127.0.0.1:8787
request method: GET

$ curl -X POST http://127.0.0.1:8787
request method: POST

リクエストメソッドを返してくれるものがデフォルトで実装されている

実装 🔗

src/handler.ts に処理が書かれているので、偶数かどうか true or false で返す処理に書き換える
バリデーションだったり、エラーハンドリングは省略する

【Mac】lsコマンドで表示されるディレクトリの青色が見えづらいので変更する

タイトル通り、ls した時のディレクトリの色が見えづらいので変更する

001.png

手順 🔗

環境変数 LSCOLORS に色の設定を指定するだけ(詳細は参考サイトを参照)

export LSCOLORS=gxfxcxdxbxGxDxabagaca

とりあえずディレクトリの色だけ水色に変更した

002.png

補足 🔗

デフォルト値: exfxcxdxbxGxDxabagacad

ジェネレーター: LSCOLORS Generator

参考 🔗

Raspberry PiでDockerコンテナがホスト側と時間同期できない問題を解決する

問題 🔗

コンテナ内で date コマンドを叩いても正しい時刻を取得できなかった

root@f38fb1bfdebb:/app# date
Thu Jan  1 00:00:00 UTC 1970

バージョン 🔗

  • Raspberry Pi OS: 10.11
  • Docker: 20.10.10

解決方法 🔗

libseccompパッケージに不具合があるようで、バージョンを上げたら解決する

$ wget http://ftp.debian.org/debian/pool/main/libs/libseccomp/libseccomp2_2.5.2-2_armhf.deb
$ sudo dpkg -i libseccomp2_2.5.2-2_armhf.deb
root@d223d1edab89:/app# date
Fri Nov  5 16:11:48 UTC 2021

正しい時刻を取得することができた

$ rm libseccomp2_2.5.2-2_armhf.deb

もう必要ないので削除しておく

補足 🔗

Raspberry Piでとあるsinatraアプリを docker-compose build をした時に、 bundle install のタイミングでコケた
これで今回の問題に気づいた

Operation not permitted - clock_gettime (Errno::EPERM)

検索してもあまりヒットしなかったので、検索用にここに載せておく

$ docker-compose build
Building web
Step 1/4 : FROM ruby:2.7.4
 ---> e788dbf3e493
Step 2/4 : ADD . /app
 ---> Using cache
 ---> 6d275a173c7b
Step 3/4 : WORKDIR /app
 ---> Using cache
 ---> a1a7eae13717
Step 4/4 : RUN bundle install -j4
 ---> Running in c8c1d74a14a9
/usr/local/lib/ruby/2.7.0/rubygems/specification.rb:106:in `initialize': Operation not permitted - clock_gettime (Errno::EPERM)
        from /usr/local/lib/ruby/2.7.0/rubygems/specification.rb:106:in `now'
        from /usr/local/lib/ruby/2.7.0/rubygems/specification.rb:106:in `<class:Specification>'
        from /usr/local/lib/ruby/2.7.0/rubygems/specification.rb:39:in `<top (required)>'
        from /usr/local/lib/ruby/2.7.0/rubygems.rb:1417:in `require'
        from /usr/local/lib/ruby/2.7.0/rubygems.rb:1417:in `<module:Gem>'
        from /usr/local/lib/ruby/2.7.0/rubygems.rb:115:in `<top (required)>'
        from <internal:gem_prelude>:1:in `require'
        from <internal:gem_prelude>:1:in `<internal:gem_prelude>'
ERROR: Service 'web' failed to build : The command '/bin/sh -c bundle install -j4' returned a non-zero code: 1
$ docker-compose build
Building web
Step 1/4 : FROM ruby:2.7.4
 ---> e788dbf3e493
Step 2/4 : ADD . /app
 ---> Using cache
 ---> 6d275a173c7b
Step 3/4 : WORKDIR /app
 ---> Using cache
 ---> a1a7eae13717
Step 4/4 : RUN bundle install -j4
 ---> Using cache
 ---> e5e01b0c4a36

Successfully built e5e01b0c4a36
Successfully tagged home_api_web:latest

時刻同期できるようになったら、無事 docker-compose build が通った

【Create React App】yarn buildした時に出た警告の対応

Tags: React Node.js

Create React AppでTypeScriptとTailwind CSSの導入まで 」で作ったReactアプリで、 yarn build を実行したらいくつか警告が出たのでその対応をした

Browserslistの更新を要求される 🔗

Browserslist: caniuse-lite is outdated. Please run:
npx browserslist@latest --update-db

Why you should do it regularly:
https://github.com/browserslist/browserslist#browsers-data-updating

書いてある通り、以下コマンドを実行したら良い

$ npx browserslist@latest --update-db

詳しくは [React] アプリのビルド時にBrowserslistの更新を要求されるので対処してみる | DevelopersIO を参照

DeprecationWarning: Use of deprecated folder mapping “./” in the “exports” field module resolution of the package at … 🔗

(node:61452) [DEP0148] DeprecationWarning: Use of deprecated folder mapping "./" in the "exports" field module resolution of the package at /Users/ytk
g/Workspace/react-typescript-tailwind-boilerplate/node_modules/postcss-safe-parser/node_modules/postcss/package.json.
Update this package.json to use a subpath pattern like "./*".
(Use `node --trace-deprecation ...` to show where the warning was created)

Node.jsの16系で出るPostCSSの不具合でPostCSS 8.2.12で直っているらしいが、Create React AppはPostCSSの8系をサポートしていないので、Node.jsを15系に落として解決

Categories


Tags