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

module.generator.asset.publicPath='/' throw error #872

Closed
ckken opened this issue Nov 18, 2021 · 32 comments
Closed

module.generator.asset.publicPath='/' throw error #872

ckken opened this issue Nov 18, 2021 · 32 comments

Comments

@ckken
Copy link

ckken commented Nov 18, 2021

Bug report

{
    module: {
      // mini-css-extract-plugin HookWebpackError: Invalid URL: /assets/logo.635a60f2.jpg
      generator: {
        asset: {
          publicPath: '/',
        },
      },
    },
   output:{
        publicPath:'auto'
   }
}

Actual Behavior

image

Expected Behavior

image

How Do We Reproduce?

{
    module: {
      generator: {
        asset: {
          publicPath: '/',
        },
      },
    },
   output:{
        publicPath:'auto'
   }
}
<!-- A great way to do this is to provide your configuration via a GitHub repository -->
<!-- The most helpful is a minimal reproduction with instructions on how to reproduce -->
<!-- Repositories with too many files or large `webpack.config.js` files are not suitable -->
<!-- Please only add small code snippets directly into this issue -->
<!-- https://gist.github.com is a good place for longer code snippets -->
<!-- If your issue is caused by a plugin or loader, please create an issue on the loader/plugin repository instead -->

### Please paste the results of `npx webpack-cli info` here, and mention other relevant information
@alexander-akait
Copy link
Member

alexander-akait commented Nov 18, 2021

Please fill out all fields

@ckken
Copy link
Author

ckken commented Nov 20, 2021

@alexander-akait
Copy link
Member

Remove:

 generator: {
      'asset/resource': {
        publicPath: '/',
      },
    },

Yes says webpack to have auto public path and override it for CSS, it is not good

@Clarkkkk
Copy link

Clarkkkk commented Dec 1, 2021

It works without specifying the publicPath. But I still don't understand why the publicPath should not be specified specifically. (because it works with mini-css-extract-plugin@2.2.0.) Maybe the error message should be more clear, or maybe the doc should mention this situation?

@alexander-akait
Copy link
Member

alexander-akait commented Dec 1, 2021

It is limitation due new URL(...) syntax, because we execute it on Node.js, you see this problem, due invalid public path calculated in new URL(...), anyway in theory we can improve it, can you provide small example? maybe we have bug

@ldrick
Copy link

ldrick commented Dec 9, 2021

Maybe my example from here helps, as it seems the same issue:
webpack/webpack#14920

The repo:
https://github.com/ldrick/webpack_asset_resource

@alexander-akait
Copy link
Member

@ckken You should not use generator in your case, just set

{
  loader: MiniCssExtractPlugin.loader,
  options: {
    publicPath: '/'
  }
},

Why? Because you can't combine auto and /, webpack can't understand how to calculate valid URL

@alexander-akait
Copy link
Member

@ldrick You example is more complex, you try to create relative URL inside auto context, I am afraid it is impossible, when you have auto, webpack calculates URL from output.path and convert them to relative based on output.path, that is why you have

../../../files/themes/mytheme/fontawesome/fa-regular-400.svg#fontawesome

But in context of all styles, you can have other url() and these files can be in other directories. Shorty - you need different public paths for different url(), hard... anyway I think you can achieve it using some hacky things - move fontawesome in separate file and setup MiniCssExtractPlugin.loader (and other loaders) only for fontawesome file like you do it for fonts and use the publicPath option of MiniCssExtractPlugin.loader. I do not test it, but in theory it should works.

@ccy303
Copy link

ccy303 commented Dec 23, 2021

I have the same problem. How to solve it

@samkelleher
Copy link

I have to chime in to say the loss of support for publicPath on the extract plugin causes an incompatibility when importing the same file from both CSS and JavaScript. For example, for a file hosted at /fonts/font.woff, let's say you import font.woff from inside a CSS file, and then inside a JavaScript file. The lost publicPath support means it's impossible for the JavaScript output and the CSS output to resolve the same public path correctly. Trying to use different asset/resource configurations (one for CSS and one for JavaScript issuers) also doesn't work as webpack won't duplicate the imported font file.

With publicPath set to "/fonts/"

import font from "./font.woff";
// font = /fonts/font.woff ✅
@font-face {
  font-family: font;
  src: url("./font.woff") format("woff"); /*** 💥 throws Invalid URL ***/
}

When publicPath not set

import font from "./font.woff";
// font = /font.woff ❌
@font-face {
  font-family: font;
  src: url("./font.woff") format("woff");  /*** ❌ resolves to "/font.woff" ***/
}

When publicPath not set on generator, but set to"/fonts/" on the loader plugin options itself

import font from "./font.woff";
// font = /font.woff ❌
@font-face {
  font-family: font;
  src: url("./font.woff") format("woff"); /*** ✅ resolves to "/fonts/font.woff" ***/
}

@alexander-akait
Copy link
Member

Can you provide full minimum configuration, we have some edge cases... want to investigate

@scarletsky
Copy link

@alexander-akait
To reproduce this issue, the key is you need to set the type to asset/resource and set publicPath in generator. Like this:

{
    module: {
        rules: [
            {
                test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
                type: 'asset/resource',
                generator: {
                    publicPath: '//cdn.example.com/assets/',
                }
            },
        ],
    },
}

Here is a reproducible project:
webpack-mini-css-public-path-issue.zip

Just run yarn install and yarn build you will see the error:

ERROR in ./src/index.css
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
HookWebpackError: Invalid URL: //cdn.example.com/assets/1fcab817090e78435061.svg
....
-- inner error --
TypeError [ERR_INVALID_URL]: Invalid URL: //cdn.example.com/assets/1fcab817090e78435061.svg
...

@alexander-akait
Copy link
Member

alexander-akait commented Jan 14, 2022

@scarletsky Yep, because it is wrong URL, please use https://cdn.example.com/assets/, try to use it in new URL("//cdn.example.com/assets/"), we use new URL(...) for creating asset dependencies, another solution is set public path on loader level, i.e.

{
  loader: MiniCssExtractPlugin.loader,
  options: {
    publicPath: '//cdn.example.com/assets/',
  },
},

@scarletsky
Copy link

scarletsky commented Jan 14, 2022

@alexander-akait Thanks for your reply. It seems the publicPath on loader level can work with background-image: url(xxx), but it does not work with the path import from js.

Just do these changes:

// src/index.js
// import './index.css';
import url from './assets/webpack.svg';

console.log("Hello World!", url);
// webpack.config.js
rules: [
  {
    test: /\.css$/i,
    use: [
      {
        loader: MiniCssExtractPlugin.loader,
        options: {
          publicPath: '//cdn.example.com/assets/',
        },
      },
      'css-loader'
    ],
  },
  {
    test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
    type: 'asset/resource',
  },
]

The publicPath is not work:

cat dist/main.js

(()=>{"use strict";var r,t={347:(r,t,e)=>{r.exports=e.p+"1fcab817090e78435061.svg"}},e={};function o(r){var i=e[r];if(void 0!==i)return i.exports;var n=e[r]={exports:{}};return t[r](n,n.exports,o),n.exports}o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(r){if("object"==typeof window)return window}}(),(()=>{var r;o.g.importScripts&&(r=o.g.location+"");var t=o.g.document;if(!r&&t&&(t.currentScript&&(r=t.currentScript.src),!r)){var e=t.getElementsByTagName("script");e.length&&(r=e[e.length-1].src)}if(!r)throw new Error("Automatic publicPath is not supported in this browser");r=r.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),o.p=r})(),r=o(347),console.log("Hello World!",r)})();%

If we set publicPath in both MiniCssExtractPlugin.Loader options and generator, it will still throw the same Error.

@alexander-akait
Copy link
Member

publicPath on plugin level only for CSS, not for JS, but yes, we need to think how to solve it, that is why it is not closed

@IPRIT
Copy link

IPRIT commented Feb 20, 2022

Any updates? Still a blocking problem right now for us.

@KevinGruber
Copy link

Same for us, it worked in previous versions like a charm and now our Framework can't use publicPath anymore because of that limitation.

How is it meant to use different runtime publicPaths for different resources then?

BR,
Kev

@alexander-akait
Copy link
Member

There is solution #915

@alexander-akait
Copy link
Member

@s3curitybug
Copy link

It still does not work for me with v2.6.0.

@alexander-akait
Copy link
Member

@s3curitybug Can you provide reproducible example?

@vankop
Copy link
Contributor

vankop commented Mar 4, 2022

@s3curitybug you need to upgrade webpack to 5.70 also.

@s3curitybug
Copy link

I reduced my project to the minimum possible:
https://github.com/s3curitybug/test-mini-css-extract-plugin

This works with v2.3.0, but does not with newer ones (even with webpack 5.70).

@vankop
Copy link
Contributor

vankop commented Mar 4, 2022

@alexander-akait I think this related to css-loader

var ___CSS_LOADER_URL_IMPORT_0___ = new URL(
/* asset import */ __webpack_require__("asset/resource|/Users/ivankopeykin/Repositories/test-mini-css-extract-plugin/src/main/front/style/fonts/S6u8w4BMUTPHjxsAUi-qJCY.woff2")
, __webpack_require__.b);

@alexander-akait
Copy link
Member

alexander-akait commented Mar 4, 2022

@vankop But we don't do nothing special in css-loader, just convert url() to new URL(...)

@vankop
Copy link
Contributor

vankop commented Mar 4, 2022

@alexander-akait yeah, I found a problem.

@vankop
Copy link
Contributor

vankop commented Apr 1, 2022

should work with webpack/webpack#15613

@scarletsky
Copy link

scarletsky commented Apr 2, 2022

Here is a reproducible project: webpack-mini-css-public-path-issue.zip

It works after upgrading webpack 5.71.0 + mini-css-extract-plugin 2.6.0.


My webpack.config.js is:

{
    test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
    type: 'asset/resource',
    generator: {
        publicPath: '//cdn.example.com/assets/',
        filename: `[name].[hash:8][ext]`
    }
}

But the output miss //:

$ cat dist/main.css
body {
  background-image: url(cdn.example.com/assets/webpack.1fcab817.svg);
}

@alexander-akait
Copy link
Member

@vankop Still buggy?

@vankop
Copy link
Contributor

vankop commented Apr 2, 2022

publicPath: '//cdn.example.com/assets/',

hm.. with one leading slash works fine..

@s3curitybug
Copy link

it works now for me :)

@alexander-akait
Copy link
Member

Closing due to inactivity. Please test with latest version and feel free to reopen if still regressions. Thanks!

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