Help us understand the problem. What is going on with this article?

YarnやWebpackでアセットがうまく管理されたWebページを作ってみる その1

More than 3 years have passed since last update.

フロントエンドのアセット管理事情を知るために、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とは

Yarn
https://yarnpkg.com/en/

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じゃなくてaddnpmとは違い明確に別れている。

ここで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

早かった。
ちなみにyarnyarn 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ページを作る。

index.html
<!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>
app/index.js
/* 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というファイルを作る。

webpack.config.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...

ikuwow
いろんなことをしているWebエンジニアです
https://ikuwow.github.io
bm-sms
高齢社会に適した情報インフラを構築することで価値を創造し社会に貢献し続ける
https://www.bm-sms.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away