Just do IT

思うは招く

webpack の設定でよく見る path.resolve は何をしているのか

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を返す。

参考

Path | Node.js v14.5.0 Documentation