-
-
Notifications
You must be signed in to change notification settings - Fork 198
Description
I've run into a bunch of issues attempting to use @import
and url()
when adding CSS modules to a current project and using less-loader
.
It looks like a lot of people have this error:
- less-loader is trying to resolve url references relative to the starting point(root less file) instead of using the current file #76 (same issue?)
- @import "~aptr-uikit/scr/index.less"; not working #101
- import with absolute paths #93
- problem with resolve relative path witch LESS function #85 (connected issue?)
... and so on.
I absolutely cannot get any kind of relative file load to work. I've attempted to create a minimal reproducible test case for the issue. The repository is located here: https://github.com/jsonnull/less-modules-resolve.
npm install
and npm run build
to see the issue.
ERROR in ./~/css-loader?modules!./~/less-loader?sourceMap!./src/index.less
Module not found: Error: Can't resolve 'material-design-icons/MaterialIcons-Regular.ttf' in '/Users/jsonnull/less-modules-resolve/src'
@ ./~/css-loader?modules!./~/less-loader?sourceMap!./src/index.less 6:470-528
@ ./src/index.less
@ ./src/index.js
See below, the file is clearly present:
├── dist
│ └── build.js
├── npm-debug.log
├── package.json
├── src
│ ├── index.js
│ ├── index.less
│ └── material-design-icons
│ ├── LICENSE
│ ├── MaterialIcons-Regular.eot
│ ├── MaterialIcons-Regular.ijmap
│ ├── MaterialIcons-Regular.svg
│ ├── MaterialIcons-Regular.ttf
│ ├── MaterialIcons-Regular.woff
│ ├── MaterialIcons-Regular.woff2
│ ├── README.md
│ ├── codepoints
│ └── material-icons.less
└── webpack.config.js
I've tried every combination for the less file import as well as the url()
import I can think of...
file
- I think this one should work?./file
- I think this one should definitely work~file
- I think this one should not work/file
- I think this one should not work
And, anyways, none of these methods work.
Assuming this is possible, how can the repository above be fixed so that all issues are resolved using the current directory structure? Otherwise, are there really combinations of relative paths that are completely impossible to use for importing?
From scrounging through issues it really does seem like nobody has a clear understanding of what this issue is or how to fix it. If we can come up with a clear answer for this issue for why it doesn't work and how to fix, hopefully others can learn from this and we can come up with good documentation for how to avoid this issue.
Activity
tamer1an commentedon Oct 14, 2016
👍 please resolve that issue
@jhnns
jhnns commentedon Oct 14, 2016
Thx for the detailed bug report. With your description and the minimal test example I was able to spot the issue very quickly 👍
Unfortunately, that's a really tricky one, let me explain it:
index.less
and passes it to less-loader@import
statement. Since nested imports are legal less, less is resolving thematerial-icons.less
with the help of the less-loaderrelativeUrls
option. This option is very useful, since it allows you to write your less files in a modular way, just reference your images and the final CSS contains valid urls. The urls look like this:node_modules
for it.url('./material-design-icons/MaterialIcons-Regular.eot')
everything would work just fine.It basically boils down to LESS + relativeUrls: true + CSS modules is not compatible. Either you convince less to rewrite their urls so that relative urls start with a dot, or you override the
relativeUrls
option in the less-loader or you get rid of less at all (I think, in combination with CSS modules less is not really necessary).jsonnull commentedon Nov 12, 2016
@jhnns Thanks for looking into this!
I'm going to close this issue, but I've left the repository in place in case anybody else comes across this issue.
m19c commentedon May 10, 2017
+1 - same problem :-/
jsonnull commentedon May 11, 2017
@MrBoolean unfortunately this problem is not going away any time soon. As stated above "It basically boils down to LESS + relativeUrls: true + CSS modules is not compatible"
I migrated away from LESS because I needed CSS modules and relative imports, and CSS formats are relatively interchangeable these days.
chardlau commentedon May 25, 2017
@jsonnull
I found that if wrap the less file with a folder and prepend '../' when using url() can work.
files distributes like below:
[module_root]/
----index.js (Here, use import './css/index.less')
----css/
--------index.less (Here, use url('../assets/test.eot'))
----assets/
--------test.eot
It looks so ugly, but i work.
txiaocao commentedon Sep 21, 2017
Haha, I resolve it; this is hack
I create
images.css
,and require the css files,and usethe code
limichange commentedon Jan 8, 2018
It is fine. 🤔
rally25rs commentedon Jan 15, 2018
@jhnns is there a way to disable this? When importing a lot of 3rd party CSS files, they have
url()
s set to where the file will be hosted not where it is on disk. These may not be resolvable by any loader, and the files can't be edited (they come from other dependencies).css-loader
can be passedurl: false
to stop processing those URLs, butless-loader
always changes them, making them incorrect at runtime.rally25rs commentedon Jan 16, 2018
For those that come across this issue and find that it completely blocks them from using less-loader... for example I have styling from some 3rd party libs that have
url(
references to files that don't exist on disk, likechosen-bootstrap
references images that ship withchosen
but aren't included inchosen-bootstrap
itself.You can disable all this URL mangling with
relativeUrls: false
on less-loader, andurl: false
on css-loader.This makes all
url()
entries stay as they were in the original less and css source (unchanged) and webpack will no longer try to resolve them. This also means that you no longer needfile-loader
orurl-loader
to process each of those files, however you also need a build step to copy the static assets into your own deploy directory where the web server can get to them. It also means there will be hot-reloading for the less files, but not for fonts and images.This was fine for me, as I was mostly just wanted the less file hot reloading.
garygreen commentedon Feb 20, 2018
@rally25rs thanks so much for that - it's worth noting that if you only need to do this for certain files you can change the rule so it only uses that loader with those custom options if needed. I'm a total noob when it comes to Webpack, so not sure if I'm doing it right but it seems to be working good for me.
Here's my current webpack config:
mqliutie commentedon May 30, 2018
@garygreen Thanks for your codes
boylec commentedon Oct 3, 2018
I got this to work without needing to turn off relativeUrls by making use of 'url-loader' for fonts/images:
url-loader converts files (fonts and images in this case) into base-64 strings. This way the resulting css references for fonts and/or images is a direct base64 string representation of the image or font instead of a path (relative or otherwise).
For example:
You could probably combine the loaders but I wanted them to behave slightly differently - ie
exclude: /node_modules/
.matthew-dean commentedon Nov 21, 2018
Does the
--rewrite-urls=local
option resolve this issue? http://lesscss.org/usage/#less-options-rewrite-urlsConsidering that @jhnns added the Less functionality, I think it addressed this issue, correct? If so, it would make sense to remove the "CSS Modules gotcha" in the readme.
Note the original issue wasn't so much even Less + relativeUrls: true (now rewriteUrls: 'all') + CSS Modules, but actually Less + relativeUrls: true + CSS modules + the Less plugin + webpack loader behavior working together to cause a problem, but the additional option should make this more flexible and compatible with Webpack + CSS modules.
matthew-dean commentedon Nov 21, 2018
Also, as noted in #276, no special
~
syntax should be needed to load styles from the node_modules folder. Less-loader is actually breaking Less module-loading functionality, but maybe that's by design. (I'm not a Webpack expert.)jhnns commentedon Apr 25, 2019
For future reference: passing
{rewriteUrls: "local"}
as Less option should fix the problem. Check out the Less documentation for more information.manugb commentedon Nov 1, 2019
For remote @import urls check this out
less/less.js#3188 (comment)
kanishka-malhotra commentedon Jun 3, 2021
Following configuration helped me resolve the issue with relative URLs due to less-loader + CSS modules (mentioned here)
Hope this helps!