Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Fresh(Deno)で 画像投稿サイトを作ってみよう! with Cloudflare x ...
Search
虎の穴ラボ株式会社
December 16, 2022
Technology
0
750
Fresh(Deno)で 画像投稿サイトを作ってみよう! with Cloudflare x Tora Viewer
Deno のWebフレームワーク Freshを使用して、
画像投稿サイトの作成
キーワード
- Deno
- Fresh
- Cloudflare
- Tora Viewer
- esm.sh
虎の穴ラボ株式会社
December 16, 2022
Tweet
Share
More Decks by 虎の穴ラボ株式会社
See All by 虎の穴ラボ株式会社
Tailwind CSSとAtomic Designで実現する効率的な Web 開発の事例
toranoana
1
520
Denoについて、同人誌記事を出しました+update
toranoana
0
170
【虎の穴ラボ Tech Talk #2】プロンプトエンジニアリング
toranoana
0
100
20241121_[TechTalk#2]虎の穴ラボでのLLMについて取り組み紹介
toranoana
0
98
社内チャットへRAG導入した話(Tech Talk #2)
toranoana
0
170
Deno Deploy で Web Cache API を 使えるようになったので試した知見
toranoana
1
550
【虎の穴ラボ Tech Talk】虎の穴ラボTech Talk説明資料
toranoana
0
390
虎の穴ラボ Tech Talk_CDKでFargate環境構築
toranoana
1
410
虎の穴ラボスキルアップ支援制度の利用例
toranoana
0
7.5k
Other Decks in Technology
See All in Technology
Obsidian応用活用術
onikun94
0
350
異業種出身エンジニアが気づいた、転向して十数年経っても変わらない自分の武器とは
macnekoayu
0
280
ZOZOマッチのアーキテクチャと技術構成
zozotech
PRO
3
1.2k
RSCの時代にReactとフレームワークの境界を探る
uhyo
9
2.8k
「魔法少女まどか☆マギカ Magia Exedra」の必殺技演出を徹底解剖! -キャラクターの魅力を最大限にファンに届けるためのこだわり-
gree_tech
PRO
0
500
5年目から始める Vue3 サイト改善 #frontendo
tacck
PRO
3
160
シークレット管理だけじゃない!HashiCorp Vault でデータ暗号化をしよう / Beyond Secret Management! Let's Encrypt Data with HashiCorp Vault
nnstt1
3
200
Automating Web Accessibility Testing with AI Agents
maminami373
0
870
エニグモ_会社紹介資料(エンジニア職種向け).pdf
enigmo_hr
0
2.2k
Kubernetes における cgroup driver のしくみ: runwasi の bugfix より
z63d
2
130
【5分でわかる】セーフィー エンジニア向け会社紹介
safie_recruit
0
30k
生成AI時代のデータ基盤設計〜ペースレイヤリングで実現する高速開発と持続性〜 / Levtech Meetup_Session_2
sansan_randd
1
120
Featured
See All Featured
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
61k
4 Signs Your Business is Dying
shpigford
184
22k
Code Review Best Practice
trishagee
70
19k
Agile that works and the tools we love
rasmusluckow
330
21k
Art, The Web, and Tiny UX
lynnandtonic
302
21k
How STYLIGHT went responsive
nonsquared
100
5.8k
Build your cross-platform service in a week with App Engine
jlugia
231
18k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
30
9.6k
Why Our Code Smells
bkeepers
PRO
339
57k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
161
15k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.8k
Transcript
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 2022/12/14 toranoana.deno
#10 虎の穴ラボ 奥谷 一陽 Fresh(Deno)で 画像投稿サイトを作ってみよう! with Cloudflare x Tora Viewer
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 自己紹介 奥谷
一陽 所属:虎の穴ラボ株式会社 担当:Fantiaなど新規事業系の開発 興味:TypeScript、Deno おすすめコンテンツ: 『暴太郎戦隊ドンブラザーズ』 『STAR WARS 小説 』 Twitter:@okutann88
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Fresh 使ってますか?
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. さっと作って、 Deno
Deployに上げるのもカンタン
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. ですが、あえてFreshを使って ちょっと込み入ったことをしてみました
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Freshで 画像投稿をやろう
- Freshをベースに開発する - 機能 - 画像のアップロード - 画像の一覧表示 - 画像の詳細表示 これらを実装する方針
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. イメージが湧きにくいと思うので、先にできたものを -
Freshをベースに開発する - 機能 - 画像のアップロード - 画像の一覧表示 - 画像の詳細表示 これらを実装する方針
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. イメージが湧きにくいと思うので、先にできたものを -
Freshをベースに開発する - 機能 - 画像のアップロード - 画像の一覧表示 - 画像の詳細表示 これらを実装する方針
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 利用技術/サービス -
Deno - Fresh - Cloudflare - Tora Viewer
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 利用技術サービス -
Deno - Fresh - Cloudflare - Tora Viewer ?
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Tora Viewer
https://www.npmjs.com/package/@toralab/tora-viewer
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Tora Viewer
- 漫画、写真集など画像一覧を閲覧できるビューアー - 虎の穴ラボ発のOSSです - Freshでも使えます。 // import_map.json { "imports": { "$fresh/": "https://deno.land/x/
[email protected]
/", "preact": "https://esm.sh/
[email protected]
", "preact/": "https://esm.sh/
[email protected]
/", "preact-render-to-string": "https://esm.sh/*
[email protected]
", "@preact/signals": "https://esm.sh/*@preact/
[email protected]
", "@preact/signals-core": "https://esm.sh/*@preact/
[email protected]
", "twind": "https://esm.sh/
[email protected]
", "twind/": "https://esm.sh/
[email protected]
/", "dotenv/": "https://deno.land/
[email protected]
/dotenv/", "huid/": "https://deno.land/x/
[email protected]
/", "tora-viewer": "https://esm.sh/v99/@toralab/
[email protected]
/es2022/tora-viewer.js", "body-scroll-lock": "https://esm.sh/body-scroll-lock", "simple-dropzone": "https://esm.sh/simple-dropzone" }
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 全体構成 deno
cli APPサーバー 画像 アップロード ・ダウンロード ページアクセス 画像ID登録 APIサーバー DB
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. その他追加導入しているモジュール -
huid:文字列のハッシュをつくるのに使用 - body-scroll-lock:ビューアーを開いたときのスクロールロック - simple-dropzone:画像ドラッグ&ドロップ操作用 body-scroll-lock と simple-dropzone は、esm.sh経由での導入
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. ソースコード //
routes/index.tsx import Uploader from "../islands/Uploader.tsx"; import Images from "../islands/Images.tsx"; export default function Home() { return ( <div class="p-4 mx-auto max-w-screen-md"> <Uploader /> <Images /> </div> ); }
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. ソースコード //
app/islands/Uploader.tsx (前半) import { JSX } from "preact"; import { useEffect, useRef } from "preact/hooks"; import { mode } from "../util/signal.ts"; import { SimpleDropzone } from "simple-dropzone"; import UploaderIcon from "../components/UpLoadIcon.tsx"; export default function Uploader(_props: JSX.HTMLAttributes) { const inputRef = useRef<HTMLInputElement>(null); const dropzoneRef = useRef<HTMLDivElement>(null); const upload = async (file: File) => { if (!inputRef.current) return; const result = await fetch("/api/get_temp_post_url"); const resultJson = await result.json(); const formData = new FormData(); formData.append("file", file); const uploadResult = await fetch(resultJson.url, { method: "POST", body: formData, }); const uploadedResultJson = await uploadResult.json(); await fetch("/api/image_updated", { method: "POST", body: JSON.stringify(uploadedResultJson), }); inputRef.current.value = ""; mode.value = 1; };
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. ソースコード //
app/islands/Uploader.tsx (後半) useEffect(() => { const dropCtrl = new SimpleDropzone(dropzoneRef.current, inputRef.current); dropCtrl.on("drop", ({ files }: { files: Map<number, File> }) => { for (const [_key, value] of files) { upload(value); } }); }, []); return ( <div class="container"> <div id="dropzone" ref={dropzoneRef}> <label class="flex justify-center w-full h-32 px-4 transition bg-white border-4 border-gray-300 border-dashed rounded-lg hover:border-gray-600"> <div class="flex flex-col items-center m-2"> <div> <UploaderIcon /> </div> <div> <span class="font-medium text-gray-600">Drop or Select</span> </div> </div> <input type="file" ref={inputRef} class="hidden" multiple /> </label> </div> </div> ); }
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. ソースコード //
app/islands/Images.tsx (tora-viewer部分抜粋) import toraViewer from "tora-viewer"; export default function Images(_props: JSX.HTMLAttributes) { const openViewer = (index: number) => { const viewer = toraViewer( originalImages.map((image: Image, index: number) => { return { url: image.url, thumbnailUrl: miniImages[index].url }; }), { pageStyle: "normal"}, ); viewer.goTo(index); const originDispose = viewer.dispose; const boundDispose = originDispose.bind(viewer); const newDispose = () => { clearAllBodyScrollLocks(); boundDispose(); }; viewer.dispose = newDispose; }; return ( <div class="flex justify-center container"> <div class="flex flex-wrap w-full justify-center container"> {!miniImages ? "" : miniImages.map((image: Image, index: number) => ( <div class="my-2 px-1 w-32 w-full" key={`key-${image.key}`} style="background-image: url(/logo.svg); background-repeat: no-repeat; background-position: center center;" > <img src={image.url} onClick={() => openViewer(index)} /> </div> ))} </div> </div> ); }
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. esm.sh 小ネタ
開発中のこと - esm.sh経由で Tora Viewer を読み込むと、どうも毎回ビルドをしているような動 きをしていて動きが遅かった - ビルド結果を直接インポートするようにすると改善 同じように、esm.shから読み込みが遅いものは同じ対応ができるかも "https://esm.sh/v99/@toralab/
[email protected]
/es2022/tora-viewer.js" "https://esm.sh/@toralab/tora-viewer"
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. まとめ -
Fresh x Cloudflare x Tora Viewer で画像投稿サイトを作ってみました。 - ユーザー認証、ローディングアニメーションなど拡張すれば、 画像投稿サイトとして十分使えそうです。 - 今回の実装は islands2つだけを使ったサイトでした。 islandsを使いこなせるといろんなことができます。
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. お知らせ 今回取り扱った
画像投稿サイトの実装の詳細な解説が入ったブログが明日公開 省略した箇所の解説も入ってますので、ご期待ください!!
Copyright (C) 2021 Toranoana Inc. All Rights Reserved. ありがとうございました