こんにちは、まろCです。
2月に2本のLTに登壇してきたのですが、どちらもwebpackを題材にして喋ってきました。
今回は、そのときのスライドを共有したいと思います。また、すぐに使えるインストール方法もあわせて解説したいと思います。
webpackとは
webpackとは、一言でいうと依存性を解決するツールです。
HTML上に、何本もscriptタグでJavaScriptを読み込んでいたものを、1本のJSにしてパックします。
エントリーポイントと呼ばれるJSにrequireと書いて、他のJSを読み込むことで、ビルド時にそれを探して1つのJSファイルの中に書き出してくれます。
自作のモジュールを、パスから引っ張ってきたりbowerから引っ張ってきたりできるのはもちろん、node_modulesからも使えるものは使えたりと何でもありなツール。
とは言え、できることが多いわりに日本語の情報が少なく、理解に時間がかかることもあります。
では、早速LTのスライドからご紹介したいと思います。
2/12 LIG・SHIFTBRAIN・Uniba合同LT会:別冊ライトニングトーク Vol.1
こちらでは、概要といいところをざっくり挙げました。
browserifyなどの他のツールではなくwebpackを選択したのは、複数のエントリーポイントと、JSだけでなくHTMLやCSS、画像といったところまでパックできるからです。
いいところとしては、以下のとおり。
- requireを意識することで、JSを機能ごとの部品でつくる意識になる(共通で使えるものはファイルを分けてclassな書き方でmodule.exportsしておくなど)。
- 例えば、PC/SPディレクトリに分けている開発環境の場合、共通に使いたいJSを1つの場所からrequireすれば、わざわざコピーして使わなくてもいい。
- jQueryなどグローバルに出す設定をすることで、requireせずに使用できる。
- loaderが素晴らしい。
2/18 第7回 HTML5minutes! 〜triton-js〜
こちらではwebpackのハイライト的な機能であるloaderの中から、使ってみてよかったものをランキングとして発表したので、ご紹介したいと思います。
第3位 coffee-loader
CoffeeScriptで書いたモジュールをrequireできるloader。ビルド時にJSにコンパイルしてパックしてくれます。
インストール
npm install coffee-loader --save-dev
第2位 url-loader
画像などのファイルをrequireできるloader。小さいサイズの画像なら、data-uriで保持してくれます。
Google マップを使うJSで使いました。開発用のパスでビルドしても、データとして保持しているので本番がWordPressでディレクトリが違っても、画像が404にならないところがいいですね。
markerOptions =
position: latlngTokyo
map: map
icon: require 'url?mimetype=image/png!../../../assets/images/icon-pin.png'
title: ''
marker = new google.maps.Marker markerOptions
インストール
npm install url-loader --save-dev
第1位 underscore-template-loader
HTMLで記述したunderscoreのテンプレートをrequireできるloader。ビルド時は文字列を返す関数としてパックされる。元のHTMLファイルにscriptで書いていたものを分離することで、メンテナンス性や再利用性が上がります。
インストール
npm install underscore-template-loader --save-dev
まだまだ使えるloaderはたくさんありますので、探してみてください!
参照ページ:loaders – webpack
http://webpack.github.io/docs/loaders.html
gulpと一緒に軽く使ってみる
せっかくなので、gulpなプロジェクト上で動かしてみます。必要なのはいつもの通り、node.jsとgulpです。
インストール
npm install webpack gulp-webpack --save-dev
設定ファイルとタスクファイル
gulp上で動かすので、webpackのタスクファイルとそれを動かす設定ファイルを作成します。その設定ファイルを、webpack.config.jsという名前で作成します。
bowerでインストールしたプラグインなどを使いやすいようにaliasで書くところ、loaderを設定するところがポイントとなります。
var webpack = require("webpack");
var path = require('path');
module.exports = {
output: {
filename: "module.js" //出力されるファイル名
},
resolve: {
extensions: ['', '.js', '.coffee', '.html'], //拡張子を省略できる
modulesDirectories: ['node_modules', 'bower_components'],
alias: { //bowerでインストールしたjqueryプラグインで以下にaliasを貼るとrequire('TweenMax');のようにパス無しでつかえる
bower: 'bower_components',
TweenLite: __dirname + '/bower_components/gsap/src/uncompressed/TweenLite.js',
TweenMax: __dirname + '/bower_components/gsap/src/uncompressed/TweenMax.js',
TimelineLite: __dirname + '/bower_components/gsap/src/uncompressed/TimelineLite.js',
TimelineMax: __dirname + '/bower_components/gsap/src/uncompressed/TimelineMax.js',
ScrollMagic: __dirname + '/bower_components/ScrollMagic/js/jquery.scrollmagic.js',
bxSlier: __dirname + '/bower_components/bxslider/jquery.bxSlider.min.js',
niceScroll: __dirname + '/bower_components/nicescroll/jquery.nicescroll.js',
colorbox: __dirname + '/bower_components/colorbox/jquery.colorbox.js'
}
},
module: {
loaders: [ //使用するloaderを記述ココに書く場合とrequire時にパスの前に書くものとがある
{ test: /\.coffee$/, loader: 'coffee' },
{ test: /\.html/, loader: "underscore-template-loader" }
]
},
plugins: [
new webpack.ResolverPlugin(
new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.AggressiveMergingPlugin(),
new webpack.ProvidePlugin({ //jqueryはグローバルに出す設定。これでrequireせず使えるのでjqueryプラグインもそのまま動く。
jQuery: "jquery",
$: "jquery",
jquery: "jquery"
})
]
};
タスクファイルはこんな感じです。
var gulp = require('gulp');
var conf = require('../webpack.config.js');
var webpack = require("gulp-webpack");
module.exports = function () {
gulp.task('webpack',function() {
gulp.src('main.coffee') //エントリーポイントはmain.coffeeです
.pipe(webpack(conf)) //gulp-webpackを実行します。
.pipe($.uglify()) //圧縮します
.pipe(gulp.dest('module.js'))
.pipe($.browser.reload({stream: true}));
});
}();
ちょっと調略して書いていますので、パスなどは適宜お使いの環境に合わせてください。
エントリーポイントとモジュール
webpackはエントリーポイントに使いたいモジュールをrequireすることで、ビルド時にその先のJSであったりファイルであったりの中身を見に行って、1つのJSにパックしてくれます。
エントリーポイント
main.coffee
window._ = require 'underscore'
ScrollMagicObject = require 'ScrollMagic'
window.ScrollMagic = ScrollMagicObject.Controller
window.ScrollScene = ScrollMagicObject.Scene
require './module/corporate'
require './module/index'
require './module/interview'
お気付きかと思いますが、webpack.config.jsで書く拡張子の省略をする設定をしていますので、わざわざ拡張子まで書く必要はありません。jQueryも、グローバルに出す設定をしているので、わざわざrequireする必要はありません。
windowにunderscoreをrequireして読み込みます。jQueryプラグインであるScrollMagicは一工夫必要で、一旦requireしたものをControllerとSceneで2つに分けてグローバルに出します。他のプラグインは使いたい箇所でrequireしてその場で読み込みます。
./moduleでrequireしているファイルは、各ページで使うモジュールです。
例えば、「./module/index.coffee」はどうなっているかというと・・・
---抜粋---
$window = $(window)
ajaxData = require './AjaxData'
FadeSlider = require './FadeSlider'
SETTING = require './setting'
newsData = new ajaxData SETTING.NEWS_URL+'?count=5', 'GET', 'json' //requireしたものをnewして使います
$.when newsData.getData()
.done (NewsData) ->
drawNews feedData
drawNews = (data) ->
html = require '../template/news.html' //underscoreのテンプレートをrequireしています。
template = _.template html()
$newsListInner.html template
data: data
$slider = $('#js-mainSlider')
slider = new FadeSlider
$wrapper: $slider
$target: $slider.find('li')
speed: 1
duration: 5000
ちなみにFadeSlider.coffeeはプラグインとして作成したので、commonjsの形式で記述しました。
webpackは基本的にどんな書き方でも受け付けてくれますが、commonjsの形式で書くことで、node.jsと同じ考えでJSを書けます。
今回のモジュールだけは、それにならって書いていきます。
---抜粋---
class FadeSlider
constructor: (option) ->
------
module.exports = FadeSlider
こうすると、newしたときにconstructorが呼ばれて〜というようなクラスを持つ言語のように記述できます(coffeescriptの書き方です)。
モジュールをrequireして、定数などのSETTINGファイルもrequireしています。あとはだいたいnewして、その中の機能を呼び出すだけです。
このようにビルド時にはmain.coffee内でrequireされたindex.coffeeをたどった際、index.coffee内でrequireしているものの中まで再帰的にたどって中身をパックします。
ビルド
gulpタスクを呼び出せば、任意の場所にmodule.jsが出力されます。
gulp webpack
こいつをHTML内に、
<script src="module.js"></script>
と書けばOKです。
まとめ
いかがでしたか?
このすばらしい依存性解決ツールを使って、順番を気にしてJSを圧縮して1つにするだけだった生活から抜け出しましょう!
初の登壇ということで、資料を作るのも苦労しました。5分で伝えたいことをまとめるのは難しいし、それを人前で話すのも思っていたようにはいきませんでした。
これから場数を踏んで思いを伝えることができるようになっていきたいです。
それでは。
【webpackの関連記事】
※ エンジニアがいい感じにフロントエンド開発を爆速化できる環境構築の手順
※ ECMAScript6で書こう!WebPackとES6-loaderで環境を作り、ES6を先取り体験する方法
※ WebPackを使ってJavaScriptを効率的に書くチュートリアル【入門編】
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。