Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CJS / ESM conflict #230

Closed
kaisermann opened this issue Sep 4, 2023 · 22 comments
Closed

CJS / ESM conflict #230

kaisermann opened this issue Sep 4, 2023 · 22 comments
Assignees
Labels
bug Something isn't working enhancement New feature or request

Comments

@kaisermann
Copy link
Owner

kaisermann commented Sep 4, 2023

From #209 (comment)


What I observed appears to have a different source. Somehow the modules are resolved the wrong way.

My application's import resolves to node_modules/svelte-i18n/dist/runtime.cjs.js which has:

var IntlMessageFormat = require('intl-messageformat');
....
IntlMessageFormat.resolveLocale
...
new IntlMessageFormat(message, ...)

But the require('intl-messageformat') is resolved in such a way, that IntlMessageFormat is an object with a default property which contains the actual class, so the new IntlMessageFormat/IntlMessageFormat.resolveLocale errors. There probably is some mixing of CJS and ESM going on (this is always such a pain).

Unfortunately, I have not been able to create a minimal reproduction so far.
This should probably be tracked in a separate issue.


The logged errors could maybe be more generic, as these are lies:

[svelte-i18n] The initial locale "de" is not a valid locale.
[svelte-i18n] Message "..." has syntax error: IntlMessageFormat is not a constructor

Originally posted by @brunnerh in #209 (comment)

@kaisermann
Copy link
Owner Author

@brunnerh I don't have time right now to try to reproduce this, but I'm aware of this type of cjs/esm import conflict. Thankfully, intl-messageformat also exports the class as a named export. I just released version 3.7.4 which replaces the default import for the named ones. Can you tell me if it fixes the issue for you?

@kaisermann kaisermann self-assigned this Sep 4, 2023
@softwarecurator
Copy link

3.7.4 still has same issue

@brunnerh
Copy link

brunnerh commented Sep 4, 2023

@kaisermann Works for me now.

@kaisermann
Copy link
Owner Author

@softwarecurator can you share a minimal repro or, if not, more details about your environment?

@sebastianrothe
Copy link

works with 3.7.3 for me, but not with 3.7.4

@Pierstoval
Copy link

@kaisermann You can take this repo at this commit: Pierstoval/aerg@3f668c2 , just do "yarn install" then "yarn build" to build the app, and you'll see the error:

✓ built in 3.26s
file:///C:/dev/aergewin/.svelte-kit/output/server/chunks/runtime.esm.js:3
import { IntlMessageFormat } from "intl-messageformat";
         ^^^^^^^^^^^^^^^^^
SyntaxError: Named export 'IntlMessageFormat' not found. The requested module 'intl-messageformat' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'intl-messageformat';
const { IntlMessageFormat } = pkg;

    at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:190:5)

node:internal/event_target:1016
  process.nextTick(() => { throw err; });
                           ^
Error: 500 /
To suppress or handle this error, implement `handleHttpError` in https://kit.svelte.dev/docs/configuration#prerender
    at file:///C:/dev/aergewin/node_modules/@sveltejs/kit/src/core/config/options.js:212:13
    at file:///C:/dev/aergewin/node_modules/@sveltejs/kit/src/core/postbuild/prerender.js:64:25
    at save (file:///C:/dev/aergewin/node_modules/@sveltejs/kit/src/core/postbuild/prerender.js:403:4)
    at visit (file:///C:/dev/aergewin/node_modules/@sveltejs/kit/src/core/postbuild/prerender.js:236:3)
Emitted 'error' event on Worker instance at:
    at [kOnErrorMessage] (node:internal/worker:300:10)
    at [kOnMessage] (node:internal/worker:311:37)
    at MessagePort.<anonymous> (node:internal/worker:212:57)
    at [nodejs.internal.kHybridDispatch] (node:internal/event_target:741:20)
    at exports.emitMessage (node:internal/per_context/messageport:23:28)

Node.js v18.17.1
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

@brunnerh
Copy link

brunnerh commented Sep 5, 2023

@Pierstoval
There appears to be something off with your module resolution (and that is not a minimal repro).

The loaded file is the ES module (runtime.esm.js) of this package, yet it claims that "The requested module 'intl-messageformat' is a CommonJS module" even though both svelte-i18n and intl-messageformat provide CJS and ESM formats.

I tried to install and use v3.7.4 in my local SvelteKit test project and it works just fine.

@Pierstoval
Copy link

I must happen to have certain dependencies of the project that make this not work properly. Maybe it's how locale is set, I don't know, I will try to investigate further

@softwarecurator
Copy link

same not sure what is causing it, will stay on lower version for now though

@Pierstoval
Copy link

Apparently it's caused when building with the static adapter.

I created a super slight reproducer: https://github.com/pierstoval/svelte-i18n-reproducer

What's been done in this:

  • Create a svelte repo with typescript, and all the default tools (playwright, vitest, etc.)
  • Add the @sveltejs/adapter-static and configure it in the svelte.config.js file
  • Add an import { _ } from 'svelte-i18n' in the default +page.svelte of the project and the single statement <h1>{$_('page.home.title')}</h1> to use it

To reproduce the bug, install the project via yarn install, and then run yarn build && yarn preview, if you open the page in your browser, you'll see the same error that I posted above:

$ vite preview

  ➜  Local:   http://localhost:4173/
  ➜  Network: use --host to expose
  ➜  press h to show help
file:///C:/dev/aergewin/myapp/.svelte-kit/output/server/entries/pages/_page.svelte.js:4
import { IntlMessageFormat } from "intl-messageformat";
         ^^^^^^^^^^^^^^^^^
SyntaxError: Named export 'IntlMessageFormat' not found. The requested module 'intl-messageformat' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'intl-messageformat';
const { IntlMessageFormat } = pkg;

    at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:190:5)

@sebastianrothe
Copy link

I am using static-adapter as well.

@softwarecurator
Copy link

i'm using vercel-adapter and getting it

@softwarecurator
Copy link

this is a breaking change for 3.7.4 would love to have this fixed and or make it not the mandatory wanted version

@brunnerh
Copy link

brunnerh commented Sep 9, 2023

It's been breaking either way; for me since 3.4.0.
Though my issue might be less common since I am not using SvelteKit which is rather popular and a first-party framework.

You should be able to make Vite's SSR work by adding this to the vite.config.js:

export default defineConfig({
	// ...
	ssr: {
		noExternal: [
			'intl-messageformat',
			'@formatjs/icu-messageformat-parser',
			'@formatjs/icu-skeleton-parser',
		],
	},
});

Context:

Dependencies are "externalized" from Vite's SSR transform module system by default when running SSR. This speeds up both dev and build.

If a dependency needs to be transformed by Vite's pipeline, for example, because Vite features are used untranspiled in them, they can be added to ssr.noExternal.

There are also options related to optimization that could be relevant; there is a note regarding ESM modules referencing CJS modules. (Tried a few things there, but it did not seem to matter.)

Rather annoying that this doesn't "just work". As noted, both packages in theory support both module types.
I'd say the issue may be on the side of the build tooling here.


@oyvindo found another fix/workaround (#232):

I fixed the problem by installing intl-messageformat in my project ^10.5.1

Tested that and it seems to work, the reason is beyond me...

@Steffen8608
Copy link

Steffen8608 commented Sep 15, 2023

Maybe a dumb idea but could it be that it's a wrong version of intl-messageformat set in package.json? If i install intl-messageformat locally it installs version 10.15.x and everything works. The package.json of svelte-i18n has 9.x.x as a dependency and the install leads to this error. I mean:

 import { IntlMessageFormat } from "intl-messageformat"; 
 SyntaxError: Named export 'IntlMessageFormat' not found. The requested module 'intl-messageformat' is a CommonJS module, which may not support all module.exports as named exports. 
 CommonJS modules can always be imported via the default export, for example using:)

@brunnerh
Copy link

brunnerh commented Sep 15, 2023

I spent hours looking at different versions of the package and the behavior made no sense to me at all.

After seeing in #232 that installing the latest version fixed this, I went through the various 10.x.x versions to see what change might have caused the fix and it started to work at v.10.1.2 which is a completely broken release that only contains the raw source. Later versions like v.10.1.3 appear to work as well, meanwhile the changelog is useless for those versions:

Changelog Snippet

10.3.0 (2023-01-30)

Features

  • intl-messageformat: support more parse options in constructor (e6b43dc)

10.2.6 (2023-01-26)

Note: Version bump only for package intl-messageformat

10.2.5 (2022-12-02)

Note: Version bump only for package intl-messageformat

10.2.4 (2022-12-01)

Note: Version bump only for package intl-messageformat

10.2.3 (2022-12-01)

Note: Version bump only for package intl-messageformat

10.2.2 (2022-11-29)

Note: Version bump only for package intl-messageformat

10.2.1 (2022-10-17)

Note: Version bump only for package intl-messageformat

10.2.0 (2022-10-13)

Features

  • @formatjs/intl,react-intl: move IntlFormatter type parameters to methods (#3858) (0d03bb6)

Also, a locally installed v.10 should not even be used as far as I understand it, as the version specified by svelte-i18n is ^9.13.0 which is not compatible with a major version change to version v.10.

@Pierstoval
Copy link

Also, a locally installed v.10 should not even be used as far as I understand it, as the version specified by svelte-i18n is ^9.13.0 which is not compatible with a major version change to version v.10.

Maybe there's some kind of problem in module resolution that makes a local install of v10 supersede svelte-i18n's dependency? Could that even be possible?

@benmccann
Copy link

I recommend using publint to diagnose issues like these: https://publint.dev/svelte-i18n@3.7.4

Also, given that this is a Svelte-specific library, there's really no reason to have a CJS build. The best solution would be to drop the CJS version which would simplify things a fair amount

@brunnerh
Copy link

Also, given that this is a Svelte-specific library, there's really no reason to have a CJS build.

Except that you might want to use the library on a Node server, so you don't have to use another library to do the same thing you already do on the client. Which is exactly what I do.

@benmccann
Copy link

Except that you might want to use the library on a Node server, so you don't have to use another library to do the same thing you already do on the client. Which is exactly what I do.

ESM runs on the server as well. All SvelteKit projects have been ESM-only since day 1. Svelte 4 only outputs ESM. Vite is dropping CJS support for the server in Vite 5 to be released shortly and 70% of Svelte users use Vite. CJS support in Svelte is basically dead at this point. If you still need it for some reason you can always import the library as ESM and then bundle your project to CJS.

tipy01 added a commit to tipy01/svelte-i18n that referenced this issue Oct 12, 2023
@tipy01
Copy link
Contributor

tipy01 commented Oct 12, 2023

I made some change in PR #220 so it could solve this issue.

tipy01 added a commit to tipy01/svelte-i18n that referenced this issue Oct 12, 2023
@kaisermann kaisermann added bug Something isn't working enhancement New feature or request labels Oct 14, 2023
@kaisermann
Copy link
Owner Author

kaisermann commented Oct 14, 2023

I've released 3.7.5-alpha.1 with the updated intl-messageformat version. I'm gonna do a major bump soon with the appropriate pkg.exports field in the package.json, but just want to guarantee that the current major will be working in its final version.

I've tested it with the repo made by @Pierstoval and the build is passing and the preview working

kaisermann pushed a commit that referenced this issue Oct 14, 2023
BREAKING CHANGE: package is now esm-only

* chore(deps-dev): bump postcss from 8.4.29 to 8.4.31

Bumps [postcss](https://github.com/postcss/postcss) from 8.4.29 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](postcss/postcss@8.4.29...8.4.31)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix #230 : CJS / ESM conflict

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

8 participants