Anyone had a situation where Webpack produces `null` instead of the `require` for PS module?

I don’t have a shareable repo or example so i’m really just wondering if anyone has ever seen such a thing before? obviously if someone has an actual fix that would be super too, but even directional suggestions would be great.

the purescript compiler certainly produces the index.js in the output directory all right but the bundle that is served by both webpack-serve and webpack-dev-server (i’ve tried both) assigns a null to the handle, like so:

var Comms_S101_Inbound = __webpack_require__(/*! /Users/afc/work/from Git/marrakesh/lib/Comms/S101/Inbound.purs */
var Comms_S101_ServerInterface = null;
var Control_Applicative = __webpack_require__(/*! /Users/afc/work/from Git/marrakesh/.psc-package/psc-0.11.7-20180524/prelude/v3.1.1/src/Control/Applicative.purs */

This is probably due to a circular dependency somewhere.

I would try using the circular-dependency-plugin for webpack. We used it with purs-loader in the past and it even found things like this:

Thanks for the suggestion, @paulyoung, circular dependencies seems like a good bet alright.

In this case the only circular dependency that the circular-dependency-plugin throws up is an explicit one in contravariant's Data.Comparison module.

But that’s not to say that i haven’t somehow got a cycle in our own code that isn’t found by the plugin. I’ll try to rule that out before adopting other approaches.

Purs does not allow real circular dependencies. It does allow a self dependency for the purpose of reexports and curiously still emits a require even though it doesn’t let you reference it in code.

So there is no point looking for circular dependencies in our own source?

In that case, i’m stumped once again as to why Webpack ends up with a null for a module that appears to compile normally and produce a perfectly ordinary index.js in the output directory

@afc do you have much JS in your codebase that isn’t produced by PureScript?

well, it’s got some legacy JS files, React, D3, SVGs, some fonts, LESS…the usual gamut of assets.

I find it just absurd that Webpack as a tool can EVER emit code that has var X = null in the bundle. It just seems unimaginably crappy to me. As i was saying to colleagues on internal Slack this morning i’m sort of dumbfounded that all the tooling problems i ever have come from the mass market language.

Purescript, by comparison, has never let me down. Both language / compiler and tooling.

Incidentally, i renamed the offending file - the one that Webpack simply won’t handle - to Foo and stripped all the code out of it AND removed all its includes except Prelude (unit, pure) and it still fails to resolve in Webpack. This makes me think it really isn’t circular references, or some weird hidden characters in the file / module name.

At this point I won’t be surprised if it turns out to be a hard limit on module numbers or something like that.

Is there a webpack option you can use to see verbose output when building?

Yes, you can get quite a lot of info by getting Webpack to dump out stats.

However, i have now moved on to looking at the purs-loader…i may have the problem licked now, will post my findings shortly

Okay so the problem turned out to be errant whitespace at the front of the file in question (minus many points to me for not spotting this but also a giant gritting of teeth at the knowledge that this was probably caused by my failing MacBook Pro keyboard accepting a Cmd-Tab as a Tab at some point in the past).

There is a regex in purs-loader's purs-module-map.js file;

var srcModuleRegex = /(?:^|\n)module\s+([\w\.]+)/i;

And this regex fails to capture the situation where the module is not the first thing in the file.

I will file an issue on the repo, i think, just as an FYI. One could change the regex but…is leading whitespace even valid PureScript? and there are many ways a regex could fail. I’m inclined to think a warning that no match has been found would be better.

-- | This is a valid module with a module comment.
module Foo where

import Prelude

foo :: Unit
foo = unit

Yes, that works okay because the 'module Foo` is first thing on the line, directly following a newline.

If i would have had a comment there i might have noticed the spaces before “module”

FWIW, I’ve found the least frustrating way to bundle with Webpack is to require and watch the actual compiler artifacts and just run purs separately. That’s how SlamData does it, and we moved from purs-loader to requiring the artifacts a few months ago at Awake.

1 Like