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
760
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
530
Denoについて、同人誌記事を出しました+update
toranoana
0
170
【虎の穴ラボ Tech Talk #2】プロンプトエンジニアリング
toranoana
0
110
20241121_[TechTalk#2]虎の穴ラボでのLLMについて取り組み紹介
toranoana
0
100
社内チャットへRAG導入した話(Tech Talk #2)
toranoana
0
170
Deno Deploy で Web Cache API を 使えるようになったので試した知見
toranoana
1
560
【虎の穴ラボ Tech Talk】虎の穴ラボTech Talk説明資料
toranoana
0
400
虎の穴ラボ Tech Talk_CDKでFargate環境構築
toranoana
1
430
虎の穴ラボスキルアップ支援制度の利用例
toranoana
0
8k
Other Decks in Technology
See All in Technology
pprof vs runtime/trace (FlightRecorder)
task4233
0
180
神回のメカニズムと再現方法/Mechanisms and Playbook for Kamikai scrumat2025
moriyuya
4
670
AWS 잘하는 개발자 되기 - AWS 시작하기: 클라우드 개념부터 IAM까지
kimjaewook
0
120
【Kaigi on Rails 事後勉強会LT】MeはどうしてGirlsに? 私とRubyを繋いだRail(s)
joyfrommasara
0
170
How to achieve interoperable digital identity across Asian countries
fujie
0
140
生成AIとM5Stack / M5 Japan Tour 2025 Autumn 東京
you
PRO
0
240
大規模サーバーレスAPIの堅牢性・信頼性設計 〜AWSのベストプラクティスから始まる現実的制約との向き合い方〜
maimyyym
2
1.8k
Geospatialの世界最前線を探る [2025年版]
dayjournal
0
140
10年の共創が示す、これからの開発者と企業の関係 ~ Crossroad
soracom
PRO
1
630
スタートアップにおけるこれからの「データ整備」
shomaekawa
2
310
AIツールでどこまでデザインを忠実に実装できるのか
oikon48
5
2.8k
Escaping_the_Kraken_-_October_2025.pdf
mdalmijn
0
150
Featured
See All Featured
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
970
Art, The Web, and Tiny UX
lynnandtonic
303
21k
Build The Right Thing And Hit Your Dates
maggiecrowley
37
2.9k
What’s in a name? Adding method to the madness
productmarketing
PRO
23
3.7k
Facilitating Awesome Meetings
lara
56
6.6k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
9
850
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.1k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
23
1.5k
Testing 201, or: Great Expectations
jmmastey
45
7.7k
How to Think Like a Performance Engineer
csswizardry
27
2k
A better future with KSS
kneath
239
18k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.1k
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. ありがとうございました