学生の楽しみ、はじめての一人旅。旅の初心者に贈る、jigインターン2021夏シーズン1チームAの作品「pulchra(ぷるくら)」は、ステキな写真を直感で選べるステキな旅をサポートしてくれるアプリ。

写真を正方形に切り取り、3段階の大きさにした強弱つけたレイアウトが印象的かつ美しい! 場所とInstagramのハッシュタグからいい感じの場所を写真で表示しようという意欲作。


詳細画面にも文字は最小限。近くのホテルと、関連記事。それぞれ楽天APIや、スクレイピングを使ったAPIで取得してモーダル表示。

ESモジュールでAPIなど機能毎に分割して、チームでうまく分担して作られたバックエンドプログラム、コンパクトにAPIと接続しつつモーダル表示を含めてSPAでまとまったフロントエンド。 どちらもとってもいい出来なので、ぜひ参考にしよう!
jigintern/2021-summer-1-a on GitHub


Aチーム、あろー、サウスケイ、るーくん、かずりゅう。


鯖江で検査すると特別なコンテンツを用意してくれたニクイ演出もあり!ありがとう!!

FIND/47オープンデータで足りない分を、フリー素材サイトPixabayで補う作戦。 初めて知ったPixabayには確かにAPIがある!便利そうなので、活用可能なESモジュール&ダウンローダーとしてみました。(PixabayAPI src on GitHub)


Pixabayで見るJapanもいい感じ。


瀧/waterfallsで検索した結果も美しい。ほしいステキ素材をコマンドラインから即座にまとめてダウンロードできるおまけコマンド get/geth/getv.js 付き!


本日、jigインターン2021夏シーズン2も、メガネ堅パンと共にスタート!今週のテーマは学生x防犯・防災!

jigインターン2021夏シーズン1チームEの作品「TRIP LIST」

ユーザー登録、ログインして、旅先スポットを音楽のプレイリストのようにまとめて共有できるサービス。GitHubのようにforkしたり、他のリストとミックスできても楽しそう!

TRIP LIST src on GitHub
美しい日本の風景「FIND/47」のオープンデータから、ランダムに3点取得して表示。旅したくなる気持ちを盛り上げます。


Eチームのメンバー、まっつん、ばやし、ショウヤ、きじょー、そしてメンターのみさき!

作品の幅が広がるログイン機能。シンプルに名前とパスワードで登録、ログイン、ログアウトできる掲示板サンプルを作ってみました。

server.js bbs-with-login on GitHub
サーバーでユーザー情報を保存する user.json と、掲示板データ bbs.json を管理するAPIを下記のように作ります。(server.js on GitHub) import { Server } from "https://js.sabae.cc/Server.js"; import { JSONDB } from "https://js.sabae.cc/JSONDB.js"; const bbs = new JSONDB("bbs.json"); const user = new JSONDB("user.json"); class MyServer extends Server { api(path, req) { if (path == "/api/list") { return bbs.data; } else if (path == "/api/add") { const u = user.data.find(d => d.name == req.name && d.session == req.session) if (!u) { return "err"; } delete req.session; bbs.data.push(req); bbs.write(); return "ok"; } else if (path == "/api/regist") { const u = user.data.find(d => d.name == req.name); if (!u) { req.session = Math.random(); user.data.push(req); user.write(); return req.session; } if (u.password != req.password) { return null; // wrong password } return u.session; } } } new MyServer(8001); 登録とログインをまとめているのでシンプル!ログイン状態は Math.random() で生成したセッションキーでユーザーを判別。
JSONDBは、write呼び出しでJSONファイルとして保存する、Deno用インメモリなオブジェクトデータベース、実装18行!

あとは、これを使ったフロントエンドを作ります。登録&ログイン部分はこんな感じ btn_regist.onclick = async () => { const item = { name: inp_name.value.trim(), password: hash(inp_password.value), date: new DateTime(), }; const res = await fetchJSON("api/regist", item); if (!res) { alert("ユーザー登録またはログインに失敗しました"); return; } session = res; inp_password.value = ""; regist.style.display = "none"; logout.style.display = "block"; write.style.display = "block"; }; パスワードは生のままサーバーに送るのは気持ち悪いのでSHA256でハッシュするhash.jsを使ってます。お塩を混ぜてもいいかもね。 受け取ったsessionを変数で持って、書き込み時に送っています。

別ページに行く場合、sessionをどう持っていくかが問題になるので、シンプルに index.html のみのSPAとして作ってしまうのが高速でセキュリティ的にも強くてオススメ! 分割したくなったら、JavaScriptのモジュールで分けたり、HTMLをfetchしたりしよう!

ややこしいなと思った人、まずはログイン機能を持たない、シンプルな掲示板からチャレンジしよう!
server.js bbs on GitHub
こちらのサーバーコードはわずか18行
import { Server } from "https://js.sabae.cc/Server.js"; import { JSONDB } from "https://js.sabae.cc/JSONDB.js"; const bbs = new JSONDB("bbs.json"); class MyServer extends Server { api(path, req) { if (path == "/api/list") { return bbs.data; } else if (path == "/api/add") { bbs.data.push(req); bbs.write(); return "ok"; } } } new MyServer(8001); どんなデータをシェアすると楽しいでしょう!?

福井県独自の緊急事態宣言下、気をつけつつ楽しむ鯖江の週末。jigインターン生が作ってくれたアプリ「Nicheller」片手に、さばぷらへ。

いちごとレモンのかき氷 by 久保田酒店
さすが酒屋さん、酒瓶固定のダンボールを再利用したテイクアウト専用お盆が車での持ち帰りにとっても便利でした!+200円でSAP吉越さん考案、大人向け梵オプションも付けられます!

思わぬ出会いや発見は、おでかけの楽しみ。エモーショナルなコメントのみが見られて詳細をあえて隠すjigインターン2021夏シーズン1のDチーム作品「MOMENTPACK

チームメンバー、もち、ムラコー、昨日、reimei


MOMENTPACK」forked from 2021夏インターン 第1回 Dチーム
GoogleMapsを使った元バージョンをAPIキー不要な地理院地図+Leafletに変更し、Places APIの替わりにFIND/47から検索するようにしてみました。 フロントエンドを client.js として切り出し、deno fmt で整形しました。インデントなどが整っているとかっこよく見えますよ。 上記リンクは、GitHub Pagesなので掲示板機能は動きません。cloneしてローカル環境でお試しください!(src on GitHub)


近くのステキ風景検索 - FIND/47
FIND/47のオープンデータを使って、近くの画像検索を実装。バックエンドに処理はなく、全件をCSVでダウンロードして近くのデータのみを切り出しています。(searchNearBy.js on GitHub)


福井県でのスポットが見られます・・・が、やはりもっと細かい単位でのスポットがいいですね。オープンデータによる整備するか、手頃なAPIと接続してみましょう。


実装はこんな感じです。searchNearBy.js 利用例 in client.js。 ボタンが押されたら現在位置を取得して、近くを探して、マーカー表示。


福井高専のジュニアドクター育成塾、本日のテーマは、IoT。インターネットにつながるモノづくりに小中学生が初挑戦!
自分で作ったプログラムで、スマホに届く様子を確認。発想、膨らみますね!

10 IF BTN()=0 GOTO10 20 ?"MAMA DASH!" 30 IOT.OUT 1234

ボタンひとつでママを呼ぼう、IchigoSodaを使ったデバイス「ママダッシュボタン」のIchigoJam BASICのプログラム!


今日もメモ取りながら、熱心に学ぶ、小中学生。


初めての電子工作。光センターモジュールを作って、IchigoJamに接続!
秋月電子通商 トップページ - 電子部品・半導体 【通販・販売】
使った光センサーは、45円、10kΩの抵抗は1本あたり100本で100円、LEDは1個10円500個で1900円! レッツ宝探し ni 秋月
福井なら、マルツ福井営業所(二の宮店)がオススメです。



福井県は、越前がにロボコンPCNこどもプロコンHana道場福井高専など環境バツグン!
いろいろ、創ろう!

jigインターン第1シーズン最終日、全5チームによる最終成果発表会では1週間で作ったとは思えない良い作品揃い!成長できたと喜びの声、こちらもうれしい!

みんな勝利!

ニッチを探る旅に着目したチームBの作品「Nicheller」は、鯖江に住んでいるメンバーも知らないスポットが表示され、シンプルなのに完成度が高いUI/UXが人気でした。 ちょうど週末、鯖江のイベント「さばぷら」もあるので、さばぷらオープンデータも混ぜたスタンドアローンバージョンを作ってみました。

Nichellersrc on GitHub, forked from jigintern
これはニッチだ!これ知らないけど行きたい!と思ったらハートボタン。あるよねーと思ったらバツボタンでサクサク次に辿れます。 詳細画面からは近場の3箇所を更に表示。行ったついでにもうちょっと楽しめる!

データは、鯖江市役所のオープンデータ「さばかん情報(XML)」と、さばぷらのオープンデータ(さばぷらマップ)。 sqlite用のdbファイルをexportDB.jsを使って、JSONにしてフロントエンドのみで動くようにちょっと改造。 これはニッチだ!とハートマークを押した回数をトータルでカウントして、よりニッチなものを表示する部分の実装ができるとサーバーで稼働させたいですね。

フロントエンドは、フレームワーク「SVELTE」を使用したSPA(Single Page Application)として実装されてます。 「鯖江 ニッチ」とかで検索してヒットするようにするには、サーバーで検索エンジン用のページ生成することの検討もいいかも。


チームBの、いつき、Yune、みその、ステキな作品ありがとう&おつかれさま!

jigインターン生達のブログでもどうぞ!
⭐jigintern diary⭐

jigインターン2021夏第一シーズン2日目、今日から本格開発スタート。5チーム、バリバリと作り始めています。 技術的な質問はSlackや、Zoomで常時受け付けます。 一人で5分悩んだらチームに相談、それでも5分で解決しないなら呼んでもらう感じで進めます。 どうにもハマって抜け出せない、そんな経験がプログラミングを止めてしまう理由になっている?


jigインターンのみなさん、進捗どうですかー?

勉強会での経験を元に、フロントエンド、バックエンド、それぞれ分担しての開発。JSON(ジェイソン)でハマったという声があったので、少し解説。

JSONとは、JavaScript Object Notationの略で、JavaScriptのオブジェクトの表記方法を元に作られたテキストベースのフォーマットです。 同じテキストベースのフォーマット、XMLと違って仕様がシンプルで人間にも読みやすいのが特徴です。

CSVとの違いは階層構造の表現ができるところ。入れ子になっているデータ構造も表現可能です。逆に、入れ子がなく、ほぼ同じ項目がずらっと並ぶ配列はCSVにした方が軽くて、Excelなど表計算ソフトなどで開きやすくなります。 CSVで表現できるものはすべてJSONで表現できます。(CSV.jsを使えばJSONとの相互変換は簡単!)

ハマりやすいポイント1。JavaScript内での表記とちょっと違う。
{ name: "jig", value: 2021, } この表記方法、JavaScriptとしてはOKですが、JSONとしてはNGです。
正しくは、こちら { "name": "jig", "value": 2021 } 微妙な違いがありますね。項目名は必ずダブルクォートで囲む必要があり、最後の項目後にコンマがあってはいけません。
JSONの方が厳格なので、JSONフォーマットはJavaScriptではそのまま使えます。

JavaScriptオブジェクトとJSONの相互変換。
JavaScriptオブジェクト → JSON
console.log(JSON.stringify(json)); 下記のようにパラメータを付けると、改行とインデントを付けて、テキストファイルとして読みやすくできます(ファイルサイズは増える) await Deno.writeTextFile("test.json", JSON.stringify(json, null, 2)); JSON → JavaScriptオブジェクト
console.log(JSON.parse('{"name": "jig", "value": 2021 }')); ファイルから読み込む時はこちら console.log(JSON.parse(await Deno.readTextFile("test.json")));

ハマりやすいポイント2。文字列になることを忘れずに!
下記のように日時を表すデータをJSONにすると・・・ $ deno > JSON.stringify({ date: new Date() })) '{"date":"2021-08-17T23:17:16.916Z"}' このように自動的に何らかの文字列になります。(new Date().toString()したものとも違うので注意)
元のDateオブジェクトとして使いたい場合、new Date("2021-08-17T23:17:16.916Z") などと再度オブジェクトを生成する必要があります。

大きくても小さくても、気軽に保存したり送ったりできるJSON、楽しく使っていきましょう!

情報セキュリティ好きもいる、jigインターン2021夏。掲示板といえばどう荒らし対策をするかが気になりますよね! 電子署名(HANKO)を使った対策も、今風でおもしろいかもしれません。

HANKOsrc on GitHub
前回はEd25519のWebAssembly版で作ったHANKOを、AES-GCMで使ったオープンソースforge内のed25519.jsを使って再実装。

HANKO_ID: ea687927de2d824363b2b1cbc62d1c42ab7a0bd79d26574b816b4f60c05d1e36
メッセージ: jigインターン2021夏、スタート
電子署名: 2719b28c34e89d9c843799d12f022a4216af0b078c477505e7ff3335b4ae1f7c1b4c51c13d551ebbcc691eae38d0c7c7d4094791010a56badcf3b8653b0af006

こちら入れると検証できます。メッセージなどに少しでも改竄あれば、検証に失敗します。

使用したライブラリ、forge-es(src on GitHub)に、ECCを使った鍵共有ECDHもあれば完璧なんだけど・・・。

電子署名はネット時代のハンコ!原理は難解な数学でややこしいですが、使うのはシンプル。いろいろ遊んで学ぶ、情報セキュリティ。

2日目のjigインターンブログ、5チーム分、更新されてます!
⭐jigintern diary⭐

いよいよ開幕、jigインターン2021夏、昨年に続きコロナ仕様でオンライン。同時最多の20名!

お楽しみjigBOXの開封後、恒例のメガネ堅パン記念写真。


盛り上がったオンラインアイスブレイクの新企画、チーム毎に分かれての家のモノでつなげるしりとりチャレンジ。制限時間5分。Dチームが15コで優勝!

テーマ別ブレイクアウトルームと合わせたランチタイムの後は、勉強会!


JavaScript (Deno) でつくる超かんたんwebアプリ入門
2時間枠、Denoのインストール、JavaScriptを使ったサーバーサイドプログラム、ブラウザで動くフロントエンドプログラムの基本をざっとハンズオンで伝授。全員動きました!

つまづき勝ちな環境構築。Denoのインストールした後、「deno」コマンドで動かない時は。環境変数のPATH(パス)を設定します。
Windowsの場合、PowerShell(VSCodeのTerminal、または、ファイル名を指定して実行 powershell)で、下記コマンドの「fukuno」を自分のコンピューターでのユーザー名に変更して実行

$ENV:Path="/Users/fukuno/.deno/bin/;"+$ENV:Path

Macの場合はこちら(同じく「fukuno」を自分のユーザー名に変更)

echo "export DENO_INSTALL="/Users/fukuno/.deno"" >> ~/.zshrc echo "export PATH="\$DENO_INSTALL/bin:\$PATH"" >> ~/.zshrc

チーム開発とスクラム、ファイル管理のGitHubに関して基本を押さえ、アイデア出しからのチーム開発開始!

各チーム、アイデアが出揃ったところで、プロダクトバックログ(優先順位付きの作るものリスト)を作って、タスクに分割。具体的な技術的な質問が出始めました。

円滑なチーム開発に必須な、プログラムのファイル分割。JavaScriptではこのようにします。
例として、パラメータを2つとって足し算する関数 add を含む、ファイル add.js を作ります。 const add = (param1, param2) => { return param1 + param2; }; 関数addを他のファイルから呼び出せるようにするために export を追加します export { add }; 試しに呼び出してみる test.js を作ってみます。(ローカルなファイルは ./ で始める必要あり) import { add } from "./add.js"; console.log(add(1, 2)); 動かす時は deno run

$ deno run test.js

複数の関数をexport/importしたい場合は、export { add, sub, mul } と増やせばok。必要なものだけimportすればいいので、import { add, sub } と書けます。 import/exportを使ったJavaScriptのプログラムをESモジュールと呼びます。

一見大きな課題も、分割して、分担して、それぞれ作って組み合わせたら、自分ひとりではなし得ないモノができますよ!


E2EEメッセージングヘルパーsrc on GitHub
PureなESモジュールによるE2EE実装。ECDHを使った鍵共有から、もう一歩進めてAES-GCMによる暗号化復号化にも対応。 AES-GCM-esのプログラムから、ForgeをforkしてESモジュール化したforge-esをimportしている様子などチェックしてみましょう。

こちら、キーペア生成、相手の公開鍵を受け取った鍵共有、暗号化、復号化の実装です。
generatebutton.onclick = async () => { const keypair = ECDH.generateKeys(curve); ecdhpublickey.value = keypair.publicKey.buffer.toString("hex"); ecdhprivatekey.value = keypair.privateKey.buffer.toString("hex"); }; generatebutton2.onclick = async () => { const privateKey = ECDH.PrivateKey.fromBuffer(curve, Buffer.from(ecdhprivatekey.value, "hex")); const peerPublicKey = ECDH.PublicKey.fromBuffer(curve, Buffer.from(ecdhpublickey2.value, "hex")); const secretKey = privateKey.deriveSharedSecret(peerPublicKey); ecdhsecretkey.value = hex.fromBin(secretKey); iv = AESGCM.createIV(); }; encryptbutton.onclick = async () => { const data = new TextEncoder().encode(ecdhmessage.value); const key = hex.toBin(ecdhsecretkey.value); AESGCM.incrementIV(iv); const [encdata, tag] = AESGCM.encrypt(key, iv, data); ecdhciphertext.value = hex.fromBin(iv) + "_" + hex.fromBin(encdata) + "_" + hex.fromBin(tag); }; decryptbutton.onclick = async () => { const key = hex.toBin(ecdhsecretkey.value); const [iv, encdata, tag] = ecdhciphertext.value.split("_").map(h => hex.toBin(h)); const data = AESGCM.decrypt(key, iv, encdata, tag); if (data) { ecdhmessage.value = new TextDecoder().decode(data); } else { ecdhmessage.value = "復号失敗"; } }; 共通鍵を使った安全な暗号化と言われるAES-GCMですが、鍵と合わせて使用するIV(初期化ベクトル)の使い方を間違うと第三者が復号できてしまいます。 上記ではIVはランダムに生成し、暗号化のたびにインクリメントする形で実装しています。 (参考、本当は怖いAES-GCMの話 - ぼちぼち日記

情報セキュリティに興味が出てきたら、中高生のためのサイバーセキュリティコンテスト「CyberSakura / サイバーサクラ」への参加、応援もご検討ください!

jigインターンによるレポート「⭐jigintern diary⭐」もスタート。各チーム、交代で毎日1名ずつアップ、最終日には全員による統括ふりかえりが公開されます。 お楽しみに!

アナログとデジタルをつなぐ日本発の技術「QRコード」、ガラケーに搭載され日本で一斉風靡、当初のスマホ(特にiPhone)には搭載されず暗黒期を経て、iPhoneの標準採用と共に今度は世界中で使われるようになりました。

以前作ったQRコードのライブラリを使って、やってみたかったQRコードへのドット絵埋め込みを開発、jig.jp ロゴをいい感じに埋め込めました。

qrdots - jig.jp
クリックやタップでドットを反転することができます。いじりすぎるとQRコードとして読み込めなくなる様子をお楽しみください。

qrdots」(src on GitHub)
汎用的なツールとしても使えます。QRコード化したい文字を書いて、いじりましょう。右クリック画像保存などでご活用ください。 誤り訂正は4段階。 ソースを辿ったり、オフラインにすると分かりますが、QRコード生成は完全にクライアントで生成しており、どこにも送信していません。


さりげなく紛れ込ませたパターン


右下パターン(バランスがいまいち)


ロゴを埋め込まない最小パターン


大きめなQRコードで読みやすくしたパターン

この機種で読み取れなかった!という方いたら、ご報告いただけるとうれしいです。

オンライン勉強会開催、JavaScript (Deno)を使ったフロント&サーバーづくり解説。

webアプリをつくろう!勉強会 超かんたんフロントxサーバー編」 (src on GitHub)
unstableなserveHttpを使っていたため、バージョン違いで動かない件を修正。簡単にフロントエンドとサーバーサイドを使ったプログラミングを体験できる資料になりました。

応用例としてゲームでは欠かせないハイスコアサーバーを作ってみましょう。

import { Server } from "https://js.sabae.cc/Server.js"; const scores = []; class MyServer extends Server { api(path, req) { if (path == "/api/list") { return scores; } else if (path == "/api/add") { scores.push(req); scores.sort((a, b) => b.score - a.score); return "ok"; } } }; new MyServer(8001);

addでscoreを含むデータを受け取りソートしておき、listで返します。簡単ですね!
上記を server.js として保存したとして、次のコマンドで動きます

deno run -A --unstable --watch server.js


http://localhost:8001/api/add?{"score":100,"name":"a"}
http://localhost:8001/api/list
など、APIアクセスして試してみましょう。

あとは、fetchJSON でフロントエンドから呼び出せばOK!
保存したい場合、jsonfs などファイルで保存したり、データベースで保存しておきましょう。
何か困ったことあれば、@taisukef までご連絡ください。

チーム開発でがっつりwebアプリ開発をしたい人にオススメ「jigインターン」今年の夏も開催です!


jigインターン 2020夏インターン募集開始」
恒例jig.jpのインターン、昨年に続きオンライン開催、1週間を3セット実施します。ご都合よいスケジュールでお申し込みくださいl

あっと言う間に最終日を迎えた、jigインターン2021春!
夕方17時から、2チーム、2作品の発表会。10分でプレゼン&デモ、観覧者による質疑応答を経て、投票によって決まった優勝チームは!?

2日間、やりきった!


ゲーム好きのための双方向情報交換サイト「ゲームちゃんねる on GitHub」 ロゴデザイン by もしゃ(jigインターン2020 OB
既存のサイトでは物足りない!主な情報源の動画だけどとまとまらない。そんなとき「ゲームちゃんねる」


今回はXAMPPで構築、サーバーの掲示板システム。フロントエンドはレスポシブ対応! 好きな人が作るのが一番!ぜひリリースに向けて育てましょう!


こどもでも苦手な人でも気軽に自分の音楽ができる「べいびぃすたじお on GitHub」 ロゴデザイン by もしゃ(jigインターン2020 OB
音楽理論とかセンスとか難しいことは置いといて、楽しくステキな音楽づくり、実現します!


ブラウザで鳴るJavaScript音源 Tone.js を使って、シーケンサーと共有するシステムを実装。GitHubのようにどんどんフォークしたり、混ぜたりできると楽しそう! 作詞や、ビジュアライズ、動画との組み合わせなど、いろんな方向への発展を考えるだけでもワクワクしますね!

優勝は「べいびぃすたじお」賞品の Oculus Quest 2 を使ったVR版にも期待です!
どちらもオープンソース。参考にしたり、フォークしたり、開発に参加したり、いろいろ作って発表しましょう!


normalize-japanese-addresses-es
DenoによるJavaScript/HTML/CSSを使えると、サーバー(バックエンド)にクライアント(フロントエンド)にいろいろ応用できて便利です。 こちら、本日発表された、Geolonia社の、日本の住所表記を正規化するオープンソースライブラリ「@geolonia/normalize-japanese-addresses」を、フォークし、ブラウザやDenoで使えるESモジュール表記に変更した「normalize-japanese-addresses-es」です。

B Inc. odp(オープンデータプラットフォーム)を使った、新宿区の行政メニューオープンデータもスタート!
東京都新宿区とB Inc.、オープンデータを使った行政サービス案内用のwebサービスを公開~利用者が迷わない窓口案内を目指して~|株式会社B Inc.のプレスリリース
DX、がんがん進める力は、エンジニアにあり!

Denoはじめのいっぽ、ぜひどうぞ!
Denoでつくる掲示板webアプリ、ハンズオン

はじまりました、jigインターン2021春!勉強会&チーム開発、2日間のオンライン開催。

やる気、6名の学生 with 眼鏡堅パンjigbox開封の儀

サーバーとクライアント、2つのコンピューターを使うwebアプリの基本をJavaScriptのランタイム、Denoを使って作る勉強会。 「Denoでかんたん、フロント&バックエンド超入門 in JavaScript」をベースにハンズオン。 全員、JavaScriptエンジニアの仲間入り!

チーム開発、スクラムのプラクティスのひとつ「KPTふりかえり」を元に作成、もっと優しい、Windows/Mac向けのハンズオン教材「Denoで作るシンプルなBBS

こんな掲示板アプリが2ファイル、90行で作成できます。
(慣れている方はこちら src on GitHub

0. エディタ VSCodeセットアップ(すでに入っている人はスキップ)
Visual Studio Code の「今すぐダウンロード」からセットアップし、起動する

1. Denoセットアップ
ブラウザで Deno を開き、Windows用インストールスクリプトをコピー

iwr https://deno.land/x/install/install.ps1 -useb | iex

Mac/Linuxの人はこちら

curl -fsSL https://deno.land/x/install/install.sh | sh

VSCodeのメニュー、Terminal、New Terminal
開いたTerminalで、貼り付けて、エンター

2. Deno動作確認
Terminalで deno と書いて、エンター
1+1 と書いて、エンター、JavaScriptが動きました!
Ctrlキーを押しながらD、で deno のREPL(リプル)を終了

3. webサーバーを動かす
適当なディレクトリ(例としてbbsserver)に、bbs.js と static/index.html を作成する
VSCodeのTerminalで、下記を書く(Windows用)

mkdir bbsserver New-Item -Type File bbsserver/bbs.js mkdir bbsserver/static New-Item -Type File bbsserver/static/index.html code bbsserver

(Mac/Linux用)

mkdir bbsserver touch bbsserver/bbs.js mkdir bbsserver/static touch bbsserver/static/index.html code bbsserver

新しくVSCodeが開く。
bbs.js を次のコードに編集する

import { Server } from "https://js.sabae.cc/Server.js"; new Server(8008);

static フォルダ内 index.html を次のコードに編集する

hello deno!

VSCodeのメニュー、Terminal、New Terminal
開いた Terminal で下記を書く

deno run -A --watch --unstable bbs.js

ライブラリをダウンロードしながら起動するので少し待つ(初回だけ)
ファイアーウォールのダイアログが出たら「プライベートネットワーク」で「アクセス許可する」
http://localhost:8008/ をブラウザで開く(Ctrl+click)と「hello deno!」と出る

4. バックエンド、APIサーバーを作る
bbs.js を下記に変更する

import { Server } from "https://js.sabae.cc/Server.js"; import { jsonfs } from "https://js.sabae.cc/jsonfs.js"; const datafn = "data.json"; let data = jsonfs.read(datafn) || []; class MyServer extends Server { api(path, req) { if (path == "/api/list") { return data; } else if (path == "/api/add") { data.push(req); jsonfs.write(datafn, data); return "ok"; } } } new MyServer(8008);

Denoのwebサーバーは自動的にファイルの更新を検出して、再起動する(--watch)
http://localhost:8008/api/add?{"date":"t","name":"test","body":"body"} にアクセスすると、"ok" とでる
VSCodeで data.json が更新されることを確認する
http://localhost:8008/api/list にアクセスすると、書き込んだデータが表示される
APIサーバーできた!

5. フロントエンド、掲示板(BBS)をHTML/CSS/JavaScriptでつくる
static/index.html を下記に変更する

<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"> <title>DenoでシンプルなBBS</title> <script type=module> import { fetchJSON } from "https://js.sabae.cc/fetchJSON.js"; const enc = (s) => { s = s.replace(/&/g, "&amp;"); s = s.replace(/</g, "&lt;"); s = s.replace(/>/g, "&gt;"); s = s.replace(/\n/g, "<br>"); return s; }; window.onload = async () => { const data = await fetchJSON("api/list"); for (const d of data) { const div = document.createElement("div"); div.className = "bbsitem"; div.innerHTML = `<span class=date>${enc(d.date)}</span> by <span class=name>${enc(d.name)}</span> <div class=body>${enc(d.body)}</div>` container.appendChild(div); } btn_write.onclick = async () => { const item = { name: inp_name.value, body: inp_body.value, date: new Date().toString() }; if (await fetchJSON("api/add", item) == "ok") { window.location.reload(); } } }; </script> <style> .bbsitem { border-top: 1px solid gray; margin: 1em; } .writebox { border: 2px solid gray; padding: 1em; margin: 1em; } input, textarea { width: 80%; } </style> <link rel="stylesheet" href="https://unpkg.com/sakura.css/css/sakura.css" type="text/css"> </head> <body> <h1>DenoでシンプルなBBS</h1> <div id=container></div> <div class=writebox> 名前:<input type=text id=inp_name><br> <textarea id=inp_body></textarea><br> <button id=btn_write>書き込む</button> </div> <footer>App: CC BY <a href=https://fukuno.jig.jp/3169>@taisukef</a></footer> </body> </html>

http://localhost:8008/ にアクセスすると掲示板として使える
あとは自由に変更しよう!

6. 演習
フロントエンド、関数 enc が無いとどうなってしまうか試してみよう。
フロントエンド、スタイルシート sakura.css の行を消すとどうなるか見てみよう。
バックエンド、jsonfs とは何者か?リンクを辿って確認してみよう。
バックエンド、書き込みを全削除するAPIを作ってみよう。(ヒント、Array mdn、キーワードとmdnと一緒に検索するのがオススメ!)

7. 参考
HTMLはじめのいっぽ
CSSはじめのいっぽ
JSはじめのいっぽ

Denoは株式会社になったようです!ますます楽しみ、DenoとJavaScript!
Announcing the Deno Company | Deno Blog

Tweet
クリエイティブ・コモンズ・ライセンス
この作品は「Creative Commons — CC BY 4.0」の下に提供されています。
CC BY / @taisukef / アイコン画像 / プロフィール画像 / RSS