jantimon / favicons-webpack-plugin

Let webpack generate all your favicons and icons for you
MIT License
1.21k stars 210 forks source link

Support Webpack 5 #222

Closed adp-psych closed 3 years ago

adp-psych commented 4 years ago

This plugin doesn’t work with Webpack 5. Here’s a minimal example of how it fails:

[user@academic:~/favicons-webpack-plugin-webpack-5-example]% cat webpack.config.js 
const HtmlPlugin = require('html-webpack-plugin');
const FaviconsPlugin = require('favicons-webpack-plugin');

module.exports = {
    plugins: [
        new HtmlPlugin(),
        new FaviconsPlugin(),
    ],
};
[user@academic:~/favicons-webpack-plugin-webpack-5-example]% cat package.json 
{
  "name": "favicons-webpack-plugin-webpack-5-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "favicons-webpack-plugin": "^4.2.0",
    "html-webpack-plugin": "^4.3.0",
    "webpack": "^5.0.0-beta.28",
    "webpack-cli": "^3.3.12"
  }
}
[user@academic:~/favicons-webpack-plugin-webpack-5-example]% npx webpack                   
(node:372532) [DEP_WEBPACK_MAIN_TEMPLATE_GET_ASSET_PATH] DeprecationWarning: MainTemplate.getAssetPath is deprecated (use Compilation.getAssetPath instead)
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:372532) [DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_HASH] DeprecationWarning: [hash] is now [fullhash] (also consider using [chunkhash] or [contenthash], see documentation for details)
(node:372532) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'assets' of undefined
    at /home/user/favicons-webpack-plugin-webpack-5-example/node_modules/favicons-webpack-plugin/src/compiler.js:69:47
    at /home/user/favicons-webpack-plugin-webpack-5-example/node_modules/webpack/lib/Compiler.js:486:11
    at /home/user/favicons-webpack-plugin-webpack-5-example/node_modules/webpack/lib/Compiler.js:981:17
    at eval (eval at create (/home/user/favicons-webpack-plugin-webpack-5-example/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:13:1)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:372532) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:372532) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
[user@academic:~/favicons-webpack-plugin-webpack-5-example]% node --no-deprecation node_modules/.bin/webpack
(node:373112) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'assets' of undefined
    at /home/user/favicons-webpack-plugin-webpack-5-example/node_modules/favicons-webpack-plugin/src/compiler.js:69:47
    at /home/user/favicons-webpack-plugin-webpack-5-example/node_modules/webpack/lib/Compiler.js:486:11
    at /home/user/favicons-webpack-plugin-webpack-5-example/node_modules/webpack/lib/Compiler.js:981:17
    at eval (eval at create (/home/user/favicons-webpack-plugin-webpack-5-example/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:13:1)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:373112) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
[user@academic:~/favicons-webpack-plugin-webpack-5-example]% 
jantimon commented 4 years ago

Thanks for reporting 👍

Could you provide a pull request?

adp-psych commented 4 years ago

I tried to fix it, but I don’t know enough about Webpack plugins.

The problem seems to be in src/complier.js, in extractAssetFromCompilation(). In Webpack 4, eval(content) returns a useful object, but in Webpack 5, it returns undefined.

Here’s what gets evaluated in Webpack 4 (with contents fields replaced with empty strings):

/******/ (function(modules) { // webpackBootstrap
/******/    // The module cache
/******/    var installedModules = {};
/******/
/******/    // The require function
/******/    function __webpack_require__(moduleId) {
/******/
/******/        // Check if module is in cache
/******/        if(installedModules[moduleId]) {
/******/            return installedModules[moduleId].exports;
/******/        }
/******/        // Create a new module (and put it into the cache)
/******/        var module = installedModules[moduleId] = {
/******/            i: moduleId,
/******/            l: false,
/******/            exports: {}
/******/        };
/******/
/******/        // Execute the module function
/******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/        // Flag the module as loaded
/******/        module.l = true;
/******/
/******/        // Return the exports of the module
/******/        return module.exports;
/******/    }
/******/
/******/
/******/    // expose the modules object (__webpack_modules__)
/******/    __webpack_require__.m = modules;
/******/
/******/    // expose the module cache
/******/    __webpack_require__.c = installedModules;
/******/
/******/    // define getter function for harmony exports
/******/    __webpack_require__.d = function(exports, name, getter) {
/******/        if(!__webpack_require__.o(exports, name)) {
/******/            Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/        }
/******/    };
/******/
/******/    // define __esModule on exports
/******/    __webpack_require__.r = function(exports) {
/******/        if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/            Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/        }
/******/        Object.defineProperty(exports, '__esModule', { value: true });
/******/    };
/******/
/******/    // create a fake namespace object
/******/    // mode & 1: value is a module id, require it
/******/    // mode & 2: merge all properties of value into the ns
/******/    // mode & 4: return value when already ns object
/******/    // mode & 8|1: behave like require
/******/    __webpack_require__.t = function(value, mode) {
/******/        if(mode & 1) value = __webpack_require__(value);
/******/        if(mode & 8) return value;
/******/        if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/        var ns = Object.create(null);
/******/        __webpack_require__.r(ns);
/******/        Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/        if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/        return ns;
/******/    };
/******/
/******/    // getDefaultExport function for compatibility with non-harmony modules
/******/    __webpack_require__.n = function(module) {
/******/        var getter = module && module.__esModule ?
/******/            function getDefault() { return module['default']; } :
/******/            function getModuleExports() { return module; };
/******/        __webpack_require__.d(getter, 'a', getter);
/******/        return getter;
/******/    };
/******/
/******/    // Object.prototype.hasOwnProperty.call
/******/    __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "/";
/******/
/******/
/******/    // Load entry module and return exports
/******/    return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {

module.exports = {"tags":["<link rel=\"shortcut icon\" href=\"/assets/favicon.ico\">","<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/assets/favicon-16x16.png\">","<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/assets/favicon-32x32.png\">","<link rel=\"icon\" type=\"image/png\" sizes=\"48x48\" href=\"/assets/favicon-48x48.png\">","<link rel=\"manifest\" href=\"/assets/manifest.json\">","<meta name=\"mobile-web-app-capable\" content=\"yes\">","<meta name=\"theme-color\" content=\"#fff\">","<meta name=\"application-name\" content=\"favicons-webpack-plugin-webpack-4-example\">","<link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"/assets/apple-touch-icon-57x57.png\">","<link rel=\"apple-touch-icon\" sizes=\"60x60\" href=\"/assets/apple-touch-icon-60x60.png\">","<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"/assets/apple-touch-icon-72x72.png\">","<link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"/assets/apple-touch-icon-76x76.png\">","<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"/assets/apple-touch-icon-114x114.png\">","<link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"/assets/apple-touch-icon-120x120.png\">","<link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"/assets/apple-touch-icon-144x144.png\">","<link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"/assets/apple-touch-icon-152x152.png\">","<link rel=\"apple-touch-icon\" sizes=\"167x167\" href=\"/assets/apple-touch-icon-167x167.png\">","<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/assets/apple-touch-icon-180x180.png\">","<link rel=\"apple-touch-icon\" sizes=\"1024x1024\" href=\"/assets/apple-touch-icon-1024x1024.png\">","<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">","<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">","<meta name=\"apple-mobile-web-app-title\" content=\"favicons-webpack-plugin-webpack-4-example\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"    href=\"/assets/apple-touch-startup-image-640x1136.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"    href=\"/assets/apple-touch-startup-image-750x1334.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"    href=\"/assets/apple-touch-startup-image-828x1792.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)\"    href=\"/assets/apple-touch-startup-image-1125x2436.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)\"    href=\"/assets/apple-touch-startup-image-1242x2208.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)\"    href=\"/assets/apple-touch-startup-image-1242x2688.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"   href=\"/assets/apple-touch-startup-image-1536x2048.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"   href=\"/assets/apple-touch-startup-image-1668x2224.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"   href=\"/assets/apple-touch-startup-image-1668x2388.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"  href=\"/assets/apple-touch-startup-image-2048x2732.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"  href=\"/assets/apple-touch-startup-image-1620x2160.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"   href=\"/assets/apple-touch-startup-image-1136x640.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"   href=\"/assets/apple-touch-startup-image-1334x750.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"   href=\"/assets/apple-touch-startup-image-1792x828.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)\"   href=\"/assets/apple-touch-startup-image-2436x1125.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)\"   href=\"/assets/apple-touch-startup-image-2208x1242.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)\"   href=\"/assets/apple-touch-startup-image-2688x1242.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"  href=\"/assets/apple-touch-startup-image-2048x1536.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"  href=\"/assets/apple-touch-startup-image-2224x1668.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"  href=\"/assets/apple-touch-startup-image-2388x1668.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\" href=\"/assets/apple-touch-startup-image-2732x2048.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"  href=\"/assets/apple-touch-startup-image-2160x1620.png\">","<link rel=\"icon\" type=\"image/png\" sizes=\"228x228\" href=\"/assets/coast-228x228.png\">","<meta name=\"msapplication-TileColor\" content=\"#fff\">","<meta name=\"msapplication-TileImage\" content=\"/assets/mstile-144x144.png\">","<meta name=\"msapplication-config\" content=\"/assets/browserconfig.xml\">","<link rel=\"yandex-tableau-widget\" href=\"/assets/yandex-browser-manifest.json\">"],"assets":[{"name":"assets/favicon-16x16.png","contents":""},{"name":"assets/favicon-32x32.png","contents":""},{"name":"assets/favicon-48x48.png","contents":""},{"name":"assets/favicon.ico","contents":""},{"name":"assets/android-chrome-36x36.png","contents":""},{"name":"assets/android-chrome-48x48.png","contents":""},{"name":"assets/android-chrome-72x72.png","contents":""},{"name":"assets/android-chrome-96x96.png","contents":""},{"name":"assets/android-chrome-144x144.png","contents":""},{"name":"assets/android-chrome-192x192.png","contents":""},{"name":"assets/android-chrome-256x256.png","contents":""},{"name":"assets/android-chrome-384x384.png","contents":""},{"name":"assets/android-chrome-512x512.png","contents":""},{"name":"assets/apple-touch-icon-57x57.png","contents":""},{"name":"assets/apple-touch-icon-60x60.png","contents":""},{"name":"assets/apple-touch-icon-72x72.png","contents":""},{"name":"assets/apple-touch-icon-76x76.png","contents":""},{"name":"assets/apple-touch-icon-114x114.png","contents":""},{"name":"assets/apple-touch-icon-120x120.png","contents":""},{"name":"assets/apple-touch-icon-144x144.png","contents":""},{"name":"assets/apple-touch-icon-152x152.png","contents":""},{"name":"assets/apple-touch-icon-167x167.png","contents":""},{"name":"assets/apple-touch-icon-180x180.png","contents":""},{"name":"assets/apple-touch-icon-1024x1024.png","contents":""},{"name":"assets/apple-touch-icon.png","contents":""},{"name":"assets/apple-touch-icon-precomposed.png","contents":""},{"name":"assets/apple-touch-startup-image-640x1136.png","contents":""},{"name":"assets/apple-touch-startup-image-750x1334.png","contents":""},{"name":"assets/apple-touch-startup-image-828x1792.png","contents":""},{"name":"assets/apple-touch-startup-image-1125x2436.png","contents":""},{"name":"assets/apple-touch-startup-image-1242x2208.png","contents":""},{"name":"assets/apple-touch-startup-image-1242x2688.png","contents":""},{"name":"assets/apple-touch-startup-image-1536x2048.png","contents":""},{"name":"assets/apple-touch-startup-image-1668x2224.png","contents":""},{"name":"assets/apple-touch-startup-image-1668x2388.png","contents":""},{"name":"assets/apple-touch-startup-image-2048x2732.png","contents":""},{"name":"assets/apple-touch-startup-image-1136x640.png","contents":""},{"name":"assets/apple-touch-startup-image-2160x1620.png","contents":""},{"name":"assets/apple-touch-startup-image-1620x2160.png","contents":""},{"name":"assets/apple-touch-startup-image-1334x750.png","contents":""},{"name":"assets/apple-touch-startup-image-1792x828.png","contents":""},{"name":"assets/apple-touch-startup-image-2436x1125.png","contents":""},{"name":"assets/apple-touch-startup-image-2208x1242.png","contents":""},{"name":"assets/apple-touch-startup-image-2688x1242.png","contents":""},{"name":"assets/apple-touch-startup-image-2048x1536.png","contents":""},{"name":"assets/apple-touch-startup-image-2224x1668.png","contents":""},{"name":"assets/apple-touch-startup-image-2388x1668.png","contents":""},{"name":"assets/apple-touch-startup-image-2732x2048.png","contents":""},{"name":"assets/coast-228x228.png","contents":""},{"name":"assets/firefox_app_60x60.png","contents":""},{"name":"assets/firefox_app_128x128.png","contents":""},{"name":"assets/firefox_app_512x512.png","contents":""},{"name":"assets/mstile-70x70.png","contents":""},{"name":"assets/mstile-144x144.png","contents":""},{"name":"assets/mstile-150x150.png","contents":""},{"name":"assets/mstile-310x150.png","contents":""},{"name":"assets/mstile-310x310.png","contents":""},{"name":"assets/yandex-browser-50x50.png","contents":""},{"name":"assets/manifest.json","contents":""},{"name":"assets/manifest.webapp","contents":""},{"name":"assets/browserconfig.xml","contents":""},{"name":"assets/yandex-browser-manifest.json","contents":""}]};

/***/ })
/******/ ]);

And here’s what gets evaluated in Webpack 5 (with contents fields replaced with empty strings):

/******/ (function() { // webpackBootstrap
/******/    var __webpack_modules__ = ({

/***/ 642:
/***/ (function(module) {

module.exports = {"tags":["<link rel=\"shortcut icon\" href=\"assets/favicon.ico\">","<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"assets/favicon-16x16.png\">","<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"assets/favicon-32x32.png\">","<link rel=\"icon\" type=\"image/png\" sizes=\"48x48\" href=\"assets/favicon-48x48.png\">","<link rel=\"manifest\" href=\"assets/manifest.json\">","<meta name=\"mobile-web-app-capable\" content=\"yes\">","<meta name=\"theme-color\" content=\"#fff\">","<meta name=\"application-name\" content=\"favicons-webpack-plugin-webpack-5-example\">","<link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"assets/apple-touch-icon-57x57.png\">","<link rel=\"apple-touch-icon\" sizes=\"60x60\" href=\"assets/apple-touch-icon-60x60.png\">","<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"assets/apple-touch-icon-72x72.png\">","<link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"assets/apple-touch-icon-76x76.png\">","<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"assets/apple-touch-icon-114x114.png\">","<link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"assets/apple-touch-icon-120x120.png\">","<link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"assets/apple-touch-icon-144x144.png\">","<link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"assets/apple-touch-icon-152x152.png\">","<link rel=\"apple-touch-icon\" sizes=\"167x167\" href=\"assets/apple-touch-icon-167x167.png\">","<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"assets/apple-touch-icon-180x180.png\">","<link rel=\"apple-touch-icon\" sizes=\"1024x1024\" href=\"assets/apple-touch-icon-1024x1024.png\">","<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">","<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">","<meta name=\"apple-mobile-web-app-title\" content=\"favicons-webpack-plugin-webpack-5-example\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"    href=\"assets/apple-touch-startup-image-640x1136.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"    href=\"assets/apple-touch-startup-image-750x1334.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"    href=\"assets/apple-touch-startup-image-828x1792.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)\"    href=\"assets/apple-touch-startup-image-1125x2436.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)\"    href=\"assets/apple-touch-startup-image-1242x2208.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)\"    href=\"assets/apple-touch-startup-image-1242x2688.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"   href=\"assets/apple-touch-startup-image-1536x2048.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"   href=\"assets/apple-touch-startup-image-1668x2224.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"   href=\"assets/apple-touch-startup-image-1668x2388.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"  href=\"assets/apple-touch-startup-image-2048x2732.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)\"  href=\"assets/apple-touch-startup-image-1620x2160.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"   href=\"assets/apple-touch-startup-image-1136x640.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"   href=\"assets/apple-touch-startup-image-1334x750.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"   href=\"assets/apple-touch-startup-image-1792x828.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)\"   href=\"assets/apple-touch-startup-image-2436x1125.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)\"   href=\"assets/apple-touch-startup-image-2208x1242.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)\"   href=\"assets/apple-touch-startup-image-2688x1242.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"  href=\"assets/apple-touch-startup-image-2048x1536.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"  href=\"assets/apple-touch-startup-image-2224x1668.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"  href=\"assets/apple-touch-startup-image-2388x1668.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\" href=\"assets/apple-touch-startup-image-2732x2048.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)\"  href=\"assets/apple-touch-startup-image-2160x1620.png\">","<link rel=\"icon\" type=\"image/png\" sizes=\"228x228\" href=\"assets/coast-228x228.png\">","<meta name=\"msapplication-TileColor\" content=\"#fff\">","<meta name=\"msapplication-TileImage\" content=\"assets/mstile-144x144.png\">","<meta name=\"msapplication-config\" content=\"assets/browserconfig.xml\">","<link rel=\"yandex-tableau-widget\" href=\"assets/yandex-browser-manifest.json\">"],"assets":[{"name":"assets/favicon-16x16.png","contents":""},{"name":"assets/favicon-32x32.png","contents":""},{"name":"assets/favicon-48x48.png","contents":""},{"name":"assets/favicon.ico","contents":""},{"name":"assets/android-chrome-36x36.png","contents":""},{"name":"assets/android-chrome-48x48.png","contents":""},{"name":"assets/android-chrome-72x72.png","contents":""},{"name":"assets/android-chrome-96x96.png","contents":""},{"name":"assets/android-chrome-144x144.png","contents":""},{"name":"assets/android-chrome-192x192.png","contents":""},{"name":"assets/android-chrome-256x256.png","contents":""},{"name":"assets/android-chrome-384x384.png","contents":""},{"name":"assets/android-chrome-512x512.png","contents":""},{"name":"assets/apple-touch-icon-57x57.png","contents":""},{"name":"assets/apple-touch-icon-60x60.png","contents":""},{"name":"assets/apple-touch-icon-72x72.png","contents":""},{"name":"assets/apple-touch-icon-76x76.png","contents":""},{"name":"assets/apple-touch-icon-114x114.png","contents":""},{"name":"assets/apple-touch-icon-120x120.png","contents":""},{"name":"assets/apple-touch-icon-144x144.png","contents":""},{"name":"assets/apple-touch-icon-152x152.png","contents":""},{"name":"assets/apple-touch-icon-167x167.png","contents":""},{"name":"assets/apple-touch-icon-180x180.png","contents":""},{"name":"assets/apple-touch-icon-1024x1024.png","contents":""},{"name":"assets/apple-touch-icon.png","contents":""},{"name":"assets/apple-touch-icon-precomposed.png","contents":""},{"name":"assets/apple-touch-startup-image-640x1136.png","contents":""},{"name":"assets/apple-touch-startup-image-750x1334.png","contents":""},{"name":"assets/apple-touch-startup-image-828x1792.png","contents":""},{"name":"assets/apple-touch-startup-image-1125x2436.png","contents":""},{"name":"assets/apple-touch-startup-image-1242x2208.png","contents":""},{"name":"assets/apple-touch-startup-image-1242x2688.png","contents":""},{"name":"assets/apple-touch-startup-image-1536x2048.png","contents":""},{"name":"assets/apple-touch-startup-image-1668x2224.png","contents":""},{"name":"assets/apple-touch-startup-image-1668x2388.png","contents":""},{"name":"assets/apple-touch-startup-image-2048x2732.png","contents":""},{"name":"assets/apple-touch-startup-image-1136x640.png","contents":""},{"name":"assets/apple-touch-startup-image-2160x1620.png","contents":""},{"name":"assets/apple-touch-startup-image-1620x2160.png","contents":""},{"name":"assets/apple-touch-startup-image-1334x750.png","contents":""},{"name":"assets/apple-touch-startup-image-1792x828.png","contents":""},{"name":"assets/apple-touch-startup-image-2436x1125.png","contents":""},{"name":"assets/apple-touch-startup-image-2208x1242.png","contents":""},{"name":"assets/apple-touch-startup-image-2688x1242.png","contents":""},{"name":"assets/apple-touch-startup-image-2048x1536.png","contents":""},{"name":"assets/apple-touch-startup-image-2224x1668.png","contents":""},{"name":"assets/apple-touch-startup-image-2388x1668.png","contents":""},{"name":"assets/apple-touch-startup-image-2732x2048.png","contents":""},{"name":"assets/coast-228x228.png","contents":""},{"name":"assets/firefox_app_60x60.png","contents":""},{"name":"assets/firefox_app_128x128.png","contents":""},{"name":"assets/firefox_app_512x512.png","contents":""},{"name":"assets/mstile-70x70.png","contents":""},{"name":"assets/mstile-144x144.png","contents":""},{"name":"assets/mstile-150x150.png","contents":""},{"name":"assets/mstile-310x150.png","contents":""},{"name":"assets/mstile-310x310.png","contents":""},{"name":"assets/yandex-browser-50x50.png","contents":""},{"name":"assets/manifest.json","contents":""},{"name":"assets/manifest.webapp","contents":""},{"name":"assets/browserconfig.xml","contents":""},{"name":"assets/yandex-browser-manifest.json","contents":""}]};

/***/ })

/******/    });
/************************************************************************/
/******/    // The module cache
/******/    var __webpack_module_cache__ = {};
/******/    
/******/    // The require function
/******/    function __webpack_require__(moduleId) {
/******/        // Check if module is in cache
/******/        if(__webpack_module_cache__[moduleId]) {
/******/            return __webpack_module_cache__[moduleId].exports;
/******/        }
/******/        // Create a new module (and put it into the cache)
/******/        var module = __webpack_module_cache__[moduleId] = {
/******/            // no module.id needed
/******/            // no module.loaded needed
/******/            exports: {}
/******/        };
/******/    
/******/        // Execute the module function
/******/        __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/    
/******/        // Return the exports of the module
/******/        return module.exports;
/******/    }
/******/    
/************************************************************************/
/******/    // startup
/******/    // Load entry module
/******/    // This entry module is referenced by other modules so it can't be inlined
/******/    __webpack_require__(642);
/******/ })()
;

Note that for Webpack 5, I set output.ecmaVersion to 5 to make the output more similar to Webpack 4 for comparison purposes; but the result of evaluating it is undefined even without this setting (as shown in my original post).

felixvictor commented 4 years ago

I have worked on a pull request (first time ever ^^)

https://github.com/jantimon/favicons-webpack-plugin/pull/227

smorimoto commented 4 years ago

5 has already been released and it seems to make a lot of sense to complete this.

bkremenovic commented 4 years ago

+1

Lumen27 commented 4 years ago

Any updates on this?

omaraltayyan commented 4 years ago

+1

+2

smorimoto commented 4 years ago

I can work on this, do you need help?

omaraltayyan commented 4 years ago

i hope this helps a bit, cache-loader also depends on webpack4 and is no longer needed in webpack5

https://github.com/webpack-contrib/cache-loader/issues/111

jantimon commented 4 years ago

I can work on this, do you need help?

sure - the pull request contains a lot of failing tests.. maybe you can try to fix them?

I would also like to drop support for node <= 10.13 and also drop support for webpack 4

jantimon commented 4 years ago

Tests passed: https://travis-ci.org/github/jantimon/favicons-webpack-plugin/builds/739620669 Released as favicons-webpack-plugin@5.0.0-alpha.1: https://www.npmjs.com/package/favicons-webpack-plugin/v/5.0.0-alpha.1

jantimon commented 4 years ago

We also need to remove the cache-loader

smorimoto commented 4 years ago

It seems that there is a bug around prefix in the latest alpha version. If you don't configure it, the "auto" prefix is somehow given.

jantimon commented 4 years ago

It seems that there is a bug around prefix in the latest alpha version. If you don't configure it, the "auto" prefix is somehow given.

Thanks for your feedback - I'll take a look

jantimon commented 4 years ago

@smorimoto I fixed it for favicons-webpack-plugin@5.0.0-alpha.3

Here is codesandbox with the current alpha:

https://codesandbox.io/s/favicons-webpack-plugin-demo-uh195

smorimoto commented 4 years ago

@jantimon No! Thank you, too! I was going to work on those, but I was busy with other projects last week than I thought... Anyway thank you for your effort on the webpack ecosystem.

AaronPorts commented 4 years ago

I've got the next error using svg to generate favicons with "webpack": "^5.3.2" and "favicons-webpack-plugin": "^5.0.0-alpha.3":

Promise rejection: Could not extract assets

extractedAsset.source() in compiler.js has following lines when I use svg icon:

/*! default exports */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: module, __webpack_require__.p, __webpack_require__.* */
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {

module.exports = __webpack_require__.p + "static/images/favicon.svg";

Using png:

/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 1:0-14 */
/***/ (function(module) {

eval("module.exports = {\"tags\":[\"<link rel=\\\"shortcut icon\\\....
jantimon commented 4 years ago

The logic for the loader is here:

https://github.com/jantimon/favicons-webpack-plugin/blob/ed6c0217e349675d09ab456139b96918ef6d727a/src/compiler.js#L37-L54

Maybe they broke the !! loader directives in webpack 5 🤔

kareljan commented 3 years ago

What's the status for webpack 5 compatibility?

CYB3RL1F3 commented 3 years ago

Not working here, trying to migrate to webpack 5, I'm getting the same error....

AsebWebDev commented 3 years ago

Same here, a quick status update would be great so we can migrate to webpack 5. :)

jantimon commented 3 years ago

I guess all topics which blocked webpack 5 support have been solved during my work on the html-webpack-plugin 5 upgrade with a lot of help by the webpack core team

thanks to some new webpack 5 api we could even speed up the favicons-webpack-plugin slightly by dropping the child compiler!

now I have to invest ~3 days to migrate to those new webpack 5 apis

is anyone interested in sponsoring this topic?

jantimon commented 3 years ago

I created a new board to show the current todos for a full webpack 5 compatible favicons-webpack-plugin release: https://github.com/jantimon/favicons-webpack-plugin/projects/1

If you have any further ideas please let me know

devlegacy commented 3 years ago

I created a new board to show the current todos for a full webpack 5 compatible favicons-webpack-plugin release: https://github.com/jantimon/favicons-webpack-plugin/projects/1

If you have any further ideas please let me know

Hi, have a good day. Sorry if it isn't the place to ask the question. Is there any plan or implementation of hooks to favicons-webpack-plugin?

jantimon commented 3 years ago

@devlegacy what kinds of hooks would you need?

devlegacy commented 3 years ago

@devlegacy what kinds of hooks would you need?

Hi, have a good day. A hook befote to emit. When the plugin was webapp-webpack-plugin, it had the hook: webappWebpackPluginBeforeEmit. Using the hook, I could access the assets and edit the manifest.json file to add more options and rename the file. With this plugin I have tried to use the same hook but currently it is not possible and I try to use the webpack hooks but I receive the files as a Buffer and I require some additional steps to perform the processes that I did with the hook.

cmloegcmluin commented 3 years ago

I'm using ^5.0.0-alpha.6 and I'm still seeing a problem with this "auto" prefix. I used to be able to simply do:

new FaviconsWebpackPlugin("./assets/favicon.png")`

but now I have to do:

new FaviconsWebpackPlugin({
    logo: "./assets/favicon.png",
    outputPath: 'auto/assets',
}),

in order for it to work.

jantimon commented 3 years ago

What happens if you just use new FaviconsWebpackPlugin("./assets/favicon.png")?

Autapomorph commented 3 years ago

@jantimon If webpack's (or plugin's) publicPath is omitted - icon path contains auto

For example (webpack's publicPath is omitted):

new FaviconsPlugin({
  logo: './assets/icons/icon.png',
  // publicPath: '/',
  prefix: 'favicons',
}),

Output: auto/favicons/favicon.ico which is oviously not expected Expected: favicons/favicon.ico

cmloegcmluin commented 3 years ago

Yes, @Autapomorph has described my problem exactly. Historically my output has been at assets/favicon.ico. A recent patch has moved it to auto/assets/favicon.ico.

jantimon commented 3 years ago

Thanks @Autapomorph and @cmloegcmluin - this is caused by a new feature in webpack 5..

I'll take a look

robertmassaioli commented 3 years ago

Just to assist, @Autapomorph was correct, this configuration worked for me with webpack 5:

new FaviconsWebpackPlugin({
  logo: './src/logo.svg',
  publicPath: '/',
  prefix: 'auto/[contenthash]'
})
jantimon commented 3 years ago

I released a fix for the auto path problem favicons-webpack-plugin@5.0.0-alpha.7 it requires html-webpack-plugin@5.0.0-beta.6 (or newer)

Autapomorph commented 3 years ago

@jantimon

Confirm: no more auto in alpha.7 But don't know if it's a bug or intended but in this config

new FaviconsPlugin({
  logo: './assets/icons/favicon.png',
  prefix: 'favicons', // not 'favicons/' - note slash at the end
}),

outputs faviconsfavicon.ico instead of favicons/favicon.ico (as it was in v4)

jantimon commented 3 years ago

Yes that was a bug - you can use favicon/ instead.

The initial idea was to allow for example red- to generate red-favicon.ico that's why the option is called prefix

jantimon commented 3 years ago

@devlegacy I added a manifest option for alpha.8 which allows overwriting manifest values - see also this example: https://github.com/jantimon/favicons-webpack-plugin/tree/feature/next-no-compilation/example/custom-manifest

devlegacy commented 3 years ago

@devlegacy I added a manifest option for alpha.8 which allows overwriting manifest values - see also this example: https://github.com/jantimon/favicons-webpack-plugin/tree/feature/next-no-compilation/example/custom-manifest

It works! Thanks a lot!

laneme commented 3 years ago

It looks like I have to install the peerDependency favicons separately?

This isn't a urgent issue though, because installing it fixes the errors. But I wonder if this is happening to everyone.

I'm using yarn 1.22.10 and 5.0.0-alpha.11 of favicons-webpack-plugin. And also just in case, webpack 5.18.0 and webpack-cli 4.4.0

jantimon commented 3 years ago

Yes that's by design to allow you to control which favicons version you would like to use

danielrsantana-sastrix commented 3 years ago

In case someone run the same issue before the release of the version 5, to solve the problem I had to upgrade my version to alpha (yep, a bit scary but we will have to trust @jantimon implementation, lmao).

  1. Update your package.json with the latest 5.* version of favicons-webpack-plugin:
    "favicons": "6.2.0",
    "favicons-webpack-plugin": "5.0.0-alpha.11",
  1. As FavIconPlugin depends on the latest version of "html-webpack-plugin", upgrade it to:
  "html-webpack-plugin": "5.0.0-beta.6",
  1. Import and use the plugin:
const FaviconsPlugin = require('favicons-webpack-plugin');

const plugins = (env, envKeys) => [
  // ..., 
  new FaviconsPlugin(`${APP_DIR}/assets/img/favicon.png`),
 }

 module.exports = (env) => {
  return {
    // ...,
    plugins: plugins(env, envKeys),

If your npm/yarn install shows version 4 as the latest, use yarn info package-name, scroll to the top and you will the the alpha and beta versions available.

Just in time: To me, this error only happened in PRD environment.

jantimon commented 3 years ago

released as favicons-webpack-plugin 5.0.0

kareljan commented 3 years ago

Are the 2 in progress issues also handled in https://github.com/jantimon/favicons-webpack-plugin/projects/1?

jantimon commented 3 years ago

@kareljan yes :)

thanks for looking into it - I just updated the board

gabrielem commented 3 years ago

I still get the 'tap' error... node: 12.16.1

I try with "favicons-webpack-plugin": "^5.0.1", and "favicons-webpack-plugin": "5.0.0-alpha.11",

package.json

{
  "main": "src/server/index.js",
  "scripts": {
    "build": "webpack --mode production --config webpack/webpack.prod.js",
    "build-dev": "env NODE_ENV=staging webpack --mode production --config webpack/webpack.prod.js",
    "start": "node src/server/index.js",
    "client": "webpack-dev-server --mode development --devtool inline-source-map --hot --config webpack/webpack.dev.js",
    "server": "nodemon src/server/index.js",
    "dev": "env NODE_ENV=development concurrently \"npm run server\" \"npm run client\"",
    "test": "mocha --exit"
  },
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^1.2.28",
    "@fortawesome/free-solid-svg-icons": "^5.13.0",
    "@fortawesome/react-fontawesome": "^0.1.9",
    "@hapi/joi": "^17.1.1",
    "@jhonnold/react-chart.js": "^1.0.0",
    "@mailchimp/mailchimp_marketing": "^3.0.28",
    "axios": "^0.19.2",
    "babel-polyfill": "^6.26.0",
    "bignumber.js": "^9.0.0",
    "body-parser": "^1.19.0",
    "bootstrap": "^4.4.1",
    "chai": "^4.2.0",
    "chalk": "^4.0.0",
    "chart.js": "^2.9.3",
    "dotenv": "^8.2.0",
    "express": "^4.16.3",
    "firebase": "^7.16.0",
    "firebase-admin": "^8.11.0",
    "i18next": "^19.5.6",
    "i18next-xhr-backend": "^3.2.2",
    "jquery": "^3.5.1",
    "moment": "^2.29.1",
    "nodemailer": "^6.4.6",
    "path": "^0.12.7",
    "popper.js": "^1.16.1",
    "prerender-node": "^3.2.5",
    "qrcode.react": "^1.0.1",
    "randomcolor": "^0.5.4",
    "react": "^16.5.2",
    "react-bootstrap": "^1.1.1",
    "react-confirm-alert": "^2.6.2",
    "react-datetime": "^3.0.4",
    "react-datetime-picker": "^3.0.4",
    "react-dom": "^16.5.2",
    "react-firebase-file-uploader": "^2.4.3",
    "react-helmet": "^6.0.0",
    "react-hook-form": "^6.0.2",
    "react-i18next": "^11.7.0",
    "react-particles-js": "^3.2.1",
    "react-player": "^2.0.1",
    "react-qr-reader": "^2.2.1",
    "react-qr-scanner": "^1.0.0-alpha.7",
    "react-router-dom": "^5.1.2",
    "react-simple-tooltip": "^2.6.2",
    "react-stripe-checkout": "^2.6.3",
    "react-textarea-autosize": "^8.2.0",
    "react-toastify": "^5.5.0",
    "react-tooltip": "^4.2.13",
    "react-vis": "^1.11.7",
    "slugify": "^1.4.0",
    "supertest": "^4.0.2",
    "swiper": "^5.3.8",
    "uuid": "^7.0.3"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/plugin-proposal-class-properties": "^7.0.0",
    "@babel/preset-env": "^7.0.0",
    "@babel/preset-react": "^7.0.0",
    "babel-eslint": "^10.0.0",
    "babel-loader": "^8.0.0",
    "clean-webpack-plugin": "^1.0.0",
    "concurrently": "^4.0.0",
    "css-loader": "^2.0.0",
    "dotenv-webpack": "^1.8.0",
    "eslint": "^5.0.0",
    "eslint-config-airbnb": "^17.0.0",
    "eslint-plugin-import": "^2.11.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-react": "^7.7.0",
    "favicons": "^6.2.1",
    "favicons-webpack-plugin": "5.0.0-alpha.11",
    "file-loader": "^3.0.0",
    "html-webpack-plugin": "5.0.0-beta.6",
    "mocha": "^8.0.1",
    "nodemon": "^1.17.3",
    "style-loader": "^0.23.0",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "url-loader": "^1.0.1",
    "webpack": "^4.5.0",
    "webpack-cli": "^3.0.8",
    "webpack-dev-server": "^3.1.3",
    "webpack-merge": "^4.2.2"
  }
}

Error:

TypeError: Cannot read property 'tap' of undefined
[1]     at FaviconsWebpackPlugin.apply (/node_modules/favicons-webpack-plugin/src/index.js:39:31)
[1]     at webpack (/node_modules/webpack/lib/webpack.js:51:13)
[1]     at startDevServer (/node_modules/webpack-dev-server/bin/webpack-dev-server.js:94:16)
[1]     at /node_modules/webpack-dev-server/bin/webpack-dev-server.js:166:3
[1]     at /node_modules/webpack-dev-server/lib/utils/processOptions.js:33:9
jantimon commented 3 years ago

@gabrielem sorry I can't reproduce that behaviour - here is a working codesandbox:

https://codesandbox.io/s/favicons-webpack-plugin-demo-uh195

Try to upgrade to the latest webpack webpack-dev-server webpack-cli html-webpack-plugin amd favicons-webpack-plugin. If it does not work please open a new issue with a minimal reproduction example