Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
79
Help us understand the problem. What is going on with this article?
@tomipetit

file-loaderで画像を扱うときのパス指定

More than 3 years have passed since last update.

webpackを利用してビルドするとき、CSS内の画像をバンドルせず外部ファイルとして出力したい場合があります。
その際「CSS内に記載したいパス」と「画像ファイルを保存するディレクトリ」をそれぞれ個別に指定したいときの方法です。

構成

例えば、以下のようなディレクトリ構成だったとして、
root/
 ├ dist/ (公開用ディレクトリ)
 │ └ asset/
 │  └ images/ ← ここに画像ファイルを出力したい
 │  └ css/ ← ここにCSSファイルを出力したい
 ├ dev/ (開発用ディレクトリ)
 │ └ images/
 │  └ example.png
 │ └ css/
 │  └ example.css
 └ webpack.config.js

CSSはこんな感じです。

root/dev/css/example.css
.sample{
    background-image: url(../images/example.png);
}

NG例(1)

まずNG例から示します。

root/webpack.config.js
// --(略)--
output: {
  path: path.join(__dirname, 'dist/asset')
},
module: {
    rules: [
        {
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback: 'style-loader',
                use: "css-loader",
            })
        },
        {
            test: /\.(jpg|png|gif)$/,
            use: [
                {
                    loader: 'file-loader',
                    options: {
                        name: '../images/[name].[ext]'
                    }
                }
            ]
        }
   ]
},
plugins: [
    new ExtractTextPlugin('css/[name].css')
]
// --(略)--

これをビルドすると、CSSは

root/dist/asset/css/example.css
.sample{
    background-image: url(../images/example.png);
}

と予定通り出力されますが、画像ファイルはoutputのpathディレクトリを基点として../images/example.pngのパスに置かれるため、
root/dist/asset/../images/example.png

root/dist/images/example.png
となり、本来ファイルを置きたい場所とズレが出てしまいます。

NG例(2)

今度はNG例(1)を変更して、画像が正常なパスに置かれるように修正してみます。

root/webpack.config.js
// --(略)--
output: {
  path: path.join(__dirname, 'dist/asset')
},
module: {
    rules: [
        {
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback: 'style-loader',
                use: "css-loader",
            })
        },
        {
            test: /\.(jpg|png|gif)$/,
            use: [
                {
                    loader: 'file-loader',
                    options: {
                        name: 'images/[name].[ext]'
                    }
                }
            ]
        }
   ]
},
plugins: [
    new ExtractTextPlugin('css/[name].css')
]
// --(略)--

これをビルドすると、画像ファイルは
root/dist/asset + images/example.png

root/dist/asset/images/example.png
となり、目的の位置に出力されますが、CSSは

root/dist/asset/css/example.css
.sample{
    background-image: url(images/example.png);
}

となり、今度はこちらのパスがズレてしまいます。

成功例

file-loaderの仕様を見たところ、これらを個別に指定する方法はないのですが、outputPathpublicPathというオプションがあり、これらにfunctionが使えることからその応用で対応できます。

root/webpack.config.js
// --(略)--
output: {
  path: path.join(__dirname, 'dist/asset')
},
module: {
    rules: [
        {
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback: 'style-loader',
                use: "css-loader",
            })
        },
        {
            test: /\.(jpg|png|gif)$/,
            use: [
                {
                    loader: 'file-loader',
                    options: {
                        name: '[name].[ext]',
                        outputPath : 'images/',
                        publicPath : function(path){
                            return '../' + path;
                        }
                        /* es2015ならば
                        publicPath : path => '../' + path
                        で書けます。*/
                    }
                }
            ]
        }
   ]
},
plugins: [
    new ExtractTextPlugin('css/[name].css')
]
// --(略)--

解説

まずoutputPathで「画像の保存先」を合わせます。
"images/" + (ファイル名).(拡張子)

次にCSSファイル内のパス指定にpublicPathを使います。
publicPathの引数(例ではpath のところ)にoutputPathを使って生成した「画像の保存先」が渡されるので、これをベースにpublicPath で加工したものをreturnします。
"../" + "images/" + (ファイル名).(拡張子)
 ↓
../images/(ファイル名).(拡張子)

これでCSS内の記述と画像保存パスを個別に指定することができました。

所感

ドキュメントには特に何もヒントが無かったので困っていましたが、node_modules内のfile-loaderファイルの中を見て解決できました。
他にも困っている方がいたら手助けになれば幸いです。

参考URL

file-loader公式GitHub

79
Help us understand the problem. What is going on with this article?
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
tomipetit
LINKA ASSOCIATES INC. Web Developper,Engineer. Toyohashi Aichi.

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
79
Help us understand the problem. What is going on with this article?