mini-css-extract-plugin
mini-css-extract-plugin copied to clipboard
module.generator.asset.publicPath='/' throw error
Bug report
{
module: {
// mini-css-extract-plugin HookWebpackError: Invalid URL: /assets/logo.635a60f2.jpg
generator: {
asset: {
publicPath: '/',
},
},
},
output:{
publicPath:'auto'
}
}
Actual Behavior
Expected Behavior
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
Please fill out all fields
https://github.com/ckken/webpack-boilerplate thanks reply
Remove:
generator: {
'asset/resource': {
publicPath: '/',
},
},
Yes says webpack to have auto public path and override it for CSS, it is not good
It works without specifying the publicPath
. But I still don't understand why the publicPath
should not be specified specifically. (because it works with [email protected]
.) Maybe the error message should be more clear, or maybe the doc should mention this situation?
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
Maybe my example from here helps, as it seems the same issue: https://github.com/webpack/webpack/discussions/14920
The repo: https://github.com/ldrick/webpack_asset_resource
@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
@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.
I have the same problem. How to solve it
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" ***/
}
Can you provide full minimum configuration, we have some edge cases... want to investigate
@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
...
@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/',
},
},
@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.
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
Any updates? Still a blocking problem right now for us.
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
There is solution https://github.com/webpack-contrib/mini-css-extract-plugin/pull/915
Somebody can try https://github.com/webpack-contrib/mini-css-extract-plugin/releases/tag/v2.6.0?
It still does not work for me with v2.6.0.
@s3curitybug Can you provide reproducible example?
@s3curitybug you need to upgrade webpack to 5.70 also.
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).
@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);
@vankop But we don't do nothing special in css-loader, just convert url()
to new URL(...)
@alexander-akait yeah, I found a problem.
should work with https://github.com/webpack/webpack/discussions/15613
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);
}
@vankop Still buggy?
publicPath: '//cdn.example.com/assets/',
hm.. with one leading slash works fine..