質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.91%

webpackによるscssのバンドル時の画像等のurlが読み込めない

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 695

torabe

score 18

webpackを利用してscssからcssへ変換を行う際にscssファイルから背景画像やフォント読み込み
Base64に変換したり、そのまま出力したりしたい場合、scssファイル中で相対パスを有効にするために
resolve-url-loaderを利用しているのですがうまくいきません。

package.jsonとwebpack.config.js

package.json
{
    "name": "packages",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "dev": "yarn run develop",
        "develop": "webpack --progress --mode development --debug --devtool source-map --output-pathinfo --config ./webpack.config.js",
        "start": "webpack-dev-server --mode development --debug --devtool source-map --output-pathinfo --open --config ./webpack.config.js --hot --inline",
        "watch": "webpack --progress --mode development --debug --devtool source-map --output-pathinfo --config ./webpack.config.js --watch --color --progress",
        "build": "webpack --progress --mode production --config ./webpack.config.js"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "browserslist": [
        "last 5 version",
        "ie >= 9",
        "iOS >= 8.1",
        "Android >= 4.0",
        ">= 2%",
        "Firefox >= 20"
    ],
    "devDependencies": {
        "@babel/core": "^7.6.0",
        "@babel/polyfill": "^7.6.0",
        "@babel/preset-env": "^7.6.0",
        "@babel/preset-react": "^7.0.0",
        "autoprefixer": "^9.6.0",
        "babel-loader": "^8.0.6",
        "copy-webpack-plugin": "^4.6.0",
        "core-js": "3",
        "css-loader": "^1.0.1",
        "dotenv-webpack": "^1.7.0",
        "eslint": "^5.16.0",
        "eslint-loader": "^2.1.2",
        "eslint-plugin-react": "^7.11.1",
        "extract-text-webpack-plugin": "^4.0.0-beta.0",
        "file-loader": "^1.1.11",
        "html-loader": "^0.5.5",
        "html-webpack-plugin": "^3.2.0",
        "http-server": "^0.11.1",
        "merge-stream": "^1.0.1",
        "node-sass": "^4.12.0",
        "openssl": "^1.1.0",
        "path": "^0.12.7",
        "postcss-loader": "^2.1.6",
        "raw-loader": "^3.1.0",
        "regenerator-runtime": "^0.13.3",
        "resolve-url-loader": "^3.1.1",
        "run-sequence": "^2.2.1",
        "sass-loader": "^7.1.0",
        "style-loader": "^0.21.0",
        "tinypng-webpack-plugin": "^2.0.0",
        "url-loader": "^1.1.2",
        "vue-loader": "^15.7.0",
        "webpack": "4.35.0",
        "webpack-cli": "3.3.5",
        "webpack-dev-server": "^3.7.1",
        "webpack-stream": "^4.0.3",
        "write-file-webpack-plugin": "^4.5.0"
    },
    "dependencies": {

    }
}
webpack.config.js

const path = require('path');
const glob = require('glob');

const srcPath = './src/**/';
const srcPathReg = './src/';

const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractSass = new ExtractTextPlugin({filename:'[name]'});

module.exports = (env, argv) => [
    {
        /* ----------------
            CSS用モジュール
            ----------------- */
        //entry: scssTargets,
        entry: scssEntries,
        // ファイルの出力設定
        output: {
            //  出力ファイルのディレクトリ名
            path: path.resolve(__dirname, 'public'),
            publicPath: '/',
            // 出力ファイル名
            //filename: 'style.css'
            filename: '[name]'
        },
        mode: argv.mode,
        devtool: (argv.mode === 'development') ? 'source-map' : 'none',
        module: {
            rules: [
                // CSSファイルの読み込み
                {
                    test: /\.scss$/,
                    exclude: /node_modules/,
                    use: ExtractTextPlugin.extract({
                        fallback: 'style-loader',
                        use: [
                            // CSSをバンドルするための機能
                            {
                                loader: 'css-loader',
                                options: {
                                    // オプションでCSS内のurl()メソッドの取り込みを禁止する
                                    //url: false,
                                    // CSSの空白文字を削除する
                                    minimize: true,
                                    // ソースマップの利用有無
                                    sourceMap: (argv.mode === 'development'),

                                    // 0 => no loaders (default);
                                    // 1 => postcss-loader;
                                    // 2 => postcss-loader, sass-loader
                                    importLoaders: 2
                                }
                            },
                            // PostCSSのための設定
                            {
                                loader: 'postcss-loader',
                                options: {
                                    // PostCSS側でもソースマップを有効にする
                                    sourceMap: (argv.mode === 'development'),
                                    plugins: [
                                        // Autoprefixerを有効化
                                        // ベンダープレフィックスを自動付与する
                                        require('autoprefixer')({
                                            grid: 'autoplace',
                                            overrideBrowserslist: ['last 5 version', 'ie >= 9', 'iOS >= 8.1', 'Android >= 4.0', '>= 2%', 'Firefox >= 20']
                                        })
                                    ]
                                },
                            },
                            {
                                loader: 'resolve-url-loader'
                            },
                            // Sassをバンドルするための機能
                            {
                                loader: 'sass-loader',
                                options: {
                                    sourceMap: true,
                                    sourceMapContents: false
                                }
                            }
                        ]
                    })
                },
                {
                    // 対象となるファイルの拡張子
                    test: /\.css/,
                    // ローダー名
                    loader: 'url-loader',
                },
                {
                    // 対象となるファイルの拡張子
                    test: /\.(gif|png|jpe?g|svg)$/,
                    // 画像をBase64として取り込む
                    loader: 'url-loader',
                    options: {
                        limit: 100 * 1024, // 100KB以上だったら埋め込まずファイルとして分離する
                        context: 'src/',
                        name: '[path][name].[ext]',
                        outputPath: './',
                        publicPath : (path) => {
                            return '/' + path;
                        }
                    }
                },
                {
                    // 対象となるファイルの拡張子
                    test: /\.(woff|woff2|eot|ttf|ttc|WOFF|WOFF2|EOT|TTF|TTC|otf|svgf)$/,
                    // 画像をBase64として取り込む
                    loader: 'file-loader',
                    options: {
                        context: 'src/',
                        name: '[path][name].[ext]',
                        outputPath: './',
                        publicPath : (path) => {
                            return '/' + path;
                        }
                    }
                }
            ]
        },
        plugins: [
            //tinyPing,
            extractSass
        ],
        resolve: {
            // style-loader の中で、.jsファイルを拡張子なしで requireしているところがあるため、'.js'が必要
            extensions: ['.css', '.scss', '.js']
        }
    }

];

scssファイルの構成とコード

public ─── css ─┬─ img ← 画像ファイル出力先
                └─ style.css ← 出力ファイル
src    ─── css ─┬─ _components ← 各コンポーネントのcss
                ├─ _variables ← 編集
                ├─ img ← 画像ファイルを保存する
                ├─ app.scss ← ここでscssファイルをimportする
                └─ style.scss ← app.scssにimportされる
src/css/style.scss
.class-name{
  background:url(./img/image.jpg) no-repeat center center;
}

エラーメッセージ

Module not found: Error: Can't resolve './_components/img/image.jpg' in '**\src\css' @ ./src/css/app.scss (./node_modules/css-loader??ref--4-2!./node_modules/postcss-loader/lib??ref--4-3!./node_modules/resolve-url-loader!./node_modules/sass-loader/dist/cjs.js??ref--4-5!./src/css/app.scss) 7:45979-46028


実際エラーが出るのはbuildのときで
developwatchでは問題ありません。

実際に試したこと

resolve-url-loaderはソースマップがないとうまくいかないとのことなのでbuildコマンドでもソースマップを有効にして試してみましたが、それでもうまくいきませんでした。

追記

色々調べた結果
webpackのmodeプロパティでproductionとした場合に発生しているのでないかの考えられるのですが、
理由をご存じの方がいらっしゃいましたらご回答よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る