Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

[bug] async js chunks that include css/scss imports cause => Uncaught (in promise) TypeError: Cannot read property 'call' of undefined #456

Closed
ericnoguchi opened this issue Mar 9, 2017 · 27 comments

Comments

@ericnoguchi
Copy link

ericnoguchi commented Mar 9, 2017

Tested with
ETP:2.1.0
webpack: 2.2.1
Node v7.7.1

There seems to be some issue when importing a scss file in a common chunk if that common chunk also imports an async/dynamic js chunk which imports another scss file.

File setup

//===== a.js =====
import './common';

//===== b.js =====
import './common';

//===== common.js =====
import './common.scss';
import ('./async.js'); // async import

//===== async.js =====
import './async.scss'

This issue happens when allChunks:false [I would like to lazy load js and associated css], and what seems to be happening is that the runtime code for css-loader is not always being included in the bundle which results in the below error?

Uncaught (in promise) TypeError: Cannot read property 'call' of undefined
    at __webpack_require__ (bootstrap 3d99482…:52)
    at Object.95 (async.scss:1)
    at __webpack_require__ (bootstrap 3d99482…:52)
    at Object.96 (async.scss?eb60:4)
    at __webpack_require__ (bootstrap 3d99482…:52)
    at Object.94 (0.cb65e0.chunk.js:8)
    at __webpack_require__ (bootstrap 3d99482…:52)

But if I for example update common.scss while webpack-dev-server is running, when the bundle gets rebuilt and the page refreshes I can see the code for css-loader in the chunk and the error goes away, but if I restart webpack-dev-server again and refresh the error comes back and css-loader code is gone.

I have created a repo with showing this error
https://github.com/ericnoguchi/webpack-testing

steps to reproduce.

  1. npm install
  2. npm run startDev
  3. go to http://localhost:8080/ and observe error
  4. updated any of the scss modules e.g. common.scss and after webpack-dev-server refreshes error is gone.
  5. check async/*.chunk.js contents in each case injected in the head tag.

Link stack overflow issue:
http://stackoverflow.com/questions/42687881/async-js-chunks-that-include-scss-imports-cause-uncaught-in-promise-typeerr

@kostasmanionis
Copy link
Contributor

I'm having the very same issue! Been trying to debug it a bit, but no luck so far.

AFAIK the code for css-loader(and style-loader) is removed when one of the extracted css files is rebuilt by extract-text-webpack-plugin.

Child deps of that css file are processed https://github.com/webpack/webpack/blob/master/lib/Compilation.js#L506 and it seems that the original, non-extracted css module is removed(might be wrong here). And this in turn removes the reasons for the css-loader and style-loader runtimes to be included in the common chunk.

I'm not really familiar with webpack internals so it's hard to pinpoint the exact location of the issue, some help would be greatly appreciated.

@kostasmanionis
Copy link
Contributor

Was kinda right...

Two files are missing in the bundle - css-loader/lib/css-base.js & style-loader/addStyles.js.
Been looking into what happens to addStyles.js. commons.scss module lands here https://github.com/webpack/webpack/blob/master/lib/Compilation.js#L502 after the extract-text-plugin triggers it. It has two dependencies, another commons.scss module(that's from the child compiler I guess?) and addStyles.js. Eventually it get's to this.removeChunkFromDependencies(d.module, chunk); and style-loader/addStyles.js get's removed from the commons chunk and it never ends up in the bundle.

@ericnoguchi
Copy link
Author

is there any update on this? Issues still remains with wepback 3.1.0 and ETP 3.0.0

@ericnoguchi ericnoguchi changed the title async js chunks that include scss imports cause => Uncaught (in promise) TypeError: Cannot read property 'call' of undefined [bug] async js chunks that include scss imports cause => Uncaught (in promise) TypeError: Cannot read property 'call' of undefined Jul 11, 2017
@alexander-akait
Copy link
Member

@ericnoguchi wip

@alexander-akait
Copy link
Member

@ericnoguchi what about set allChunks: true ?

new ExtractTextPlugin({
  filename: '[name].css',
  allChunks: true
})

@ericnoguchi
Copy link
Author

@evilebottnawi

That is what we are doing for the time being but ideally we would like to be able to lazy load css modules that are included in async JavaScript chunks

@alexander-akait
Copy link
Member

@ericnoguchi Looks like an error, looking for a solution, thanks!

@alexander-akait
Copy link
Member

@ericnoguchi what about this (async: true):

new webpack.optimize.CommonsChunkPlugin({
   names: ['common', 'vendor', 'webpackBootstrap'],
   async: true
})

@kostasmanionis
Copy link
Contributor

If anyones interested I've got a temp fix working by excluding css-loader & style-loader from the common chunks. Looks like this

webpack.config.js

const handleCommonChunks = excludeCommons(entryFileCount); // Entry file count is calculated during build time.

// Somewhere in the webpack config.
new CommonsChunkPlugin({
    name: 'common',
    chunks: commonEntries, // Also generated when the build starts
    minChunks: handleCommonChunks
})

excludeCommons.js

/**
 * List of modules to be excluded from the common chunks. Keep in mind this is checked against the full file path of
 * the module. Separate files or whole folder/pacakages can be excluded.
 */
const excludedModules = [
    'css-loader',
    'style-loader'
];

module.exports = function (entryFileCount, modulesToExclude = excludedModules) {
    return function (module, occurenceCount) {
        const {resource} = module;
        const excludeModule = modulesToExclude.some(moduleName => resource.includes(moduleName));

        /**
         * Returning true will include the module in the common chunk.
         * 1. Do not include excluded modules.
         * 2. If the module occurs in every entry chunk - include it in the common chunk.
         * 3. Exclude every other module.
         */
        if (excludeModule) {
            return false;
        } else if (occurenceCount === entryFileCount) {
            return true;
        } else {
            return false;
        }
    };
};

toddw added a commit to TrueCar/gluestick that referenced this issue Aug 1, 2017
@ericnoguchi ericnoguchi changed the title [bug] async js chunks that include scss imports cause => Uncaught (in promise) TypeError: Cannot read property 'call' of undefined [bug] async js chunks that include css/scss imports cause => Uncaught (in promise) TypeError: Cannot read property 'call' of undefined Aug 28, 2017
@prannayb
Copy link

This really making extract text plugin unusable when using Code Splitting. This issue along with #120 prevent the use of allChunks:false and make css splitting completely broken.

@alexander-akait
Copy link
Member

@prannayb can you provide minimum reproducible test repo?

@kayneb
Copy link

kayneb commented Sep 29, 2017

+1 this is affecting our team too.

allChunks:false does somewhat fix this issue, but we do not want to load unnecessary CSS on our initial Single Page App page load.

@kostasmanionis I tried your solution, but I'm hitting a problem. I'm excluding css-loader and style-loader from the common chunk that is based on the async chunks, as your suggestion describes. However, in excluding those modules, they of course then do not exist in my common chunk but they are needed there too, as well as in the chunks themselves, as I have common CSS sitting in the common chunk that has been extracted.

@kayneb
Copy link

kayneb commented Sep 29, 2017

I got around the above mentioned issue by also excluding all CSS/LESS/SCSS from the common chunking too.

@ArgonAlex
Copy link

ArgonAlex commented Oct 10, 2017

I worked around the problem by adding css-loader/lib/css-base and style-loader/lib/addStyles to my vendor bundle. So if you have already a vendor bundle, this is a much simpler workaround.
Anyone who's using an implicit vendor bundle (they have a custom minChunks function that matches modules in node_modules) would actually already be doing this.

@ericnoguchi
Copy link
Author

ericnoguchi commented Oct 29, 2017

@ArgonAlex

Good find! I tested your solution with the repo above and so far the error is gone and the css dynamically loads

e.g.

    entry: {
        'vendor': [
            "style-loader/lib/addStyles",
            "css-loader/lib/css-base",
        ],
        'a': './a.js',
        'b': './b.js',
    },

@payne8
Copy link

payne8 commented Apr 4, 2018

This bug bit me on upgrading to Webpack 4 with the new splitChunks stuff. This thread lead me in the right direction, but the suggestions didn't make a difference. But they did get me on the right track.

I ended up requiring those two files within my app.

require('style-loader/lib/addStyles');
require('css-loader/lib/css-base');

They were then correctly added to a bundle and were available for webpack to load on entry.

EDIT: this fix doesn't solve the issue and the error persists in subsequent rebuilds.

@pleerock
Copy link

pleerock commented Apr 5, 2018

@payne8 same issue with webpack4 here - adding those lines fixes issue with chunks for me, but solution looks so unreliable

@payne8
Copy link

payne8 commented Apr 7, 2018

@pleerock Looks like my fix only temporarily fixed the problem. It is super odd because if you modify and save a file and let webpack do an incremental build the issue goes away. But I can't do that for a production build. I edited my comment to reflect my experience.

martin-corevski added a commit to martin-corevski/react-redux-app that referenced this issue Apr 13, 2018
@AaronLayton
Copy link

I am getting this issue as well - is there any sign of a fix?

@messutied
Copy link

Getting this issue too, no fix on the sight?

@messutied
Copy link

messutied commented May 3, 2018

Looking at one PR referenced above seems like they have a working fix (works for me too), also similar to the solutions proposed in this page, but placing the 'style-loader/addStyles', 'css-loader/lib/css-base', under the entry point that gives the error instead of placing it in the vendor entry point.

entry: {
  main: [
    'your-app.js',
    'style-loader/addStyles',
    'css-loader/lib/css-base',
  ]
}

nkonev added a commit to nkonev/blog that referenced this issue Jun 10, 2018
…tract-text-plugin breaks page loading in conjunction with dynamic-import
@JeroenReumkens
Copy link

I came across this bug as well and haven't been able to fix this. Adding the loaders like mentioned in the comment above does work, but I don't want to have this in production.

The allChunks: true option really is the only option which solved the issue for me. Only downside is that you have all the CSS in 1 bundle and you don't lazy load that.

@jasonbiondo
Copy link

@JeroenReumkens Unfortunately, your solution was the only one that worked for me as well! Thanks for the short term fix.

@lucaschen
Copy link

Not sure if this'll help anyone, but I had the same problem, which went away when I switched from extract-text-webpack-plugin to mini-css-extract-plugin.

Took me quite a while to realize that you're not meant to use extract-text-webpack-plugin with Webpack v4 anymore.

@jbroadice
Copy link

jbroadice commented Oct 12, 2018

I've tried all the workarounds above, and none have worked for me.

In my case a dependency in node_modules loads its own sass, and when running the app (using next.js with next-sass [e.g. with mini-css-extract-plugin]) in development mode, when navigating between pages, webpack dynamically builds the resources, but then throws the error mentioned in this issue (TypeError: Cannot read property 'call' of undefined), which relates directly to the sass import declaration in the dependency. Refreshing the page will avoid the errors (until next rebuild).

@ripvannwinkler
Copy link

So, I just ran into this bug today while using create-react-app. Short of ejecting and trying some of the web pack config changes above, the only solution that worked reliably for me was to move the css imports to the root of the app to avoid any async css imports.

@alexander-akait
Copy link
Member

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

No branches or pull requests