今までは、JSの依存性の解決にはbrowserifyを使っていたんですけど、webpackの場合は複数ファイルの出力に対応していたり、js以外を扱うこともできるとのことで触ってみることにしました。
まずは、タイトルにある通りのことをやってみます。
やりたいこと
以下のディレクトリ構成があるとします
┌ public
│ └ js
├ assets
│ └ coffee
├ gulpfile.coffee
├ webpack.config.coffee
└ package.json
assets/coffee 配下にcoffeescriptファイルが配置してあって、それをコンパイルして1ファイルに纏めてpublic/js配下に出力します。
インストールしておくもの
package.jsonは以下のとおり(※name等は省略)
{
"devDependencies": {
"coffee-loader": "^0.7.2",
"coffee-script": "^1.10.0",
"gulp": "^3.9.1",
"gulp-load-plugins": "^1.2.2",
"gulp-webpack": "^1.5.0",
"gulp-webserver": "^0.9.1",
"path": "^0.12.7"
}
}
設定ファイル
まず、webpackの設定をwebpack.config.coffee にかきます。
webpack = require('gulp-webpack').webpack
path = require 'path'
current = process.cwd()
module.exports = {
output:
filename: 'app.js' # 出力するファイル名
resolve: {
extensions: ['', '.js', '.coffee'] # requireする際に、拡張子を省略するための設定
root: path.join(current, './assets/coffee') # require時にファイルを検索する際のrootパス
}
module:
loaders: [
{test: /\.coffee$/, loader: 'coffee-loader'} # coffeescriptをコンパイルするための設定
]
}
次にgulpfile.coffee
gulp = require 'gulp'
$ = do require 'gulp-load-plugins'
gulp.task 'build', ->
gulp.src './assets/coffee/**/*.coffee' # coffeescriptの格納場所
.pipe $.webpack require './webpack.config.coffee' # webpack.config.coffeeの指定
.pipe gulp.dest './public/js' # 出力ディレクトリ
動かしてみる
サンプル用に以下のファイルを用意します。
class Common
@echo: (str) ->
console.log str
module.exports = Common
window.sample = window.sample || {}
Common = require 'common'
class Hoge
constructor: () ->
init: () ->
Common.echo 'hoge'
window.sample.Hoge = Hoge
で以下をコマンドを実行
$ gulp build
すると、「public/js」配下にapp.jsが出力されます。
で、出力されたapp.jsを適当なhtmlに読み込ませると、インラインスクリプトからHogeクラスを使用できます。
<script src="public/js/app.js"></script>
<script>
new sample.Hoge().init() // コンソールに"hoge"と表示される
</script>
ファイルをそれぞれコンパイルする場合
上記のサンプルでは、複数CoffeeScriptを1つのJSファイルにしていますが、個別にしたい場合は以下のように設定ファイルを記入
webpack = require('gulp-webpack').webpack
path = require 'path'
current = process.cwd()
module.exports = {
# entryポイントを設定(複数設定可)
entry:
sample: './assets/coffee/sample.coffee'
'common/sample2': './assets/coffee/common/sample2.coffee'
# sample.coffee ⇒ sample.js
# sample2.coffee ⇒ common/sample2.js
# として出力される
output:
filename: '[name],js'
resolve: {
extensions: ['', '.js', '.coffee']
root: path.join(current, './assets/coffee')
}
module:
loaders: [
{test: /\.coffee$/, loader: 'coffee-loader'}
]
}
共通でrequireしておきたい場合
上記のhoge.coffeeではcommon.coffeeをrequireしているが共通で使用するモジュールをわざわざわ各CoffeeScriptにrequireと書くのが面倒なので、一律requireしたい場合は以下の設定を追加する
webpack = require('gulp-webpack').webpack
path = require 'path'
current = process.cwd()
module.exports = {
output:
filename: 'app.js'
resolve: {
extensions: ['', '.js', '.coffee']
root: path.join(current, './assets/coffee')
}
module:
loaders: [
{test: /\.coffee$/, loader: 'coffee-loader'}
]
# 以下を追加
plugins: [
new webpack.ProvidePlugin(
Common: 'common', # common.coffeeをCommonという名前で共通でrequireする
$: 'jquery', # 自作のモジュールだけでなく'jquiry'等のnode_modules配下のモジュールも指定可能
)
]
上記のようにしておくと、各CoffeeScriptで「Common = require 'common'」のように書かなくてもCommonや$を参照できるようになる
その他
上記のサンプルだと、HTMLからクラスを呼ぶために「hoge.coffee」でwindowオブジェクトを使用してるんだけど他にいい方法はないものか。。。