Slide 1

Slide 1 text

Riot.jsでSPAを作る 2018/12/13 fun-tech #7 @khdd-mks

Slide 2

Slide 2 text

自己紹介 ・北島久資 (@khdd-mks) ・オープンストリーム所属 アーキテクト ・ fun-tech 運営 ・ Scala が好きですが 仕事では Golang, Python, javascript とかやってます …

Slide 3

Slide 3 text

Riot.js

Slide 4

Slide 4 text

https://riot.js.org/

Slide 5

Slide 5 text

Riot.js ・ Web 上の UI コンポーネントを作るためのライブラリ ・要するに React.js や Vue.js と同じような領域のライブラリ ・ React.js や Vue.js よりも軽量でシンプルなのが特徴

Slide 6

Slide 6 text

基本 1. カスタムタグファイルを作る 2. HTML で Riot.js のスクリプトを読み込む ( コンパイラ含む ) 3. HTML 内にカスタムタグのマウント場所を用意する 4. HTML でカスタムタグファイルを読み込み、マウントする

Slide 7

Slide 7 text

基本 1. カスタムタグファイルを作る 2. HTML で Riot.js のスクリプトを読み込む ( コンパイラ含む ) 3. HTML 内にカスタムタグのマウント場所を用意する 4. HTML でカスタムタグファイルを読み込み、マウントする

Slide 8

Slide 8 text

{ opts.title }

  • { item }
Add #{ items.length + 1 } this.items = [] add(e) { e.preventDefault() var input = this.refs.input this.items.push(input.value) input.value = '' }

Slide 9

Slide 9 text

{ opts.title }

  • { item }
Add #{ items.length + 1 } this.items = [] add(e) { e.preventDefault() var input = this.refs.input this.items.push(input.value) input.value = '' } 全体をカスタムタグ名で囲む

Slide 10

Slide 10 text

{ opts.title }

  • { item }
Add #{ items.length + 1 } this.items = [] add(e) { e.preventDefault() var input = this.refs.input this.items.push(input.value) input.value = '' } HTMLを記述する 変数の埋め込みとかあるけど 何となく分かる感じ

Slide 11

Slide 11 text

{ opts.title }

  • { item }
Add #{ items.length + 1 } this.items = [] add(e) { e.preventDefault() var input = this.refs.input this.items.push(input.value) input.value = '' } CSSを記述する 普通に h3 { font-size: 14px; } みたいな感じで記述

Slide 12

Slide 12 text

{ opts.title }

  • { item }
Add #{ items.length + 1 } this.items = [] add(e) { e.preventDefault() var input = this.refs.input this.items.push(input.value) input.value = '' } 処理を記述する thisでカスタムタグ自身にアクセスできる メソッドを定義してHTML側のイベントハンドラ に指定する等が可能

Slide 13

Slide 13 text

{ opts.title }

  • { item }
Add #{ items.length + 1 } this.items = [] add(e) { e.preventDefault() var input = this.refs.input this.items.push(input.value) input.value = '' } カスタムタグに関する内容が 全て同じ場所に記述されているので 分かりやすい

Slide 14

Slide 14 text

基本 1. カスタムタグファイルを作る 2. HTML で Riot.js のスクリプトを読み込む ( コンパイラ含む ) 3. HTML 内にカスタムタグのマウント場所を用意する 4. HTML でカスタムタグファイルを読み込み、マウントする

Slide 15

Slide 15 text

Hello Riot. riot.mount('todo')

Slide 16

Slide 16 text

Hello Riot. riot.mount('todo') コンパイラ付のRiot.js クライアント側でカスタムタグをjavascriptに変換して実行す る

Slide 17

Slide 17 text

基本 1. カスタムタグファイルを作る 2. HTML で Riot.js のスクリプトを読み込む ( コンパイラ含む ) 3. HTML 内にカスタムタグのマウント場所を用意する 4. HTML でカスタムタグファイルを読み込み、マウントする

Slide 18

Slide 18 text

Hello Riot. riot.mount('todo') カスタムタグ名そのままのタグを用 意するのが簡単 マウント方法が若干変わるが divタグ等でも可能

Slide 19

Slide 19 text

基本 1. カスタムタグファイルを作る 2. HTML で Riot.js のスクリプトを読み込む ( コンパイラ含む ) 3. HTML 内にカスタムタグのマウント場所を用意する 4. HTML でカスタムタグファイルを読み込み、マウントする

Slide 20

Slide 20 text

Hello Riot. riot.mount('todo') カスタムタグファイルは普通にスクリプト タグで読み込めばいい riot.mount(‘todo’) で にtodoタグの内容が埋 め込まれる

Slide 21

Slide 21 text

webpack のようなビルドシステムを 使わなくても普通にできる すごく簡単!!

Slide 22

Slide 22 text

|゚д゚) < とか言って 実システムで webpack とか使 おうとすると逆に困るんだろ、 騙されんぞ

Slide 23

Slide 23 text

|゚д゚) < とか言って 実システムで webpack とか使 おうとすると逆に困るんだろ、 騙されんぞ 大丈夫です

Slide 24

Slide 24 text

ビルドシステムを使用する場合 ・ webpack であれば riot-tag-loader 等の loader を使えば問題ない ・仮に他のビルドシステムを使用しており、そのビルドシステム用のものが 存在しなかったとしても $ riot --esm [カスタムタグのあるディレクトリ] [出力先のディレクトリ] でESモジュールに変換できるので、変換後のファイルを使用すればいい

Slide 25

Slide 25 text

ビルドシステムを使用する場合 // エントリポイントのjavascriptファイル import riot from 'riot'; require('./tags/todo.tag'); riot.mount('todo');

Slide 26

Slide 26 text

…require?

Slide 27

Slide 27 text

ビルドシステムを使用する場合 // エントリポイントのjavascriptファイル import riot from 'riot'; require('./tags/todo.tag'); riot.mount('todo'); Riot.jsは内部的に カスタムタグ名とその内容を対応付けて管理している (のでマウント時にカスタムタグ名しか指定していない) → ESモジュールに変換しても何もexportしないのでimportで はなくrequire

Slide 28

Slide 28 text

Riot.js の基本は分かった というわけで

Slide 29

Slide 29 text

SPA ※ここからが本題です

Slide 30

Slide 30 text

SPA SPA(SinglePageApplication) ・1つのページでアプリケーション全体を構築する手法 ・利点:ページ遷移を伴わないので高速化・通信量削減が期待できる ・欠点:クライアントサイドが複雑化しやすい

Slide 31

Slide 31 text

SPA に欠かせないのが 「見た目上ページ遷移して いるように見える機能」

Slide 32

Slide 32 text

Riot.js の場合 何を使用することも可能だが 特にこだわりが無いのであれば Riot.js の補助ライブラリである

Slide 33

Slide 33 text

Riot-Route

Slide 34

Slide 34 text

Riot-Route ・Riot.jsに標準では組み込まれていない → 別のものを使ってもいい ・特にRiot.jsと相乗効果は無い → Vue.jsのRouter (「Vue.js のコアと深く深く統合されており」とか紹介されている) 等とは真逆の発想 ・Riot.jsと同じくシンプル

Slide 35

Slide 35 text

基本 1. カスタムタグファイルを作る 2. HTML で Riot.js のスクリプトを読み込む ( コンパイラ含む ) 3. HTML で Riot-Router のスクリプトを読み込む 4. HTML 内に各ページ用のカスタムタグのマウント場所を用意する 5. HTML でカスタムタグファイルを読み込むが、直接マウントしない 6. Riot-Route の設定を行い、ルーティングを開始する

Slide 36

Slide 36 text

ちなみに webpack とか使わなくても できると思うけど ここでは webpack 使う前提で

Slide 37

Slide 37 text

基本 1. カスタムタグファイルを作る 2. HTML で Riot.js のスクリプトを読み込む ( コンパイラ含む ) 3. HTML で Riot-Router のスクリプトを読み込む 4. HTML 内に各ページ用のカスタムタグのマウント場所を用意する 5. HTML でカスタムタグファイルを読み込むが、直接マウントしない 6. Riot-Route の設定を行い、ルーティングを開始する

Slide 38

Slide 38 text

import riot from 'riot'; import route from 'riot-route'; import todoRoute from './router/todo'; import todo2Route from './router/todo2'; import todo3Route from './router/todo3'; require('./tags/menu.tag'); riot.mount('menu'); route.base('/'); // ホスト名以下の部分を #hoge -> /hoge で表示するのに必要 const subRoutes = [todoRoute, todo2Route, todo3Route]; for (const subRoute of subRoutes) { subRoute('div#main'); } route('', () => { route('/todo'); }) route.start(true); 普通にnpm install --save riot-route

Slide 39

Slide 39 text

基本 1. カスタムタグファイルを作る 2. HTML で Riot.js のスクリプトを読み込む ( コンパイラ含む ) 3. HTML で Riot-Router のスクリプトを読み込む 4. HTML 内に各ページ用のカスタムタグのマウント場所を用意する 5. HTML でカスタムタグファイルを読み込むが、直接マウントしない 6. Riot-Route の設定を行い、ルーティングを開始する

Slide 40

Slide 40 text

Hello Riot.
複数のタグ(各ページ用のタグ)を マウントするため divタグで定義

Slide 41

Slide 41 text

基本 1. カスタムタグファイルを作る 2. HTML で Riot.js のスクリプトを読み込む ( コンパイラ含む ) 3. HTML で Riot-Router のスクリプトを読み込む 4. HTML 内に各ページ用のカスタムタグのマウント場所を用意する 5. HTML でカスタムタグファイルを読み込むが、直接マウントしない 6. Riot-Route の設定を行い、ルーティングを開始する

Slide 42

Slide 42 text

import riot from 'riot'; import route from 'riot-route'; import todoRoute from './router/todo'; import todo2Route from './router/todo2'; import todo3Route from './router/todo3'; require('./tags/menu.tag'); riot.mount('menu'); route.base('/'); // ホスト名以下の部分を #hoge -> /hoge で表示するのに必要 const subRoutes = [todoRoute, todo2Route, todo3Route]; for (const subRoute of subRoutes) { subRoute('div#main'); } route('', () => { route('/todo'); }) route.start(true); // ./router/todo.js import riot from 'riot'; import route from 'riot-route'; require('../tags/todo.tag'); // 直接マウントはしない export default function(mainSelector) { const todoRoute = route.create(); todoRoute('/todo', () => { riot.mount(mainSelector, 'todo'); }); return todoRoute; }

Slide 43

Slide 43 text

基本 1. カスタムタグファイルを作る 2. HTML で Riot.js のスクリプトを読み込む ( コンパイラ含む ) 3. HTML で Riot-Router のスクリプトを読み込む 4. HTML 内に各ページ用のカスタムタグのマウント場所を用意する 5. HTML でカスタムタグファイルを読み込むが、直接マウントしない 6. Riot-Route の設定を行い、ルーティングを開始する

Slide 44

Slide 44 text

import riot from 'riot'; import route from 'riot-route'; import todoRoute from './router/todo'; import todo2Route from './router/todo2'; import todo3Route from './router/todo3'; require('./tags/menu.tag'); riot.mount('menu'); route.base('/'); // ホスト名以下の部分を #hoge -> /hoge で表示するのに必要 const subRoutes = [todoRoute, todo2Route, todo3Route]; for (const subRoute of subRoutes) { subRoute('div#main'); } route('', () => { route('/todo'); }) route.start(true); // ./router/todo.js import riot from 'riot'; import route from 'riot-route'; require('../tags/todo.tag'); export default function(mainSelector) { const todoRoute = route.create(); todoRoute('/todo', () => { // URLが /todo のとき riot.mount(mainSelector, 'todo'); // div#main にtodoタグをマウント }); return todoRoute; }

Slide 45

Slide 45 text

import riot from 'riot'; import route from 'riot-route'; import todoRoute from './router/todo'; import todo2Route from './router/todo2'; import todo3Route from './router/todo3'; require('./tags/menu.tag'); riot.mount('menu'); route.base('/'); // ホスト名以下の部分を #hoge -> /hoge で表示するのに必要 const subRoutes = [todoRoute, todo2Route, todo3Route]; for (const subRoute of subRoutes) { subRoute('div#main'); } route('', () => { route('/todo'); }) route.start(true); ルーティング開始

Slide 46

Slide 46 text

あと どのエンドポイントを呼ばれても 同じ HTML を返すように サーバー側を設定したりする必要がある が割愛

Slide 47

Slide 47 text

デモ ( 時間あれば )

Slide 48

Slide 48 text

ちなみに このスライド内のコードの完全版は $ git clone https://github.com/khdd-mks/funtech.git で見れます

Slide 49

Slide 49 text

ご清聴ありがとうございました