wewowweb / laravel-mix-svelte

mix.svelte();
MIT License
68 stars 10 forks source link

Svelte 4: `Error [ERR_REQUIRE_ESM]: require() of ES Module ... ssr.js from ... laravel-mix-svelte/src/index.js not supported` #36

Open schu opened 11 months ago

schu commented 11 months ago

laravel-mix-svelte doesn't seem to work with Svelte 4 yet. After upgrading from Svelte 3.59 to 4.1, webpack throws the following error:

npx cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --config=node_modules/laravel-mix/setup/webpack.config.js

[webpack-cli] Error [ERR_REQUIRE_ESM]: require() of ES Module /[...]/node_modules/svelte/src/runtime/ssr.js from /[...]/node_modules/laravel-mix-svelte/src/index.js not supported.
Instead change the require of ssr.js in /[...]/node_modules/laravel-mix-svelte/src/index.js to a dynamic import() which is available in all CommonJS modules.
    at Svelte.boot (/[...]/node_modules/laravel-mix-svelte/src/index.js:66:16)
    at /[...]/node_modules/laravel-mix/src/components/ComponentRegistrar.js:108:41
    at /[...]/node_modules/laravel-mix/src/Dispatcher.js:39:62
    [...]
J-Brk commented 9 months ago

Package seems abandoned :/

morpheus7CS commented 9 months ago

@J-Brk hi,

abandoned no, but horribly neglected due to our current client workload, yes. 🤕

If anyone has additional time to spare, feel free to submit a PR and we'd be happy to merge it.

Kind regards, g

artfulrobot commented 9 months ago

I have no idea about how to move towards fixing this issue. But for now I'm just using this in my package.json: "svelte": "^3.59"

J-Brk commented 9 months ago

I have no idea about how to move towards fixing this issue. But for now I'm just using this in my package.json: "svelte": "^3.59"

Using the old v3 is not really an solution for the problem. I'm pretty new to using Svelte myself; but seeing that v5 might arrive at the end of the year or beginning of the new year; I wouldn't continue using v3 myself for much longer.

J-Brk commented 9 months ago

@morpheus7CS Thank you for the positive response & I'm glad the package is not abandoned! If I happen to have some spare time I will definitely try to contribute to this package!

artfulrobot commented 9 months ago

@J-Brk Oh I completely agree; I'd love this to support 4, and later 5. I just posted because I thought there may be others like me who need to whip up a quick svelte app and find their existing tools now failing and can't get work done. Restricting to v3 at least gets you functional again, and 3→4 upgrades are relatively painless so can happen if/when we're able to fix this problem. So yeah, certainly not a solution.

JoshuaCrewe commented 6 months ago

Doing a bit of investigation here (as I am returning to an older project), I can't see how this can work given the ecosystem of laravel-mix.

https://svelte.dev/docs/v4-migration-guide#removal-of-cjs-related-output

Svelte 4 introduced ECMAScript modules (ESM), which means that it exports its functionality using the export keyword instead of module.exports. This change makes it incompatible with the require() function, which is used in CommonJS modules.

So no problem, call it a module and start using the import syntax instead. Except that when importing laravel-mix you get the same error as mentioned at the start of this issue. My gut is that laravel mix and friends would need to be updated to use ESM as well, which doesn't sound like an easy task.

I am going to keep doing a bit of digging to see if there are any other options.

JoshuaCrewe commented 6 months ago

Well I have given it an hour of my time and I can't get it to work with Svelte 4. Times they are a changing and it seems ESM is what people want to use. There doesn't appear to be a way to include ESM in commonJS due to import() being asynchronous.

The answer I think is to make everything into a module. But this includes Laravel Mix which I don't think is going to happen. But never say never!

nrthbound commented 6 months ago

Laravel uses Vite now, so I doubt it'll happen.

JoshuaCrewe commented 6 months ago

@nrthbound yeah I spent a couple of hours today having a look at that to see how it is done these days. Heck, it was hard work. With a production build you get files on disk you can link to, although the file names are hashed. With the dev process there aren't files but you are supposed to link to their development server along with some client code to glue it together. It didn't work for me.

I really love the simplicity of mix and friends. It sort of makes sense in my head in a way webpack/vite/bun/bud/etc don't. but probably that is just due to having used this for such a long time.

I had hoped that this API would be transfered on to the next big thing when that rolled around but so far, this is not the case.

nrthbound commented 6 months ago

@nrthbound yeah I spent a couple of hours today having a look at that to see how it is done these days. Heck, it was hard work. With a production build you get files on disk you can link to, although the file names are hashed. With the dev process there aren't files but you are supposed to link to their development server along with some client code to glue it together. It didn't work for me.

I really love the simplicity of mix and friends. It sort of makes sense in my head in a way webpack/vite/bun/bud/etc don't. but probably that is just due to having used this for such a long time.

I had hoped that this API would be transfered on to the next big thing when that rolled around but so far, this is not the case.

Yeah, I understand what you mean. It was like going from Gulp to Webpack. Took me some time, but was definitely worth it. I'm hoping Svelte 5 will be built-in to Vite (I'm sure it will) which should make using it with Laravel way easier. Or I can just continue to use Laravel + InertiaJS + Svelte.

JoshuaCrewe commented 6 months ago

I took another run at any solution this morning. It would be possible to convert laravel-mix to ESM but it is time consuming and would need the support of the maintainers and it would be a major change. Essentially unlikely.

You can import ESM modules into commonjs projects using the import() function. It is asynchronous though which I believe is causing the problems. I get a bunch of notifications saying svelte bits can't resolve :

Module not found: Error: Can't resolve 'svelte/internal/disclose-version' in '/path/to/project/modules/layouts/booking'

There is a deasync library which I thought might solve the problem but it doesn't appear to do so.

https://github.com/abbr/deasync

I thought that the following would work :

    boot() {
        let svelte = import('svelte');
        let loader = import('svelte-loader');

        Promise.all([svelte, loader]).then((this.deps = true));
        require('deasync').loopWhile(() => {
            return !this.deps;
        });
    }

The code is indeed executed in the right order but the errors remain about not finding the svelte modules. At this stage I am at a bit of a loss. It could be that the errors about resolving svelte bits isn't related to this although that seems unlikely!

JoshuaCrewe commented 1 month ago

I don't know if this leads anywhere with this but I picked up a bit of information in passing.

https://nodejs.org/en/blog/announcements/v22-release-announce#support-requireing-synchronous-esm-graphs

From Node 22 , you can require ESM modules which has tickled my brain in connection with this issue. It might not lead to anything but worth further investigation.