bholloway / resolve-url-loader

Webpack loader that resolves relative paths in url() statements based on the original source file
563 stars 71 forks source link

Webpack 4 Configuration not working - Request for Documentation #85

Closed jamesopti closed 5 years ago

jamesopti commented 6 years ago

_Minimally reproducible setup here: https://github.com/jamesopti/webpack_playground/tree/resolve_url_loader_issue_

Hi! Excited to use this loader, 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/icons/buttons.png) no-repeat -31px -276px;
}

Which is ending up in my css as exactly the same thing

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/icons/buttons.png
  /Users/usr1/optimizely/src/www/frontend/static/img
  /Users/usr1/optimizely/src/www/frontend/static/img/docs
  /Users/usr1/optimizely/src/www/frontend/static/img/icons  
  /Users/usr1/optimizely/src/www/frontend/static/img/signin
  NOT FOUND

Is there some output config thats not correct? I read through #79 but couldnt figure out what to do with the rootContext setting

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

span.arrow {
  background: url(/dist/static/img/icons/buttons-dhsye47djs82kdhe6.png) no-repeat -31px -276px;
}

// 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/scss',
                path.join(__dirname, './node_modules/optimizely-oui/src'),
              ],
            },
          },
        ],
      },
]
bholloway commented 6 years ago

@jamesopti the resolve-url-loader is less suited to cases where all the assets are in a central directory. It is more suited for "feature" structure where assets are co-located with the .scss. I am thinking your use-case is the former on, is that correct?

If so maybe postcss/postcss-url might be more suited, although I have not taken a deep look at your use case.

EDIT: Don't let me put you off. I am more than happy to work though resolve-url-loader here. I just want to find the best solution for your use-case.

davidpelayo commented 6 years ago

@bholloway maybe your answer doesn't properly answer the question? Regardless the use-case exposed, it's true the loader doesn't correctly cowork with Webpack 4. Expecting at least to see the debug information provided through options and not possible. I guess the loader needs work on being fully compatible with Webpack4?

bholloway commented 5 years ago

Please refer to #97 as version 3 as docs have been updated. Hopefully some the options are more sensible now.

@jamesopti use-case is root-relative url(). The resolve-url-loader is primarily for fully relative url(). Hopefully this is better explained in the new version.

The updated root option can probably get the job done. However a similar option was recently removed from css-loader@1.0.0 release since "use postcss-loader with postcss-url plugin" is considered the better option.

"I guess the loader needs work on being fully compatible with Webpack4?"

@davidpelayo I hope I have addressed the problem in version 3. I encourage you to look at #97 and try the new alpha. Certainly I value any feedback you can give in #97.

bholloway commented 5 years ago

With the recent release of 3.0.0 I finally got some bandwidth to look at this in detail.

RE: https://github.com/jamesopti/webpack_playground/tree/resolve_url_loader_issue

The options in 3.0.0 are a little clearer. I was able to use root: __dirname to handle the root-relative URI.

The revised root option is now essentially the same option as in css-loader. However this option was removed from css-loader as of July. In css-loader they suggest the use of "postcss-url plugin" instead.

I also suggest that this is better handled by some url rebase and not resolve-url-loader.

However if you really want to use resolve-url-loader then here is a configuration that worked for me.

use: [
  MiniCssExtractPlugin.loader,
  {
    loader: 'css-loader',
    options: {
      sourceMap: true,
    },
  },
  {
    loader: 'resolve-url-loader',
    options: {
      debug: true,
      root: __dirname
    },
  },
  {
    loader: 'sass-loader',
    options: {
      outputStyle: 'compressed',
      sourceMap: true
    },
  },
],

This produces css and the required image in the dist directory.

span.arrow{background:url(/dist/css/audiences-c2b865eee00aca891d3f78200b3df45f.png)}

However to reiterate - this is case is fully relative URI, whereas resolve-url-loader is intended for fully-relative URI in feature centric project structure.

It is co-incidental (and not intentional) that resolve-url-loader@3.0.0 can actually solve this problem. I don't believe that is possible with resolve-url-loader@2.x.x.