mini-css-extract-plugin icon indicating copy to clipboard operation
mini-css-extract-plugin copied to clipboard

External assets' urls get prefixed with "webpack:///mini-css-extract-plugin/"

Open yoannmoinet opened this issue 2 years ago • 17 comments

Bug report

Once built our CSS file tries to load external assets from webpack:///mini-css-extract-plugin/<actual url>.

It happens to fonts that loads with a relative path. But not when the font loads from an absolute path (eg. Google Fonts)

Actual Behavior

External assets' urls, when not absolute, are prefixed with webpack:///mini-css-extract-plugin/.

Expected Behavior

Once exported, the CSS should not have the prefix webpack:///mini-css-extract-plugin/ in the external assets' urls and load the asset as it's configured.

How Do We Reproduce?

Here's our mini-css-extract-plugin config:

new MiniCssExtractPlugin({
    filename: [...],
    chunkFilename: [...],
    attributes: {
        media: 'all'
    },
    ignoreOrder: true
}),

And our loader's configuration:

{
    test: /\.(less|css)$/,
    use: [
        MiniCssExtractPlugin.loader,
        {
            loader: 'css-loader',
            options: {
                sourceMap: true,
                import: false
            }
        },
        {
            loader: 'less-loader',
            options: {
                sourceMap: true,
                lessOptions: {
                    relativeUrls: true
                }
            }
        }
    ]
}

Please paste the results of npx webpack-cli info here, and mention other relevant information

  System:
    OS: macOS 12.3.1
    CPU: (8) x64 Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
    Memory: 331.20 MB / 32.00 GB
  Binaries:
    Node: 16.3.0 - ~/.volta/tools/image/node/16.3.0/bin/node
    Yarn: 3.2.0 - ~/.volta/tools/image/yarn/1.22.18/bin/yarn
    npm: 7.15.1 - ~/.volta/tools/image/node/16.3.0/bin/npm
  Browsers:
    Brave Browser: 101.1.38.109
    Chrome: 101.0.4951.64
    Firefox: 98.0.2
    Safari: 15.4
  Monorepos:
    Yarn Workspaces: 3.2.0

I've managed to "fix" the problem by using experimentalUseImportModule: false in the plugin's configuration.

I'm coming from https://github.com/webpack-contrib/mini-css-extract-plugin/issues/936 as it apparently didn't follow the template, I'm trying to create a correct issue here.

Example of a CSS where you can see both absolute and relative urls
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap');
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Regular-webfont-f2ca9b9f576ab78110a5fdd2477950a4.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Regular-webfont-d0c801fcdde512010a9541ee88fad273.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Regular-webfont-942475f652bbbabd2d3cce5085020560.ttf) format('truetype');
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Bold-webfont-6cd614a680bf9ad4d3c4dbc489cce52b.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Bold-webfont-89f2d03c0fd6881f91f062e3f54574d9.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Bold-webfont-feda1ac068b693c673265c31254fd376.ttf) format('truetype');
  font-weight: bold;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBold-webfont-1aef7e2308de2eea6d9c04a0d9e42e59.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBold-webfont-32cc3d694fd0e73903b137e3707b80ca.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBold-webfont-e2c2bc20049bf8fc82a94927ae111294.ttf) format('truetype');
  font-weight: 600;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Light-webfont-d923425660284e0d066a47a395d65595.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Light-webfont-a7ca6811908abe1695b35f82fa669573.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Light-webfont-e8303047513bc70e9fc6cb1e6c222785.ttf) format('truetype');
  font-weight: 300;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Italic-webfont-5f46ce03d422f513e34a43cf344eb831.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Italic-webfont-8e53d983f215727af85995f8e080e4c6.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Italic-webfont-102f599d6b71b64d0ec7e19e08e92de8.ttf) format('truetype');
  font-style: italic;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-BoldItalic-webfont-317b0ce976190591633c19234fe54190.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-BoldItalic-webfont-f713c40de27886b77b0a997534dccd9f.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-BoldItalic-webfont-087173dea1d4956e0c5b8a31492f3ad9.ttf) format('truetype');
  font-weight: bold;
  font-style: italic;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBoldItalic-webfont-69e481b884bfe32236810da3289300de.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBoldItalic-webfont-2e93ba504a6bd00b870540b2a4feca25.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBoldItalic-webfont-3fda80b8bdf65bfaeee8497d0041320b.ttf) format('truetype');
  font-weight: 600;
  font-style: italic;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-LightItalic-webfont-1ea8d3a02ec18c95b9463d5c1cb2928c.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-LightItalic-webfont-beab8ff982cccf6d2f6a7c3414149754.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-LightItalic-webfont-b1e83b2f2bb6869f046f46a2a60d4a11.ttf) format('truetype');
  font-weight: 300;
  font-style: italic;
}

yoannmoinet avatar May 18 '22 09:05 yoannmoinet

could you provide example css file?

vankop avatar May 18 '22 09:05 vankop

I can give a snippet of one of them.

Click to expand
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap');
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Regular-webfont-f2ca9b9f576ab78110a5fdd2477950a4.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Regular-webfont-d0c801fcdde512010a9541ee88fad273.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Regular-webfont-942475f652bbbabd2d3cce5085020560.ttf) format('truetype');
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Bold-webfont-6cd614a680bf9ad4d3c4dbc489cce52b.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Bold-webfont-89f2d03c0fd6881f91f062e3f54574d9.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Bold-webfont-feda1ac068b693c673265c31254fd376.ttf) format('truetype');
  font-weight: bold;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBold-webfont-1aef7e2308de2eea6d9c04a0d9e42e59.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBold-webfont-32cc3d694fd0e73903b137e3707b80ca.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBold-webfont-e2c2bc20049bf8fc82a94927ae111294.ttf) format('truetype');
  font-weight: 600;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Light-webfont-d923425660284e0d066a47a395d65595.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Light-webfont-a7ca6811908abe1695b35f82fa669573.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Light-webfont-e8303047513bc70e9fc6cb1e6c222785.ttf) format('truetype');
  font-weight: 300;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Italic-webfont-5f46ce03d422f513e34a43cf344eb831.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Italic-webfont-8e53d983f215727af85995f8e080e4c6.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-Italic-webfont-102f599d6b71b64d0ec7e19e08e92de8.ttf) format('truetype');
  font-style: italic;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-BoldItalic-webfont-317b0ce976190591633c19234fe54190.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-BoldItalic-webfont-f713c40de27886b77b0a997534dccd9f.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-BoldItalic-webfont-087173dea1d4956e0c5b8a31492f3ad9.ttf) format('truetype');
  font-weight: bold;
  font-style: italic;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBoldItalic-webfont-69e481b884bfe32236810da3289300de.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBoldItalic-webfont-2e93ba504a6bd00b870540b2a4feca25.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-SemiBoldItalic-webfont-3fda80b8bdf65bfaeee8497d0041320b.ttf) format('truetype');
  font-weight: 600;
  font-style: italic;
}
@font-face {
  font-family: 'NotoSans';
  font-style: normal;
  font-weight: normal;
  src: url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-LightItalic-webfont-1ea8d3a02ec18c95b9463d5c1cb2928c.woff2) format('woff2'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-LightItalic-webfont-beab8ff982cccf6d2f6a7c3414149754.woff) format('woff'), url(webpack:///mini-css-extract-plugin//static/v/33.dev0/js/NotoSans-LightItalic-webfont-b1e83b2f2bb6869f046f46a2a60d4a11.ttf) format('truetype');
  font-weight: 300;
  font-style: italic;
}

Adding it to the main issue's description.

yoannmoinet avatar May 18 '22 09:05 yoannmoinet

@yoannmoinet I mean original one, that you are using in your application and can you provide full list of module.rules

vankop avatar May 18 '22 10:05 vankop

full list of module.rules

It's not shareable, it's 300+ line of codes, relies on outside functions, and it's private. So I've shared the relevant part, the only rules applied to .less files.

We have two others that may be related to assets:

{
    resourceQuery: /raw/,
    type: 'asset/source'
},
{
    test: /\.(png|jpg|gif|woff2|woff|eot|ttf|mp4|webm|cur|)$/,
    use: {
        loader: 'file-loader',
        options: {
            name: `${destination.chunk}/[name]-[hash].[ext]`
        }
    }
},

With destination.chunk = 'c'

I mean original one

Here's a snippet of the less code that generates the faulty CSS.

// Parametric mixin to generate the static urls for web fonts
.webfont(@family, @file, @name) {
    @f: %('~[...local-assets-path...]/%s', @file);
    @woff2: %('%s.woff2', @f);
    @woff: %('%s.woff', @f);
    @ttf: %('%s.ttf', @f);

    font-family: @family;
    font-style: normal;
    font-weight: normal;
    src: url(@woff2) format('woff2'), url(@woff) format('woff'),
        url(@ttf) format('truetype');
}

@font-face {
    .webfont('NotoSans', 'NotoSans-Regular-webfont', 'NotoSansRegular');
}

@import (css)
    url('https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap');

yoannmoinet avatar May 18 '22 12:05 yoannmoinet

Please add resourceQuery: { not: [/raw/] }, for file-loader, described here https://webpack.js.org/guides/asset-modules/#replacing-inline-loader-syntax

alexander-akait avatar May 18 '22 13:05 alexander-akait

You just apply two loader for the same file

alexander-akait avatar May 18 '22 13:05 alexander-akait

Please add resourceQuery: { not: [/raw/] }, for file-loader

Thanks for the tip. Just to note that it doesn't fix the issue though.

yoannmoinet avatar May 18 '22 14:05 yoannmoinet

@yoannmoinet, why you use file-loader? It is deprecated and should be removed, anyway you miss type: 'javascript/auto', you can found all cases https://webpack.js.org/guides/asset-modules/.

As alternative solutions you can set esModule: false for css-loader and mini-css-extrat-plugin, so we will generate require for assets

alexander-akait avatar May 18 '22 14:05 alexander-akait

{
    test: /\.(woff2|woff|ttf)$/,
    type: "asset"
},
{
    resourceQuery: /raw/,
    type: 'asset/source'
},

you can just use type: asset instead of file-loader also you can control naming by assetFilename https://webpack.js.org/guides/asset-modules/#custom-output-filename


but I'm not sure that this will resolve problem..

vankop avatar May 19 '22 07:05 vankop

bumped into the same issue while importing css in nextjs app.

lxndr avatar Jul 11 '22 08:07 lxndr

@lxndr could you create reproducible repo?

vankop avatar Jul 11 '22 09:07 vankop

I had this issue with nextjs importing minified css from a node_module using webpack 5. I'm not at all clear yet which of nextjs, mini-css-extract-plugin or myself were to blame. I'll try to put together a minimal example.

However, since this is a top result on google I can say at this point that adding

config.module.generator.asset.publicPath = "/_next/";

to next.config.js to force the public path made the problem go away!

PeterBerryman avatar Sep 21 '22 16:09 PeterBerryman