第51回html5とか勉強会行った #html5j
パフォーマンスに関するWeb標準についてとか、Web Animation APIとかは知らなかったのでちゃんと追わないと。。。
Chrome Dev Toolsの使い方とか、やらねばやらねばと思いつつも、FluxとかRact.jsとか、 ものを作るために必要な技術の勉強を優先してしまっているので、 会社で勉強会開くとか無理やりでも時間作らないとなーと思いました。
以下、メモ
ブラウザのパフォーマンスを限界まで高める、HTMLコーディングの考え方
ブラウザのパフォーマンスを限界まで高める HTMLコーディングの考え方
- 川田寛さん
- NTTコムウェア株式会社
- @kawada_hiroshi
- HTML5expoerts.jpとかに書いた記事、半年くらいでレガシー化した
- 戦略の立て方
- 改善の方法
- Google I/O 2014のPaul Lewis氏
- Initial Rnnder
- Visually Complete
- 見た目が完成している
- Speed Indexを使え
- Webページを表示される過程を評価
- 結果は同じでも、途中でどこまでレンダーされてるかは重要
- ずっと真っ白で3秒でレンダーされるよりも
- ちょっとずつレンダーされて3秒で完成するほうが
- UX的に優れている
- JS, CSS, imageの最適化
- Grunt, Gulpでやってくれる
- Critical Rendering Path
- 全体の対策
- ネットワークの最適化
- HTTP 1.1は
- 一度に6つのDLしかできないので、
- タグを書く順序でちょっと変わったりする
- SPDYはもうちょっと複雑
- Load Complete
- 大して重要じゃないけど
- Load後に、次のページのリソースを読み込んどくテクニックある
- Web標準
- Web Performance Working Group
- public-web-perf@w3.org
- ブラウザから情報とって最適化しよう
- Navigation Timing, Resource Timing, User Timing
- それらをサーバに送る → Beacon
- Page Visibility
- requestAnimationFrame
- Resource Hints
- Resource Priorities, Prefetch/Prerenderを統合
- Web Performance Working Group
ブラウザーに優しくして、アニメーションを滑らかに
- Brian Birtlesさん
- Mozilla Japan
- オーストラリアの方
- 10年くらいアニメーションの開発に関わってる
- アニメーションは多くの情報を伝えるが、
- パフォーマンスが悪いと不快になる、
- DOMツリーとレンダーツリー
- FirefoxではFrame Tree
display: none
するとレンダーツリーから外れるので速くなるとか
- スタイル決定とレイアウト(リフロウ)
- 高さとかは相対で決まったりするのでレイアウトで決まる
- FirefoxではReflowの時間見れる
- リフローを避ける
- transformを使う
- 配置と関係ないプロパティを使う
font-size
よりtransform: scale
- 適用されているスタイルの取得もリフロー発生する
- 描画のコスト=描画の領域x描画の重さ
- レイヤー
- レイヤー化はブラウザが勝手にやってる
- Firefox
aboudt:config
>layer.draw-borders = true
- どこがレイヤ化されてるか可視化できる
will-change
プロパティでレイヤ化する
- コンポジター上のアニメーション
- 全てのCSSアニメーションがコンポジターになるわけじゃない
- 現状、
transform
,opacity
- FirefoxだとFirefox OSのみ
- スクリプトのアニメーションはダメかも
- Web Animation APIだとコンポジターになる
部分最適化から全体最適化へ ― Webの情報品質管理手法
- 竹洞陽一郎さん
- 株式会社Spelldata 代表取締役社長
- html5j パフォーマンス部部長
- Spelldataのサイトは世界最速
- キャリアとして低から高レイヤまで経験してる
- SoftBank回線は勝手に画像圧縮してる
- だいたい夜の9時から12時に高負荷で、圧縮処理が重くなる
- パフォーマンスと情報品質の関係
- そもそも価値のある情報を送っているか考えろ
- 「速さ」は情報の質の1つ
- そもそもの情報の内容が悪ければ
- コミュニケーションという目的を達成するパフォーマンスは悪い
- シャノンの情報理論
- 情報源符号化定理 − 情報をどのように区切れば効率が上がるか
- 情報路符号化定理
- 通信路の容量を超えるスピードで情報が入ってくると処理できない
- 誤りを減らすためにはどう送ればよいか
- 情報エントロピー
- 情報の分類
- 知ってることを知ってる、知らないことを知ってる、知らないことを知らない
- 「知らないことを知らない」を解決するのが広告
- トピックに対して意識が高い層、低い層で「言葉」を変えないといけない
- 情報の三要素
- 整合性、完全性、アバウトネス
- コンテキストに合った情報
- 情報の価値
- 決定を可能とする情報を提供する
- on time(時間通りに), in time(時間内に)
- ダイレクトメールをもっとも活用してるのはGoogle
- 「情報は関心を消費する」ハーバート・サイモン
- 情報を適切に配置しないとだめ
- 選択肢が多いほど決断できない
- 画像のコスト
- 「1の写真は1,000言葉にまさる」ジブコーレン
- Webは見た目の画像が多い。情報じゃない
- 無線網は有限なので、画像は出来る限り使わない方がいい
- まとめ
- パフォーマンスイコール速さではない
- 情報品質も高めて、全体最適化しよう!
テンプレートエンジンNight行った #tenight
Ustream.tv: ユーザー moznion: Template Engine Night, Recorded on 2014/10/17. コンピュータ
昨日行ってきたー。テンプレートエンジンいっぱいあるなーと思った(小並感)
React.jsみたいにサーバサイドレンダリングが簡単にできるとFE/BEで同じの使えるからいいなーと思ってるけど、mizchiさんがLTで言っていたように、AltJSとの相性が悪かったり、Emmetで書けるとうれしいんだけどまだそういうの無いし(たぶん。あったら教えてほしい)、とかまだまだパーツが足りないんだろうなーと思う。けど、今のところ自分はReact.jsがすごい好き。
あと、PHPならFacebookのXHPがかなり良さそうだった。Facebookってすごいなーと思った(小並感)
結構長丁場で自分が知らない分野が多かったのでメモ適当です。。。
ほとんど適当なメモ
PHPのテンプレートエンジンの話
- @uzulla
- PHPにはいっぱいテンプレートエンジンあるけどどれ使えばいいのか?
- 安定のタグ方式
- HTML系は破綻しやすい
- デザイナーが壊す問題
- オートエスケープ重要やで
- 次の人のことを考えて選定するべき
- 他の人がメンテできなくなって困る
- PHPは高機能だが、テンプレートエンジンとしてはやたら低機能
- HTMLではないテキスト生成ならPHPはいい
- FacebookのXHPがいいかんじらしい
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン
Smartyつらいからテンプレートエンジン作ってる話
- @atsumu_t 田中集さん
- pixiv 6年目
- そもそもPHPにテンプレートエンジンは必要なのか
- smartyの辛さ
- PIXIVの理想→高速、読み書きしやすい
- 文脈で適切にエスケープ
- jingu
- https://github.com/atsumu/jingu
- 関数呼び出しがボトルネックになっていたが、それを減らしたら10倍くらい速くなった
- パーサコンビネータ→パーサジェネレータ
- インライン展開を抑制(しないとアウトプットがすごい量になる
- 変換大変や
Scala脳がテンプレートまでコンパイルしてしまう話
Template Engines in Scala // Speaker Deck
- @tototoshi
- Scalaの話
- String Interpolation
- XML Literal
- Lift Template
- Playに押されてる
- Scalate
- 多くの記法をサポート
- Easy to Use
Mixer2
- わたなべさん bizreach
- デザイナのせいにするのは甘え
テンプレートの静的解析とリファクタリング
テンプレートの静的解析とリファクタリング // Speaker Deck
Xslate開発の振り返り
- @gfx
- モバイル・アプリエンジニア
- はてな
- 2010頃に開発開始 Xslate
- Xslate
- perl最速のテンプレートエンジン
- 高速と機能が両立しないというのを否定したった
- ASTをコンパイル
- 汎用・独自言語型(SmartyとかMustacheみたいな
- 振り返り
LTタイム
Thymeleaf
JVMでテンプレートに迷っているあなたに伝えたい
I wanna tell you about "Groovy Template" // Speaker Deck
- 吉田さん @grimrose
- 横浜から来たよん
- Groovy
仮想DOM
仮想DOMテンプレーティング概念 // Speaker Deck
D言語の話
jRuby + JavaFX + fxmlでアプリ作ったら地獄だった
- せみやさん
- ローカルで動くexe作りたかった
#
- @ssig33
- PR&レビューがコスト高いよねー
Razor
- ASP.NETの一部
Slimテンプレエンジン多すぎ問題
- @katryo
- FEとBEで2つ使ってるのおかしくない?
- 管理コスト・学習コスト無駄じゃない?
- 人気あるやつ使おう
marionette
- スク水ドリブンさん
_.mixin
_.template
- ひどい実装
- stack traceで負えない
- Hogan速い
IME確定前の入力内容をngModelで取得する
ngModelはIME入力確定後に入力内容が変数に反映される。確定前の「はてn」みたいな入力途中の内容は取得できない。
確定前の内容も反映したいときに、上記のようなDirectiveを作るのもありだが、Angular1.3からngModelOptionsが導入され、updateOnでngModelの更新イベントを指定できるようになったので、
<!-- inputイベント発生時にngModelを更新する --> <input type="text" ng-model="text" ng-model-options="{ 'updateOn': 'input' }">
これで簡単にできる!、、、かと思いきや、上記でも確定後更新となってしまう。。
バグかなーと思いソースを読むとこのあたりでIME入力開始〜確定(compositionstartイベントからcompositionendイベントまで)まで更新をストップする処理が書かれている。1.2.2から導入されていて、意図はここに書いていた。
ngModelは(かなり大まかにだけど。。。)、①inputイベントで入力内容を監視、一時的に内部の変数に保持し、②updateOnで指定されているイベント発生、③ngModelで指定されている変数にその内部変数の値をコピーする、という流れになっていて、「一時的に内部の変数に保持」のところがそもそも更新されていないのでupdateOnで指定しても動作しない。
Directiveを使わない解決方法
下記のように特定のinputだけ、compositionstartイベントとcompositionendイベントをstopImmediatePropagationでストップすれば、Directiveを作らずに問題を解決できるのでおすすめや!!
<!doctype html> <body ng-app="App"> <p>{{ text }}</p> <input type="text" ng-model="text" class="disabled-composition-events"> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script> <script> angular.module('App', []) .run(function () { // compositionstart, compositionendをストップする angular .element('.disabled-composition-events') .on('compositionstart compositionend', function (e) { e.stopImmediatePropagation(); }); }); </script> </body>
Atomの.atomの.gitignore
最近、VimからAtomに乗り換えようと自宅・会社で触ってる。
で、PackageとかSnippetとか結構追加したので、そろそろ設定をgithubで管理しようと~/.atom
を覗いたのだが、どれをコミットすればよいかわからなかったので調べた。
Adding Atom to Your Dotfiles · Splitting Atoms
↑記事をどれくらい信用していいかはわからないけど、下記をコミットしろとのこと。
- config.cson
- init.coffee
- keymap.cson
- snippets.cson
- styles.less
packages/
やstorage/
は保存しなくてもいいから、.gitignore
に入れてね☆、だってよ。
なので、.gitignore
は、こんな感じにした。
# https://github.com/pirosikick/dot-atom/blob/master/.gitignore .DS_Store .node-gyp packages/ storage/ compile-cache/
config.json
にはuserId
など一見センシティブな値が格納されているが、それらはハッシュ化されているので問題無いですよーみたいなことも書いている。
Should I publish my userId? · Issue #7 · atom/exception-reporting · GitHub
Should I publish my userId? · Issue #18 · atom/metrics · GitHub
Angularのservice, factory, providerの使い分け #scripty01
SCRIPTY#1 〜フロントエンド紳士・淑女のための勉強会〜 - connpass
「Angular.jsとThree.jsを一緒に使った時の話」というタイトルでLTしました。 資料とかは後日会社のブログにて公開されるのでもう少々お待ちください。
で、自分の発表の時に「service, factory, providerをどう使い分けているか」という質問があって、なんかうまく回答できたか自信がなかったのと、ちょっと間違ったことを言ってしまったので、ここで補足したいと思います。
単純な違い
Service
.service()
に渡した関数がコンストラクタとして実行され、DIされる
angular.module('App') // exampleをserviceで定義 .service('example', function () { this.methodA = function () { console.log('call methodA!!'); } }) // exampleをInjectする .controller('Ctrl', ['example', function (example) { example.methodA(); // 'call methodA!!'とコンソールに出力される }]);
Factory
.factory()
に渡した関数を実行した返り値がDIされる
angular.module('App') // exampleをserviceで定義 .factory('example', function () { function Example() { ... } Example.prototype.methodA = function () { console.log('call methodA!!'); } // これがcontrollerや他のserviceにInjectされる return new Example() }) // exampleをInjectする .controller('Ctrl', ['example', function (example) { example.methodA(); // 'call methodA!!'とコンソールに出力される }]);
Provider
- factory, serviceと大きく違うのがconfigブロックに渡せること
- configブロックはアプリケーション開始前に実行される
- configブロックでproviderのプロパティの変更ができる
- providerの
$get
を実行した返り値がDIされる
angular.module('App') // exampleをproviderで定義 .provider('example', function () { // 外に晒す設定値 this.options.message = 'call method of example.'; // こいつの返り値がcontrollerや他のserviceにInjectされる this.$get = function () { var message = this.options.message; // これがInjectされる return { methodA: function () { console.log(message); } } } }) // configブロックで使う場合、 // サービス名 + ProviderでInjectする。 // 今回の場合、example + Provider = exampleProvider .config(['exampleProvider', function (exampleProvider) { // 設定値をいじり挙動を変えることができる exampleProvider.options.message = 'change behavior of methodA.'; }]) // exampleをInjectする .controller('Ctrl', ['example', function (example) { example.methodA(); // 'change behavior of methodA.'とコンソールに出力される }]);
使い分け
provider
- 外部に公開するライブラリなど、再利用性を高くしたい場合にproviderを使う
serviceとfactory
.service
と.factory
については「これだ!」っていう理由が無い限り、- シンプルな
.service
で定義すればいいんじゃないかと思う。
これだ!っていう理由
- Angularの外で定義しているクラスとかをそのままインスタンス化して使いたい
.factory('example', function () { // Angularの外で定義しているクラスをそのまま返す return new OutOfAngularWorldClass(); })
- valueに依存関係がほしい、または初期化関数が欲しい場合
// .valueは第2引数がそのままInjectされる .value('apiKey', 'XXXXXXX') // 依存関係がほしい&初期化したい .factory('apiKey', ['otherService', function (otherService) { // 例えば別のサービスの値や関数を使って初期化して返す return otherService.someValue + 'XXXXXXX'; }]);
注意点
provider, factory, serviceともにシングルトンになっていて、生成後は内部でキャッシュされる。 なので下記のようなfactoryは最初にInjectされたタイミングで生成された値で固定されてしまう
.factory('randomValue', function () { // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript var guid = (function() { function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } return function() { return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); }; })(); return guid(); });
Angular2.0でどうなるか
今日のQ&Aの時に「2.0ではfactory, serviceはなくなるかも」と言いましたが、あれは自分の記憶違いでした。 ごめんなさい。。。
正確には、
.config
,.constant
,.provider
が廃止され.constant
は.value
に一本化、.provider
は下記のように.config
ブロックではなく.value
で設定値の変更が可能になる
module.value('$http.config', { defaultHeaders: { // ... } });
でした。
2.0でDI周りがどうなるかは以前ブログに書いたのと、ここにコードと仕様があるのでそちらを見てください。(ブログの方はちょっとふるくなっているかもです)
まとめ
- 今はAngular.jsの本が2冊も出てるのでそれを見てからやればいいと思う。
- 公式のドキュメントが充実しているのでそちらを出来る限り見るのと、
- derectiveに関しては
ng
モジュールのソースを見て勉強するといいと思う
yeomanのgenerator-webappのオプションからcompassが外れたのを今更調べた
Option for Sass without Compass · Issue #302 · yeoman/generator-webapp · GitHub
PRがmergeされたのが3月で今更だけど、気になってたので調べた。
単純にcompassのコンパイルが遅いから、libsassのラッパーであるnode-sassを使ったgrunt-sassを使ったら?っていう流れだったっぽい。
「compass無いと困らないの?」って思ってたけど、compass/css3
くらいしか使ってなかったので、それだったらautoprefixerやpleeeaseでできるし、node-sass + pleeeaseでいいやーと思った。
var gulp = require('gulp'); var sass = require('gulp-sass'); var pleeease = require('gulp-pleeease'); gulp.task('sass', function () { gulp.src('./scss/**/*.scss') .pipe(sass()) .pipe(pleeease()) .pipe(gulp.dest('./css/')); });
Duo.jsちょっと使ってみた #duojs
Duo - A next-generation package manager for the front-end.
ちょっと良さ気だったので調べてみた。
準備
# install duo $ npm install -g duo
Github APIを使うらしく、duo用にAPI Tokenをここから生成し、
~/.netrc
に下記フォーマットで保存する。
# なんかGHEとかもできそうな感じがするけど調べてはいない machine api.github.com login <username> password <生成したGithubのapi token>
これで準備完了。
使う
var uid = require('matthewmueller/uid'); var fmt = require('yields/fmt'); var msg = fmt('Your unique ID is %s!', uid()); window.alert(msg);
上記サンプルコードをindex.js
で保存し、
$ duo index.js > bundle.js
と実行すると、matthewmueller/uid
とyeilds/fmt
をGithubから持ってきてくれてbundle.js
に出力してくれる。
cssも@import
に書いているの引っ張ってきてくれて挿入してくれる。
// https://github.com/necolas/normalize.css/ @import 'necolas/normalize.css';
component.json
かpackage.json
で管理されているリポジトリはrequire("github-account/repository-name")
だけでOKみたい。
Bowerはbower.js
でmain
を指定していても、:index.js
みたいに更にどのファイルを読み込むかを指定しないといけなかった。(BowerはcommonJS前提じゃないからだろうなーたぶん)
// https://github.com/mrdoob/three.js // bower.json有り、mainはbuild/three.min.js // three.jsはcommonJS対応されてる // ビルドはエラー無く終了するが、ブラウザでエラー var THREE = require('mrdoob/three.js@r68'); // Uncaught Error: cannot find module "mrdoob/three.js@r68" // どこにmainファイルが有るか指定してあげるとうまくいく var THREE = require('mrdoob/three.js@r68:build/three')
さらっと書いたけど、バージョンはrequire("hoge/hoge@バージョンタグ")
で指定。
ローカルのJS, HTML, JSONもrequireできる
// 同じディレクトリにあるlocal.jsもしくは、local/index.js var local = require('./local'); // HTMLはStringとして var template = require('./template.html'); // jsonはJavaScriptのオブジェクトとして var json = require('./data.json');
感想
- browserify勉強しなきゃ−と思ってたけど、Duoのほうがシンプルで良さそう
- バージョン指定、パス指定はどうなんだろうかと思った。
browserify、Webpack、componentをもうちょっと使ってみてもう1度考えたい。