Невозможно разрешить абсолютные пути url() для фоновых изображений в CSS с помощью Webpack

У меня есть следующая конфигурация Webpack (примерно, она была упрощена для этого поста):

const rootPublic = path.resolve('./public');
const LOCAL_IDENT_NAME = 'localIdentName=[name]_[local]_[hash:base64:5]';
const CSS_LOADER = `css?sourceMap&${LOCAL_IDENT_NAME}&root=${rootPublic}`;
const SASS_LOADER = 'sass?sourceMap&includePaths[]=' + path.resolve(__dirname, './src/styles');

// ... loaders:

loaders: [
  {
    test: /\.(jpe?g|png|gif|svg)$/,
    loader: 'url-loader?limit=10000&name=[path][name].[ext]'
  },
  {
    test: /\.scss$/,
    loader: config.DEVELOPMENT_MODE ? `style!${CSS_LOADER}!autoprefixer!${SASS_LOADER}`
                : ExtractTextPlugin.extract('style', `${CSS_LOADER}!autoprefixer!${SASS_LOADER}`)
  }, // ...
]

Теперь это отлично работает для изображений, на которые обычно ссылаются в файлах scss:

.some-static-class {
  background: url('/images/bg.png');
}

Однако он не работает при использовании директивы :local:

:local .SomeClass {
  background: url('/images/bg.png');
}

И я думаю, это потому, что root определено для загрузчика CSS. Я получаю сообщение об ошибке сборки: Module not found: Error: Cannot resolve 'file' or 'directory' ./../../../../../../../../images/bg.gif

Если вместо этого я удалю root из конфигурации css-loader, то он будет работать нормально, но тогда путь «выглядит» правильным в инспекторе Chrome, но когда вы на самом деле открываете ссылку в новой вкладке, она указывает на: chrome-devtools://devtools/bundled/"/images/bg.png" что, очевидно, не решить правильно.

Я не уверен, связана ли проблема с конфигурацией url-loader или что именно происходит.

Я играл с различными конфигурациями веб-пакетов, чтобы указать resolve.root, resolve.modulesDirectories и т. д., но совершенно не уверен, имеют ли они какое-либо влияние или я просто делаю это совершенно неправильно. Я также наткнулся на resolve-url-loader, но не уверен, что это вообще то, что мне нужно.

Любые идеи? МТИА!

ОБНОВЛЕНИЕ

Я должен отметить, что он отлично работает в Safari, но не в Chrome. Так что это похоже на ошибку, специфичную для Chrome, но нецелесообразно выполнять всю нашу разработку в Safari.

Я также наткнулся на vue-style-loader, который является ответвлением style-loader. который утверждает, что решает эту проблему, но он решает ее, полагаясь на хакерский устаревший метод escape/unescape.


person Muers    schedule 04.03.2016    source источник


Ответы (2)


Одно из возможных решений, которое я мог придумать, было следующим:

Используйте resolve-url-loader (сразу после sass-loader):

style!${CSS_LOADER}!autoprefixer!resolve-url!${SASS_LOADER}

Затем определите разрешение.псевдоним для статических изображений:

resolve: {
  alias: {
    images: path.join(__dirname, 'public/images')
  }
}

И затем в CSS вы можете указать на изображения следующим образом:

:local .SomeClass {
  background: url('images/bg.png');
}

В зависимости от вашей структуры URL вам также может понадобиться настроить параметр имени url-loader:

{
  test: /\.(jpe?g|png|gif|svg)$/,
  loader: 'url-loader?limit=10000&name=images/[name].[ext]'
}

Поэтому я не знаю, есть ли более чистый способ решить эту проблему, но это лучшее, что я смог придумать до сих пор. Буду рад любым отзывам или альтернативам.

Спасибо!

ОБНОВЛЕНИЕ 30 6 июня 2016 г.

Есть пара PR, которые могли бы решить эту проблему, но сопровождающий предпочитает, чтобы решение было в CSS AST, а не в загрузчике CSS...

https://github.com/webpack/style-loader/pull/124 https://github.com/webpack/style-loader/pull/96

Будем надеяться, что скоро произойдет реальное исправление...

person Muers    schedule 04.03.2016

С веб-пакетом 2:

В ваших файлах .scss используйте ~ перед путем.

.yourClass {
      background: url('~img/wallpaper.png');
}

Используйте разрешение root из webpack, добавьте это в свой webpack.config.js:

resolve: {
        modules: [
            path.resolve(root),
            'node_modules'
        ]
    },

Это должно работать и для @import, например, @import "~otherfile.scss"

person Sergiu    schedule 16.01.2017