Mini-css-extract-plugin: adding splitChunks all is breaking the module exports

Created on 11 Jun 2019  ·  26Comments  ·  Source: webpack-contrib/mini-css-extract-plugin

  • Operating System: macOS mojave
  • Node Version: v11.3.0
  • NPM Version: 6.7.0
  • webpack Version: 4.33.0
  • mini-css-extract-plugin Version: 0.7.0

Expected Behavior

Having concatenated all CSS in the file should not break the module exports.

Actual Behavior

Adding the splitChunks optimization for a single css file is breaking the umd build exports.

Code

optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          test: /\.css$/,
          chunks: 'all',
          enforce: true,
        },
      },
    },
  },

How Do We Reproduce?

  • create with umd build as output and configure the optimization rule and try and importing the component from the library. it fails with error

TypeError: Cannot read property of undefined

Most helpful comment

Guys, I dont know a root problem, but I make this thing works for me.
splitChunks all generates two files.
1 - styles.css itself.
2- styles.js file with empty css files modules
And the problem is - this styles.js file is not used in main bundle file index.js

so in my html file

was

<script defer src="/index.js"></script>

now

with AutomaticPrefetchPlugin for makes this work before main bundle

<script defer src="/styles.js"></script>
<script defer src="/index.js"></script>

All 26 comments

Looks you have old global installed webpack, if not, please create minimum reproducible test repo

No, I don't have globally installed webpack. I will try and create a minimum reproducible test repo.

Heres the repo with the minimum reproducible test: https://github.com/varenya/webpack-reprod

@evilebottnawi I have reproduced the issue could u take a look? thanks.

@varenya can't run you reproducible test repo, i will always got Module not found: Error: Can't resolve 'sample-package/style.css'

I'm running into this problem as well. My main module's import is undefined with the splitChunks block. Removing it fixed the problem. Target UMD.

@kalbert312 can you create minimum reproducible test repo?

Done. Not super minimal but I reproduced the problem.
Repo: https://github.com/kalbert312/main-module-undefined

Steps:

  1. Add "main-module-undefined": "git+ssh://[email protected]/kalbert312/main-module-undefined.git#good", to your project's package.json and run npm install.
  2. Add this to your project somewhere:
import * as MainModule from "main-module-undefined";
console.log("Module: ", MainModule);
  1. Run it and see that the export is as expected.
  2. Change the dependency version to "main-module-undefined": "git+ssh://[email protected]/kalbert312/main-module-undefined.git#bad" and run npm install again.
  3. Run project again. MainModule is undefined.

What about this https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free?

Looks like that did the trick for me: https://github.com/kalbert312/main-module-undefined/tree/maybe-bad Thanks!

...though that's extremely confusing.

I think we should output better error for this case

I was focusing on the JS imports instead of the CSS import. Looks like adding the sideEffects: false fixed the JS import, but now the styles chunk is completely missing from the dist. Going to see if I can run two builds to work around it.

After more digging, it looks like the extra JS file produced might be the cause?. Something isn't getting executed.

1.index.js:

(this["webpackJsonpmymodule"] = this["webpackJsonpmymodule"] || []).push([[1],{

/***/ 6:
/***/ (function(module, exports, __webpack_require__) {

// extracted by mini-css-extract-plugin

/***/ }),

/***/ 7:
/***/ (function(module, exports, __webpack_require__) {

// extracted by mini-css-extract-plugin

/***/ })

}]);
//# sourceMappingURL=1.index.js.map

When this file gets generated, the main js file has different code generated:

Good:

return /******/ (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 = 9);

Bad:

    return /******/ (function(modules) { // webpackBootstrap
        /******/    // install a JSONP callback for chunk loading
        /******/    function webpackJsonpCallback(data) {
            /******/        var chunkIds = data[0];
            /******/        var moreModules = data[1];
            /******/        var executeModules = data[2];
            /******/
            /******/        // add "moreModules" to the modules object,
            /******/        // then flag all "chunkIds" as loaded and fire callback
            /******/        var moduleId, chunkId, i = 0, resolves = [];
            /******/        for(;i < chunkIds.length; i++) {
                /******/            chunkId = chunkIds[i];
                /******/            if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
                    /******/                resolves.push(installedChunks[chunkId][0]);
                    /******/            }
                /******/            installedChunks[chunkId] = 0;
                /******/        }
            /******/        for(moduleId in moreModules) {
                /******/            if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
                    /******/                modules[moduleId] = moreModules[moduleId];
                    /******/            }
                /******/        }
            /******/        if(parentJsonpFunction) parentJsonpFunction(data);
            /******/
            /******/        while(resolves.length) {
                /******/            resolves.shift()();
                /******/        }
            /******/
            /******/        // add entry modules from loaded chunk to deferred list
            /******/        deferredModules.push.apply(deferredModules, executeModules || []);
            /******/
            /******/        // run deferred modules when all chunks ready
            /******/        return checkDeferredModules();
            /******/    };
        /******/    function checkDeferredModules() {
            /******/        var result;
            /******/        for(var i = 0; i < deferredModules.length; i++) {
                /******/            var deferredModule = deferredModules[i];
                /******/            var fulfilled = true;
                /******/            for(var j = 1; j < deferredModule.length; j++) {
                    /******/                var depId = deferredModule[j];
                    /******/                if(installedChunks[depId] !== 0) fulfilled = false;
                    /******/            }
                /******/            if(fulfilled) {
                    /******/                deferredModules.splice(i--, 1);
                    /******/                result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
                    /******/            }
                /******/        }
            /******/
            /******/        return result;
            /******/    }
        /******/
        /******/    // The module cache
        /******/    var installedModules = {};
        /******/
        /******/    // object to store loaded and loading chunks
        /******/    // undefined = chunk not loaded, null = chunk preloaded/prefetched
        /******/    // Promise = chunk loading, 0 = chunk loaded
        /******/    var installedChunks = {
            /******/        0: 0
            /******/    };
        /******/
        /******/    var deferredModules = [];
        /******/
        /******/    // 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 = "";
        /******/
        /******/    var jsonpArray = this["webpackJsonpmymodule"] = this["webpackJsonpmymodule"] || [];
        /******/    var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
        /******/    jsonpArray.push = webpackJsonpCallback;
        /******/    jsonpArray = jsonpArray.slice();
        /******/    for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
        /******/    var parentJsonpFunction = oldJsonpFunction;
        /******/
        /******/
        /******/    // add entry module to deferred list
        /******/    deferredModules.push([11,1]);
        /******/    // run deferred modules when ready
        /******/    return checkDeferredModules();
        /******/ })

@kalbert312 it is in my todo list, look on this in near future (today/tomorrow)

You should not use sideEffects: false, because css is sideEffects always

I can't reproduce, what is branch i should use?

bad and maybe-bad branches have bad bundles (importing the JS bundle elsewhere should result in undefined).

i believe we may be experiencing a similar issue. however, if we set maxInitialChunks: Infinity. does that happen with your build @kalbert312 ?

I am experiencing the same issue and the setup is the one from @kalbert312's testcase.
@evilebottnawi can I help in any way?

https://github.com/webpack-contrib/mini-css-extract-plugin/issues/408#issuecomment-529656695

I have just observed this exact issue in my project and its lead me into a dead-end trying to split css. Hopefully it gets fixed soon.

Guys, I dont know a root problem, but I make this thing works for me.
splitChunks all generates two files.
1 - styles.css itself.
2- styles.js file with empty css files modules
And the problem is - this styles.js file is not used in main bundle file index.js

so in my html file

was

<script defer src="/index.js"></script>

now

with AutomaticPrefetchPlugin for makes this work before main bundle

<script defer src="/styles.js"></script>
<script defer src="/index.js"></script>

Have the same issue - i need to extract vue's components styles into one single css file and got two js files - bug "bundle.js" file and little (window[jsonp]) "0.bundle.js" file. Its annoying.

setting the splitchunks.cacheGroups.[chunkname].name='main' solves the problem with additional little file.

        splitChunks: {
            cacheGroups: {
                extractedCSS: {
                    test: (module, chunks) => module.constructor.name === 'CssModule',
                    name: "main",
                    chunks: "all",
                    enforce: true
                }
            }
        }

Has someone been able to fix this problem? I got the same issue with Webpack 4 where I activate splitChunks and get undefined for my imports.

I still have the problem :(

Was this page helpful?
0 / 5 - 0 ratings