yuw27b’s blog

技術メモと雑記

GCP Cloud FunctionsでPuppeteerを使う

1日1回スクレイピングしてきてSlackに流してほしい、みたいな簡単なやつなので、Firebaseまではいらない。

Cloud FunctionでランタイムにNode.jsを選択→package.jsonとindex.jsを登録しておき、Cloud Scheduler->Pub/Sub経由で呼び出せばOK。

プチハマりどころ
  • Puppeteerのバージョンが新しすぎると動かない→2020年1月現在ではv2.0.0なら動く。Node.jsのバージョンが10系なので仕方ないのかも。
  • Puppeteer起動時のオプションで、--single-processとか--no-sandboxとかを有効にしておかないと動かない。

最終的にこうなった:

  const browser = await puppeteer.launch({
    headless: true,
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
      '-–disable-dev-shm-usage',
      '--disable-gpu',
      '--no-first-run',
      '--no-zygote',
      '--single-process',
    ],
  });
  • メモリ1GB割り当てておかないと足りなかった。(処理内容によっては512MBでもなんとかなるかもしれない。または、たまになら失敗しても構わないケースとか。)

console.log()でGCPのログに吐き出せるし、1日1回くらいの頻度であれば無料枠におさまってくれた。
データの永続化も、小さいデータならFirestoreに読み書きで十分という印象。
同じプロジェクト内ならデフォルトでアクセス権もあるので、こんな感じ:

  const firestore = new Firestore({
    projectId: '(PROJECT_ID)'
  });
  const document = firestore.doc('path/to/doc');
  const currentDoc = await document.get(doc => {
    return doc;
  });

/////(なんか処理とか)

  await document.update({
    'xxx': 'yyy'
  });

2019年の振り返り

もう22時だ…簡単に振り返り。(あれ、去年は書いてない)
今年も引き続き、大学の研究室でエンジニア業をしていました。ほぼ1人チーム開発です。
(昨年度からは副業しづらい契約なので、フリーランス業はお休み中)

Webアプリ開発

フロントはReact、バックエンドはRubyPHPでRESTful API、がほぼ定番化してきた感じ。今年は新規開発は少なめ。APIの仕様はSwaggerで定義している。
データベースはほぼMySQLだけど、最初のテーブル設計などはかなりマシにできるようになってきたと思う。
これまでに4〜5個は作っているので、だいぶ慣れては来たけど、もう少し丁寧にやりたい気持ちもある。
TypeScript入れるとか、テスト書くとか、CI入れるとか。
ただし、一般消費者向けサービスではないし、仕様変更も頻繁なので、どの程度までやるべきなのかが難しい。一人なので、なんとかなってしまってる、というのもあるかもしれない。

年明けに、仕様をきちんと固めてから作る案件がありそうなので、そこで導入したい。

そもそもWebアプリの仕様ってどういう風に記述するのが良いのでしょうか。おすすめあったら知りたいです。

機械学習

医療画像の判別モデルの作成にも取り組んでいました。
ディープラーニングアルゴリズム自体は、全く専門外ですし手を出せず、既存のものを使っていましたが、学習データをいかに準備するか、というところが重要なのだ、というのが私の印象です。
そのためのツール(Webアプリ)作りや、効率化のためのスクリプト作成など、結果的にはかなり学ぶことも多かったです。

これから機械学習をメインにすることはないと思いますが、周辺でのエンジニアリングには引き続き興味があります。

心残り

やはり、フリーランスでのコーディング業がなくなったので、CSSを書く機会が激減しました。
いかに分かりやすく、無理せず、メンテナンスしやすくCSSを書くか、ということに取り組むのはとても好きなので、もう少し書きたい気持ちがあります。

その他

出張:オーストラリア・アメリカ。国内は九州が多かったかな?
あまり遠出すると、コードを書く時間は減るので、それはちょっとどうなんだ、という気持ちもあり。
勉強会とか技術系のカンファレンスももう少し参加したかったです。

あとは、自分用のお役立ちBotを作ったり、遊びでBot作って友達に笑ってもらったり、Puppeteer使って遊んだり…ちょっとしたことでも技術で何か解決したり、物作りしたりするのは楽しいですね。

来年

やりたい:TypeScript、TDD
サーバレスな設計も興味はあるが、仕事では様々な理由でオンプレサーバがメインになるので、難しそう。

CSSカウンターを使って変則的な番号付きリストを実装する

久しぶりにCSSカウンター便利だな、と実感したのでメモ。

CSSカウンターとはこういうものです:
CSS カウンターの使用 - 開発者ガイド | MDN


こんな感じの文書をWebページに掲載するときに(あくまで例ですがこういう構造)、
f:id:yuw27b:20191105214629p:plain

マークアップにはOL要素を使うのが妥当に思えます。
リストの通し番号より先にカッコ付きの文が出てくるので、CSSカウンターを使ってこんな感じでコーディングしました。


See the Pen
List with CSS counters
by Yu Watanabe (@yuw27b)
on CodePen.

リストアイテムの先頭でなくても、任意の場所で通し番号を表示できるので便利です。
もちろんOL要素以外でも使えます。

改行入りのテキストをReactでレンダリングする

改行が含まれてると分かっている時は、component内に関数を用意して、行ごとにpタグで囲む。

または、brタグを挿入する

const textWrap = (text) => {
  if (typeof text !== 'string') {
    return null;
  }
  return text.split('\n').join('<br />');
}


改行が2連続の場合は、

<br /><br />

になるので、マークアップとしてはよろしくない。
そういう連続した改行というのは段落の切れ目を表しているので、ひとかたまりのテキストではなく、配列データにすべき、という気がする。

ユーザーがテキストエリアに入力するテキストなどは自由に改行ができてしまうが、場合によっては、連続していたら1つにする、みたいな処理をしてもいいのかもしれない。

ボタンを押したことが伝わるCSS

a要素やbutton要素のボタンのCSSは、最近よくこんな感じにします。
:active属性でボタンを押下した状態のスタイルを指定できますが、1px下に動かすだけでもユーザーに「ボタンを押した」ことが伝わります。


See the Pen
button:active
by Yu Watanabe (@yuw27b)
on CodePen.

margin-topまたはmargin-bottomでも下に1px動かすことはできますが、もともとのマージンや、隣接・親要素のマージンとの相殺が起こっている場合もあるので、それらに影響のないtransformを使っています。

特に装飾に指定がない場合は、この「とりあえず1px動かしておくCSS」を入れています。