フロントエンドのアセット管理事情を知るために、YarnとWebpackでシンプルなWebページを作ってみる。最終的に俺的ベストプラクティスを作るのが目標。
作ったものは以下のリポジトリにまとめていく。
ikuwow/yarn-and-webpack
https://github.com/ikuwow/yarn-and-webpack
バージョン
- yarn 0.23.2
- Webpack 2.4.1
今回作るのはただのWebページ。
アセットの管理がテーマなので、React, Angular, jQuery, Vue.jsなどは使わないただのJavaScript。
当然SPAなんていう高度なものではない。ご了承ください。
Yarnとは
npmの上位互換を謳う、Facebook, Exponent, Google, Tildeなどが作ったjsのパッケージマネージャ。yarn.lock
ファイルが作られて厳密にバージョンを固定できたり、ダウンロードなどが並列で行われたりキャッシュが賢かったりして早いのが特徴。
Yarn: A new package manager for JavaScript | Engineering Blog | Facebook Code
https://code.facebook.com/posts/1840075619545360/yarn-a-new-package-manager-for-javascript/
確かに機能を見てると上位互換な感じ。package.jsonの記法も互換性があるので、いまnpm install
を叩いているプロジェクトにもほぼ何も変えずに導入できる。
今のところnpmと比較した際の欠点がわからない。バージョン1に到達していない点が懸念点か。
下に書いたように実際に早かったので、今回はこれでJavaScript特有のライブラリ地獄を乗り切る。
yarnを使えるようにする
Macならbrew install yarn
、Linux(debian系)ならapt-get install yarn
と、一般的な方法で導入できる。
Installation | Yarn
https://yarnpkg.com/lang/en/docs/install/#alternatives-tab
npm install yarn
もできるみたいだけど、やめましょう・・・。
$ yarn
yarn install v0.23.2
info No lockfile found.
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 📃 Building fresh packages...
success Saved lockfile.
✨ Done in 0.44s.
Emojiが積極的に使われてて黒い画面がとっても楽しげになる。
リポジトリのinit
今回使うGitHubでinitした空のリポジトリ。
$ ls
LICENSE README.md
yarn init
でインタラクティブに初期化する。
$ yarn init
yarn init v0.23.2
question name (yarn-and-webpack):
question version (1.0.0): 0.1.0
question description: my test repository
question entry point (index.js):
question repository url (git@github.com:ikuwow/yarn-and-webpack.git):
question author (Ikuo Degawa <degawa@ikuwow.com>):
question license (MIT):
success Saved package.json
✨ Done in 25.44s.
IkuosMacmini:yarn-and-webpack degawaikuo$ ls
LICENSE README.md node_modules package.json yarn.lock
node_modules、package.json、yarn.lockができた。
生成されたpackage.jsonはnpmのときと全く同じようにみえる。
yarn.lockはなんと呼ぶ記法なのかはよくわからないが、編集するものじゃないし気にしないでおく。
コミットする。
echo node_modules > .gitignore
git add .
git commit -m 'Initialize yarn'
webpackを入れてみる
$ yarn add webpack
yarn add v0.23.2
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 📃 Building fresh packages...
(略...)
success Saved lockfile.
success Saved 280 new dependencies.
✨ Done in 21.03s.
install
じゃなくてadd
。npm
とは違い明確に別れている。
ここでnpmと比較するインストール時間を比較してみる。
$ rm -rf node_modules
$ npm cache clean
$ time npm install
(...略...)
real 0m29.508s
user 0m13.474s
sys 0m4.642s
$ rm -rf node_modules
$ yarn cache clean
$ time yarn
yarn install v0.23.2
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 📃 Building fresh packages...
✨ Done in 9.82s.
real 0m10.065s
user 0m8.322s
sys 0m5.152s
早かった。
ちなみにyarn
はyarn install
(npmでいうnpm install
)と同じ。
$ git add package.json yarn.lock
$ git commit -m 'install webpack'
Webpackを使ってみよう
Getting Started
https://webpack.js.org/guides/get-started/
ここにある例をそのまま使う。
ひとまずwebpack以前のサンプルwebページを作る。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Webpack 2 demo</title>
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>
</head>
<body>
<h1>webpack 2 demo</h1>
<script src="app/index.js"></script>
</body>
</html>
/* jshint browser: true */
'use strict';
function component() {
var element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'Webpack'], ' ');
return element;
}
document.body.appendChild(component());
適当にwebサーバーを作ってページを見れるようにしておく。
php -S localhost:8383
この状態だとグローバルにlodashを置いてapp/index.js
が利用する形無で以下の問題がある。
- 依存してるものが読み込まれなかったり読み込み順番が変わると全く動かなくなる可能性がある
- 依存しているものが読み込まれているのに使われていないと、不要なコードをブラウザにダウンロードさせることになる
というわけでWebpackを使ってこれを解消する。
yarn add lodash
yarnだとnpm install --save lodash
みたいに--save
のようなオプションがいらないのがよいよい。
/* jshint browser: true */
'use strict';
+import _ from 'lodash';
+// const _ = require('lodash');
+
function component() {
var element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'Webpack'], ' ');
<head>
<meta charset="UTF-8">
<title>Webpack 2 demo</title>
- <script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>
</head>
<body>
<h1>webpack 2 demo</h1>
- <script src="app/index.js"></script>
+ <script src="dist/bundle.js"></script>
</body>
</html>
import
はes2015の機能で、ブラウザにはまだないけどWebpackやBabelなどのトランスコンパイラには実装されている。
Nodeの書き方でconst _ = require('lodash');
でも動く。
mkdir dist/
$(yarn bin)/webpack app/index.js dist/bundle.js
これで同じものが動く。
ついでに、lodashのダウンロードを待たなくてもhtmlが描画されるのでページが見えるまでの時間が短い。
コミットする。
echo dist >> .gitignore
git add .gitignore app/index.js index.html package.json yarn.lock
git commit -m 'First webpack use'
Configファイルに書く
毎回webpack
にオプションをたくさんつけるのは面倒なので、ファイルにまとめる。
プロジェクトのルートディレクトリでwebpack.config.js
またはwebpackfile.js
というファイルを作る。
'use strict';
const path = require('path');
module.exports = {
entry: './app/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
第一引数を第二引数をファイルに移しただけ。
これで以下のように叩くと全く同じ動きをする。
$(yarn bin)/webpack
その1のまとめ
yarnはnpmとコマンドがやや違うだけで基本的にnpmと同じように使えるので、導入ハードルはほぼ感じなかった。しかも速い。
Webpackはいままでちょくちょく使っていたが分かっていない部分も多いのでその2以降にしっかりやる。
次回はファイルやディレクトリを増やしたり、sass, html,画像などもwebpackで管理できるようにする予定。
その2: comming soon...