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

Resolve-Url-Loader doesn't seem to do anything #51

Closed CmdrShepardsPie closed 5 years ago

CmdrShepardsPie commented 7 years ago

I'm trying to bring in an image to my SCSS and have it resolve using the WebPack (2) aliases I have setup. It doesn't seem to make any difference if I use resolve-url-loader or not, the outcome is the same.

      resolve: {
        modules: [
          path.resolve(__dirname, 'client'),
          'node_modules'
        ],
        alias: {
          'assets': path.resolve(__dirname, 'client/assets')
        }
      }

Loader rules:

      {
        test: /\.s(a|c)ss$/,
        use: [
          'style-loader',
          { loader: 'typings-for-css-modules-loader', options: { sourceMap: true, importLoaders: 3, modules: true, camelCase: true, namedExport: true, localIdentName: '[path][name]__[local]--[hash:base64:5]' } },
          { loader: 'postcss-loader', options: { sourceMap: true } },
          { loader: 'resolve-url-loader', options: { sourceMap: true, debug: true, keepQuery: true } },
          { loader: 'sass-loader', options: { sourceMap: true } }
        ],
        include: [/\.module\.s(a|c)ss$/]
      }

example.module.scss:

    .box-background {
      background: no-repeat center center;
      background-size: cover;
      background-image: url("~assets/images/yeoman.png");
      cursor: pointer;
      margin: 13.5px 0;
      position: relative;
      height: 252px;
      width: 448px;
    }

When it's formatted like "~assets/..." (which I've confirmed works for @import and html img src=) it says it can't find it with or without resolve-url-loader, with or without the alias. If I type just "assets/...", it works, with or without resolve-url-loader, with or without the alias.

Basically, it just looks like it's doing nothing.

Do I have it configured wrong? Am I using it wrong? Does it not work with the toolchain I'm using? (All my tools/packages/loaders are using the current latest versions as of this post).

Thanks

bholloway commented 7 years ago

@CmdrShepardsPie I don't think you need this loader if you want to centralise your assets. Resolving those centralised assets (i.e. use alias or not) is a secondary issue.

Let me explain...

Webpack css-loader will get assets out of url() statements. That is not what this loader does.

This loader sits before css-loader and rewrites url() paths before they get to css-loader.

Imagine you have a url() relative a scss file, which itself is imported into another scss file. Webpack will only see the root scss file and expect the asset to be relative to it. It will never know there was a nested scss file. It will go looking for the assets relative tot he root scss file and not find them.

This loader looks in the source-map and finds the original file where the url() statement resides. It can then rewrite the path so that css-loader will be able to find the asset.

Originally I wrote this loader because I had a root scss file for the project, and feature-based scss files and assets in a number of directories.

Conversely if you have all your assets centralised then this is not your use-case.

CmdrShepardsPie commented 7 years ago

I was totally mistaken on what it does and how it works. I have updated accordingly.

Perhaps I should start a new thread for this, but now I'm encountering this problem: When I import at the root level of a local .scss file, it rewrites the urls inside: @import '~core/src/styles/web.scss';

but if I nest it in another selector (because we're going to be switching base style sheets on the fly, and thus assign them all to different base selectors) it doesn't rewrite the urls in the included .scss file:

    . web {
        @import '~core/src/styles/web.scss';
    }

Is this expected behavior? Is there another way to do this or make it work?

Thanks!

bholloway commented 7 years ago

Yes maybe close this and open a different issue.

I think you might need some community help and a good title is a start.

Importing into a selector like that strikes me of code smell. But I have but tracked Sass very well so I won't comment further. Allow will say its satisfy yourself that this is best practice.

CmdrShepardsPie commented 7 years ago

I agree, but we're not sure how else to dynamically change whole-page styles between two style sheets. Certainly open to suggestions.

bholloway commented 7 years ago

I don't know how coupled things are so this may be completely redundant advice...

Ideally you will want to extract CSS and manage it at the style tag level.

That way you load only the assets you need. Loading CSS for both variants up front will probably trigger load off fonts or other assets you don't need.

In production I don't believe I'm using style loader. You should be extracting anyway.

Dynamically managing style tags is one step further. I am not an expert but it may be worth investigating.

bholloway commented 7 years ago

@CmdrShepardsPie to clarify

OR