[追記] Node.js 14 から警告なしに拡張子 .mjs は export / import できるようになります。
背景
Ecma 262 + JScript でユニットテストを書いて から 10 年以上が経ち、途中 Rails 3 + CoffeeScript いいじゃないか、Underscore.js いいじゃないか期を経て現在は ES2015 が標準で当たり前ですよね、な時代になった。
ES2015 自体はなんでもかんでも式になってくれないと CoffeeScript の代わりにはならないよ、return 書くの面倒くさいよという気持ち以外はまぁそんなもんかなという程度の理解だったんだけど、Mithril を試した時 のように無理やり Browserfiy で CoffeeScript を挟んだりせずにそろそろ 素直に ES2015 をフルに使って書きつつ、それ以外に本当に必要なライブラリのセットをまとめる作業を行った方が UI 側の実装に弾みがつくかなと思って触ってみたらどうも ES2015 がフル実装されている処理系はないっぽいので、結局ややこしさが残っているのだなということが分かってきた。
ということでそろそろ少なくとも ES2015 でよく分からんなと思っていた部分を整理していこうと思う。これ以上時間が経つと情報が見つからなくなるかもしんないし。
これを書いている時点での自分の理解をまとめると Node.js と Browserify を適当に使っている範囲のもので、Ecma 262 3rd 以降に加わったものはちゃんと追えておらず、以下のような状態。
- Webフロントエンドのツールチェインはブラウザなしに動く Node.js であれこれ処理するのが基本になった
- 伝統的な JS にはライブラリを読み込む機能はなく、ホスト側でまかなっていた(<script>)が、XHR + eval などで動的に読み込むこともできる
- Node.js 登場以降 module と require の概念が持ち込まれて function 以外のスコープが増えた
- Browserify は Node.js のこのメリットをブラウザの世界に持ち込んだもの
- ついでに Node.js 上でしか動かない機能以外は組み込めるようになった
- Babel は先行案の JS の文法を使ったコードを変換して Ecma 5 相当にしてくれる
ここから、もうちょっとつっこんだ部分の理解を深めたいと思う。
ちなみに、以降の確認は主に以下の環境で行っている。
- Node.js v6.9.5
- Yarn 0.19.1
- Babel 6.23.1
import / export
import とかよく見るじゃないですか、React とか Babel 前提になったコードで。でもなんとなく見よう見まねの域を出なくて気持ち悪いと思っていたのでした。
- Learn ES2015 · Babel
- import - JavaScript | MDN
- export - JavaScript | MDN
- ブラウザには実装されていないからトランスパイラ使えと
- ES Modules と Node.js について - from scratch
- 議論の最中ということで、こういうのは結論待ってもあんまり意味なさげ。
2017-02 時点で結論から言うとまず Babel を使えと。そういう状況らしい。
ES Modules(ES2015) import -> Babel -> CommonJS require
結局 require に書き換えて読み込むことになる。
安定して動かせる import は今のところこの手の変換以外ないみたい。
単純な import
import './export' -> require('./export')
無名で(defaultで)定義して import 側で名前の割り当て
export default で名前のない function や class を export できるので、import 側で名前を割り当てて利用する。
※ 以降、<name> となっている部分は <> 含めて実際の名前に読み替えplz
import.js
import <name> from './export'
<name>()
export.js
export default function() {
...
}
を babel で変換すると
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = function () {
...
};
てな感じで exports.default に function が入る。class の場合はもうちょっと複雑になるけど
export default class {
method {
...
}
}
が
var _class = function() {
...
_createClass(_class, [{
key: <method>,
value: function <method>() {
...
}
}]);
return _class;
}();
exports.default = _class;
てな感じで、やはり exports.default に class が入る。
名前付きで定義したものを export / import
{ } で囲む。
※ as は割愛
import.js
import { <name> } from './export'
<name>()
export.js
function <name>() {
...
}
export { <name> }
class もまったく同様。
'use strict'
Ecmascript 5 で追加された機能で Babel で変換したコードには現時点では自動で追加される。
- 意図せぬグローバル汚染を防止
- 代入の失敗は例外に
- 削除できないプロパティの削除をエラーに
- オブジェクトリテラルのプロパティ重複もエラーに
- 関数の引き数名の重複もエラーに
- 8進数表記の禁止
基本的には予期せぬエラーが起きにくくなる改善なんだけど、一つ問題があって strict モードでの動作の指定をグローバルに行おうとした場合、strict モードでの動作を意図したコードと strict モードでの動作を意図していないコードを混ぜると、先に決まったモードで動くのでお互いに意図せぬ動作をする場合があること。
したがってどんなコードを混ぜ込んでいるか分からない、伝統的な JS のコピペベースのライブラリの利用を行った場合、この指定は function 単位で行うことが望ましい。でないとどこで何が起きるかよく分からなくなってしまう。
いや、面倒だよねそれ。
というところまで分かったところで Babel に戻ると、Babel は es2015 の preset で Ecmascript 5 に変換する際に自動的に 'use strict' を必ずファイルの先頭に置くので、自動的にすべて strict モードで動作するように変換される。
ということで Ecmascript 5 を前提にするなら Babel 使えという話に帰ってくるのであった。
class / メソッド定義
JavaScript MDN</a> - class定義は事前に済んでいないと呼び出せない
- なんか PHP 3 までの制限のような?
- constructor, extends, super なんか PHP というか Java っぽい?
- name: function() {} が 単に name() {} で書けるようになった
- オブジェクトリテラルでもclass式でも同様
- やった! function 地獄からの解放?
- でも割とブラウザの対応状況はよくない(まぁ Babel 通すならどっちでもいいけど)
メソッドとグローバルな関数の定義はベツモノで function を書かずに済むようになったわけではないうえに => (arrow function)もまたベツモノ。
いったんここまで。
前回をその0とします。正直、盛り込みすぎました。
railsコマンド
- rails コマンドはものすごくよく使うので alias r=rails するらしい
- rails console が便利
特に Model の動作を確認するのに rails console が便利。要するに rails 環境が丸ごと載った irb だと思う。上の alias と合わせて
r c
で呼べるようにしておく。またこの console 上で
reload!
すると model などの変更に追随できる。
ただし、文字通り reload するだけなので新たに追加されたものは反映されない。
- rails server でサーバを起こす
凝った使い方はしたことがない。普通に port 3000 で WEBRick を使ってる。
-u --debugger
オプションはのちのち便利。
development のうちは基本的にファイルの変更には自動で追随してくれるんだけど、
config/locals/ 以下のファイルが増減したときには再起動しないとダメ
なのはちょっと忘れがち。他にもそういうのあるかもしれないけど、ちょっとよく分かってない。とりあえず「あれー反映されてないな?」と思ったら再起動オススメ。
- rails generate はやたら使う
だから
r g
で呼び出す。model, helper, migration, 他のツールなどかなりのものがここから作業を開始する。
- rails dbconsole は適切な設定で sqlite コマンドや psql コマンドなどを叩いてくれる
Model からではなく生の DB の様子を確認するのに使う。こうしたツールに不慣れな人はあまり嬉しい機能じゃないかな。SQLite くらいなら GUI のツールが充実してるので development の間はそれで押すのも手かも。
最近自分は Rinari の rinari-sql を経由して使ってることが多いかも。
rvm で複数の ruby を入れている場合
あんまりこんなことやらないと思うけど、複数の ruby を入れて検証を行う場合、
- rvm use で ruby の切り替え
- bundle install
- source ~/.zshrc ( bash でもなんでも )
が必要。最後の source をやらないと alias の r から呼び出される rails コマンドがそれまで使っていた ruby で動くのでややこしくなる。
rvm wrapper を使えばもしかしたら解決する問題かもしれないけど、やったことないので分からない。
rakeタスク
とりあえず rake -T db の部分。
- create, drop, migrate, rollback は(端折って)いいよね
- db:fixtures:load で fixture ファイルを読み込める
基本的に fixtures は test 環境で利用するものでパスも
test/fixtures/
以下になっている(デフォルト)。これを development 環境で読み込むのに
rake db:fixtures:load
が使える。ただし、対象のテーブルにそれまで入っていたデータはクリアされる。
- db:setup が便利
基本は db:migrate でいいんだけど、何回もやり直してるうちに一度きれいにして初期データを入れ直したいと思うことがある。そんなとき setup が便利。
datebase.rake の中で
task :setup => [ 'db:create', 'db:schema:load', 'db:seed' ]
と定義されているので、rake db:setup だけで、create して
db/schema.rb
db/seeds.rb
を実行してくれる。
てなことを2ヶ月前に Twitter で教えてもらっていた。
Twitter / @ゆーけー/赤松 祐希: @wtnabe rake db:setup でdb: …
db/seeds.rb
seeds.rb は Model 作って自分で save しろということらしい。少なくとも rails new したばかりの db/seeds.rb には何も書かれていない。そこでこんなものを作ってみた。
結構便利。
cf.
Twitter / @Dai Akatsuka: @wtnabe Model.create(:id = …
fixtureのパスはデフォルトの方に合わせた方がいいかも?
- 基本は test/fixtures/ 以下
- rspec の基本は spec/fixtures/ 以下
- rspec の設定は spec_helper.rb 内で変更可能
Rails 全体の設定をする場所はたぶんなくて、RAILS_ENV と FIXTURES_PATH などの環境変数経由で設定する感じっぽい。Rails の環境設定の外で指定するのはちょっと再現性に難があるので、rspec の方で
config.fixture_path = "#{::Rails.root}/test/fixtures"
して設定を変えておいた方が楽な気がする。例えば前述の
rake db:fixtures:load
は
test/fixtures/
以下を見にいく。
ところで fixture は Model の制約を無視して DB に直接データを INSERT INTO してるみたい。ということは Model の制約を無視した(DBMS の制約にだけ従う)データを突っ込むことができる。ちょっと注意が必要かも。
一ヶ月ほど前に変えた新しいケータイである re なんだけど、唐突にアラームが鳴らなくなった。
以前のケータイはバイブ機能が効かなくなって変えたんだけど、なんと、それよりも悪いアラームそのものが効かないという状態。
[これはひどい]
2ch で見てみると同じ症状が出ている人はいるが、それほど有名なものではないのか書き方が悪いのか割と冷たくあしらわれている感じ。そこで「オレもなったよ」と書き込もうと思ったら何が悪いのか書き込めないでやんの。プロバイダがなんか制限してるの?知らんけど。
とりあえず電池パック抜きリセットで回復した1けど、はっきり言ってこれはかなりタチが悪いよ。アラームがダメになるのはひどいって。
これは翌20日に確認 ↩
ふとしたきっかけで OKI MINI KEYBOARD Pro に TrackPoint のキャップをつけてみた。<strong>こっちの方が動きの感じがいい。</strong>ドライバのチューンが足りない部分(例えばピクセル単位で動かすとか)は相変わらずだけど、こっちの方がずいぶん感触がいいので、ちょっと配色のバランスが悪いけど TrackPoint キャップで行くことにする。いやー久しぶりだね。(ThinkPad の方で毎日使ってるんだけど。)
結局今回もまた情報処理技術者試験は見送ってしまった。一応去年だったか一昨年に新しい試験を開拓したりもしたのだが、自分に合う試験がないっていうか、自分の仕事の評価を正当に与える試験てないんだよな。 どうにかならんのかい。
今度は代わりに何を削るんですか? :-)
若いやつの方が体調を崩しやすいと言う。まぁ確かにそうかなと思う。その理由の大きなものは過信と食生活だと言う。まぁそれも妥当な推論だろう。でもそれだけじゃーないよね。外回りの機会も若いやつの方が多いからどこでどんな雑菌もらってくるか分からないし、初めて経験することも若いやつの方が多いから緊張から気疲れすることだって多いはずだ。それに、若いときの方が実は体調は不安定なんじゃないか? そりゃ社会人なら成長期のような不安定さはないかもしれないが、若いやつの方が権限なくストレスにさらされてるし、時間の自由も効かない。(拘束時間の長さではなく時間の設定権限があるかないかってこと。)昔の社会はシンプルだったからガムシャラに頑張ることで乗り切れたかもしれないが、今の社会は権力のない人間はひどいストレスにさらされているのだ。上に立つ人間には見えにくいかもしれんがね。
電話というのはやはり通信手段として不適切だな。少なくとも手を離せないというか思考を中断させることが著しく生産性を落とす現場にははっきり不適切と言える。そういう仕事してる人って、一般的には少ないのかね。ネット上には多そうだが。まぁ生産しない人には関係ないことかもしれん。メールと irc 中心の世の中はそりゃこないだろうが、テレビ電話なんて拘束性の強いもん作ってる場合じゃねーだろ、と思う。まー電話屋の仕事ではないんだろうけど、人間のコミュニケーションを、もっと人間の活動を豊かにする(断じて情報量を増やすという意味ではない)ものにする道具と考え方の浸透が必要だ。電話の方が速いことが多いのは事実だろうが、短いとは言えその他の作業をすべてストップさせてしまう電話が増えれば、トータルでは損することだって十分に考えられるんだよな。そして「そんなこと言ったってしょうがないじゃん」という現状肯定を越えられないと、身を削る以外に生産性を向上させられなくなるわけだ。そりゃ「頑張ってる」やつかもしれんが、バカだよな。まぁバカしか生き残れない現場もあるんだろうけどさ :-P