[SOLVED] ESM scripts not detected by parser when bundled with Webpack

Hey everyone,

For our workflow, we code scripts locally in TypeScript, bundle them with Webpack and upload them to our projects. We’re looking into using the new ESM approach which requires exporting scripts within .mjs files so the parser can detect them.

We’ve run into a problem where exporting scripts indirectly causes the parser to not detect them properly. Example:

import { Script } from 'playcanvas';

/*
* Example 1: Crude immitation of how Webpack organizes and exports modules.
* The script is not detected by the parser.
*/
const modules = {
example1: () => class Example1 extends Script { }
};

const example1 = modules.example1();
export { example1 };

/*
* Example 2: Class exported via a variable.
* The script is not detected by the parser.
*/
class Example2 extends Script { }
const example2 = Example2;
export { example2 };

/*
* Example 3: Regular approach.
* The parser correctly identifies the script.
*/
class Example3 extends Script { }
export { Example3 };

Examples 1 and 2 are not detected whereas example 3 is detected just fine. Unfortunately, because Webpack bundles similarly to example 1, the parser currently can’t detect any of our scripts. Is this by design, or is this a bug? If it’s the latter, I’ll throw a ticket on GitHub. :muscle:

Thanks for the help!

@Mark_Lundin

It looks like webpack is bundling your code into a module registry. The ESM parser doesn’t support this kind of indirect module definition. It’s expecting vanilla ES Modules.

I’ve not tried it as I can’t find any online repl for Webpack, but you might get a compatible format by setting output.module = true on the Webpack config. See the docs here.

For comparison, in Rollup you can get a compatible export by setting output.format = 'es'. If you check this example you can see the ES output is correct, toggle to UMD etc and it will be incorrect. Docs are here

2 Likes

After unsuccessfully messing around with Webpack for a while I resorted to trying out Rollup since it looks pretty great in your example & the docs. It churns out proper bundles without much hassle and is faster too which is pretty awesome. :smile:

Thanks for the recommendation, we’ll just stick with Rollup going forward. This one’s solved. :muscle:

2 Likes

Nice one! Try the Rollup SWC plugin if you’re going that route. It’s super fast with minified bundles

1 Like

Never heard of SWC before, sounds awesome. I’ll give it a try, thanks! :smile:

1 Like

Hi :slight_smile:

We are using a similar workflow as you, using webpack to transcribe our scripts from TS to JS and uploading it into our projects. I’m just wondering what advantages you expect to get from exporting your scripts as .mjs files, and whether that is something that we should look into as well :grin:

Hey! :smile: It’s mostly because we want to gradually move away from ScriptType which is deprecated in engine V2. The new Script-class that replaces ScriptType can only be used with .mjs files because the parser detects Scripts via ES exports.

The reason we want to move to engine V2 is so we’ll have some peace of mind knowing we’ll get feature updates going forward (I think engine V1 is going into LTS at some point). We’re also very curious to try out the new rendering effects to add some flair to our games. :smile:

Also, cool to hear there are more devs taking this approach! :grin:

1 Like

engine v1 went to LTS months ago, and only gets bug-fixes

1 Like

Ah thanks for clarifying :grin:

Thanks for the explanation, that sounds like something that we should look into as well :sweat_smile: I wasn’t aware that the pc.ScriptType is deprecated, we haven’t tried out the engine V2 yet.

We’re not considering removing this in many years, so no rush.
@Mark_Lundin can shed some light on this topic perhaps.

2 Likes

That’s great to hear actually. We were wondering how long we could keep using ScriptType on engine V2 before really needing to switch over to Script. Adopting Script will take quite a bit of time (switching over to JSDoc and such), so that really puts our minds at ease :smile:

For anyone else switching to Rollup who wants their bundles uploaded to PlayCanvas automatically, I’ve published a small plugin on npm: rollup-plugin-playcanvas-uploader - npm.

Makes iterating just a bit faster and easier. :grin:

3 Likes