spago
spago copied to clipboard
Spago does not emit an error when bundling an app's main module that does not have a `main` function
Steps to reproduce:
mkdir explore-bundle-no-main
cd explore-bundle-no-main
spago init
# edit the `src/Main.purs` file to remove the "main" function
spago bundle -m Main -t dist/main.js
Spago doesn't fail with an error that Main.purs
does not have a function called main
. Thus, the output of the bundle is this:
// Generated by purs bundle 0.12.5
var PS = {};
PS["Main"].main();
One won't realize that the source of their issue is the compiled output until after exploring a few things more.
I only came across this because I used the wrong module name in the spago bundle
command.
Good catch! This is interesting because spago bundle
just shells out to purs bundle
, which is happy to generate that malformed js.
Pulp however implements this check, and fails with a nice error message:
$ pulp build -m Main -t dist/main.js
* Building project in /Users/fabrizio/code/explore-bundle-no-main
* Build successful.
* Bundling JavaScript...
* Main cannot be used as an entry point module because it
* does not export a `main` value.
*
* If you need to create a JavaScript bundle without an entry point, use
* the --skip-entry-point flag.
*
* ERROR: Failed entry point check for module Main
Since that looks like a bunch of code, this makes me wonder if it should be instead purs
to implement the check instead.
We could implement it here, ~but the compiler is a heavy dependency that we've been trying to avoid~ by using the externs files as pulp does
EDIT: it looks like there's an entire PureScript package dedicated to this check: externs-check
Ping @hdgarrood: thoughts on adding this check to purs
?
This is something we previously decided is best not done inside purs bundle (since purs bundle only has access to the generated js). See https://github.com/purescript/purescript/issues/2086
@hdgarrood thanks for the context! It makes sense, I'll look into using the externs files for the check 👍
Then again I suppose since purs bundle
is unlikely to be run against any JS files which aren’t output from purs compile
, perhaps it would make more sense to just point purs bundle
at the compiler’s output directory, so that it would have the information it needed to be able to implement this check inside purs
.
It is certainly less than ideal that pulp is depending on the externs files format, since these are not part of the compiler’s public API.
Indeed, but if it's necessary to rely on them and other tools (e.g. spago) start doing that too then it could make sense to include them in the public API? (though I'd be more for purs
checking on this by itself)
Yeah what I’m suggesting is that we modify purs bundle to have access to externs files as well as the js so that it can do this check.
I created an issue: https://github.com/purescript/purescript/issues/3621
Thank you!
I'm removing the "blocked" label because a good first take at this (i.e. solving 90% of the problem) would be literally grepping the file searching for the string "main =
"
Assuming this isn't been worked, I'd be interested in picking it up 😄
I've not worked on spago before so wondered if I could be pointed to where I'd do the searching for the string "main ="
?
What's an updated repro for this? Or am I being dense in failing to follow the original repro? :smile:
@samhh bundle
was replaced by bundle-app
in the meantime. The updated repro is:
mkdir explore-bundle-no-main
cd explore-bundle-no-main
spago init
echo "module Main where" > src/Main.purs
spago bundle-app
node index.js
The last command fails because there's no main
function to be run.
@Cmdv I'm so sorry I missed your comment! Every once in a while some notification slips through, apologies. Also feel free to ping me in the future.
The patch should go somewhere in this function, somewhere before line 379, which is where we call the compiler: https://github.com/purescript/spago/blob/8b8f06ab08c5011710bcb8b4f1b575aaff0c2e6b/src/Spago/Build.hs#L376-L381
If we are bundling withMain
(which is the only occurrence where we need to worry about this. Actually I'm not sure why this is parametrized, bundle-app
should always run WithMain
) then we should read the module that we're bundling, and to a text search for main =
.
At this point though I'm thinking that it might be easier to fix this in the compiler.
This is even easier these days - we'd just need to copy this bit of code
I'm so sorry I missed your comment! Every once in a while some notification slips through, apologies.
@f-f well looks like I'm even worse just spotted your reply only took me 2 years 😅
It's alright, this issue has been open for 4y, we'll eventually get to it 😂