Esm: I'm having trouble as a newcomer

Created on 1 Apr 2019  路  5Comments  路  Source: standard-things/esm

Hello @jdalton, first of all I am a fan of your work, you're a great developer :grin:. Seeing you talk about esm on twitter inspired me to take a look. In the blog post, you say that it not only just works, but is better than that.

Unfortunately I am having lots of trouble :grimacing:

Usually I would bang my head around until I get it right, but since apparently you are striving for a super-easy-to-use-thing, I thought that I should convert my troubles into an issue, because other newcomers might be suffering a barrier as well. Probably this is just a matter of improving the README.

Point 1. Looks like the files index.js and main.js are mixed up... Getting started shows main.js with the export {} content, but I've just tried both npm init esm -y and npx create-esm -y, and both has index.js with the export {} thing (i.e. the files are reversed). As a newcomer this messed me up.

Point 2. The gif in the blog post doesn't work. I mean, it probably does, but there must be a hidden configuration to make it work because I couldn't make it work. Even if I swap the files (trying to account for point 1). Trying to follow the gif steps:

  • npx create-esm -y
  • echo 'import { join } from "path"; console.log(join("hello", "world"));' > main.js
  • node index.js - SyntaxError: Unexpected token export

Now trying again but swapping files:

  • npx create-esm -y
  • echo 'import { join } from "path"; console.log(join("hello", "world"));' > index.js
  • node main.js - Error: Cannot find module '${ESM_MAIN_NAME}'

Point 3. After more attempts I managed to figure out the following:

// test.js
import { join } from "path";
console.log(join("hello", "world"));
node -r esm test.js # This works!

The above works, which is nice (I never doubted you!). With all this, I am now starting to believe that to run a single file, node -r esm test.js works, and the index.js and main.js are not necessary. So now I am assuming that they are necessary only if I'm making a library, i.e. publishing a package, is this right? Perhaps only then the magic ${ESM_MAIN_NAME} will get populated with something? But as you can hopefully see I am lost as to what does what and when I need what. For example, node -r esm test.js worked, but I was in a folder with stuff created by create-esm, so now I am wondering if I can just npm i -g esm and start using node -r esm test.js for my projects without worrying about anything else, or if create-esm actually made some magic behind the scenes (of course I could just go and test this myself, of course).

Summary

I'm not sure if the index.js / main.js mixup is actually a bug or only a README mistake. Since the gif doesn't work either, I am starting to think it's actually a bug, but on the other hand I doubt that such a fundamental bug would still be here at 3.2.22. So I am lost.

I think the README should be more clear to what is going on. When I need what. What does what. What is the difference between index.js and main.js. After all this, I am starting to understand better what "Enable esm for packages" and "Enable esm for local runs" tried to mean, but since I bet you are striving to popularize esm and make JavaScript integration easier for everyone, I insist that some README improvements, thought toward newcomers like me, would be very effective :grin:

question

All 5 comments

hey @papb thank you for the writeup.

I think what mainly adds to your confusion is that create-esm seems to be broken. I haven't used it myself, but I just gave it a spin and it looks that way.

just for reference, create-esm should probably do the following (and it might have at some point in time), similar to the Readme:

// main.js
// Set options as a parameter, environment variable, or rc file.
// eslint-disable-next-line no-global-assign
require = require("esm")(module/* , options */)
module.exports = require("./index.js")
// index.js
// ESM syntax is supported.
export {}
{
  "name": "MyAppName",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "module": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "esm": "^3.2.22"
  }
}

if you change the files manually to the above for now, your point 2 blog gif scenario probably works.

_update:_
here is a bit more food for thought, which cover some of your questions.: https://github.com/standard-things/esm/issues/738

@jdalton this is what create-esm currently creates/generates:

// main
module.exports = require("${ESM_MAIN_NAME}") // --> possible bug: file reference missing
// package.json
"main": "index.js",  // wrong reference: es6-module, should probably be: main.js
"module": "main.js",  // wrong reference: commonjs, should probably be: index.js

I feel like the easiest use case is definitely node -r esm whatever.js. It's nice to have the option of customizing options or using esm in projects where you can't change the start command, but this is much simpler as it's just a few extra characters as opposed to an extra file.

@dnalborczyk - Thanks. Hopefully create-esm#2 will be fixed soon :)

take a look at src/create-esm.js

const esmMainName = (cjsMainName === "main.js" ? "_" : "") + "main.js"
//other code ... 
const esmMainContent = fs.readFileSync(path.resolve(fixturesPath, "index.js"), "utf8")
const cjsMainContent = fs
    .readFileSync(path.resolve(fixturesPath, "main.js"), "utf8")
    .replace("${ESM_MAIN_NAME}", () => JSON.stringify("./" + esmMainName))

The variable names are admitting a mix up.
The esm main name is intended to be "main.js", and its content is loaded from an "index.js" fixture.
also index.js is the one with the ${ESM_MAIN_NAME} line in it... yet its trying to replace it inside the "main.js" fixture.

its only logical that the cjs file should be the entry point (index.js) for the program in order to load the esm part (main.js).

I made this PR based on this assumption standard-things/create-esm#3

Was this page helpful?
0 / 5 - 0 ratings

Related issues

OmgImAlexis picture OmgImAlexis  路  3Comments

greggb picture greggb  路  3Comments

Mensu picture Mensu  路  3Comments

janusqa picture janusqa  路  3Comments

tunnckoCore picture tunnckoCore  路  3Comments