RIT Tech Blog

株式会社RITのエンジニアが知見を共有する技術ブログです。

セマンティックHTMLでセクショニングをする

f:id:sk0515:20191227182921p:plain

はじめに

こんにちは!デザイナーの金森です。

仕事納めですね。2019年いろいろありましたね、お疲れさまでした! RITではデザイナーも企画のアイディエーションから入り、開発まで幅広く携わっています。 今回はその中でも開発の「セマンティックHTML」のお話をしようかと思います。

セマンティックHTMLとは?

セマンティックとは、一般的には「意味」や「意味論」に関することを指す語である。IT用語としては、コンピュータに文書や情報の持つ意味を正確に解釈させ、文書の関連付けや情報収集などの処理を自動的に行わせる技術について用られる語である。セマンティックとは何?Weblio辞書

????ちょっとわかりにくいですね 簡単に説明すると、各部品に対応する意味のあるHTML要素を使いましょうという考え方です。

そうすることによって

  • マシンリーダブルなコードになり、SEOに強くなる

  • 人間にとっても読みやすいコードになる(延々とdivを見比べる必要がなくなる)

  • アクセシビリティが向上し、障がいをお持ちのかたでも快適にサイトやサービスが使えるようになる

などのメリットがあります!

セマンティックHTMLの例

例えば、最上位レベルの見出し要素をコーディングする際に、 <h1>これが最上位レベルの見出し!</h1> と書きますよね? f:id:sk0515:20191227175042p:plain

このように記述することで、検索エンジンがその内容をSEOに影響する重要なキーワードと見なしたり、ブラウザの読み上げ機能などを使用できるようになります。

一方で、正直どの要素でも上記のような最上位レベルの見出しのようなデザインに見せることができます。 <div>これが最上位レベルの見出し?</div> f:id:sk0515:20191227175324p:plain これは一見、最上位レベルの見出しのように見えますが、h1のようにセマンティックな意義がないのでSEOやブラウザの読み上げなどのメリットを受けることが出来ません。

見かけ上は正しいように見えていて書けているけど、SEOアクセシビリティの観点からは良くないというのがHTMLの難しいところですね....! 超基本なことですが、わたしも意図して書かないと良くないコードを書いてしまったりするので常日頃から注意する必要があります。。。

セクショニング・コンテンツ

セマンティック要素はめちゃめちゃある(おおよそ100ほどある)ので、今回はセクショニング・コンテンツだけ取り出して解説します。

セクショニング・コンテンツとは、文章の区分や節などの、区切りを表すコンテンツで以下のものを指します。 順を追って説明していきます。

  • <article>
  • <section>
  • <nav>
  • <aside>

<article>について

HTML の article 要素は文書、ページ、アプリケーション、サイトなどの中で自己完結しており、 (集合したものの中で) 個別に配信や再利用を行うことを意図した構成物を表します。例えば、フォーラムの投稿、雑誌や新聞の記事、ブログの記事などが含まれます。MDN Web Docs: 記事コンテンツ要素

  • 注意点
    • articleの内容が単独で切り出しても、独立して意味を持っていること
    • 子要素として見出し要素が必要(h1〜h6のどれか)
    • 子要素としてsectionタグが少なくとも1つ必要
    • articleのなかで、articleを子要素として持つことも可能
<article>
    <h1>RITについて</h1>
    <p>千代田区にあるコンサルティングとインキュベーションの会社です。</p>
    <section>
        <h2>やってること</h2>
        <p>テキストテキスト</p>
    </section>
</article>

<section>について

HTML の section 要素は、 HTML 文書の中で単独のセクション (区間) を表します。セクションを表現するより意味的に具体的な要素がない場合に使用します。必ずではありませんが、通常はセクションには見出しがあります。MDN Web Docs: 汎用セクション要素

  • 注意点
    • 子要素として見出し要素が必要(h1〜h6のどれか)
    • 単独で切り出しても、独立して意味を持っているものには使用してはならない
      • その場合はarticleを使用すること
    • 文書のアウトライン上のみで使用すること
      • スタイル付けのみが目的なのであれば、divを使用すること
<section>
    <h1>ABOUT</h1>
    <p>この記事はセマンティックhtmlの説明をしています。</p>
</section>

<nav>について

HTML の nav 要素は、現在の文書内の他の部分や他の文書へのナビゲーションリンクを提供するためのセクションを表します。ナビゲーションセクションの一般的な例としてメニュー、目次、索引などがあります。MDN Web Docs: ナビゲーションセクション要素

  • 注意点
    • すべてのリンクに対してnavを使用する必要はなく、ページ内でも重要な部分にのみ使用すること
    • 上述のようにヘッダーやサイドバーなどnav要素は複数使用してもOK!

<aside>について

HTML の aside 要素は、文書のメインコンテンツと間接的な関係しか持っていない文書の部分を表現します。サイドバーやコールアウトボックスなどを表現するためによく使われます。MDN Web Docs: 余談要素

  • 注意点
    • 文章中の括弧書きについては、文章の主要な流れに属するものであるといえますので、これをタグ付けするためにaside要素を使用することはできません
      • 注意書きや、注釈などに用いるための要素です
<p>こんにちは、RITでデザイナーをしている金森です。</p>

<aside>
    <p>余談ですが、好きなことは音楽を聞くことです。</p>
</aside>

<p>これからセマンティックhtmlについて説明します。</p>

まとめ

今回ご紹介したものはHTML構造のアウトラインをつくる上で重要になるものばかりです。 全部divでいいんじゃない???って気持ちにもなったりしますが、ユーザーを一番に考えて良いコードを書くように気をつけましょう。 長くなりましたがここまで読んでくれた方ありがとうございます!良いお年を〜!

Headless CMSのStrapiをECSで運用してみる(後半)

rit-inc.hatenablog.com

↑の続きです

ECRにリポジトリ作る

とりあえずECRにリポジトリを作りましょう

f:id:rit-inc:20191216132313p:plain

f:id:rit-inc:20191216132447p:plain

URIを控えておきましょう

ビルド

ECRにpushするDocker imageをbuildします

PS C:\Users\tetsu\dev\new_blog> docker build -t <↑で控えておいたURI>:latest .
Sending build context to Docker daemon  527.4kB
Step 1/7 : FROM node:12
 ---> 11e92fc50c4a
Step 2/7 : COPY . /strapi
 ---> Using cache
 ---> d12f81986c35
Step 3/7 : WORKDIR /strapi
 ---> Using cache
 ---> 55776038dbb7
Step 4/7 : RUN yarn
 ---> Using cache
 ---> f4e982ccbbc1
Step 5/7 : RUN yarn build
 ---> Using cache
 ---> e986f88a755d
Step 6/7 : EXPOSE 8000
 ---> Using cache
 ---> bc4357547272
Step 7/7 : CMD ["yarn", "start"]
 ---> Using cache
 ---> 3e5b72ab37a0
Successfully built 3e5b72ab37a0
Successfully tagged <↑で控えておいたURI>:latest
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.

ECRにpush

ECRへのログインに関しては省略します

PS C:\Users\tetsu\dev\new_blog> docker push <↑で控えておいたURI>:latest
The push refers to repository [<↑で控えておいたURI>]
ddcc6d87877d: Pushed
e16bf0fde55b: Pushed
9b567c0e90e9: Pushed
16bf97960ee7: Pushed
190990e6fae4: Pushed
e44afd48b6d5: Pushed
799e7111d6d4: Pushed
a72a7e555fe1: Pushed
b8f8aeff56a8: Pushed
687890749166: Pushed
2f77733e9824: Pushed
97041f29baff: Pushed
latest: digest: sha256:9daa204795d9930d14f189041a05f8a355623b4684048fef7ff95db827b79f7d size: 2850

f:id:rit-inc:20191216133700p:plain

ちゃんとpushされてる

ECSでタスク作成

FARGATEで作ろう

f:id:rit-inc:20191216133835p:plain

f:id:rit-inc:20191216133957p:plain

f:id:rit-inc:20191216134717p:plain

f:id:rit-inc:20191216134746p:plain

f:id:rit-inc:20191216134805p:plain

設定はこんな感じ

f:id:rit-inc:20191216134849p:plain

できた

クラスター作成

fargateで

f:id:rit-inc:20191216215128p:plain

f:id:rit-inc:20191216215301p:plain

f:id:rit-inc:20191216215443p:plain

できた

タスク実行

f:id:rit-inc:20191216222500p:plain

アラートが出るのでswitch to launch typeでfargateに

VPCはデフォルトで、サブネットは適当に付けちゃいます

セキュリティグループはtcpの1337ポートを開けときましょう

パブリックIPの自動割当はとりあえずENABLED

f:id:rit-inc:20191216222554p:plain

f:id:rit-inc:20191216222703p:plain

f:id:rit-inc:20191216222821p:plain

起動しました

f:id:rit-inc:20191216222931p:plain

pendingからrunningに変わるまで待つ

f:id:rit-inc:20191216223044p:plain

runningになったのでpublic ipにアクセスしてみましょう

f:id:rit-inc:20191216223142p:plain

起動しています

これだと失敗っぽく見えちゃうので管理画面にもアクセスしてみる

f:id:rit-inc:20191216223226p:plain

うまくいってる

まとめと課題

  • 簡単にECSでstrapiのコンテナを実行することができた
  • DBだとかの設定には環境変数の変更が必要(タスクの定義で変えられる)
  • CI/CDにはもうひと工夫必要(commit hashとってきてタスク定義を更新するとか)

長々とECSについて書きましたが、最近はEKSやGKEなどのk8s活用にも力を入れているので、そのうちk8sでも構築してみたいですね

RITでは、様々な技術を活用してクライアントや自社サービスを作り上げることに興味のあるエンジニアを募集しています!

rit-inc.co.jp

iPadで開発業務を効率化

初めまして、RITのエンジニアの前田です。 僕は普段MacBookPro(以下MBP)一台で仕事をしているのですが、サブ機としてiPadを導入したところ意外と役に立ったので、共有したいと思います。

そもそもなぜサブ機としてiPadの導入をしたかというと、 僕はエンジニアなので開発をメインの業務としているのですが、 MBP一台で開発・連絡・タスク管理・メモなど全てを行うことに限界を感じたからです。 こんな感じ↓

画面がグチャグチャ・・・イライラ(`‐●_‐´怒)

そこでサブ機としてiPadを導入して、それにタスク管理とメモは集約させようと考えたのです。 結論から報告すると、かなり良いです。

タスク管理をiPadでするようになりました。

個人的にタスク管理にはTrelloを活用していて、今まではMBPで開いていたのですが、当然開発をしているとその他のたくさんの画面のうちの一つとして埋もれてしまいます。

タスクも一応はTrelloで管理していたのですが、自分のタスクは頭の中だけで管理していたも同然でした。(いつまでにこれをやる。。。など)

頭の中だけでタスクの管理をしていると、開発中も自分の抱えている別タスクがちらついてしまい、開発効率が20%くらい落ちているような気がしていました。

しかし、iPadを導入しタスク管理をそちらに集約するようにしたため、

頭の中でタスクを管理していた分の領域を開発に向けることができ、MBPもタスク管理で開いていた画面が消え、開発に集中して取り組めるようになりました。

また、メモもiPadでとるようになりました。

今までは、紙ベースの簡易的なメモとMBPの文字ベースのメモの二つでメモを取っていました。メモという一つのことをするために、2つの媒体を使ってしまっていて自分の中で管理することができず、とりあえずメモをとるだけになってしまっていました。

iPadでメモを取るようになってから、手書き、文字ベース両方同じ端末で取ることができる上に、開発用のMBPからメモをとる画面を消すことができてだいぶスッキリしました!

f:id:keimaeda0817:20191210183744j:plain

f:id:keimaeda0817:20191210183810j:plain

iPadを実戦投入してみたまとめ

before

  • MBPでタスク管理とか連絡とかメモとか開発全部やるの辛い

after

  • MBPは開発に集中!
  • iPadでメモを一元化、
  • タスクは頭の中で管理するのではなく常にiPadで目の前に出しておく

以上が、iPadを実戦投入してみた感想です。

今後はメモの質を上げていくために経費でApple pencilやiPad用のキーボードの導入も検討しています。

ここまでお読みいただきありがとうございました。

Headless CMSのStrapiをECSで運用してみる(前半)

WordPressのスケーリングとか考えるの辛いしフロントは自由に作りたいですよね?

今回はHeadless CMSのStrapiをECSで運用した話(の前半、ローカルのDockerで動かすまで)をしたいと思います。

環境

  • Windows 10 Pro
  • Node.js 12.13.0
  • Yarn 1.19.1
  • Docker 19.03.4
  • Strapi 3.0.0-beta.17.2
    • 最新版だとstrapi buildコマンドが動かなかったのでちょっと前のバージョン使ってます

StrapiのProjectを作成する

strapi.io

公式のドキュメントに従って進めてみましょう。 Project生成用のコマンドが用意されてるのでyarnかnpxで実行します(今回はyarn使いました)

PS C:\Users\tetsu\dev> yarn create strapi-app new_blog
yarn create v1.19.1
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...

success Installed "create-strapi-app@3.0.0-beta.17.5" with binaries:
      - create-strapi-app
'C:\Program' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
error Command failed.
Exit code: 1
Command: C:\Program Files (x86)\Nodist\bin\bin\create-strapi-app
Arguments: new_blog
Directory: C:\Users\tetsu\dev
Output:

info Visit https://yarnpkg.com/en/docs/cli/create for documentation about this command.

うまくいかない… npxで再チャレンジ

PS C:\Users\tetsu\dev> npx create-strapi-app new_blog
npx: installed 84 in 12.995s
Creating a new Strapi application at C:\Users\tetsu\dev\new_blog.

? Choose your installation type (Use arrow keys)
? Choose your installation type Quickstart (recommended)
Creating a quickstart project.
Creating files.
Dependencies installed successfully.

Your application was created at C:\Users\tetsu\dev\new_blog.

Available commands in your project:

  yarn develop
  Start Strapi in watch mode.

  yarn start
  Start Strapi without watch mode.

  yarn build
  Build Strapi admin panel.

  yarn strapi
  Display all available commands.

You can start by doing:

  cd C:\Users\tetsu\dev\new_blog
  yarn develop


> new_blog@0.1.0 build C:\Users\tetsu\dev\new_blog
> strapi build "--no-optimization"

Building your admin UI with development configuration ...

√ Webpack
  Compiled successfully in 12.32s

Running your Strapi application.

> new_blog@0.1.0 develop C:\Users\tetsu\dev\new_blog
> strapi develop

[2019-11-15T09:28:19.454Z] info File created: C:\Users\tetsu\dev\new_blog\extensions\users-permissions\config\jwt.json

 Project information

┌────────────────────┬──────────────────────────────────────────────────┐
│ Time               │ Fri Nov 15 2019 18:28:21 GMT+0900 (GMT+09:00)    │
│ Launched in        │ 6508 ms                                          │
│ Environment        │ development                                      │
│ Process PID        │ 26676                                            │
│ Version            │ 3.0.0-beta.17.5 (node v12.13.0)                  │
└────────────────────┴──────────────────────────────────────────────────┘

 Actions available

One more thing...
Create your first administrator 💻 by going to the administration panel at:

┌─────────────────────────────┐
│ http://localhost:1337/admin │
└─────────────────────────────┘

[2019-11-15T09:28:21.602Z] debug HEAD index.html (10 ms) 200
[2019-11-15T09:28:21.604Z] info ⏳ Opening the admin panel...
[2019-11-15T09:28:21.763Z] debug GET index.html (3 ms) 200
[2019-11-15T09:28:21.780Z] debug GET runtime~main.c1955456.js (2 ms) 200
[2019-11-15T09:28:21.781Z] debug GET main.9cb7efe0.chunk.js (2 ms) 200
[2019-11-15T09:28:22.114Z] debug GET /favicon.ico (4 ms) 200
[2019-11-15T09:28:22.116Z] debug GET /users-permissions/init (11 ms) 200
[2019-11-15T09:28:22.121Z] debug GET /admin/init (2 ms) 200
[2019-11-15T09:28:22.164Z] debug GET 6301a48360d263198461152504dcd42b.svg (2 ms) 200
[2019-11-15T09:28:22.194Z] debug GET 2ff0049a00e47b56bffc059daf9be78b.png (2 ms) 200
[2019-11-15T09:28:22.204Z] debug GET bd03a2cc277bbbc338d464e679fe9942.woff2 (6 ms) 200
[2019-11-15T09:28:22.204Z] debug GET cccb897485813c7c256901dbca54ecf2.woff2 (5 ms) 200
[2019-11-15T09:28:22.205Z] debug GET 8b4f872c5de19974857328d06d3fe48f.woff2 (5 ms) 200
[2019-11-15T09:28:22.205Z] debug GET af7ae505a9eed503f8b8e6982036873e.woff2 (4 ms) 200
[2019-11-15T09:28:22.206Z] debug GET 33d5f0d956f3fc30bc51f81047a2c47d.woff2 (4 ms) 200
[2019-11-15T09:28:22.210Z] debug GET 4c4e7d0d5ebd40343f6e1281f0bd9438.ico (3 ms) 200

strapiが起動して管理者の登録画面が開くはずなので適当に登録しましょう (1337番portが別のプロセスですでに使われてて一度失敗してます)

f:id:rit-inc:20191115182946p:plain

登録が完了したらダッシュボードに遷移します

f:id:rit-inc:20191115183220p:plain

Dockerで動かす

一旦この状態をDockerで動かせるようにしましょう 公式がDocker Imageを提供してますが今回は手動で構築してみます

github.com

yarnしてbuildしてstartするだけのやつ

Dockerfile
FROM node:12

COPY . /strapi
WORKDIR /strapi

RUN yarn
RUN yarn build

EXPOSE 1337

CMD ["yarn", "start"]

ローカルで生成されたファイルと衝突しちゃうので.dockerignoreも作成しておきましょう

node_modules
build
.cache
.tmp
public

buildして

PS C:\Users\tetsu\dev\new_blog> docker build . -t new_blog
Sending build context to Docker daemon  527.4kB
Step 1/7 : FROM node:12
 ---> 11e92fc50c4a
Step 2/7 : COPY . /strapi
 ---> d12f81986c35
Step 3/7 : WORKDIR /strapi
 ---> Running in 41a2b9cb2e88
Removing intermediate container 41a2b9cb2e88
 ---> 55776038dbb7
Step 4/7 : RUN yarn
 ---> Running in 89413fd02861
yarn install v1.19.1
[1/5] Validating package.json...
[2/5] Resolving packages...
[3/5] Fetching packages...
info fsevents@1.2.9: The platform "linux" is incompatible with this module.
info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation.
info fsevents@2.1.2: The platform "linux" is incompatible with this module.
info "fsevents@2.1.2" is an optional dependency and failed compatibility check. Excluding it from installation.
[4/5] Linking dependencies...
warning "strapi-admin > bootstrap@4.3.1" has unmet peer dependency "jquery@1.9.1 - 3".
warning "strapi-admin > bootstrap@4.3.1" has unmet peer dependency "popper.js@^1.14.7".
warning "strapi-admin > @buffetjs/styles > react-dates@21.5.0" has unmet peer dependency "react-with-direction@^1.3.1".
warning "strapi-plugin-users-permissions > grant-koa@4.6.4" has unmet peer dependency "koa@>=0.x.x".
warning "strapi-hook-bookshelf > bookshelf@0.15.1" has incorrect peer dependency "knex@>=0.13.0 <0.18.0".
[5/5] Building fresh packages...
Done in 53.53s.
Removing intermediate container 89413fd02861
 ---> f4e982ccbbc1
Step 5/7 : RUN yarn build
 ---> Running in 92f0d4414e4b
yarn run v1.19.1
$ strapi build
Building your admin UI with development configuration ...
ℹ Compiling Webpack
✔ Webpack: Compiled successfully in 24.15s
Done in 25.48s.
Removing intermediate container 92f0d4414e4b
 ---> e986f88a755d
Step 6/7 : EXPOSE 8000
 ---> Running in e8c7cc8fd917
Removing intermediate container e8c7cc8fd917
 ---> bc4357547272
Step 7/7 : CMD ["yarn", "start"]
 ---> Running in da37576c9adf
Removing intermediate container da37576c9adf
 ---> 3e5b72ab37a0
Successfully built 3e5b72ab37a0
Successfully tagged new_blog:latest
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.

runしてみる

PS C:\Users\tetsu\dev\new_blog> docker run -p 1337:1337 new_blog
yarn run v1.19.1
$ strapi start

 Project information

┌────────────────────┬──────────────────────────────────────────────────┐
│ Time               │ Fri Nov 15 2019 10:20:05 GMT+0000 (Coordinated … │
│ Launched in        │ 1795 ms                                          │
│ Environment        │ development                                      │
│ Process PID        │ 28                                               │
│ Version            │ 3.0.0-beta.17.5 (node v12.13.0)                  │
└────────────────────┴──────────────────────────────────────────────────┘

 Actions available

Welcome back!
To manage your project 🚀, go to the administration panel at:
http://localhost:1337/admin

To access the server ⚡️, go to:
http://localhost:1337

localhost:1337にアクセスしてみましょう

f:id:rit-inc:20191115192124p:plain

ローカルで実行したときと同じように登録画面が出るはず

ECSで動かす

ちょっと長くなってきたので今回はここまで 次回はECRにpushしてECSで動かすとこまでやります!

React Hooks使ってリファクタしてみた話

CTOの福田です

React 16.8 リリースされましたね

新機能のReact Hooksを使って自社サービスのコードをリファクタしてみたので、全体的な使用感とかハマったポイントを挙げていこうと思います。

前提

  • Reduxは使ってません
  • statefulなコンポーネントを多用してます
  • React + React RouterのSPA
  • TypeScript

ざっくり

  • 〇 Class ComponentがFunction Componentにできてネストが一段減って行数も微妙に削減されてうれしい
  • useState使うとsetState({hoge: 'fuga'})setHoge('fuga')みたいにできてうれしい
  • useEffectの第二引数が直感的じゃない?

詳しく

Class ComponentがFunction Componentにできる & setStateがシンプルに

何かすごいメリットがあるかって言われると微妙なんですが、単純にネストと行数が削減されるのでよいとおもいます

単純なカウンターの例を書いてみると

class HelloComponent extends React.Component<{}, {count: number}> {
    state = {
        count: 0;
    };

    render() {
        return (
            <button onClick={() => this.setState({count: this.state.count + 1})}>{this.state.count}</button>
        );
    }
}

function HelloComponent() {
    const [ count, setCount ] = useState(0);
    return (
        <button onClick={() => setCount(count + 1)}>{count}</button>
    );
}

になります

useEffectの第二引数

componentDidMountajaxしたりcomponentDidUpdateでrefからdomを操作したい場合はuseEffectの第一引数にコールバック関数渡してその中で処理するんですが、asyncなコールバックが渡せなかったり何も考えずにasyncな関数呼び出してその中でsetStateしてると無限ループしちゃうのでちゃんとドキュメント読みましょう

メッセージ一覧を取得して表示する画面で最初書いてたコード(サンプル用に改変済み

import React, { useState, useEffect } from 'react';
import { Message } from '../entities';
import { MessageRepository } from '../repositories';

export default function Messenger() {
    const [ messages, setMessages ] = useState(new Array<Message>());

    const fetchMessages = async () => {
        setMessages(await MessageRepository.getAll());
    };

    useEffect(() => {
        fetchMessages();
    });

    return (
        <ul>
            {messages.map(m => <li key={m.id}>{m.text}</li>)}
        </ul>
    );
}

useEffectはstateやpropsが変更される度に呼び出されるので、この例ではsetMessagesを呼び出すたびにfetchMessagesが呼び出されて無限ループしてしまいますが、 useEffectの第二引数を使うことによって特定の値が変更された場合のみコールバックを実行するように制御できます

なので、ここに空の配列を渡してやることで初回だけ実行されるコールバックが実現できます

useEffect(() => {
    fetchMessages();
}, []);

これで初回だけ実行されるので、componentDidMount相当になります

最後に

ハマりポイント何個か書こうと思ったんですがほとんどハマらなかったので書くことがありませんでした

現状複雑な状態や副作用を持ってるコンポーネントだと大幅な改修が必要になっちゃうんですが基本的にコード量は減るので、新しいコンポーネント書くときには積極的に使うといいんじゃないでしょうか

RITでは新規事業に携わりたい方を様々な職種で募集しているので、ご興味ある方はぜひオフィスに遊びに来てください!

https://rit-inc.co.jp

昨年の振り返りと今年の目標

新年明けましておめでとうございます。CTOの福田です。

年始なので昨年の振り返りと今年の目標でも書いてみようと思います。

昨年の振り返り

マッチングサービス多いですね。 この他にも以前受託したプロダクトの改修案件や仕込み中の案件もあり、エンジニア3人(うち一人デザイナー兼務)で割とスピード感持って開発できたのではないでしょうか。

よかったこと

  • スピード感持って開発できた
    • だいたい1サービス2~3ヶ月でリリースできた
    • VIRECが最初で、そのマッチングサービスのノウハウで他サービスの基盤構築を短縮できた
  • 技術レベルの底上げができた
    • ほぼ新卒で未経験のエンジニアを採用したけど半年程度である程度RailsとReactが触れるようになってる(インフラはまだちょっと怪しい)

改善したいこと

  • マッチングサービス多すぎ
    • 中間マージンを排除するという世の流れもあるけどマッチングサービス以外も作りたい
  • 技術の幅を広げたい
    • 基本的にRails + React + AWS(Beanstalk)で固定されてしまっているので、どんどん新しい言語とかフレームワーク試してさらなる高速化に繋げたい

今年の目標

社内に蓄積されたナレッジで、サービス立ち上げを通じてチャレンジしやすい環境が整ってきたので、 様々なサービス立ち上げに対応できるような組織づくりを推進します。 具体的な目標は以下の通り

  • エンジニアとデザイナー増員
    • 技術の幅を広げて開発するサービスの幅も広げるために増員したい
    • 少なくとも今年2~3人は増やしたい
  • 開発部隊の年収15%以上アップ
    • 教育にちゃんとコストかけて外の世界でも魅力的な人材になってもらうとともに、それに見合った給与を支払えるように売り上げも作る
  • 6サービス以上リリース
    • 開発ラインを増やして前年比1.5倍で
  • イケてる技術をプロダクトに導入したい
    • GraphQL(AWS AppSync)とかFlutter興味あります

最後に

RITでは新しいサービスや技術が好きで、新サービスの立ち上げを通して成長したい方を募集しています。

まずはオフィスまで遊びに来てみませんか?

ActionMailerでdeliver_laterしてるテストが頻繁に止まるようになった話

内容は薄いですが結構ハマったのでメモ

結論

非同期処理内でDBからデータ取ってくるときはassert_enqueued_jobsとかassert_enqueued_emailsで囲んどこう

経緯

弊社のプロダクトではRuby on Railsを利用していてMinitestでテストを書いているんですが、最近になって頻繁にテストが失敗するようになりました。 成功する時もあれば失敗する時もあり、docker-composeでコンテナ立ち上げすぎて色々足りてないのかなーぐらいに思ってたのですが、大体止まったタイミイングのログを見るとActionMailer周りの処理だったので、非同期処理が何か悪さしてるのかと思って調査をはじめました。

予想

最近入れたactive_elastic_jobが悪いんじゃないか

最近非同期処理に影響を与えそうな改修をしたのはこれだったので一番怪しんでたのですが冤罪でした

そもそもtestのqueue_adapterにactive_elastic_job使ってなかったので関係ない

testのRollback先に走ってjobのdeserialize失敗してるんじゃないか

基本的にはログ出さずに止まってるだけだったのですが、たまにdeserializeでエラーログ出ることがあったので怪しいと思い調査 queueを処理してからテスト終わるようにしたらうまくいくんじゃないかと思ったので↓みたいにassert_enqueued_emailsで囲んでみたところ

class SampleTest < ActiveSupport::TestCase
  include ActionMailer::TestHelper

  test 'sample test' do
    assert_enqueued_emails 1 do
      Sample.test_method
    end
  end
end

ActiomMailer起因で失敗することがなくなりました

絶対失敗するわけじゃなかったり最近失敗が増えてきたのはコンテナの立てすぎでテストの処理が重くなってJobの処理する前にRollbackしちゃうケースが増えちゃったって感じなんですかね