webpack の入門書では、webpack.config.jsにファイルの出力先として以下の記述をよく見る。
output: { path: `${__dirname}/dist`, filename: 'main.js' },
これは、「ビルドした後のファイル出力先(output)は、ルートディレクトリ/distディレクトリにmain.jsというファイル名で設置してね」という意味。
しかし、次の記述もよく見る。
const path = require('path') module.exports = { ~ output: { path: path.resolve(__dirname, 'public/js') } ~ }
さきほどは ${__dirname}/dist と書いていたのに、今度はpath.resolve()メソッドを使ってパスを指定している。また、Node.js モジュールの path も requireしている。
path.resolve(__dirname, 'public/js')と書くことで、ルートディレクトリ/public/jsという絶対パスが返る。ビルド後のファイルはこのディレクトリ下に設置される。
「絶対パスを指定している」という点では、両方とも同じだ。
ではなぜ、path.resolveを使っているのか?
結論からいうと、OSの違いによって思わぬ挙動が起こらないように、安全のためこういった書き方をしているようだ。
まず、そもそもpath.resolve()が何をしているのかを調べてみた。
path.resolve()は絶対パスを返す
これについては挙動を見てみたほうがわかりやすい。
#REPLを起動する
$ node
#pathをrequireして使えるようにする
const path = require('path')
#今はこのパスにいる
:~/dev/webpack-jissen-nyumon
ためしに、path.resolve('index.js')をしてみるとどうなるか?
> path.resolve('index.js')
'/Users/kotakanazawa/dev/webpack-jissen-nyumon/index.js'
プロジェクト直下にindex.jsを設置した絶対パスが返ってきた。
次に、path.resolve('src', 'index.js')をやってみるとどうなるか?
> path.resolve('src', 'index.js')
'/Users/kotakanazawa/dev/webpack-jissen-nyumon/src/index.js'
第一引数には src 、第二引数には index.js を指定すると、プロジェクト直下にsrc/index.jsを設定した絶対パスが返ってくる。
これでなんとなくの動きはわかってくると思う。
path.resolve('src/js', 'index.js')をやってみると…
> path.resolve('src/js', 'index.js')
'/Users/kotakanazawa/dev/webpack-jissen-nyumon/src/js/index.js'
src/js/index.jsになって返ってきた。
path.resolve('src/js', 'public/index.js')をやってみると…
> path.resolve('src/js', 'public/index.js')
'/Users/kotakanazawa/dev/webpack-jissen-nyumon/src/js/public/index.js'
src/js/public/index.jsになって返ってきた。
つまり、path.resolve()は、引数があればそれらを結合して絶対パスを返してくれる。
webpack の設定:出力先は絶対パスを指定する
webpack の設定において、output の path には絶対パスを指定しないとエラーが出てしまう。
output: {
// 絶対パスを指定する
path: path.resolve(__dirname, 'public/js')
}
Macであれば、${__dirname}/distといった書き方でも問題はない。
output: {
path: `${__dirname}/dist`,
filename: 'main.js'
},
しかし、OSによってはパスの書き方が/じゃないことがあり、${__dirname}/distだと変になってしまって動かない可能性が出てくる。
だから、絶対パスを確実に設定するため、path.resolve()を使っているというわけ。
path ライブラリの基本
こちらはおまけ。
「そもそも path ライブラリってなにをしてくれるもんなの?」という疑問があったので、他のメソッドも調べてみた。ざっと見るだけで「あ〜 path ライブラリってこんな感じのことをしてくれるやつなのね〜」と知ることができるかも。
path.dirname()
path.dirname()は名前から想像できるとおり、ディレクトリパスを取得する。
ターミナルでREPLを起動して挙動を確かめてみる。
$ node
# pathをrequireして使えるようにする
> const path = require('path')
#適当にパスを定義する
> const path_name1 = '/foo/bar/baz'
# dirnameメソッドを使う
> path.dirname(path_name1)
'/foo/bar'
#もう一つ適当にパスを定義する
> const path_name2 = '/foo/bar/baz/hoge/bbb'
# dirnameメソッドを使う
> path.dirname(path_name2)
'/foo/bar/baz/hoge'
/foo/bar/bazと定義したパスをpath.dirname()で読み取ると、'/foo/bar'が返ってくる。
/foo/bar/baz/hoge/bbbと定義したパスをpath.dirname()で読み取ると、'/foo/bar/baz/hoge'が返ってくる。
path.dirname()
path.basename()はファイル名を返す。
> const path_name1 = '/foo/bar/baz' > path.basename(path_name1) 'baz' > const path_name2 = '/foo/bar/baz/hoge/bbb' > path.basename(path_name2) 'bbb'
たとえば、/foo/bar/index.htmlだったらindex.htmlを返す。