18
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

N/S高等学校Advent Calendar 2023

Day 2

個人開発で使いやすいフレームワークたち

Last updated at Posted at 2023-12-01

はじめに

こんにちは!、普段は https://abc.osaka とかで色々書いたりしてるS高生(3期生)です
今回は個人でウェブサイトやウェブアプリケーションを作る時の毎回フレームワークについて悩むので、(嘘です、毎回ノリで決めています) どう言ったフレームワークがあるのかと、個人的によかった構成についてまとめてみました

ウェブアプリケーションには何が必要か

ウェブアプリケーションには、FrontendとBackendが必要な場合が多いです
簡単に説明すると

FrontendはWebページです、データが必要な場合はBackendと通信してデータを取得します
BackendはDBなどのデータを保存、または処理、ユーザーの認証をするところです

何かデータを保存する、または高度な処理をする必要がなければBackendは必要ありません
保存する場合でもローカルに保存するだけ場合 ( 他人と、または他のデバイスと共有しない場合 )はBackendは必要ありません

具体的にはTwitterのようなSNSにはBackendが必要ですが、Todo listやBlog等には必要ありません ( Todoに共有機能をつける場合や、Blogのコンテンツを管理するものが必要な場合は除く )

最近ではRSCなどが出てきてBackendなしでもDBが使えたり、認証できたりします
(FrontendがBackendの機能も持っただけですが)

Full Stack Framework

中にはFull Stack Frameworkと呼ばれるBackendとFrontendが一緒になったFrameworkが存在します
BackendとFrontendが分かれている場合、BackendでApiを作り、Frontendでそれを呼び出す、という感じですが

Full Stack FrameworkではBackendがFrontendの領域までやります
代表的なフレームワークにDjangoやRuby on Railsがあります

Full Stack Frameworkは早く開発ができると言われていますが、WEBの基本的なところやDatabaseがかなり奥に隠されています
基本的なことを理解したい場合はBackend FrameworkとFrontend Frameworkで作ることをお勧めします

Frontend Frameworkを選ぶ

ぶっちゃけ今回はBackendがメインみたいなところがあるのですが、書いておきます

Next.js ( TS | JS )

const Home = () => {
	const [value, setValue] = useState(0)
	return <button onClick={()=> setValue((v)=> v + 1)}>{value}</button>
}

Next.jsは個人的には一番気に入っているFrontend Frameworkです
理由がなければとりあえずNext.jsを使うレベルで使ってます
SSG, RSCなど多くの機能があり、基本的に機能で困ることはありません

Next.jsはVercelが開発しているため、ワンクリックでNext.jsをVercelにデプロイすることができるのも魅力的です

Vercelは簡単にデプロイでき、尚且つアナリティクス等もあり、無料でも十分使えます
Vercelの無料枠が足りないことはあまりないと思いますが、足りない場合は少し手間が掛かりますがCloudflare Pagesが便利です、静的なサイトだとLimitがないので静的なサイトだと困ることはなくなります

Vanilla ( フレームワーク無し )

<button class="btn">0</button>
<script>
	let value = 0;
	const btn = document.querySelector(".btn")
	btn.addEventListener("click", ()=> {
		value += 1;
		btn.innerHTML = value;
	})
</script>

はい、最速です、フレームワークの紹介でフレームワーク無しを選択するのは流石にふざけてるでしょ、と思われる方が多いでしょうが、半分本気です
それには色々と理由があります

  • 最速です
  • 無駄なリクエストを出すこともありませんし
  • サイズも最小化できます
  • Buildもする必要ありません
  • Backendから適当にhtmlを組み立ててcontent-typeとか色々やって返すだけ
  • 自由度が高い

まぁデメリットも多いんですが、意外とおすすめです

うん、今回の場合は例が悪い、上のコード見たら誰もやりたくなくなるよ

Backend Frameworkを選ぶ

backendは数が多すぎるのでここでは一部しか取り上げていませんが、その他にも素晴らしいフレームワークがたくさんあるので色々試してみることをお勧めします、もちろん自作を含めて

Gin ( Golang )

package main

import (
	"net/http"
	"github.com/gin-gonic/gin"
)

func main() {
	app := gin.Default()
	app.GET("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, "pong")
	})
	_ = app.Run(":8080")
}

GinはGoで書かれているため、ある程度の速度が出ますし、なんと言っても楽に書けます
その上ライブラリも比較的多いです
サックと作りたい場合はおすすめです

Hono ( TS | JS )

import { Hono } from "hono"
const app = new Hono()

app.get("/ping", (c) => c.text("pong"))

export default app

Honoはさまざまなランタイムで動いて、色々なところにデプロイできるのが魅力的です
Nodeはもちろん、BunやDenoでも動きますし、Cloudflare workerでもAWS Lambda、Vercelなどにデプロイできます

Actix Web ( Rust )

use actix_web::{web, App, HttpServer, middleware::Logger, HttpRequest, HttpResponse, dev::Service};
use env_logger::Env;

#[actix_web::get("/ping")]
pub async fn ping() -> impl actix_web::Responder {
	actix_web::HttpResponse::Ok().body("pong")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
	env_logger::init_from_env(Env::default().default_filter_or("info"));
	HttpServer::new(|| {
		App::new()
			.wrap(Logger::default())
			.service(ping)
	})
	.bind("0.0.0.0:8081")?.run().await
}

早いです、そしてRustなので型が厳密で書きやすいです
昔はよく使ってましたが、最近は実行速度よりもサックと書きたい衝動にかられてGinに浮気してます

Flask ( Python )

from flask import Flask,jsonify

app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
	SECRET_KEY = "secret",
	JSON_AS_ASCII = False
)

@app.route("/ping", methods=["GET"])
def ping():
	return jsonify({"msg": "pong"})

if __name__ == '__main__':
	app.run(debug=True, host='0.0.0.0', port=5000)

簡単に色々な機能を実装できるのが魅力的です
Socket.ioもflask_socketioがあり、認証 ( JWT ) にもflask_jwt_extendedがあります
もちろんデータベースにもflask_sqlalchemyがあり、ライブラリが豊富で至れり尽くせりです

もちろんデメリットもあります速度が遅いです、また色々ラップされてるので返ってやりにくいかもしれません、逆に言えばそのくらいです、初心者にはおすすめのフレームワークです

Phoenix Framework ( Elixir )

defmodule RealtimeWeb.RoomChannel do
	use Phoenix.Channel

	def join("room:" <> _private_room_id, _params, socket) do
		{:ok, socket}
	end

	def handle_in("new_msg", %{"body" => body}, socket) do
		broadcast!(socket, "new_msg", %{body: body})
		{:noreply, socket}
	end
end

chatを作りたいならこれ、というレベルでリアルタイムなものに特化したフレームワークです
フルスタックですが、apiのみという使い方もできます

backendをginやactixで作っていて、リアルタイム性を要求されるものが出てきた時、backendの補助的な立ち位置でPhoenixを入れると便利です

唯一の懸念点は言語がElixirだという点、Phoenixのために新しい言語を覚えなければならないなんて野暮な文句は言いません、Elixirという言語の特性上からPhoenixが生まれたことは理解しています
問題はデプロイです、Elixirは人気ですが、まだそこまでメジャーではありませんそのため対応している場所が少なくデプロイが大変です

個人的におすすめの構成

個人的におすすめの方法がいくつかあります

無料でどこかにデプロイしたい場合や簡単にウェブアプリケーションを作りたい場合

Frontend Backend DB Strage
Next.js Hono D1 R2

例えばSNSを作って、それを全世界に公開したい場合自宅で公開するにはいろいろな問題があるため、どこかにデプロイすることが多いのですが、その時楽にデプロイできる構成です

Next.jsはCloudflare Pages、HonoはCloudflare Worker
データベースはCloudflare D1、画像などを保存するストレージはCloudflare R2と全てCloudfalreのサービスで作れるので管理も楽です

Cloudflare D1はまだベータ版状態です、ある程度までは使えますがカラム数やレコード数の制限が多かったり巨大なデータベースを扱うには不安要素があります
(スケーラビリティ要求するならAWS使えよって話ですが)
そう言う時はPlanetScaleがおすすめです

また認証などにKey Value DBが必要な場合はCloudflare KVがあります

Cloudflare KVで大量に読み書きしたい時はちょっときついなー (料金的に)と思ってます
そういう時はsqliteとか mysqlとか (planetscaleとか) でkv_xxx的なテーブル作って最適化するのも一つの手かもしれません (僕はplanetscaleでやりましたよ、仕方なく)

Honoを独自のフレームワークに置き換えるのもおすすめです
Cloudflare Workerの場合、以下のような関数が全てのリクエストを受け取って処理するので実装の難易度は低いです

async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    Response.json({received: true})
}

独自のフレームワークを作るメリットとして、
StripeのwebhookやDiscordのwebhook、DB、Logを出力するロジックを内部に組み込めるなどのメリット?がありますが、デメリットももちろんあります
例えば、セキュリティを意識しないと詰む、パフォーマンスに気をつけないといけない、など

忘れてましたが、サービスをマネタイズしたくなったら、Stripeがおすすめです

比較的大きなチャット機能をつけたい場合

Frontend Backend
Next.js Phoenix Framework + 任意のフレームワーク

高速で大規模なChat機能が欲しい場合はPhoenix Frameworkが便利ですが
それだと少し物足りない時もあると思います、そういう時別にBackend Frameworkを使うと便利です

前述の無料でどこかにデプロイしたい場合や簡単にウェブアプリケーションを作りたい場合の構成にPhoenix Frameworkを追加するような構成でもいいかもしれません
その場合Phoenix FrameworkだけGCP (Google Cloud Platform)などにデプロイすることになります

速度を求める場合

Frontend Backend
Next.js Actix web

速度を求める場合はActixを使うことをお勧めします
え?、速度を求めてるならNext.jsなんて使うな?、その通りだよ、でもNext.js信者だから仕方ない

本当に速度が必要な場合

Backend
Actix web

ほんとに速度が必要な場合はこれしかありません (大嘘)

#[actix_web::get("/ping")]
pub async fn ping() -> impl actix_web::Responder {
	actix_web::HttpResponse::Ok()
		.content_type("text/html; charset=UTF-8")
		.body("<p>pong</p>")
}

これは普通にテキストを返してますが、適当なHTMLを返すマクロを組んだり、関数を作ったりすると動的なページが結構楽に作れます

モダンに早く作りたい場合

Frontend Backend
Next.js Gin

いつものNext.jsとGinをくっつけた感じです
goはdbもsqlやredis、neo4jなどさまざまな選択肢を取れるので、個人的には気に入っています

え?rustでもpythonでもjsでもできるって?..........

おまけ - 自宅サーバーをしたい場合

自宅サーバーは自分や家族に公開するだけの場合、デプロイ先の第一候補となり得ますが
全世界に公開する場合、リスクが高過ぎます
その時便利になるのがngrokやcloudflare tunnelのようなリバースプロキシです
リバースプロキシを使うと通信をそのプロキシが仲介してくれて簡単にローカルのapiを全世界に公開できます

僕がよく使ってるcloudflareは簡単に使えて便利です
cloudflaredを入れてこんな感じのコマンドを実行するだけで使えます

$ cloudflared tunnel run --url 127.0.0.1:3000

もちろん、独自ドメインを接続することも可能です

終わりに

ここまで長々書いてきましたが、まずは自分で色々試してみることをお勧めします

それでは、また!

18
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?