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

URLs are being treated as relative, without relative-url option #112

Closed
bambielli opened this issue Oct 12, 2016 · 12 comments
Closed

URLs are being treated as relative, without relative-url option #112

bambielli opened this issue Oct 12, 2016 · 12 comments

Comments

@bambielli
Copy link

bambielli commented Oct 12, 2016

I'm trying to use the less-loader to load a less file with a url import at the top. This url import is for a file that is hosted elsewhere (on a cdn).

app.less

    @import url("http://cdn-name/mixins.less");

When I try to load this less file with the less-loader, I get the following error:

    ERROR in ./~/css-loader!./~/less-loader!./static-content/less/app.less
    Module build failed: Cannot resolve 'file' or 'directory' ./http://cdn-name/mixins.less 

It appears that the less loader is treating my url import as a relative path, instead of actually detecting that it is its own url that contains a resource to be fetched.

My webpack config looks like this:

    module.exports = {
      entry: {
        bundle: ['./static-content/js/index.js'],
        vendor: ['react', 'react-dom']
      },
      output: {
        path: jsGeneratedPath,
        filename: 'bundle.min.js',
        publicPath: 'http://localhost:8444/assets/',
        hotUpdateChunkFilename: 'hot/js-update.js',
        hotUpdateMainFilename: 'hot/json-update.json',
        recordsPath: path.resolve(__dirname, '/assets/hot/')
      },
      stats: {
        colors: true,
        reasons: true
      },
      module: {
        preLoaders: [
          {
            test: /\.jsx?$/,
            loader: 'eslint-loader',
            exclude: /node_modules/
          }
        ],
        loaders: [
          {
            test: /.js?$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
            progress: true
          },
          {
            test: /.less$/,
            loader: 'style!css!less',
            exclude: /node_modules/,
            progress: true
          }
        ]
      },
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({
          names: ['vendor'],
          minChunks: Infinity,
          filename: '[name].min.js'
        })
      ]
    }

Any thoughts on why this might be happening? I think it might have something to do with the type of file I'm trying to import (a less file) because if I swap my import with a css file instead (hosted on one of google's CDNs for example) then the resolution happens fine.

I've tried with and without quotes around the url.

webpack v 1.13.1
webpack-dev-server v 1.14.1
less loader v 2.2.3

@DNFcode
Copy link

DNFcode commented Oct 26, 2016

As I can tell from source codes relative-url option is set to true by default. You may override it like this:
loader: "style!css!less?relativeUrls=false"

@redboul
Copy link

redboul commented Nov 29, 2016

Hi,

I'm facing the same issue.
Actually, using the lessc compiler directly on the less file produce no error and the generated css is valid.

From what I saw from the code, it comes from the fact that less-loader override the less.FileManager.prototype and file resolution is left to webpack loaderUtils.urlToRequest resolver which does not treat the filename as an external URL and assume it is local.
The generated moduleRequest has a ./ at the beginning afterwards which produce an error when the file is tried to be loaded...

However, I don't know if it is less responsability or webpack's to resolve external URL. I did not see any documentation on that in the resolve section of the webpack documentation.

the same issue occurs on webpack 2.10-beta26

@mediafreakch
Copy link

The same issue arises basically if you want to import a file like @import "config.less" without any path prefix. Normally in with less you would just pass a paths option (in node) like: { paths: [ '/dir/lookhere' ] } or --include-path= (in cli) to tell the less compiler where to look for the files. The less compiler has some default directories it looks in too (works the same way as the node_modules require algorithm).

However due to the fact that less-loader replaces the default less fileManager with it's own, which is then using the loaderUtils.urlToRequest resolver, the whole system breaks. Particularly because of the line @redboul mentioned.

That's really a pitty as I cannot seriously consider using webpack with less until this is fixed!
But I really see this as an issue that has to be fixed by the guys from less-loader or loader-utils packages...

@mediafreakch
Copy link

This should help to reproduce the issue: https://github.com/mediafreakch/webpack-less-loader-bug

@VictorChen
Copy link

Hi, any updates on this? I'm trying to do this:

@import url('https://mycdn.com/test.less');

but it fails with:

@import url('https://mycdn.com/test.less');
^
Can't resolve './https://mycdn.com/test.less' in '/Users/test/some/relative/path/here/src'

@VictorChen
Copy link

VictorChen commented Nov 13, 2017

ah I figured it out! I believe the webpack resolver was the issue. What I did was instead of:

{
  loader: 'less-loader'
}

use:

{
  loader: 'less-loader',
  options: {
    paths: [path.resolve(__dirname, "node_modules")]
  }

By using the paths option, we're basically telling webpack to not use webpack's resolver, see:
https://github.com/webpack-contrib/less-loader#less-resolver

Now, it works when I do:

@import url('https://mycdn.com/test.less');

@go2sujeet
Copy link

go2sujeet commented Feb 21, 2018

+1, I also facing the same issue.
And what about relative path in the less files?

@dhazelett
Copy link

dhazelett commented Apr 19, 2018

The only problem with @VictorChen's solution is that you loose all aliasing; how is this that difficult to fix, seems like it should be pretty simple to see if it starts with a network protocol no?

@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&subset=latin);
^
Can't resolve './https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&subset=latin'

Edit forgot to do my diligence, this is using less-loader@4.1.0

@dhazelett
Copy link

quick update after some more digging around, the workaround that I have for now is this:

e("@import url(https://fonts.googleapis.com/css?family=Lato:400,400i,700,700i)");

@leondeng
Copy link

leondeng commented Sep 18, 2018

try this:
@import (css) url(https://fonts.googleapis.com/css?family=Lato:400,400i,700,700i)

reference: less/less.js#3188

@bawantha
Copy link

try this:
@import (css) url(https://fonts.googleapis.com/css?family=Lato:400,400i,700,700i)

reference: less/less.js#3188

This works perfectly ,thank you

@alexander-akait
Copy link
Member

Fixed in master, release will be soon

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