Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a vue-cli resolve-url-loader example #2099

Closed
Hebilicious opened this issue Aug 7, 2018 · 14 comments
Closed

Add a vue-cli resolve-url-loader example #2099

Hebilicious opened this issue Aug 7, 2018 · 14 comments

Comments

@Hebilicious
Copy link

Hebilicious commented Aug 7, 2018

What problem does this feature solve?

Looking for similar things in the issues, the only one I could find was this one #1019.

I'll use font awesome to illustrate :

This is the project structure :

/node_modules/font-awesome

/src/folder/MyComponent.vue

This style bloc in MyComponent.vue:

...
<style lang="scss">
@import '~font-awesome/scss/font-awesome';
//...
</style>

Throws this error :

These relative modules were not found:

* ../fonts/fontawesome-webfont.eot in ./node_modules/css-loader??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/lib??ref--8-oneOf-1-2!./node_modules/sass-loader/lib/l
oader.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/folder/MyComponent.vue?vue&type=style&index=0&lang=scss

EDIT : Here's a reproduction repository : https://github.com/Hebilicious/vue-cli-relative-url-import-issue-test
The font files are relative to '~font-awesome/scss/font-awesome', but webpack tries to resolve them relatively to 'MyComponent.vue'.

https://github.com/bholloway/resolve-url-loader solve this problem elegantly, but it needs to be 'placed' directly right after css loader :

module.exports = {
  module: {
    loaders: [
      {
        test   : /\.css$/,
        loaders: ['style-loader', 'css-loader', 'resolve-url-loader']
      }, {
        test   : /\.scss$/,
        loaders: ['style-loader', 'css-loader', 'resolve-url-loader', 'sass-loader?sourceMap']
      }
    ]
  }
};

According to https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-loader

TIP

For CSS related loaders, it's recommended to use css.loaderOptions instead of directly targeting loaders via chaining. This is because there are multiple rules for each CSS file type and css.loaderOptions ensures you can affect all rules in one single place.

I don't see any straightforward way to do it for all the styling related rules for vue cli with chain webpack.

There's a possible (very) dirty workaround, which is to modify @vue/cli-service/lib/config.css.js :

module.exports = (api, options) => {
   //...
    function createCSSRule (lang, test, loader, options) {
      //...
      function applyLoaders (rule, modules) {
       //...
        rule
          .use('css-loader')
          .loader('css-loader')
          .options(cssLoaderOptions)

       //Add resolve-url-loader here

        rule
          .use('resolve-url-loader')
          .loader('resolve-url-loader')
          .options({ //... })

Other ways to go around the problem is to actually have the assets at the relative path file from your source files, or to modify the font-awesome import statements, which isn't ideal.

What does the proposed API look like?

If there's a way to do it currently with chain webpack, documenting it would be very helpful.

Otherwise this ...

module.exports = {
  css: {
    loaderOptions: {
      resolveUrl: {
        // options here 
      }
    }
  }
}

...would be ideal.

@yyx990803
Copy link
Member

yyx990803 commented Aug 7, 2018

Have you tried

<style lang="scss" src="font-awesome/scss/font-awesome.scss"></style>

@Hebilicious
Copy link
Author

Hebilicious commented Aug 7, 2018

Hi, thanks for the quick answer.
I tried it and a bunch of variants,

<style lang="scss" src="font-awesome/scss/font-awesome"></style>
<style lang="scss" src="~font-awesome/scss/font-awesome"></style>
<style lang="scss" src="../../node_modules/font-awesome/scss/font-awesome"></style>

All of them outputs something like

 ERROR  Failed to compile with 1 errors                                                                                                                                                                              5:21:54 PM

This dependency was not found:

* font-awesome/scss/font-awesome?vue&type=style&index=0&lang=scss in ./src/folder/MyComponent.vue

To install it, you can run: npm install --save font-awesome/scss/font-awesome?vue&type=style&index=0&lang=scss

Edit : Create a reproduction repository : https://github.com/Hebilicious/vue-cli-relative-url-import-issue-test

@yyx990803
Copy link
Member

Forgot to mention you cannot omit the .scss extension.

@Hebilicious
Copy link
Author

Hebilicious commented Aug 7, 2018

Works like a charm for my use case, thanks a lot!

<style lang="scss" src="font-awesome/scss/font-awesome.scss"></style>
<style lang="scss">
@import "sheet/that/uses/fontawesome";
//...
</style>

@RehanSaeed
Copy link

Did you figure out how to add a loader after the css-loader? I'm trying to do the same.

@Hebilicious
Copy link
Author

@RehanSaeed I didn't find a clean way to do it. However I didn't need to do it to achieve what I wanted, but if you really do need that feature it might be worth re-opening this or creating a new similar issue.

@benkiefer
Copy link

Anybody got a solution to this with the new vue.config.js format?

@cstuncsik
Copy link

Yes @benkiefer but it's not working :(
I got the same error: These relative modules were not found

config.module
  .rule('scss')
  .oneOf('vue')
  .use('resolve-url-loader')
  .loader('resolve-url-loader').options({
    keepQuery: true
  })
.before('sass-loader')

@cstuncsik
Copy link

After googleing towards found the solution!
resolve-url-loader docs says:

source-maps required for loaders preceding resolve-url-loader (regardless of devtool).

so just write the following under what I wrote in my previous comment:

config.module
  .rule('scss')
  .oneOf('vue')
  .use('sass-loader')
  .loader('sass-loader')
  .tap(options => ({
    ...options,
    sourceMap: true,
    sourceMapContents: false
  }))

@callumacrae
Copy link

callumacrae commented Oct 22, 2019

Sorry for bumping a super old issue again, but here's what I ended up with to add resolve-url-loader to all the rules:

['vue-modules', 'vue', 'normal-modules', 'normal'].forEach(rule => {
  config.module.rule('scss')
    .oneOf(rule)
      .use('resolve-url-loader')
        .loader('resolve-url-loader')
        .before('sass-loader')
        .end()
      .use('sass-loader')
        .loader('sass-loader')
        .tap(options =>
          merge(options, {
            sourceMap: true
          })
        );
});

It's basically the same as what @cstuncsik posted but all in one go :)

@dreusel
Copy link

dreusel commented Jun 5, 2020

If someone else lands here and like me has no idea what to do with these magical snippets of code that should fix your problem: You're supposed to put a chainWebpack(config) function in vue.config.js's module.exports and that's where it goes. Like so:

module.exports = {
	chainWebpack: (config) => {
		['vue-modules', 'vue', 'normal-modules', 'normal'].forEach(rule => {
			config.module.rule('scss')
				.oneOf(rule)
				.use('resolve-url-loader')
				.loader('resolve-url-loader')
				.before('sass-loader')
				.end()
				.use('sass-loader')
				.loader('sass-loader')
				.tap(options =>
					({...options, sourceMap: true})
				);
		});
	},
}

Note that this is @callumacrae's solution without the dependency on merge. Obviously you also need to npm install --save resolve-url-loader.
After that it works like... well actually, like I'd expect to it work out of the box.
Thanks a bunch to everyone for posting their (parts of the) solution.

@selfagency
Copy link

selfagency commented Jun 13, 2020

I have been struggling with this issue all day and it sucks supremely. I have tried two dozen different ways of trying to do the simplest damn thing — include a global stylesheet via webpack. And it has been a complete and total nightmare. I love Vue but this is making me hate it. None of the solutions here or anywhere else work for me.

@jiraguha
Copy link

jiraguha commented Jun 19, 2020

Same question than @dreusel why this not work out of the box? It was painful to make relative path work for url's!

@JayDouglass
Copy link

If someone else lands here and like me has no idea what to do with these magical snippets of code that should fix your problem: You're supposed to put a chainWebpack(config) function in vue.config.js's module.exports and that's where it goes. Like so:

module.exports = {
	chainWebpack: (config) => {
		['vue-modules', 'vue', 'normal-modules', 'normal'].forEach(rule => {
			config.module.rule('scss')
				.oneOf(rule)
				.use('resolve-url-loader')
				.loader('resolve-url-loader')
				.before('sass-loader')
				.end()
				.use('sass-loader')
				.loader('sass-loader')
				.tap(options =>
					({...options, sourceMap: true})
				);
		});
	},
}

Note that this is @callumacrae's solution without the dependency on merge. Obviously you also need to npm install --save resolve-url-loader.
After that it works like... well actually, like I'd expect to it work out of the box.
Thanks a bunch to everyone for posting their (parts of the) solution.

Thanks! I wish they would just make resolve-url-loader a default! Or have an easy config option to enable it.

danigm added a commit to endlessm/kolibri-explore-plugin that referenced this issue Jun 4, 2021
To make this work a new sass variable was declared,
eos-components-fonts-path, that's used to calculate the real path of the
fonts.

In the template-ui it's easier to fix because we're using vue-cli and we
can modify the way the css is loaded, so in this case we use the module
resolve-url-loader to make it work the relative path.
vuejs/vue-cli#2099 (comment)

In the case of the plugin vue modules, I was unable to find the way to
use the resolve-url-loader, but I was able to fix the problem just
setting the variable to the real eos-components fonts path.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants