留年報告

はじめに

どうも、さぃと (@saitoeku3) です。
既に Twitter で報告したように、この度留年をしてしまったので詳しい事情をまとめておきます。

なぜ留年したのか

1 つ目の原因は、僕の優先順位の付け方が普通の人とズレていることです。

例えば

  • 学業よりクライアントが待っているタダ働きの仕事 (インターン) を優先
  • 学業より周囲の人が困っていることを解決することを優先

といった感じです。

この問題は以前から自覚をしていたのですが、自己犠牲で誰かにメリットを与えられるならそれでいいと思って放置していました。今までの大学3年間の中で B2 から B3 までは特にこれに囚われて自己犠牲を続けていました。

こんなことを書いていると「さぃとは留年を他人のせいにしている」と思われそうですが、これらは自己満足で勝手にやっていたことなので悪いのは僕です。(しかもメリットどころか迷惑をかけていたかもしれない)

2 つ目の原因は、プログラミングが楽しくてやりすぎたことです。

プログラミングに出会ったのは大学に入ったばかりのことでした。Web アプリケーションの受託開発をしている組織に加入したときに、HTML / CSSRuby を学びました。しかし、当時はグラブルと野球にドハマリしていたので、プログラミングは全くやらず RubyArray#each すらわかりませんでした。

転機は B2 の夏でした。相変わらず受託の案件はあるのに手をつける人がいなくなったので、仕方なく謎の優先順位の付け方で強引に 1 人で開発を始めました。技術的に頼れる人は周囲におらず、独学を始めると思ったより楽しくて、そこから JavaScript を学んで今の僕に至ります。

プログラミングは凡人だった僕をクリエイターにしてくれて、イベントやインターンに行くうちに多くの素敵な方と出会わせてくれました。 こんなものを知ってしまうとやめられなくなります。

3 つ目の原因は、僕の身体の弱さです。

知っている人は少ないと思いますが、僕は B2 の春から夏にかけて大学に通えなくなるくらいの頭痛に苦しめられていました。1ヶ月以上常に今まで感じたことがないほどの頭痛が消えず、頭痛専門の病院に行っても原因不明と判断されて完治はしませんでした。

今では寛解しましたが、時々偏頭痛の人と同じかそれ以上の頭痛が襲ってくることがあります。このときに落とした単位があれば進級できたというのは言い訳です。

懸念していること

留年したことによって、これまで築いた人間関係を失うことは避けたいです。
世代が変わることで、大学にいる限りは当然周りにいる人も変わります。そうやって交流が減ったり、距離を感じるようになったりするのは嫌なので今後も仲良くしてください。

あとは心が病まないか少しは気にしています。
「普通」から外れた経験は今までゼロだったわけではありませんが、やはり心配です。一緒に何か作ったり、ゲームしたり、ご飯に行ったりすると MP は回復しそうなので誘ってください。

今後の予定

ざっとまとめるとこんな感じです。

  • B3 前期: 休学、個人事業主として Gaiax 等の業務委託、内定先の内定者バイト
  • B3 後期: 復学して単位を取得して進級、個人事業主と内定者バイトを継続
  • B4 前期: 必修と取りこぼした単位の取得研究、個人事業主と内定者バイトを継続
  • B4 後期: 研究、個人事業主と内定者バイトを継続

本当はお金を貯めて海外に行ってみたかったのですが、コロナのせいで無理になりました。
せっかく 1 年猶予があるので、OSS 活動など他にも色々やっていきたいです。

Q&A

ここからは事前にマシュマロでいただいた質問を返していきます。

就職はどうするんですか?

2022年に pixiv に入社する予定です。
仮に他社から pixiv を上回るオファーがあってもこの気持ちは揺らぎません。

大学はどのくらいの頻度で行っていましたか?

先に挙げたタダ働きの仕事やインターン選考、就活、大きな技術イベント等があればそちらを優先していましたし、酷い頭痛に見舞われたときなどは休んでいました。

頭痛で通えなかった時期を除いて、単位取得を諦めた科目も含むと出席率は平均 80% 程度でした。

1年あるけどその間にしたいことはある?

個人事業主は始めましたが、まだ悩んでいます。
今後したいことを考える期間にするのもいいかもしれませんね。

金沢にずっといるつもり?

いるつもりです。
本当は東京で暮らしたいですが、コロナや生活費を考えると厳しそうです。金沢にも素敵な人はたくさんいるので、今まで通り楽しくやっていきたいです。

おわりに

留年を隠すために嘘を重ねるのは嫌だったので、正直に書きました。
ハッキリ言うと、今回の失敗は残念だけど現段階では後悔はしていません。1 年を失いましたが、得られるものや残せたものはたくさんあったからです。

しかし、両親や内定先で面倒を見てきくださった方々には本当に申し訳ないと思って反省しています。今後も失敗続きの人生だとしても、同じ過ちは繰り返さないように心がけます。

以上が、留年報告です。ここまで読んでいただきありがとうございました。
何か質問があれば、マシュマロ でお待ちしています。

『HOT PEPPER Beauty』Frontend スピードハッカソンに参加した

はじめに

こんにちは、さぃと (@saitoeku3) です。
今回はリクルートが主催するハッカソンに参加したので、振り返りや学びを残しておこうと思います。

ハッカソンなので最終的に順位がついて僕のチームは残念ながら 4 位でしたが、普段とは違う体験がたくさんできて最高のイベントでした。

イベントの内容

HOT PEPPER Beauty のあるページの速度改善を行いどれだけパフォーマンスを高められるかを競うハッカソンです。

レギュレーションは「Chrome Canary を使用する」「見た目の大きな変更をしてはならない」「機能の変更をしてはならない」というもので、Lighthouse の計測結果を参考にして順位を決定しました。

後に触れるのですが、参加者はフロントエンドだけではなくてバックエンドやインフラの領域まで自由に触ることができます。

やったこと

チームとしての施策は同じチームで大活躍してくれた @kaa_a_zuRecruit主催のスピードハッカソンに参加してきた にまとめているので、そこで確認してください。

僕の取り組みとどんな思いで取り組んだのかを書いていきます。

予習

行きの新幹線の中で超速本を読んだり、JSConf JP で行われたスピードハッカソンのリポジトリ を触ったりしていました。

実は以前超速本を読んだときに Scrapboxネットワーク処理の改善というメモを残しており、短い時間でこれを元に思い出しながら実践する時間を取れたのは良かったです。

アプリケーションの測定

1 番最初に環境構築が終わったので、すぐに Chrome Developer Tools で測定をしました。
よく使われるものとして思いつく施策はいくつかありましたが、アプリケーションによって抱える問題は変わってきます。がむしゃらにやっても効果は薄いので、最初に原因を明らかにしたのは正解だったと思います。

ネットワークタブのウォーターフォールの測定

DOM の描画を除けば初期描画までの時間の多くはネットワークが影響しています。
何が原因で通信に影響が出ているのか調べるためにネットワークタブのウォーターフォールを見ていました。

これは qiita.com のネットワークタブで時間がかかっている通信を順番に並べた様子です。
多くは画像の読み込みですよね。題材のページも同様に画像がボトルネックになっていました。

カバレッジの測定

これは pixiv.net の CSS と JS のカバレッジです。
Chrome Developer Tools を開いて Cmd + Shif + P の後に Show Coverage と入力すると表示されます。

トップを開いただけで全ての CSS や JS が適応されるわけではありませんが、使われていない赤色の部分が多いことがわかります。これらの多くは本来不要な通信を行ってパフォーマンスを下げていることになるので、理想を言うと削るべきです。

題材のページはもっと酷い状況でした。

施策の提案と実施

すぐ調べられる範囲では「無駄な CSS と JS が多い」「画像が大きすぎる」という課題を発見できたので、僕は次のことに取り組んでいました。

なお「題材のページが 1 ページのみで規模が小さいこと」や「全員が使い慣れているわけではないこと」を考慮して webpack は使用しませんでした

CSS の最適化

デッドコード (使われていない CSS) を削除するために PurgeCSSスクリプトを書きました。ただし、Qiita で見つけたサンプルはバージョンの違いによって期待する動作をしなかったので、途中でメンバーにパスして minify のスクリプトを書いていました。

minify には clean-css を使いました。ファイルの中身を渡すだけでシュッと簡単にやりたいことができて体験が良かったです。

JavaScript の最適化

uglify-js を使って minify をしました。選定理由は「題材のページは全て ES5 であるから」「使用した経験があるから」です。

webpack のプラグインとしてよく使われている (記憶が正しければ Webpacker に標準で搭載されている) terser でも minify ができるので候補としては考えていましたが、使い慣れていないので使いませんでした。(引き出しが少ないと窮屈で辛い)

画像の遅延読み込み

Chrome Canary を使っていたので最初は安心して loading="lazy" を採用しました。

しかし、行きの新幹線の中で標準の遅延読み込みよりも IntersectionObserverisIntersecting で画面に入ったか判定するほうがシビアに遅延読み込みを実現できることを確認していたので、途中からは lazysizes を使用しました。

※ 体感なので根拠は薄い

ここは自分で React 用のライブラリ を書いていたのことにも助けられて、スムーズに導入できました。

結果

これらに加えて画像の圧縮、HTTP2 化、リソースの gzip 化などを行ったところパフォーマンスは 97 まで改善させられました。
終了 30 分前までは他のチームに 300P 差をつけた 1位だったので優勝を確信しましたが、最終的には 4位 で終わってしまい悔しかったです。

タネ明かし

優勝チームは静的ファイルを Express から配信するのは遅いことを知っていたので、Nginx から直接配信することで高いパフォーマンスを実現していました。
Why is it not recommended to serve static files from Node.js?

そもそも Express は Node.js フレームワークの中でも遅い部類です。
fastify によるベンチ https://github.com/fastify/benchmarks

そして、主催者の 1 人である古川さんが次のように仰っていました。

実際にパフォーマンスタブを見ないと気づけない問題もあったので、もっと使えるものはフルで使って測定するべきだと思いました。

おわりに

今回のイベントでは、これまで僕がフォーカスを当ててこなかったパフォーマンスのチューニング方法とその重要性を学ぶことができました。

業務だとパフォーマンスとプロダクトの成長や DX はトレードオフだと思われがちかもしれませんが、今後はユーザーにとって本当に良いアプリケーションを開発できるように気を配りながら実装していきたいです。

最後にこのような素晴らしいイベントを開催してくださったリクルートと一緒に取り組んだ最高のチームメンバー、競い合ったライバルに感謝を述べて締めます。ありがとうございました。(またやりたい)

CLIP STUDIO の .clip ファイルを読み取れる JavaScript ライブラリを公開した

はじめに

こんにちは、さぃと (@saitoeku3) です。
コロナの影響で春休みの予定がことごとくなくなり、暇な大学生です。

ずっと引きこもっていてあまりにも暇だったので、何かしたいという気持ちが高ぶり、以下のツイート思い出して .clip ファイルの解析をしていました。

そこから色々考えた結果、Photoshop や CLIP STUDIO を持っていなくても .psd や .clip を見て楽しめるといいなと思い始めてサービスを作りたくなりました。

最近は FANBOX などの支援型プラットフォームを通して、多くの方がプロのイラストデータを入手できるようになりましたが、その全員が有料のイラストソフトを持っているわけではないため、楽しめるのは一部の限られた方です。もし、今考えているサービスが完成すると新しい楽しみ方が生まれそうで良くないですか。

ということで、下準備としてライブラリを書きました。

作ったもの

clipstudio.js - 📎A JavaScript library for using CLIP STUDIO .clip file on browsers and Node.js

ブラウザでも Node.js でも同様の API で .clip ファイルを読み取れるライブラリです。
既に実装されている機能について使用例を紹介します。

Node.js でサムネイル画像を生成する

Node.js は ClipStudio.load にファイルの Buffer を渡すことで初期化できます。 改行を含めて 8 行で .clip ファイルのサムネイル画像を生成できます。便利ですね。

import { ClipStudio } from 'clipstudio'
import { promises as fs } from 'fs'

const file = await fs.readFile('path/to/clip-file')
const clip = await ClipStudio.load(file)

const thumbnail = clip.getThumbnail()
await fs.writeFile('thumbnail.png', thumbnail)

ブラウザでレイヤーの情報を取り出す

ブラウザでは ClipStudio.load に input で受け取った File オブジェクトを渡すことで初期化できます。 インスタンスに生えている getLayers() でレイヤーの情報を取り出せます。

import { ClipStudio } from 'clipstudio'

const input = document.querySelector('input')

input.onchange = event => {
  const [file] = event.target.files
  const clip = await ClipStudio.load(file)
  const layers = clip.getLayers()
  console.log(layers)
}

レイヤーの型

残念ながら各レイヤーの画像データは .clip 上には保存されていない?ので、現在はちょっとしたデータしか扱えません。

type Layer = {
    id: string // uuid
    index: number
    name: string
    opacity: number
    isVisible: boolean
    isFolder: boolean
}

課題と展望

実は .clip ファイルを読み取るために SQLite を使用しているのですが、ブラウザでも動作させるために sql.js というライブラリを使っています。これは「SQLite を Wasm にしてブラウザでも動くようにした」という頭のおかしいもの (褒め言葉) なので、以下のような少々面倒なことがあります。

  • そもそもの実行速度が遅い
  • Jest でテストをすると .wasm の読み込みに失敗する

今後は処理を Worker に逃したり、Jest や Node.js と Wasm の関係について学んだりする必要がありそうです。このままだとテスト環境を自作する必要がありそうで面倒です(何か解決策はあるはず)。

また、ライブラリを充実させたくても僕一人で .clip を解析して API の仕様を考えるのはかなり大変です。将来的にドキュメントや議論の場を整備して複数人でやっていけると嬉しいです。

おわりに

今回は CLIP STUDIO の .clip ファイルを読み取れる JavaScript ライブラリの紹介をしました。

機能はまだまだ少ないので用途は限られてきますが、このライブラリの登場によって可能性は広がったと思います。今後も開発は続けていくので興味のある方は watch やスターをして暖かく見守っていただけると励みになります。

mixi の Bug Shooting Challenge #4 に参加しました

はじめに

どうも、さぃと (@saitoeku3) です。
今回は「周りの人はみんな行ってる。行ってないの僕だけ。」になっていた mixi のイベントに行ってきました。 mixi 主催のイベントは TDD や Git、Unity など様々なトピックに分かれていますが、僕が参加したのは Bug Shooting Challenge #4 (#mixi_BSC) でした。

イベントについて

僕とペアのさんぽしさん (@sanpo_shiho) が CRE (Customer Reliability Engineer) に配属されたという設定で、仮想のユーザーからの問い合わせに対してバグを調査して改善するという内容のイベントでした。

流れはざっと次のような感じです。

  • 環境構築
  • 使用技術の説明
  • ランチ
  • 問題1 - 3 (各問題ごとにヒントと答え合わせあり)
  • 懇親会

最初はガチでやるというより普段使わない筋肉を使って楽しもうという気持ちでしたが、想定より内容が面白くて競技形式ということで気がついたら夢中になっていました。

やったこと

参加者は最初に Rails + MySQL + Redis 等を docker-compose で立ち上げる環境とログを確認するための Amazon EMR が与えられます。

そこからは基本的どの問題もやることは同じで、ひたすら EMR 上のログを Hive で調べたり、Rails Console で問題に関係するレコードを調べたりしていました。僕は Rails には慣れていましたが、SQL (今回は Hive SQL) を叩いて調査するのは初めてで勝手を掴むのに苦労したのを覚えています。

ペアで行うので見つけたバグの情報や修正はすぐ GitHub や Slack で共有してお互いの共通理解を作るのが大切でした。

結果

3問中の1つで優秀賞をいただくことができました :tada: 正直もう少しできたという気持ちが強いですが、最初から最後までペアと楽しくやれたので割と満足できました。

おわりに

mixi さんにはイベントの準備・運営だけではなく、交通費の補助 (東京までの往復の半額) や素敵な懇親会の食事までいただけて感謝でいっぱいです。また、世代が近い学生と交流する場にもなったので多くの刺激を得られました。

mixi さんは毎年何度かイベントを主催しています。楽しいイベントだったので、このエントリを読んで興味を持った方は機会を見つけて申し込んでみてはいかがでしょうか。

2019年の振り返り

サクッと振り返ります。

できごと

  • インターンに色々行けた
  • 好きがたくさん増えた
    • VTuber (名取さな、アンジュ、JK 組など)
    • 音楽 (JPOP、Futurebass、EDM)
    • 野球 (神宮やハマスタに行けた)
    • イラストレーター (れい亜さん、金子あるさん、しゅがおさんなど)
  • プログラミング
  • 友達・知り合いが増えた
    • 逆求人やインターン、イベント等で多くの人と出会えた
    • みんな優秀でその中で一緒に活動できるのが嬉しすぎる
    • 野球、音楽、アニメ、VTuber 等で趣味が合う人もいるのでもっと一緒に遊びたい
    • 社会人と学生の垣根なく接してくださる人が多くて過ごしやすかった
    • 自分が働き始めたら受けたぶんを後輩に与えていきたい
  • 旅行・観光
    • 京都: CAMPHOR- HOUSE や「やが君」の聖地巡礼、温泉にも行けて最高だった
    • 東京: クラブ、野球、FAVRIC
    • 福岡: RubyKaigi、ご飯が美味しすぎる
  • コミュニティ活動
    • KIT Develoers Meetup: 僕主催の金沢工業大学生向けイベント、出会いが多くてやってよかった
    • Toyama RubyKaigi: スタッフしてました

KPT

  • K
    • 継続的に楽しみながらプログラミングをできている
    • OSS が当たり前に感じられるようになれた
    • チーム開発の知見を少し貯められた
  • P
    • コミュ力ない
    • 東京にいるとき以外引きこもりがち
    • あまり自炊できなかった
    • アウトプットが少ない
    • プログラミング以外のクリエイティブな活動ができていない
    • 大学の成績よくない
    • 野球見れてない
  • T (来年の抱負)

来年の抱負

  • イベントでの登壇を増やす (地方住みなので年6回が目標)
  • 大きなカンファレンスに CfP を出す
  • 人に合う
  • 単位取得、研究をちゃんとして卒業する
  • 少しギターを弾けるようになる
  • 100人に使ってもらえるライブラリ (スター) かサービス (ユーザー数) を作る
  • 3回はハマスタに行く
  • コミケ、技術書典で1冊出す

そのために…

  • 新しい技術や手法のキャッチアップを増やす (RSS リーダー使いたい)
  • 朝起きる
  • 休日はギターを触る
  • 毎日ライブラリかサービスのアイデア (不便に感じたことなど) を1つ書き出す
  • 人間関係はなるべき積極的にいく (迷惑にならない程度)
  • ブログ等で定期的にアウトプットする