こんにちは、エンジニアのづやです。
突然ですがエンジニアのみなさん、TypeScriptに触れた経験はありますか? TypeScriptはGitHubが毎年発表しているランキングで今年4位に急上昇したくらい、もっともアツいプログラム言語の1つです。
出典:https://octoverse.github.com/
しかし、いざ試してみようと思っても、
-
- フレームワークは何を使えば良い?
- どうやって導入したら良い?
など、意外とハードルって高くないですか?
そこで「frourio(フルーリオ)」という画期的なフレームワークを見つけました。こういうのってある程度経験を積んだエンジニアでないと使いこなせない……というケースも多いですよね。
でもfrourioはそんなことはなく、TypeScriptに触れたことがないエンジニアでも、サクッと使えるフレームワークなんです!
どんな感じなのか実際に触っていこうと思いますが、その前にfrourioについて少し説明します。
「frourio」とは?
端的にいうとTypeScriptのフルスタックフレームワークです。
- フルスタックフレームワークとは?
- フロントエンドからバックエンド、DBの操作(O/Rマッパー)までWebサービス開発に必要な機能のほぼ全てを含んだプログラムの集合です。代表的な例としては、Ruby on RailsやPHPのLaravelなどがあります。
frourioはフロントエンドからバックエンドまで全てTypeScriptで開発できます。RailsやLaravelを使うとフロントエンドではJavaScriptを書く必要があり、2つの言語を習得する必要があります。
一方、frourioはTypeScriptだけでWebサービス全体を開発することが可能で、開発速度と品質の両方を向上できることが大きな特徴。プログラム全体を通してタイプミスやエラーの原因になる操作が行われていないかどうかをTypeScriptが自動検知してくれるので安心です。
ちなみにfrourioを開発したのは松田さん(@m_mitsuhide)という方で、Qiitaで執筆した記事がわかりやすいので参考にしてみてください!
憧れのTypeScriptフルスタック環境がコマンド1発で作れる超軽量フレームワーク「frourio」
コマンド1発でフロントSPA + RESTサーバー + O/Rマッパーの環境構築ができるとのことなので、早速試してみましょう!
環境構築について
では実際に触っていきます。TypeScriptはNode.jsの環境で動作するプログラム言語なので、あらかじめNode.jsのインストールが必要です。
また、RDBMSも必要に応じてインストールしておきましょう。今回はこちらの内容で環境構築をしてみます(npmはNode.jsと一緒にインストールされます)。
- Node.js: v14.15.0
npm: v6.14.8
RDBMS: MySQL v8.0.22
まずは以下のコマンドを実行してみます。
$ npx create-frourio-app
しばらくするとブラウザでhttp://localhost:3000が開き、以下の画面が表示されました。
この画面でfrourioの構成を選択します。今回フロントエンドフレームワークはNuxt.jsにしました。
そのほか下の画像のように、SSRorSPA、HTTPクライアントなどの項目をぽちぽち選びます。開発者の好みのものがカスタムできるのは素直にいいなと思いました。
O/Rマッパー以降では、データベースの設定をしていきます。ユーザー名やパスワード、データベース名も画面から入力します。
最後にCreateボタンを押すと、インストールが始まります。完了すると自動で以下のページが開きました。この時点でデータベースも含めて環境の作成が完了しています!
これでフロントSPA + RESTサーバー + O/Rマッパーの環境構築は完了です。本当にコマンド1発でした、早いですね!
デフォルトでTODOリストのサンプルが実装されているので、フロント→バックエンドまでの動作を一通り確認することができます。
処理の流れを確認してみよう!
フロント→バックエンドまでの処理の流れを把握するべく、TOP画面中央でフォームに値を入力し、ADDボタンをクリックした時の挙動を追ってみましょう。
おおまかな処理順序は以下の通りです。
- 処理順序
- ①pages/index.vueのcreateTask
②server/api/tasks/controller.tsのpost
③server/service/task.tsのcreateTask
ADDボタンをクリックすると、pages/index.vueのcreateTask()メソッドが呼び出されます。
createTask()の中ではthis.$api.tasks.post()でエンドポイントを指定してAPIの呼び出しを行なっています。
ここには松田さんが開発したaspida(アスピーダ)というライブラリが利用されており、型安全なAPIの呼び出しを可能にしてくれます。
aspidaは、エンドポイントをディレクトリの階層から自動生成してくれるライブラリです。詳細が気になる人はこちらをご覧ください。
frourioについての記事なので、aspidaの説明は割愛しますが、
this.$api.tasks.post()
と記載することで、server/api/tasks/controller.tsのpostが呼び出されます。
続いてpostの中ですが、createTask()でserver/service/task.tsのcreateTaskの処理が実行されます。
初期設定の際にO/RマッパーとしてPrisma(https://www.prisma.io/)を選択したため、ここではprisma.task.create()でデータベースに値を生成しています。
ちなみに、DBのスキーマはserver/prisma内でバージョン管理しており、デフォルトでTaskテーブルの定義があります。
schema.prismaに記載がありますので、テーブルを追加する場合はこちらを更新することになりますね。
createTask()でタスクを作成した後は、fetchTask()メソッドでgetのAPIを呼び出し、TODOリストを取得する流れになります。以上がTODOをADDした時の挙動です。
API側の実装は全てTypeScriptで提供されており、エンドポイント指定やO/Rマッパーの仕組みがわかれば効率良く開発ができそうですね。
一連の流れがわかったところで、簡単な機能追加をしてみましょう。
背景画像をPOSTするAPIを実装してみる!
こちらにあるTOPページの背景が味気ないので、背景画像を変更できるボタンを実装してみましょう!
server/apiの下にbackgroundディレクトリを作成すると自動的にtsファイルが生成されます。
次に画像投稿用のPOST APIを追加するべく、以下のように実装してみます。
自動生成されたserver/api/background/index.tsにPOST APIのパラメータ型を定義します。
元々書かれているgetをpostに書き換えます。
export type Methods = {
post: {
reqFormat: FormData
reqBody: { img: Blob }
resBody: {
imageUrl: string
}
}
}
次にserver/api/background/controller.tsでPOST時の動作を記述します。
先ほど、server/api/background/index.tsの型定義を書き換えた影響でエディタ上にエラーが出ているはずです。ここもgetをpostに書き換えていきます。
import { defineController } from './$relay'
import { changeImage } from '$/service/background'
export default defineController(() => ({
post: async ({ body }) => ({
status: 201,
body: await changeImage(body.img)
})
}))
この時点ではchangeImage関数が未定義なのでエラーが残ります。server/api/service/background.tsを作成して画像を保存し、URLを返してくれるchangeImage関数を定義します。
import fs from 'fs'
import path from 'path'
import { Multipart } from 'fastify-multipart'
import { API_ORIGIN, BASE_PATH } from './envValues'
export const changeImage = async (imgFile: Multipart) => {
const imgName = `${Date.now()}${path.extname(imgFile.filename)}`
await fs.promises.writeFile(
path.resolve('public', imgName),
await imgFile.toBuffer()
)
return { imageUrl: `${API_ORIGIN}${BASE_PATH}/${imgName}` }
}
server/api/publicディレクトリに保存したファイルは静的にホスティングされます。ここまで書くと、先ほどのserver/api/background/controller.tsのエラーがなくなるはずです。
これで画像を投稿するAPIが完成しました。残りはフロントエンドで投稿ボタンを実装するだけです。
pages/index.vueに以下のコードを追加します。
<template>
+<div class="container" :style="pageStyle">
<user-banner />
<div>
<logo />
<h1 class="title">frourio-todo-app</h1>
+ <input type="file" accept="image/*" @change="editImage" />
...
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import { Task } from '$prisma/client'
export default Vue.extend({
data() {
return {
+ pageStyle: {
+ background: ''
+ },
tasks: [] as Task[],
newLabel: ''
}
},
...
methods: {
...
+ async editImage(e: { target: HTMLInputElement }) {
+ if (!e.target.files?.length) return
+ const res = await this.$api.background.$post({
+ body: { img: e.target.files[0] }
+ })
+ this.pageStyle = { background: `center/cover url(${res.imageUrl})` }
+ }
}
})
</script>
これにて完了。ブラウザ中央に出現したボタンから画像ファイルを選択すると、背景が変更されました!
冬らしい背景に設定完了。編集したのは4ファイルだけで、ここまでかかった時間は1時間程度でした。
TypeScriptが初めてでも、フロントエンドとデータベースの知識があればfrourioを短時間で使えるようになると思います!
ちなみに全て英語で書かれていますが、frourio公式のドキュメントはこちらから読めます。
日本語の解説記事はfrourioのコミッターがQiitaに不定期で連載しているとのことなので、ぜひこちらもチェックしてみてはいかがでしょうか?
開発者の松田さんに話を聞きました
せっかくなので、frourioを開発した松田さんにお話を聞いていきたいと思います!
松田さん(@m_mitsuhide)大企業の社内ツールをNuxt.js+TypeScriptで作りながら個人でfrourioとaspidaを開発。7年前にWebGLライブラリjThreeを公開して以来オープンソースを作り続けている。 |
ーー「frourio」を開発しようと思ったきっかけは何ですか?
松田さん:フロントエンドからのAPIリクエストを型安全にするaspidaを公開したあとに、バックエンドも型安全にしたくなったのがきっかけでした。両方を統合してTypeScriptで書けるようになれば、早く高品質なWebサービスを開発できるようになると考えたのです。
ーーなるほど。frourioを使ってみて、TypeScriptが初めてでも書きやすいと感じました。開発者としてはどこが魅力だと考えていますか?
松田さん:そうですね、1つ目はTypeScriptの複雑な型を使わずに書けることです。TypeScriptは従来のJavaScriptに型を追加した言語ですが、複雑な部分をfrourioで極力隠蔽しているのでほとんどJavaScriptに近い見た目で書くことができます。
2つ目は、画面上で構成を決めるだけで環境構築ができることです。新しい言語・フレームワークを習得する際に最も面倒で難しいのは環境構築です。経験年数に関係なくつまずきますし、エラーコードは役に立たずググっても答えが出ないことがありませんか?
ーーそういう経験をしたエンジニアは多いと思います!
松田さん:3つ目は、テストコードを書けないような状況でも、高い品質のサービスを開発しやすいことです。今までのフルスタックフレームワークは言語を二つ使う必要があったり、TypeScriptを導入してもフロントエンドとバックエンドが統合されていなかったりするため「APIが正しく繋がること」を型でチェックすることが困難でした。
そのため本体のコードと同じくらいのコストをかけてテストコードを書くか、ブラウザ上で手動確認する必要があります。frourioならAPIのリクエスト含め、フロントエンド・バックエンド・O/Rマッパーまで統合してTypeScriptでの型チェックが可能です。
どうしてもテストを書くリソースを確保できない状況でも、従来より早く安全にサービス開発ができるようになりますね。
ーー確かに素早くテストも書ける優秀なエンジニアを確保するのはどの会社でも苦労しているし、案件やチーム編成によってテストを書けないことはよくあると思います。frourioを導入するとテストを書かなくても良くなるのですか?
松田さん:「書かなくてもいい」とは言いづらいですが、「書けない現状がある」ことを認識しています。
frourioを使ってもTypeScriptでカバーできない部分があるので、テストを書くことが理想です。今回の記事では触れていませんが、frourioには関数に依存性を注入できる画期的なテスト機能があります。
一方で納期や予算、文化によって必ずしも理想通りにいかない現場をたくさん見てきました。そんな課題に少しでも貢献したい思いで、TypeScriptの恩恵を最大限享受できるフレームワークとしてfrourioを開発しました。世界中のエンジニアに、この安心感を体験して欲しいです。
ーー理想を追求しつつ、現実的な課題も解決できるように設計されたフレームワークということですね。frourioがより多くのエンジニアに広まっていき、素晴らしいWebサービスが産まれることを願っています!
「frourio」を触ってみたリアルな感想
コマンド1つで環境構築からAPI実装まで、TypeScriptを使って簡単に実現できました! 環境構築に時間をかけずにTypeScriptを触ってWebアプリケーションが作成できるので、これからTypeScriptを始めたい方にとってはうってつけのフレームワークではないかと思います。
またaspidaを使って、ディレクトリ/ファイルによってオートルーティングができる点や、型の安全も保証されている点において、「手軽さ」と「保守性」の両面を兼ね備えているのが大きな強みだと感じました。
今回はローカル環境での動作確認のみでしたが、今後Dockerで本番環境デプロイなども試してみたいと思います。
難しい知識が必要ないフレームワーク「frourio」
- 「frourio」の特徴
-
- TypeScriptだけで扱えるフルスタックフレームワーク。
- コマンド一発で環境構築からAPI実装までできる。
- TypeScriptが初めてでも読みやすくて書きやすい。
いくら手軽でも、仕事として使えるレベルまで習得するにはある程度の時間が必要です。この機に誰より早くfrourioに入門して「TypeScriptフルスタックエンジニア」を目指してみませんか?