Modern JavaScript Explained For Dinosaurs の読書メモ
2003年ごろ、ウェブは恐竜が支配する時代だった。
恐竜(今)「フロントエンドの開発するのにnode.jsが必要?!?!?!」
Browserifyを使えば、すべての依存をバンドルしてmoduleとしてrequireしてくれます。
2014年ごろにこの説明を読んだ私は、これが開発者としての自分にどれだけ意味のあることなのか、ほぼまったく理解できませんでした。この記事では、恐竜時代のやり方(素のhtmlとjavascript)から2017年現在までの変遷を説明したい。
古いやり方
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example</title>
<link rel="stylesheet" href="index.css">
<script src="moment.min.js"></script>
<script src="index.js"></script>
</head>
<body>
<h1>Hello from HTML!</h1>
</body>
</html>
Javascriptライブラリを使ってウェブサイトを作る時はこうやって(scriptタグで読み込んで)たよね。良い点としてはわかりやすいこと。悪い点としてはライブラリがバージョンアップするたびに新しいのを探してダウンロードしなければならないこと。
npm - JavaScript パッケージマネージャ
- 開発はモジュールを読み込んで使う。モジュール管理の手間を軽減する必要がある。
- 現時点では npm が一番メジャー
pakcage.json に必要なモジュールを列記
-
npm init
package.json 作成、初期化 -
npm install
でまとめてインストール
{
"name": "your-project-name",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
-
$ npm install moment --save
で xxxをpackage.jsonへ追記 -
node_module ディレクトリに保存される(直接ここを触ることはない)
{
"name": "modern-javascript-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"moment": "^2.19.1"
}
}
モジュールバンドラー(webpack)
- 開発時は、node.js の
var moment = require('moment');
というモジュール読み込み方法を使う。 - このままだとブラウザで動かしたときにfsにアクセスできないので require は動かない。
- すべてのjsを、ブラウザで動く形式のひとつのスクリプト(通常 bundle.js)に変換してまとめる
- 代表的なのは webpack
- webpackも npm install する
- webpack.config.js が設定ファイル
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js'
}
};
- global変数汚染が防げる
- ひとつのスクリプトを読み込んだほうがパフォーマンスがよい
コードのトランスパイリング(babel)
- トランスパイリングは、一つの言語を他の言語に変換すること
- ブラウザは実装が遅いので、新機能を古いブラウザでも動く言語に変換する
- cssでいえば、Sass, Less, Stylus
babel
$ npm install babel-core babel-preset-env babel-loader --save-dev
設定ファイル
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
}
]
}
};
タスクの自動化 task runner
- ビルドプロセス(コードミニファイ、画像最適化、テスト、etc...)
- Grunt → Gulp と来て今は npmのscriptsでやるのが主流
scripts部分の build と watch
{
"name": "modern-javascript-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --progress -p",
"watch": "webpack --progress --watch"
},
"author": "",
"license": "ISC",
"dependencies": {
"moment": "^2.19.1"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"webpack": "^3.7.1"
}
}
以下を追加したことになる
npm run build
npm run watch
live reloading用のシンプルなウェブサーバー
$ npm install webpack-dev-server --save-dev
serverコマンド追加
{
"name": "modern-javascript-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --progress -p",
"watch": "webpack --progress --watch",
"server": "webpack-dev-server --open"
},
"author": "",
"license": "ISC",
"dependencies": {
"moment": "^2.19.1"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"webpack": "^3.7.1"
}
}
$ npm run server
で、デフォルトでは localhost:8080 の index.html が開く
npm scripts talk
まとめ
- package manager
- module bundler
- transpiler
- task runner
ツールは多く、トレンドはすぐに変わるのでうんざりするだろうけど、でも見た目ほど悪い状況ではない。nodeのエコシステムとしてフロントエンドまわりの状況は落ち着いてきてる。npmをパッケージマネージャとして使い、requireやimportでモジュール読み込み。npm run scriptsでタスク実行。これはほんの1,2年前と比べてもかなりシンプルになってる。
最近のフレームワークは最初のプロセスを簡単にする仕組みがついており、初心者にも熟練者にとっても同様によい。Emberの ember-cli、 Reactの creat-react-app、 Vueの vue-cli など。すぐにコードを書き始められる。もちろん特別なカスタマイズが必要になることはしばしばあるので、このきじのひとつひとつのツールが何をするのかを理解することは重要。
モダンJavaScriptは速いペースで変化し進化し続けているので、それに関わることは、間違いなくめんどくさい。けれど、それが車輪の再発明のように見えたとしても、それらはホットリロードやリアルタイムリンティング、タイムトラベルデバッギングなどの実現を後押ししてきた。デベロッパーとしてはエキサイティングな時期だ。この記事に書かれている情報があなたの旅のロードマップになってくれることを願っているよ。