Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack 4 with sass-loader & resolve-url-loader - Image paths not being found

Minimally reproducible setup here: https://github.com/jamesopti/webpack_playground/tree/resolve_url_loader_issue

Im trying to use resolve-url-loader to add a hashname to my scss url() image paths, but I'm having a heck of a time getting it to work with webpack 4. I have a bunch of images in /static/img/** which are referenced in my SCSS like:

span.arrow {
  background: url(/static/img/audiences.png);
}

Which is ending up in my css as exactly the same thing (resolve-url-loader isnt finding them)

When I run the following configuration through webpack, I see that resolve loader is finding the right url() and its path, but debug mode is saying NOT FOUND.

resolve-url-loader: /static/img/audiences.png
  /Users/usr1/webpack_playground/src
  /Users/usr1/webpack_playground/static/img
  NOT FOUND

Is there some output config thats not correct? I've tried various combinations of the settings to no avail:

  loader: 'resolve-url-loader',
  options: {
    debug: true,
    root: path.join(__dirname, './static/img'),
    includeRoot: true,
    absolute: true,
  },

My end goal is for file-loader to transform them to the /dist hashed version:

span.arrow {
  background: url(/static/img/audiences-dhsye47djs82kdhe6.png);
}

// Webpack rules config

rules: [
      {
        test: /\.(png|jpg|gif)$/,
        include: [
          path.resolve(__dirname, './static/img'),
        ],
        use: {
          loader: 'file-loader',
          options: {
            name: '[name]-[hash].[ext]',
          },
        },
      },
      {
        test: /\.svg$/,
        use: {
          loader: 'svg-inline-loader',
          options: {
            name: '[name]-[hash].[ext]',
          },
        },
      },
      { test: /\/src\/js\/(?:.*)\.css$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader' } ] },
      {
        test: [/\.scss$/, /\.sass$/],
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'resolve-url-loader',
            options: {
              debug: true,
              root: './static/img',
              includeRoot: true,
            },
          },
          {
            loader: 'sass-loader',
            options: {
              outputStyle: 'compressed',
              sourceMap: true,
              includePaths: [
                './src'
              ],
            },
          },
        ],
      },
]
like image 783
jamis0n Avatar asked Apr 12 '18 16:04

jamis0n


People also ask

Is Sass-loader deprecated?

Warning: LibSass and Node Sass are deprecated. While they will continue to receive maintenance releases indefinitely, there are no plans to add additional features or compatibility with any new CSS or Sass features. Projects that still use it should move onto Dart Sass.

What is Sass-loader webpack?

sass-loader is a loader for Webpack for compiling SCSS/Sass files. style-loader injects our styles into our DOM. css-loader interprets @import and @url() and resolves them. mini-css-extract-plugin extracts our CSS out of the JavaScript bundle into a separate file, essential for production builds.

Does webpack compile SCSS?

javascript - Webpack compile scss to css and minify - Stack Overflow. Stack Overflow for Teams – Start collaborating and sharing organizational knowledge.

What is Sass-loader used for?

Webpack provides an advanced mechanism to resolve files. The sass-loader uses Sass's custom importer feature to pass all queries to the Webpack resolving engine. Thus you can import your Sass modules from node_modules .


2 Answers

It turns out all I needed was file-loader to do what I wanted.

When an image (matching my specified file extensions) is encountered by any of the css/sass/style loaders, its processed through file-loader, which both copies it to the output directory specified with the naming format specified and returns the name for the sass loader to use as the file name.

rules: [
  {
    test: /\.(png|jpg|gif|svg)$/,
    exclude: [
      path.resolve(__dirname, './node_modules'),
    ],
    use: {
      loader: 'file-loader',
      options: {
        name: '[path][name]-[hash].[ext]',
        outputPath: '../',
        publicPath: '/dist',
      },
    },
  },
  {
    test: /\.svg$/,
    include: [
      path.resolve(__dirname, './node_modules'),
    ],
    use: {
      loader: 'svg-inline-loader',
      options: {
        name: '[name]-[hash].[ext]',
      },
    },
  },
  { test: /\/src\/js\/(?:.*)\.css$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader' } ] },
  {
    test: [/\.scss$/, /\.sass$/],
    use: [
      MiniCssExtractPlugin.loader,
      {
        loader: 'css-loader',
        options: {
          sourceMap: true,
          root: path.resolve(__dirname),
        },
      },
      {
        loader: 'postcss-loader',
        options: {
          ident: 'postcss',
          plugins: () => [
            autoprefixer({
              'browsers': ['last 2 versions', 'ie >= 10'],
            }),
          ],
          sourceMap: true,
        },
      },
      {
        loader: 'sass-loader',
        options: {
          outputStyle: 'compressed',
          sourceMap: true,
          includePaths: [
            './src/scss',
          ],
        },
      },
    ],
  },
  {
    test: /\.html$/,
    use: [
      {
        loader: 'html-loader',
        options: {
          root: path.resolve(__dirname),
        },
      },
    ],
  },
  {
    test: [
      /\/bundles\/(?:.*)\.js$/,
    ],
    use: {
      loader: 'babel-loader',
    },
  },
];
like image 172
jamis0n Avatar answered Sep 22 '22 11:09

jamis0n


Actually resolve-url-loader is still needed sometimes... it depends if you want to be able to resolve url() calls from files imported inside the sass compilation. Without it urls would be broken in this case.

But if you don't use multi-file scss build (for example if each component has only 1 scss file local to it without calling shared library scss code or partials of some some sort) - then you don't need resolve-url-loader.

Of course you will still need url-loader (wraps file-loder with inlining abilities) or file-loader (for straight copying of assets to dist folder)

resolve-url-loader works by re-working original files from the sourcemap emitted by sass and sass-loader does have an issue with sourcemaps when working with the dart-sass implementaion. In this case sourcemap sources would mistakenly be stdin inplace of the filename see issue 671 and fix that came in PR 681

this is still unreleased fix as of today (July 2019) , the only option is to work with node-sass or use unreleased sass-loader

like image 34
Nadav SInai Avatar answered Sep 26 '22 11:09

Nadav SInai