Skip to content

adding splitChunks all is breaking the module exports #408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
varenya opened this issue Jun 11, 2019 · 29 comments
Closed

adding splitChunks all is breaking the module exports #408

varenya opened this issue Jun 11, 2019 · 29 comments

Comments

@varenya
Copy link

varenya commented Jun 11, 2019

  • 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

@alexander-akait
Copy link
Member

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

@varenya
Copy link
Author

varenya commented Jun 12, 2019

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

@varenya
Copy link
Author

varenya commented Jun 12, 2019

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

@varenya
Copy link
Author

varenya commented Jun 15, 2019

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

@alexander-akait
Copy link
Member

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

@kalbert312
Copy link

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.

@alexander-akait
Copy link
Member

@kalbert312 can you create minimum reproducible test repo?

@kalbert312
Copy link

kalbert312 commented Sep 9, 2019

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.

@alexander-akait
Copy link
Member

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

@kalbert312
Copy link

kalbert312 commented Sep 9, 2019

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

@kalbert312
Copy link

...though that's extremely confusing.

@alexander-akait
Copy link
Member

I think we should output better error for this case

@kalbert312
Copy link

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.

@kalbert312
Copy link

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();
		/******/ })

@alexander-akait
Copy link
Member

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

@alexander-akait
Copy link
Member

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

@alexander-akait
Copy link
Member

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

@kalbert312
Copy link

kalbert312 commented Sep 17, 2019

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

@ianks
Copy link

ianks commented Oct 30, 2019

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

@giuseppeg
Copy link

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

@tylerexmg
Copy link

tylerexmg commented Dec 13, 2019

#408 (comment)

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.

@yazonnile
Copy link

yazonnile commented Dec 26, 2019

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>

@Sellec
Copy link

Sellec commented Feb 21, 2020

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.

@Sellec
Copy link

Sellec commented Feb 21, 2020

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
                }
            }
        }

@rwieruch
Copy link

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.

@sean-au
Copy link

sean-au commented Jan 27, 2021

I still have the problem :(

@jkarttunen
Copy link

For me, it's a 600kb js file, consisting of only CSS classnames

@alexander-akait
Copy link
Member

Should be solved, only one problem is empty JS files, but it should be fixed in webpack itself webpack/webpack#11671, if anybody will faced the the problem feel free to feedback and I will help

@bturner1273
Copy link

my split chunks css bundling issue example
I have a 'good' branch that doesn't include optimizations.splitChunks.chunks = 'all' and a 'bad' branch that does. The bad branch will not umd export to my client-side js correctly for whatever reason. I tried using MiniCssExtractPlugin to no avail

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests