mini-css-extract-plugin
mini-css-extract-plugin copied to clipboard
Wrong path for assets inside css files, when use subfolder for css files
Bug report
Actual Behavior
For begin I set a publicPath for my assets (ex fonts) :
test: /\.(eot|ttf|otf|woff|woff2)$/i,
type: 'asset/resource',
generator: {
publicPath: '/dist/fonts/',
outputPath: './fonts/',
},
When I set no subfolder for my css files it's work fine :
new MiniCssExtractPlugin({filename: "[name].css"}),
And I got the right path in my css files :
@font-face
{
font-family: 'Poppins';
src: url(/dist/fonts/3bd71aafa4de4b4a8875.eot);
src: url(/dist/fonts/3bd71aafa4de4b4a8875.eot?#iefix) format('embedded-opentype'),
url(/dist/fonts/e9b88d1590baa248f3e2.woff2) format('woff2'),
url(/dist/fonts/081fa188b65fb4393803.woff) format('woff'),
url(/dist/fonts/5c210093630fe230c462.ttf) format('truetype');
font-weight: 300;
font-style: normal;
}
But now if I want to put my css files into a subfolder like css/myfiles.css :
new MiniCssExtractPlugin({filename: "css/[name].css"}),
I get wrong path in my css files :
@font-face
{
font-family: 'Poppins';
src: url(..//dist/fonts/3bd71aafa4de4b4a8875.eot);
src: url(..//dist/fonts/3bd71aafa4de4b4a8875.eot?#iefix) format('embedded-opentype'),
url(..//dist/fonts/e9b88d1590baa248f3e2.woff2) format('woff2'),
url(..//dist/fonts/081fa188b65fb4393803.woff) format('woff'),
url(..//dist/fonts/5c210093630fe230c462.ttf) format('truetype');
font-weight: 300;
font-style: normal;
}
Expected Behavior
When I use subfolder for my css files the path of my fonts inside my css files must be only /dist/fonts/, but actually ../ are added in addition.
Please paste the results of npx webpack-cli info here, and mention other relevant information
System: OS: Linux 4.4 Debian GNU/Linux 10 (buster) 10 (buster) CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz Memory: 8.02 GB / 15.89 GB Binaries: Node: 18.12.1 - ~/.nvm/versions/node/v18.12.1/bin/node npm: 9.2.0 - ~/.nvm/versions/node/v18.12.1/bin/npm Packages: @webpack-cli/generators: ^3.0.1 => 3.0.1 babel-loader: ^9.1.0 => 9.1.0 copy-webpack-plugin: ^11.0.0 => 11.0.0 css-loader: ^6.7.3 => 6.7.3 html-webpack-plugin: ^5.5.0 => 5.5.0 style-loader: ^3.3.1 => 3.3.1 terser-webpack-plugin: ^5.3.6 => 5.3.6 webpack: ^5.75.0 => 5.75.0 webpack-cli: ^5.0.1 => 5.0.1 webpack-dev-server: ^4.11.1 => 4.11.1 webpack-manifest-plugin: ^5.0.0 => 5.0.0 workbox-webpack-plugin: ^6.5.4 => 6.5.4 Global Packages: webpack-cli: 5.0.1 webpack: 5.75.0
Thanks
Please creare repdocuible test repo, I think you have a problem with public path
I happen to have run into the same issue and put together a reproduction repo: https://github.com/vetruvet/mini-css-extract-public-path-bug
In digging into the issue, I've found some seemingly useful information (not enough for me to propose a fix though):
- When this plugin's loader runs
importModule, it passesABSOLUTE_PUBLIC_PATH(webpack:///mini-css-extract-plugin/) as thepublicPath - When the webpack asset module rule has a
publicPath(that overrides the fulloutput.publicPath), webpack's AssetGenerator will put that in the generated code instead of apublicPath + filenameexpression. This causes theABSOLUTE_PUBLIC_PATHto not be used, and insteadBASE_URI(webpack://) - When this plugin then does replacement of the
webpack://URIs, it ends up trying to make a relative path from the CSS file to the asset usinggetUndoPath, but (at least in the reproduction repo) it ends up being../and then the asset rule'spublicPathand file name get appended to that. In the case of the reproduction repo, it would need to be../../. - This only happens when the CSS file is output into a subfolder. Otherwise
getUndoPathreturns an empty string, and the asset rule'spublicPathis not prepended with../
I'm not sure where a proper fix would be, but hopefully that info at least helps.
@WebCimes as a workaround what I've done is make output.assetModuleFilename a function and not use the outputPath or publicPath options on the asset rule e.g.
assetModuleFilename: ({ filename }) => `${/\.(eot|ttf|otf|woff|woff2)$/i.test(filename) ? 'fonts/' : ''}[name][ext]`,
@vetruvet thanks for your reproduction repo and your great explanation of the problem, I hope someone could correct the bug. Also thanks for your workaround who works well, but finnaly I have also find another easy workaround (similary to yours), like you said I don't use outputPath or publicPath, and I add the subfolder for my asset directly inside the generator.filename :
{ test: /\.(eot|ttf|otf|woff|woff2)$/i, type: 'asset/resource', generator: { // publicPath: '/dist/fonts/', // outputPath: './fonts/', filename: 'fonts/[name][ext][query]', }, },
I encountered this issue after enabling esModule and module.namedExport in css-loader. While the above workarounds were not really applicable to my config, I found the setting experimentalUseImportModule: false bypasses the bad code in question and resolved my issue.
@MLoughry You should not use experimentalUseImportModule