Upload
doannga
View
235
Download
3
Embed Size (px)
Citation preview
自己紹介
• 白石俊平– shumpei.shiraishi
• 株式会社オープンウェブ・テクノロジーCEO– TechFeedというサービスを
やっています
• HTML5 Experts.jp編集長• html5jファウンダー
TechFeed
• http://techfeed.io
• ITエンジニア向けキュレーションサービス– Web&モバイルアプリ
• エンジニアの興味・関心に沿った情報を、世界中から日々自動的に収集し、整理して届ける。
※ http://jp.techcrunch.com/2012/09/14/20120911mark-zuckerberg-our-biggest-mistake-with-mobile-was-betting-too-much-on-html5/
W3Cにおけるニュースリリース数(月平均)
0
5
10
15
20
25
30
2011 2012 2013 2014 2015 2016
W3Cのニュースリリース数(月平均)
W3Cのニュースリリース数(月平均)
プラットフォームとして見ると、
• Webの利用時間は減ってきている
– →Webの重要度は、以前に比べて下がっている。「モバイル・オンリー」という選択も珍しくない。
– →モバイル中心で考えると、Webはオプショナルな存在になった。
• Webには技術的な問題や制約も多い
– →しかし、技術的なトレンドとしては退潮傾向にあり、停滞も予想される
Webの利点
• Secure (安全)
• Linkable (リンク可能)
• Indexable (インデックス可能)
• Composable (再構成可能)
• Ephemeral (一時的な利用)
出典: https://html5experts.jp/agektmr/20527/
ECMAScriptとは?
• ECMAScript = JavaScriptの仕様• この仕様に基づき、各ベンダーが
JavaScriptエンジンの開発を行っている
• 仕様書はGitHub上でオープンに開発されている– https://github.com/tc39/ecma262
• 現在の正式な最新バージョンはES2016。– バージョン番号はスナップショット
的な扱いであり、それほど深い意味はない
– 本スライドでは、「次期ES」という意味のES.nextと呼称する
ES.nextを書くには
• ブラウザごとの対応状況にばらつきがあることから、トランスパイラ(ES.nextのコードをES5に変換する)を使う必要がある
// ES6const f = (a,b) => a+b;
// ES5var f = function(a,b) {return a+b;}
ES.nextが変えたWeb開発
• ES.nextの変更点は多岐にわたるが、特に以下の点でWeb開発を大きく変える
– モジュール&クラス
– 非同期処理に対する言語レベルでのサポート
• その他、「書いていて楽しい」機能も満載
ES6を試してみる:
クラス
• クラス定義
• コンストラクタ
class Greeter {greeting: string;constructor(message: string) {
this.greeting = message;}greet() {
return "Hello, " + this.greeting;}
}
ES6を試してみる:
クラス
• 継承
– 親クラスのメンバーを引き継いだ新たなクラスを作れる
...(略)...class MorningGreeter extends Greeter {
greet() {return "Good morning, " + this.greeting;
}}
モジュール
• 基本は1ファイル=1モジュール
• export…モジュール外にメンバーを公開
• import…他のモジュールを参照
export const GREETING = 'Hello';export class Greeter {}
import {GREETING, Greeter} from './greetings';
モジュールバンドラー
• モジュールバンドラーで、import/exportをJSコードに変換
import {Component} from '@angular/core'↓ (TypeScriptコンパイラ)var Component = require('@angular/core').Component;↓ (モジュールバンドラーがrequireをブラウザ上で使えるよう変換)var component_1 = __webpack_require__(1);
ES6を試してみる:
Promise• 非同期処理を、コールバックよりも記述しやすくする
– コードのネストが少なくなるため読みやすい– エラー処理を行いやすい
// 指定したミリ秒待つ関数function waitFor(millis): Promise<void> {
return new Promise((resolve, reject) => {if (millis >= 0)setTimeout(resolve, millis);
elsereject(new Error(`Invalid arg:${millis}`));
});}// 非同期関数function hello(seconds) {
waitFor(seconds * 1000).then(() => alert('Hello')).catch (e) {}
}hello(3); // 3秒後に「Hello」が表示される
ES6を試してみる:
async/await• Promiseベースの非同期なコードを、あたかも同期的なコードであるかのように記述できるようにな
る– 処理は依然として非同期なので、並列度が下がることもない– 一度使うとやめられないくらい便利。
• asyncキーワードは関数に指定する。– 指定した関数内ではawaitを使える– async関数の戻り値はPromiseとなる
• awaitキーワードは、Promiseを返す関数呼び出しの前に付与する– Promiseを返す関数の結果を戻り値として受け取れる。– エラーをtry-catchできる。
…// 非同期関数async function hello(seconds) {
try {// awaitで、Promiseの終了を待ち合わせawait waitFor(seconds * 1000);alert('Hello');
} catch (e) {}}hello(3); // 3秒後に「Hello」が表示される
ES6を試してみる:
変数• letやconstが使えます。
– let: スコープが {...} に限定された変数の定義• varは、関数スコープしか持たない
– const: 再代入不可のlet
• 正直、varの出番はもうありません– ぼくらは、「基本const、たまにlet」というルールでやってます
let a ='Hello';const b = 'World';b = 'Error'; // 再代入不可
ES6を試してみる:
文字列
• テンプレート文字列
– バッククォートで囲んだ文字列内では、"${ }" を使って式を埋め込める
let a ='Hello';const b = 'World';const c = `${a}, ${b}`;
ES6を試してみる:
配列
• spread演算子
– 配列の中身をいい感じに展開
• for...of
– 配列(正確にはイテレータ)をループ処理
let a ='Hello';const b = 'World';const c = `${a}, ${b}`;const d = [a, b];const e = [1, 2, ...d]; // [1, 2, 'Hello', 'World']e.push(...d); // [1,2,'Hello','World','Hello','World']for (let f of e)console.log(f); // 1, 2, Hello, World
ES6を試してみる:
オブジェクトリテラル• Property Shorthand
– 変数名と同名のプロパティを簡単に定義– {a: a} みたいなのを {a} で宣言できる– 個人的には異様に便利
• Computed PropertyNames– {[式]: 値} とすることで、プロパティ名に式を使用できる
• Method properties– オブジェクトのメンバーに関数を指定するのが楽になった
let a ='Hello';const b = 'World';const c = {a, b}; // {a: Hello, b: World}const d = {[a]: a}; // {Hello: Hello}const f = {method() {}
};
ES6を試してみる:
デストラクチャリング
• 配列やオブジェクトの中身を変数に展開するのがとても楽に
• オブジェクトも配列も展開可能
const fullName ={firstName: 'Shumpei', lastName: 'Shiraishi'};
// Destructuringconst {firstName, lastName} = fullName;
const array = [firstName, lastName];// Destructuringconst [first, last] = array;
ES6を試してみる:
関数1• アロー関数
– ( ) => { 関数本体 } という形式で関数定義可能– 関数本体が単一の式な場合、中括弧を省略可能
• デフォルト引数– 関数の仮引数に「= デフォルト値」と指定することで、引数
のデフォルト値を指定可能
const sum = (a = 0, b = 0) => { return a + b; };
// 上と同義// const sum = (a = 0, b = 0) => a + b;
ES6を試してみる:
関数2
• Rest Parameter– 関数の最後の仮引数を「...仮引数名」とすることで、
可変長引数を配列として扱うことが可能
• Spread Operator– 「...配列」とすることで、配列を関数の引数に展開で
きる
// 可変長引数を取る関数const join = (s, ...rest) => [s, ...rest].join(' ');
let s = ['Wor', 'ld'];// 配列を引数に展開join('Hello,', ...s);
Advanced: TypeScript
• Microsoftが開発したJavaScriptトランスパイラ。
• 大きな特徴は厳密な型付き言語であること。– ざっくりいうと「ES.next + 型 + α」
• どうせビルドが必要な昨今、型チェックもしてもらえるTypeScriptの人気は増している– Angular2は、TypeScriptで書くのがほぼ前提
コンポーネント指向がなぜ有用か
• 従来のWebページ(アプリ)は、全てがグローバルな単一空間– HTML (DOM)– CSS– JavaScript
• SPA (Single Page Application) では、常に衝突や状態破壊の危険性がある– CSSのIDやクラス名はその典型– 外部ライブラリに勝手にDOMをいじられたり– 非SPAでは、毎回ページがリフレッシュされるから問題は少ない
SPAとは
• 単一ページアプリケーション、つまり「HTMLが1枚のアプリ」
• UI変更は、JavaScriptによるDOM操作によって実現される– ページ全体の書き換えが発生しないため、UXに優れる
SPAの開発は難しい
• 実現すべき要件が数多い
– 一貫したアーキテクチャ
– より良いパフォーマンス
– ブックマーク可能に(URLルーティング)
– SEO対策
• 開発の助けとなるフレームワーク・ライブラリが必要となる
コンポーネント指向がなぜ有用か
• アプリケーションをコンポーネントに分割して管理する– 問題がコンポーネントに局所化される
– コンポーネント単位で再利用が可能になる
一覧の項目はいたるところで再利用する
なぜ今頃コンポーネント指向か?
• コンポーネント分割は、UIプログラミングの基本
• なぜ今頃、ようやく?
https://www.amazon.com/Adobe-Flash-Builder-4-Premium/dp/B003739DRS
http://win32easy.blogspot.jp/2011/03/dialog-controls-explained-part-1.html
なぜ今頃コンポーネント指向か?
• 基盤技術のアップデートが必要だった
– HTML/CSS…Web Components
– JavaScript…ECMA Script 6 Modules & Classes
• 厳密には、これらのアップデートはまだ道半ばであり、ツールの手助けを必要とする
– Web Components…相当する機能(+α)を提供するフレームワークやライブラリが存在
– ESモジュール…モジュールバンドラーが、モジュール間の関連性を考慮しつつまとめ上げる
Web Components
• コンポーネント指向を実現するための標準技術
• 以下の要素技術から成る
– HTML Templates
– Shadow DOM
– Custom Elements
– HTML Imports
HTML Templates
• template要素のこと。
• 不可視の要素
<template id="tmpl"><div>テンプレート内のコード</div>
</template>
<script>var template = document.getElementById('tmpl');template.content; // テンプレートの内容(DOM)を参照</script>
Shadow DOM
• DOMの詳細を隠蔽し、カプセル化することのできる仕組み• 例えば、video要素などは複数の要素から構築されているが、詳細
は隠蔽されている。– 開発者ツールの設定で「Show user agent Shadow DOM」を有効にす
ると詳細を見ることが出来る
• Chrome 53から、Shadow DOM v1が利用可能になった
Custom Elements
• カスタム要素を作れる仕組み• 既存の要素を継承し、document.registerElement()という
APIで登録する• Chromeがバージョン54から対応
class XFoo extends HTMLElement {connectedCallback() {this.innerHTML =
`<b>I'm in the custom element'!</b>`;}
}window.customElements.define('x-foo', XFoo);
HTML Imports
• 他のHTMLをインポートできる仕組み
• link要素のrel属性にimport、href属性にHTMLのURLを指定する
<head><link rel="import" href="bootstrap.html">
</head>
Web Componentsを使う<template id="sdtemplate"><style>p { color: orange; }
</style><p>Shadow DOM内部のコード</p>
</template><script>class XFooTemplate extends HTMLElement {connectedCallback() {var t = document.querySelector('#sdtemplate');var clone = document.importNode(t.content, true);this.attachShadow().appendChild(clone);
}}customElements.define('x-foo-from-template', XFooFromTemplate);
</script>
想像してみよう
1. (モバイル)Webサイトにアクセスする
2. 何度目かのアクセスで、「ホームスクリーンに入れとく?」と聞かれる
3. ホームスクリーンから起動すると、ネイティブアプリと同様にアドレスバーなしで表示される。
4. そのアプリ経由で、プッシュ通知が届くようになる
5. そのアプリは高速で起動し、オフラインでも動作する
このスライドの画像はこちらのページより引用:https://googledevjp.blogspot.jp/2015/04/service-worker-google-developers-summit.html
これを実現するのがプログレッシブ・ウェブアプリ
インストールバナーが出るようにするには
• manifest.jsonを書き、linkタグに指定する• バナーの出現タイミングはブラウザが自動で決定する
{"name": "Weather","short_name": "Weather","icons": [{"src": "images/icons/icon-128x128.png","sizes": "128x128","type": "image/png"
}],"start_url": "/index.html","display": "standalone"
}
<link rel="manifest" href="/manifest.json">
プッシュ通知が出るようにする
• ServiceWorkerを使用する– ServiceWorkerはバックグラウンドで動作し続ける
JavaScriptコードを定義できる仕組み
• 既存のWebサイトにそれほど影響を与えずに組み込める
self.addEventListener('push', function(event) {const data = event.data.json();const notification = {
body: data.message,data: {url: data.url}
};event.waitUntil(self.registration
.showNotification('TechFeed', notification));});
高速起動&オフライン動作
• ServiceWorkerのCache APIや、Indexed Database API(ブラウザ組み込みのデータベースAPI)を使用する。
var filesToCache = [...];self.addEventListener('install', function(e) {e.waitUntil(caches.open('TechFeed').then(function(cache) {
return cache.addAll(filesToCache);})
);});
TechFeedの実コードで学ぶWeb最新トレンド
• これまで学んだことを、実際に動作するコードを見ながら復習しましょう
– ECMAScript.next
– コンポーネント指向開発
– プログレッシブ・ウェブアプリ
プログレッシブ・ウェブアプリ
• ServiceWorker & プッシュ通知
– ServiceWorkerの登録
– プッシュ通知
navigator.serviceWorker.register('file')
self.addEventListener('push', function(event) {const data = event.data.json();const notification = {
body: data.message,data: {url: data.url}
};event.waitUntil(self.registration
.showNotification('TechFeed', notification));});
Angular2(コンポーネント指向フレームワーク)
• Angular2におけるコンポーネントは、@Component でデコレートされたクラス
• HTMLでコンポーネントのテンプレートを、CSSでスタイルを定義– これらもデコレータ内に指定する– TechFeedでは、require() を使用して別ファイルに切り出し
• CSSはカプセル化されるので、クラス名の衝突は考えなくて良い
tf-entry-listitem
というタグで使えるコンポーネント。CSSとHTMLはrequireで別出し
※現在のTechFeedはAngular2 RC.4ベースのコードです
Angular2(コンポーネント指向フレームワーク)
• コンポーネントのツリー構造でアプリケーションが構築される
• コンポーネントに値を受け渡すには属性を、コンポーネントから値を受け取るにはイベントを用いる
※現在のTechFeedはAngular2 RC.4ベースのコードです
tf-entry-listitem
を使用adプロパティに値を
セット
Digest
Realtime
EntryList EntryListItem1 *
1
*
*1
開発フロー上のポイント
• 基本的にはブラウザで開発
• 実機上の開発版アプリも、コードを修正すると自動的にリブートする
BrowserSync
ブラウザはもちろん、アプリもリロードできる(CordovaがリモートWebアプリも読み込めるのを利用)動画あります: http://goo.gl/ub6AxU