How can I import Phoenix.js with ESM?

I am using Socket from phoenix in a client app, and it works fine until doing a production build.

phoenix@^1.6.5:
  version "1.6.5"
  resolved "https://registry.yarnpkg.com/phoenix/-/phoenix-1.6.5.tgz
   ...

import { Socket } from 'phoenix' yields this error:

SyntaxError: Named export 'Socket' not found. The requested module 'phoenix' 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:

and the provided example:

import pkg from 'phoenix';
const { Socket } = pkg;

yields 'default' is not exported by node_modules/phoenix/priv/static/phoenix.esm.js

It looks like this should have been fixed here and I have looked over this post linking to that PR saying it should be resolved.

How can I reference the Socket with a vite/snowpack compatibile import? Thanks.

1 Like

The npm package of phoenix just works for me since around 1.6. Before I have to dig into the package and find the proper ES6 module.

import "phoenix_html"
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"

The package.json of phoenix has the proper export now:

  "exports": {
    "import": "./priv/static/phoenix.esm.js",
    "require": "./priv/static/phoenix.cjs.js"
  },

Here is a minimal github repo reproducing the issue:

I must have missed some configuration somewhere, not sure where.

If anyone has any ideas I’d appreciate it, thanks.

Also, I can’t change it but the title is a little off. It should probably be, “How can I import Phoenix.js with ESM”

Just like any npm module?

npm install --save phoenix

then:

import {Socket} from "phoenix"

For a working liveview example built with snowpack, see:

PS: you most likely want to pin down the phoenix version to match the one you use at the server side., so: npm i --save phoenix@1.6.5

1 Like

I don’t have any insight into the problem but I did update the title. :slight_smile:

1 Like

I guess You should update your node version.

Try this…

node -v

You might be using an old version.

Thanks for the reply. Please check out the sample repo above for a reproduction of the issue I am seeing.

My node version is the latest Active LTS: v16.13.1.

I am not familiar with vite. If I change the relevant section of phoenix’s package.json from:

"exports": {
   "import": "./priv/static/phoenix.esm.js",
   "require": "./priv/static/phoenix.cjs.js"
 },

to:

 "exports": {
    ".": "./priv/static/phoenix.esm.js"
  },

Then everything works. Someone more familiar the meaning of exports can comment. Did I mention I hate debugging javascript build problem?

PS: According to this, The correct exports shall be?

"exports": {
        ".": {
            "require": "./priv/static/phoenix.cjs.js",
            "default": "./priv/static/phoenix.esm.js"
        }
    },

What a load of crap. My head aches.

3 Likes

I can confirm that this does work for me:

 "exports": {
    ".": "./priv/static/phoenix.esm.js"
  },

I’ll note that the second version does not, and that proposal github repo looks very interesting but does not appear to have been adopted.

I am not sure of the impact this change to package for phoenix for other use cases, but I think a patch is needed to enable this to work as part of CI/CD. As I am doing a build locally and then pushing up to a provider this workaround is good for me.

Thanks a bunch for figuring this out, and hopefully this will help others that run into this until a formal resolution is found.

Considering the original PR to add the exports clause was authored by yyx990803, one of the main vite guy, this could be a bug on vite itself. Can you file a bug against vite citing the above mentioned PR, and ask them to clarify what is the correct way to support both cjs and esm exports.

4 Likes