我尝试使用 Polymer.dart + start 制作了一个网页应用程序
Dartsummit中々アツアツでしたね(ちょろっとしか見てないけど)。
DartVMの夢を捨てた代わりに現実世界で頑張る感じに期待が持てます。
Fletchとかどのレベルで使い物になるのか超楽しみっす。
さてさて、それとは特に関係なく、
せっかくのゴールデンウィークなんでDartの勉強のためにWebアプリ作ってました。
Slack提醒
ソースコード
https://github.com/takyam-git/slack_reminder
何か適当に登録するとその日時にSlack経由で通知してくれるだけのWebアプリ。
ログイン周りはSlackのOAuthをそのまま使った。
OAuthでユーザー認証するんじゃねーよ!って怒られそうな気もするけど気にしない。
さて、フロントもバックも全部Dartで書いてみたんですが、結論としては辛い。
以下内容只是一些感想或者抱怨,或者说是什么什么,总之只是一篇普通的诗歌。
使用了 Polymer 的前端
首先,使用Polymer非常困难。
制作时间大约为4天半左右,其中超过一半的时间都在为Polymer而奋斗。
我第一次接触Polymer,花了将近两天才摸索出技巧,或者说了解core-elements/paper-elements的使用方法和思想。我认为Polymer元素就像是(可能会成为)功能强大的TwitterBootstrap。
在确切的CustomElements封闭世界中,能够在小范围内实现非常强大的功能确实令人赞叹,而且通过自己制作SPA也实际感受到了它的便利之处。
不过话虽如此,提供的默认元素组的使用方法很难。
答えが分かれば別に「あーね、なるほどね」くらいな感じなんだけど、何故か画面が真っ白に!とか、何でか思った通りに表示されねぇ・・・とかとかいろいろハマりまくった。
沉迷其中的地方
大体问题可分为以下三种类型。
-
- import忘れ
-
- ドキュメント読んでなかった
- そもそもそんな事はできない事をしようとしてた
一开始忘了导入(import)的时候,感觉很烦恼,不停地问自己为什么没出来。但是过了大约10次重复之后,我的身体终于记住了要先检查一下是否已经导入(import)了。我相当容易忘记这个。
ドキュメントは超不親切で、基本的には「demoのソース読め」状態。
何となく「Polymerの雰囲気」つかめてくると「あぁ、必要最低限のこと書いてあるなぁ」とは思えるんだけど、いきなりあのドキュメントだけだと辛い。
あとは何か期待値があがっちゃって「これできそう!やってみよう!」->「んなことできねーよ」は割とあった。
たぶんやりたい事やるには core-elements/paper-elements を継承したオレが考えた最強の core-elements/paper-elements を作ればいいだけなんだけど、そこまでするのはちょっと・・・って感じ。継承元のソースコード読み解くのとか辛い。
聚合物的感受
-
- データバインディング便利だけどちゃんとドキュメント読んでから使え
-
- CSSセレクタマジ糞
-
- かゆいところに手がとどかない
-
- 意外とクロスブラウザで動いてる(たぶん)
- isomorphic的なやつ
数据绑定的讨论
数据绑定非常方便,只需适当管理模型,显示部分会自动相应地变化,真的很方便。而且绑定的指定也可以不用指定具体细节,只需像这样
{{model.hoge}}
,当模型的hoge值发生变化时,相应的
标签部分也会自动变化。
それはもうそれはもう便利なんだけど、バインディング指定してると みたいにしてるINPUTで、カチャカチャ入力すると入力した内容にmodel.hogeの値も変わったりして、それはもう何ていうか超双方向バインディングなわけなんですが、その辺の機能を全く理解せずに作り始めたので、編集フォームとか作ったら保存するまえにモデルのプロパティ書き換わってうわぁぁあみたいな。
有关CSS选择器的讨论
CSS选择器太难了,我仍然有很多地方不太理解。
(对于普通的DOM选择器,我是一个能够普通写的人)
:host(#hoge) とか ::shadow とか hoge-elements /deep/ .fugaとか、shadow-dom用のCSSセレクタがいくつかあるんですが、コレが何か期待どおりに動かない。マジで理由分からんけどスタイルが当たらなかったりする。「とりま /deep/ つけときゃ楽勝っしょwww」とか思ってた時代が俺にもありました。/deep/とか:hostとかそんなチャチなもんじゃスタイルが反映されない事がザラにある。
最終的には style=”background-color: white;” みたいにstyle属性つけるのが最高に間違いない事が分かったので、もうなんかコレでいいかなと思ってる。
痒处无法及时抓到
GoogleっぽいUIがお手軽に作れそうな雰囲気の core-elements と paper-elements ですが、色指定とかサイズ指定とかその辺はCSSで各自指定してねっって感じのがほとんどなので、Bootstrap気分でデザインの部分を全く気にせずにすむかというとそうでは無いので注意。
只剩下我之前提到的那样了,即使有时候我以為”那个东西可以做到!”,但实际上却无法实现的情况太多了,所以我认为在从梦中醒来的状态下开始编码会更加辛苦。
基本上,在DEMO页面上已经实现的功能之外的事情,最好还是不要去考虑,这对精神健康更好。
跨浏览器
何も意識せずに開発中はChromeしか見てなかったけど、みたいなPolymerと関係ないところ以外はどのブラウザでも普通に動いてる(ように見える)。
細かいところでもしかしたら挙動に違いとか出てくるのかもしれんけど、開発中に細かく全部のブラウザ気にしながら〜みたいな事はしなくてよさそう。Good。
なお、IEでは見てないので分からん。
同构的东西
如果使用Polymer进行开发,很可能在页面加载后会出现原则上的“渲染等待时间”。可能的话,能否在服务器端展开只需要的Polymer部分呢…
不过初始化的成本可能很高。
解決方法あるのかなぁ・・・
关于聚合物的未来
よう知らんし、Reactによって駆逐されるのかもしらんけど、割と使えるやつだとは思いました。
そもそもバージョン0.5だしChrome以外だとshadow-domの実装がイマイチなんで、今後はどうなっていくんだろうなーわくわく。でいいかと。
在服务器端使用的start。
上次我使用 http_server 来编写服务器端,但这次我尝试使用 start。
由于Dart的服务器端框架没有像Express或Rails一样的终极选择,所以暂时我们只提供REST格式的API就足够了,所以我们选择了启发自Sinatra的start框架。
这是一个巨大的错误。
轻一些是好事,但是我发现在超轻量级的比赛中变得困难了。
困境
-
- セッションがオンメモリ一択
-
- テンプレートレンダリングとか無いです
-
- 共通処理とか出来ると思ったら大間違いです
-
- CSRFなにそれ美味しいの
- JSONでレスポンスするといったがそれは嘘だ
会谈
在Dart的标准库dart:io中有一个名为HttpServer的类,它内部有一个SessionManager,用于管理会话。这个SessionManager非常方便地管理会话,但它只能在内存中存储会话数据。
从Dart的角度来看,“这是个抽象的东西,随便你怎么实现它”这种感觉,但实际上我们在启动时就直接使用了它。
如果不需要准备memcache或Redis之类的东西会很不错吧?但如果以为只能选择基于内存的会话,那就大错特错了。每次服务器重新启动(代码改变后重新启动对吧),都需要重新登录,这是一种非常痛苦的现实。
セッションの実体はabstractなHttpSessionクラスだからココ差し換えたり自前実装に出来たりするならまだよかったんだけど、そういったセッションハンドラ的な部分の処理の差し換えとかstartはたぶん全く考えてなくて、「いいよね!オンメモリでいいよね!」くらいのノリ。
というかたぶん「何でstartにセッションが必要なの?馬鹿なの死ぬの?」くらいのテンション。
制作一个只有超轻量级公开API的应用程序!你可以从实现中强烈地感受到这种感觉。
如果有人说“哎呀,还没到1.0版本呢”,我只能回答“是呢”。
只有这一点,我公开选择了开始。
範本
Github的README中写着有一个名为render(viewName, [Map params])的方法。
真遗憾啊!那是谎言!
在任何地方都没有这样的实现。好辛苦。
需要写出类似这样令人沮丧的代码:request.response.send(await templateFile.readAsString())。
嗯,大概是说你可以使用其他模板引擎的意思吧!
使用 Polymer,最终生成的 index.html 变成了经过处理的、构建的HTML,处理了很多不同的操作,所以没有空间插入模板!
通用处理
我想要类似于Express中间件的功能,就像在server.addMiddleware(new AuthorizationMiddleware())这样做一样!
显然没有这样的事情
server.get('/hoge').listen((req){
if(await this._isLoggedin(req)){
req.response.redirect('/login');
return;
}
//....
});
server.get('/fuga').listen((req){
if(await this._isLoggedin(req)){
req.response.redirect('/login');
return;
}
//....
});
仿佛是这样嘛!不写这样的东西的话就不行啊!虽然这样想,但是用where或者pipe之类的方式努力的话,能做出类似的事情吗?但是我不想用那样的努力方式啊。
跨站请求伪造 (CSRF)
自然而然地,開始功能沒有那樣的功能。
而且發布的庫也沒有那樣的函式庫。
結果我們不得不自己實現它。
非常辛苦…。
今回は適当にCookieベースのワンタイムトークンを実装したけどセキュリティ的に問題が有るのか無いのか良う分からん。たぶん大丈夫だと信じてやまない。ちゃんとするなら何か他の実装を参考にしたいところ。
Content-Type的陷阱
request.response.json({“hoge”: something}) みたいにするといちいちJSON.encode()かけなくても勝手にJSONでレスポンスしてくれるメソッドがある。
然而,Content-Type保持不变。确切地说应为text/plain。
为什么啊啊啊!最终,为什么啊!
request.response
..send(200)
..header('Content-Type', 'application/json; charset=utf-8')
..json(responseData);
みたいな事しなきゃいけない。あんだかなぁ・・・
startの感想
也许再也不会用了。
也许会被说”发个公关,改善一下吧!”,但这个程度还远远不够。
startはフレームワークではなく、http_serverパッケージのラッパー、くらいのテンションで使うと良いと思う。
http_serverパッケージを生で使うよりはだいぶらくなのは確か。
总结
-
- Polymerは悪くない
-
- startは良くない
-
- エコシステムが育ってない世界のマイクロフレームワークはフレームワーク足り得ない
-
- こんなの作ってるせいで昼夜逆転したし、連休の半分が消えた。
- 作りなおしたい。でももう疲れた。