Looking for similar things in the issues, the only one I could find was this one https://github.com/vuejs/vue-cli/issues/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.
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.
Have you tried
<style lang="scss" src="font-awesome/scss/font-awesome.scss"></style>
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
Forgot to mention you cannot omit the .scss
extension.
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>
Did you figure out how to add a loader after the css-loader
? I'm trying to do the same.
@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.
Anybody got a solution to this with the new vue.config.js format?
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')
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
}))
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 :)
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.
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.
Same question than @dreusel why this not work out of the box? It was painful to make relative path work for url's!
Most helpful comment
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:Note that this is @callumacrae's solution without the dependency on
merge
. Obviously you also need tonpm 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.