url-loader / file-loader разрывая относительные пути в выводе css с помощью веб-пакета - PullRequest
0 голосов
/ 15 декабря 2018

Я использую веб-пакет с некоторыми плагинами и загрузчиками, чтобы взять мою папку src / и создать папку dist /.url-loader (который возвращается к загрузчику файлов, когда изображения больше определенного предела) выводит изображения, найденные в моих файлах html и scss, в правильный каталог, как и ожидалось.Однако он изменяет относительные пути в этих файлах и при этом выводит файл css с неверным путем.

Структура файла:

src/
    index.html
    assets/
        js/
            index.js
        scss/
            style.scss
        img/
            pic.jpg
            background.jpg

dist/
    index.html
    assets/
        js/
            index.js
        css/
            style.css
        img/
            pic.jpg
            background.jpg

Как вы можете видеть мои зеркала dist / folderМоя папка src /, за исключением того, что scss скомпилирована в css.

src / index.js, импортирует index.html и style.scss, так что эти файлы можно анализировать через веб-пакет, а любые изображения в них можно обрабатывать по URL-loader:

index.js

import '../../index.html';
import '../scss/style.scss';

style.scss устанавливает фоновое изображение на теле, используя относительный путь:

style.scss

body {
    background: url('../img/background.jpg');
}

index.html просто отображает изображение, также используя относительный путь:

index.html

<img src="./assets/img/pic.jpg" alt="pic">

Я использую HtmlWebpackPlugin для копирования через мои html-файлы, поскольку он позволяет мне указывать, какие фрагменты автоматически включать в качестве тегов сценария.Для css я либо внедряю его в html-файлы с помощью style-loader в разработке, либо извлекаю его в свой собственный файл при производстве с помощью MiniCssExtractPlugin.

Однако, когда webpack анализирует index.html и style.scss,относительные пути заменяются на «assets / img / pic.jpg» и «assets / img / backgorund.jpg» соответственно.Это не нарушает путь в index.html, так как это фактически тот же относительный путь, но это явно проблема для style.css.Как мне остановить url-loader от изменения относительных путей или просто сгенерировать правильные?Также обратите внимание, что, когда CSS внедряется в HTML с помощью style-loader в разработке, путь работает, так как он тогда относительно файла HTML.В идеале веб-пакет должен иметь возможность генерировать правильный относительный путь в зависимости от того, извлекаю ли я css-файл в производственном процессе или внедряю его в процессе разработки.

Я пытался использовать resol-url-loader, указав publicPath и outputPath иКонечно, поиск ответов онлайн, но не повезло.

webpack.config.js

const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

const devMode = process.env.NODE_ENV !== 'production';

module.exports = {
    mode: devMode ? 'development' : 'production',
    entry: {
        index: './src/assets/js/index.js',
    },
    output: {
        filename: 'assets/js/[name].js',
        path: path.resolve(__dirname, 'dist')
    },
    devServer: {
        contentBase: path.join(__dirname, 'src'),
        watchContentBase: true,
        hot: devMode,
    },
    devtool: devMode ? 'source-map' : '(none)',
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'src/index.html',
        }),
        new MiniCssExtractPlugin({
            filename: 'assets/css/style.css',
        })
    ],
    module: {
        rules: [
            {
                test: /\.html$/,
                use: [
                    {
                        loader: 'html-loader'
                    }
                ]
            },
            {
                test: /\.(jp(e?)g|png|svg|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192,
                            name: 'assets/img/[name].[ext]'
                        }
                    }
                ]
            },
            {
                test: /\.scss$/,
                use: [
                    {
                        loader: devMode ? 'style-loader' : MiniCssExtractPlugin.loader
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            sourceMap: devMode,
                            importLoaders: 2
                        }
                    },
                    {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: devMode
                        }
                    }
                ]
            }
        ]
    }
};

if (devMode) {
    module.exports.plugins.push(new webpack.HotModuleReplacementPlugin());
}

Ответы [ 4 ]

0 голосов
/ 20 мая 2019

потратил на это века!publicPath Настройка ниже отсутствует!

 output: {
     publicPath: '/'
 },
0 голосов
/ 15 декабря 2018

РЕШЕНО

Решено благодаря этому сообщению на github: https://github.com/webpack-contrib/mini-css-extract-plugin/issues/44#issuecomment-379059788.

Просто добавьте параметр publicPath к MiniCssExtractPlugin следующим образом:

...
{
    test: /\.scss$/,
    use: [
        {
            loader: MiniCssExtractPlugin.loader,
            options: {
                publicPath: '../../' // path to director where assets folder is located
            }
        },
        {
            loader: 'css-loader',
            options: {
                sourceMap: devMode,
                importLoaders: 2
            }
        },
        {
            loader: 'sass-loader',
            options: {
                sourceMap: devMode
            }
        }
    ]
},
...

Чтобы использовать загрузчик стилей в режиме разработки вместо MiniCssExtractPlugin, как в моем оригинальном webpack.config.js, вам придется добавить опцию в условно, потому что загрузчик стилей не принимает опцию publicPath.Я сделал это в нижней части webpack.config.js примерно так:

if (!devMode) {
    module.exports.module.rules[0].use[0].options = { publicPath: '../../' };
}

Затем убедитесь, что первый объект в массиве правил предназначен для scss.Какой-то грязный способ добавить это условно, но пока подойдет.

0 голосов
/ 08 марта 2019

Вот мое решение:

const devMode = process.env.NODE_ENV !== 'production';

...rules: [
        {
            test: /\.scss$/,
            use: [
                devMode ? 'style-loader' :
                {
                loader: MiniCssExtractPlugin.loader,
                    options: {
                        publicPath: '../',
                    }
                },
                {
                    // translates CSS into CommonJS
                    loader: 'css-loader',
                    options: {
                        sourceMap: true,
                    },
                },
                {
                    // Autoprefixer usw.
                    loader: 'postcss-loader',
                    options: {
                        ident: 'postcss',
                    },
                },
                {
                    // compiles Sass to CSS, using Node Sass by default
                    loader: 'sass-loader',
                    options: {
                        sourceMap: true,
                    },
                }
            ],
        },
    ]
0 голосов
/ 15 декабря 2018

Попробуйте добавить параметр publicPath

 {
    loader: 'url-loader',
    options: {
        limit: 8192,
        name: "[name].[ext]"
        publicPath: '/assets/img/   //<-- assuming assets is in web root
    }
 }

и измените style.scss на

body {
    background: url('background.jpg');
}
...