Some help with Webpack needed



  • So, there's a project that's being updated from Webpack 3 to Webpack 4. Let's say that a part of it uses React. I've got to review the result... and it was broken. (Let's save the snark about developers not use-testing what they do for another day, that's not the point right now.)

    Inspecting the webpack config didn't reveal anything alarming. It uses Babel 6 (for now, one thing at a time) to translate the Reactish into JavaScriptese, and modern JS into a slightly more ancient JS. There was CommonsChunkPlugin which got replaced with what's needed in Webpack 4, and some CSS loaders which were also bumped to Webpack 4. However, the code bundled with Webpack 3 works impeccably, and code bundled with Webpack 4 vomits and dies when rendering a particular React component:

    ButtonGroup.js.jsx?f8e1:29 Not rendering function Button() {
        var _ref;
    
        var _temp, _this, _ret;
    
        _classCallCheck(this, Button);
       // ... redacted
    }. Only <Button> components are allowed in <ButtonGroup>!
    

    I understand that before Webpack 4, render() got something else, but this thing looks like the <Button> component already translated from Reactish to Javascriptese (=into a function).

    I guess there must be poor souls who bumped into this kind of error before. Thing is, this error message is entirely un-googleable, for starters. Another thing is, I don't know if it could be caused by sloppy React coding, or Webpack is really shit and needs more magic to process things in the correct order or something.

    Help?



  • @wft Well, what does the offending file look like?



  • @Rhywden the React thing that tries to render components or the webpack config? I'm starting to feel like the whole thing is offending ;)



  • @wft The React file.



  • Hmmm, it's getting curiouser and curiouser.

    The error message cannot be googled (now it can FWIW) because it's emitted by a homegrown component. The component has the following check:

    React.isValidElement(child) && child.type === Button
    

    I've checked, child.type is the Button constructor alright, it's just that it's not identical to the Button function the check is against. Their toString() return identical contents, which brings us back to Webpack: somehow it doesn't get that Button here and Button there are the same thing, and creates two objects that look the same.

    Now you can tell that that check is lame and doesn't make any sense, but hey, it worked before :)



  • @wft Maybe child.type.prototype instanceof Button?



  • @Rhywden This one works, thanks! I'm sure going to make note of it. However! How come it worked before but stopped now?

    FFS, Webpack's job is to take the source files and pack them together, making sure they have been included only once. Clearly it failed its function, since we now have two Button functions roaming in the application bundle.



  • @wft Don't ask me. Could also be down to the wonders of Javascript.



  • @Rhywden When in doubt, blame Javascript



  • Le sigh. Turns out the component called Button is defined in two places across the whole codebase, but the imports take care that the right one is imported, so this shouldn't be a problem. I've also looked at the generated bundles, and they both included two definitions of that function.

    So it's not our code. It's the freaking webpack.

    Makes me wonder: is there an alternative which is doing more or less the same thing webpack does (take the codebase, pipe through Babel, produce app.js and vendor.js, pass SCSS files through sass, produce app.css and vendor.css, minify), but without all the bugs? I feel like this could be done with Makefiles and homegrown Babel/sass invocation with less pain than all the amazing JS Wunderwaffen offer.



  • @wft said in Some help with Webpack needed:

    Le sigh. Turns out the component called Button is defined in two places across the whole codebase, but the imports take care that the right one is imported, so this shouldn't be a problem. I've also looked at the generated bundles, and they both included two definitions of that function.

    :wtf:

    Makes me wonder: is there an alternative which is doing more or less the same thing webpack does (take the codebase, pipe through Babel, produce app.js and vendor.js, pass SCSS files through sass, produce app.css and vendor.css, minify), but without all the bugs? I feel like this could be done with Makefiles and homegrown Babel/sass invocation with less pain than all the amazing JS Wunderwaffen offer.

    I've been wondering the same thing for ages. Unfortunately, Webpack seems to be the current champion.

    In the past, I've had good results with gulp, because it uses code to define build tasks instead of a humongous configuration object, and that in turn lets me invoke whatever I want in those build steps, from invoking Webpack to bundle the JS files after a different step transpiles TS to JS, to invoking custom JS to perform special processing on HTML template files. But it's still JS and too much magic sometimes.
    For simple builds, your suggested approach would work and I've seen it done. But then you'd be trading Webpack warts for Make warts, so 🤷 .


  • BINNED

    @hungrier said in Some help with Webpack needed:

    @Rhywden When in doubt, blame Javascript

    Doubt not necessary.



  • @DCoder gulp and make are almost interchangeable in my books, since they both are task managers of sorts (at least in how they are used). Make, I'd say, is more versatile since it has incremental build capability out of the box (based on file timestamps, sounds restricted, but you can go a very long way with it), and it's more of a dependency management tool.

    The duplicate definitions are actually not a problem language-wise, since modules namespace them away from each other, and as long as you import the right one, you should be good. Or... as long as your toolchain doesn't mess with you, of course.


Log in to reply