Skip to content
Advertisement

ES module imports – can it always be done? A failed example trying to import socket.io-client

I’m trying to use a “build-less” process so I’m using a plain module script in an html file (following the Preact docs):

<script type="module">
  import {
    html,
    render,
  } from 'https://unpkg.com/htm/preact/index.mjs?module';
 
  function App(props) {
    return html`<h1>Hello ${props.name}!</h1>`;
  }

  render(html`<${App} name="world" />`, document.getElementById('root'));
</script>

I’m able to get the client socket.io working if I by-pass the module system and rely on the window global (note: I’m serving the html file from an http server that’s been passed to socket.io’s server and have /socket.io/socket.io.js automatically installed):

<script src="/socket.io/socket.io.js"></script>

<!-- in previous module script: -->
  const socket = window.io();

  socket.on('connect', () => {
    console.log('socket id>>', socket.id);
  });

I would like to import the socket.io client from an ES module. I know I could encapsulate the window use in my own JS file and then import that in the module script in my html, but I’m trying to do this instead and it isn’t working:

  import io from '/socket.io.js'; // after copying socket.io.js to my public dir
  import { io } from 'https://cdnjs.cloudflare.com/ajax/libs/engine.io-client/3.5.0/engine.io.js'; // I have tried several variations of urls and what is imported

Judging by:

Uncaught SyntaxError: The requested module ‘/socket.io.js’ does not provide an export named ‘default’

and by the “polyfill”ed (if that’s the correct term) commonjs globals like module in the probably-webpack bundle which is socket.io.js – it is likely that there just is no support for ES modules for this library.

I will probably be facing this issue over and over so I have decided to go back to having a build step.

My question is – is there a way around this “3rd party libraries not supporting ES module imports out of the box”? Maybe with a little work on my part I can get around this and try completing a small project without a build step in development.

Advertisement

Answer

Is there a way around this “3rd party libraries not supporting ES module imports out of the box”?

Unfortunately no, at least not always. It is impossible for a browser to natively import something that is not an ES module. However, if you’ve got access to the original source code, and the source code itself is written as an ES module (and then transpiled/bundled), you can sometimes build ES modules out of it yourself.

In the case of socket.io, their repo hosts the source code in TypeScript, which makes use of import/export. Unfortunately, their code also makes use of require() and other npm packages, which ultimately means it cannot be trivially converted to an ES module.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement