ryhmrt’s blog

意識低い系プログラマの雑記

Audible + Kindle

今月中に10冊くらい本を消化したいので、テンポよく読み進めるためにAmazonのAudibleを試すことに。

Audibleを流しながらKindleの字を目で追うと、集中を切らさずにテンポを維持して読める。

音声は1.5倍くらいのスピードが多少のゆとりも持てていい感じがする。

Kindleには章単位とかで残り目安時間を表示する機能があるけど、Audibleだと時間が明確なので、予定が立てやすく、次のスケジュールがある時なども取りかかりやすい。

Amazon.co.jp: Audibleオーディオブック

New MacBook

約8年ぶりに家のパソコンを買い替えたので、設定内容をメモ。古いパソコンからの移行はせずに、まっさらな状態から設定。

アカウントセットアップ

iCloudとメールアカウントを設定。 1 Passwordインストール。

必要なアプリのインストール(コマンドライン)

まずはHomebrew

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

Ghostty。これまでiTerm2を使っていたが、特にこだわりがあるわけではないので変えてみた。

brew install --cask ghostty

Karabiner-Elements。最新のMacOSはUSキーボードでも左下のfnで入力言語切り替えができるが、どうも慣れなかった。

brew install --cask karabiner-elements

Docker。今までDocker Desktopを使っていたが、ColimaだとRosetta経由でx86イメージが動くとのことなので、乗り換えてみることに。

brew install docker
brew install docker-compose
brew install colima

perlbrewとかJDKとかも必要かもしれないけど、必要になったら入れることにする。

必要なアプリのインストール(AppStore、または直接ダウンロード)

よく使うものをいくつかインストール

  • Cyberduck
  • Microsoft Word
  • Microsoft Excel
  • Microsoft PowerPoint
  • DaisyDisk
  • Visual Studio Code

ファイル移行

ほとんどのファイルはiCloudeのフォルダで同期。

GitプロジェクトはAPIキーなどが入った設定ファイルがignoreされているので、cloneによる移行を避けてSSDでまるっとコピー。

homeにある設定ファイルは移行せずに必要な設定を一から始めることにした。秘密鍵だけ移行。

Pappeteer vs PlayWright

背景

先日テンプレを元にサイトを生成するという面倒な手仕事をAstroで片付けたのだが、それに付随して、生成したサイトのキャプチャ画像をとるというタスクもあり、こいつも何とか楽をしようと自動化ツールを選定した。

Pappeteer と PlayWright の2つが候補に上がって、両方触ってみたのでメモ。

先に結論

特にこだわりがなければ PlayWright を使っておけば良いと思う。

比較

ツールの位置付け

Pappeteerがブラウザのオートメーションツールとされているのに対して、PlayWrightはテストフレームワークとして強く売り出している感じ。

ただ、PlayWrightもテスト以外の目的てブラウザオートメーションに使えるし、PappeteerもJestなどのテストフレームワークと組み合わせることができる。

対応ブラウザ

PappeteerはChrome(Chromium)とFirefoxに対応。

PlayWrightはChromium, WebKit, Firefox, Chrome, Edgeに対応し、モバイル端末のエミュレーションもできる。

言語

Pappeteer は TypeScript と JavaScript のみ。

PlayWright は TypeScript, JavaScript, Python, .NET, Java にオフィシャルで対応。アンオフィシャルなものならば Perl や Ruby なども。

機能差分

ブラウザのオートメーションの観点では、両者ほぼほぼ同じ。Pappeteerの作者がMSに入って作ったのがPlayWrightとのことで、API仕様も大体同じ。

ネットで見かけた比較記事ではPlayWrightの方が使いやすいAPIになっているような記載も見かけたが、Pappeteerの方に一部PlayWrightの改善が取り入れられている節がある。

PlayWrightの方が便利だと感じたことの一つは Auto-wait という機能。

DOM読み込みの遅延、JS処理などで、特定のエレメントが参照できずにエラーになるということが Pappeteer では発生し、適宜スリープ処理を入れる必要があった。

PlayWright では対象エレメントが有効になるまで自動で待ってくれるので、処理を書くのが楽だし、無駄にスリープ処理を入れないおかげでスクリプト全体の速度が上がった。

Pappeteer でも locator では自動リトライをしてくれるらしいが、Pappeteer の locator は使い所が限られる。タイミングがシビアな場面では waitForSelector を使えば良いのだろうけれど、処理が遅くなる感じがするし、あまりそのようなコンテキストをスクリプトに入れたくない。

あと、PlayWright は大体の処理を locator からネストして書けるので楽。

使い方

PlayWright

公式サイトだとテストフレームワークとしての利用の案内ばかりだが、ブラウザの自動化だけならば以下でパッケージをインストール。chromium以外を使いたい場合は、playwright-firefoxまたはplaywright-webkitを指定。

$ npm install playwright playwright-chromium

以下のように使用。

import { chromium } from 'playwright';

const browser = await chromium.launch();
const page = await browser.newPage();
await page.setViewportSize({width: 1200, height: 1200});

await page.goto('https://blog.ryhmrt.com/');
await page.locator('#container').screenshot({path: 'blogshot.png'});

await browser.close();

Pappeteer

以下でパッケージをインストール。

$ npm install pappeteer

以下のように使用。

import playwright from 'playwright';

const browser = await playwright.launch();
const page = await browser.newPage();
await page.setViewport({width: 1200, height: 1200});

await page.goto('https://blog.ryhmrt.com/');
await (await page.$('#container')).screenshot({path: 'blogshot.png'});

await browser.close();

コードはほとんど同じ。

Astro備忘録

同じ構成のウェブサイトを一部の内容を書き換えて何回も作る必要があり、設定ファイルを元にサイトを生成するものをAstroで構築した。

ユースケース

今回Astroを使うことになったユースケースは以下の通り

  • ほぼ同じ内容のサイトを一部のテキスト等を修正して何回も作る
  • サイトのパスは一定ではないし、全く同じサイトの内容を異なるパスに何箇所かアップロードする
  • JavaScriptを使った動的なコンテンツがあるが軽い内容
  • 特に依存しているライブラリはない
  • 生成するHTMLはすべて同じディレクトリに配置する

Astroの何が良かったか

フットプリントが軽い

完全に静的な内容だけであれば素のHTMLが吐き出されるだけなので、React系のものと比べると段違いに軽い。

Reactのインテグレーションを追加すると途端に重くなるのでPreactなども検討したが、今回は大した処理ではないし、既存の素のJavaScriptを流用して実装した。

React/Preactだとレンダリングのタイミングもちょっと遅い感じがしたのも一つの理由。

相対パスが使える

公式が対応しているわけではないが、astro-relative-link というインテグレーションを入れることにより、リソースのパスを相対パスに変更することができた。

やってることは静的ファイルが生成された後、その中に記載されてる hrefsrc といったアトリビュートなどの内容を原始的に書き換えている感じで、構成によってはこれがうまく動かないこともある。今回のケースはこのインテグレーションでうまくいった。

尚、SSGのツールをいくつか調べたが、軒並みサイト全体の生成を対象にしており、リンクには絶対パスが使われることが基本。

AstroのGitHub Issueで相対パスへの対応を熱望する人達の声をいくつか見かけたが、ニーズとしてはニッチな方だし、パスの解決に複雑な問題を持ち込むことになるため対応は消極的なようだ。

わかりやすい

スタートガイドの以下のページを読めばサイトを作り始めることができると思う。

設定周りを少しいじりたくなったら以下のページと、必要に応じて各APIリファレンスを読むような感じ。

あとは Guides and recipes の項目のページ群も使う機能に絞って読んでおくと良い。

ドキュメントの日本語訳がけっこう進められていて、英語読むのに疲れたりしなくてありがたい。

拡張も容易

いろんなライブラリのインテグレーションも用意されているし、自分でビルド時のフックスクリプトを書くのも簡単。

Tips

いくつか今回のプロジェクトで役立ったことのメモ。

サイト全体で共有されるパラメータを設定する

ビルド開始時にサイトの設定ファイルを読み込み、それをミドルウェアで context.locals に設定すると、各ページの Astro.locals でその値を参照できた。

参考: https://docs.astro.build/ja/guides/middleware/

開発時とビルド時でインテグレーションを切り替える

astrobook というものを導入したのだけれど、これがビルド時に有効になっていると余分なファイルが出力されてしまう。

以下のようにしてビルド時に無効になるようにした。

integrations: [
  import.meta.env.DEV ? astrobook({ directory: 'src', subpath: 'docs' }) : null
]

参考: https://docs.astro.build/ja/guides/environment-variables/

ビルドの際はnullがインテグレーションとして渡って無視される。この後ろにインテグレーションを書くと、このnullによって後続のインテグレーションが実行されなくなるので注意。

自分でインテグレーションを書く

簡単なものならば、astro.config.* にインテグレーションをインラインで書いてしまえば良い。

クライアント実行のスクリプトにパラメータを入れる

Reactのインテグレーションを使っていたりするのだったら、アトリビュートとして渡せば良いのだが、素のJavaScriptだとそうもいかない。

そんな時は以下のように解決できる

---
import planData from '@/data/plans.json'
---

<script set:html={`var plans = ${JSON.stringify(planData)};`}></script>

DB定義ドキュメント生成のワンライナー

稼働中のDBスキーマをリバースエンジニアリングしてドキュメント生成するようなツールはいくつかあるけれど、フリーで使えて便利なものの一つが SchemaSpy

オフィシャルのDockerイメージがあるので、これで実行するとお手軽

$ docker run --network host -v "$PWD/doc:/output" schemaspy/schemaspy -t pgsql11 -host localhost -db mydatabase -u postgres -p password

最近システムの引き継ぎをしていて思い出したのでメモ

ソフトウェア/プロダクト開発、あるいは企業の文化

このゴールデンウィークで「Hit Refresh」と「ユニコーン企業のひみつ」という2冊の本を読んだ。

ソフトウェア開発には組織や文化が重要ということは数十年前から言われているけれど、ソフトウェアの重要性が高まる中で、開発の部署やプロジェクトといった局所的な取り組みではなく、会社全体/経営としての取り組みが強く求められているという風潮を感じる。

一年位前に読んだ「ジョイ・インク」も、この2冊と同じようなことを主張しているように思える。

若者が下手に読むと現状との格差に絶望してしまうかもしれないのでお勧めしない。上司や社長の机にそっと置いておく本という位置付けにしたい。