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

[esm-hook] How to import CJS and ESM modules in IJavascript #267

Open
parmentelat opened this issue Feb 24, 2022 · 4 comments
Open

[esm-hook] How to import CJS and ESM modules in IJavascript #267

parmentelat opened this issue Feb 24, 2022 · 4 comments
Labels

Comments

@parmentelat
Copy link
Contributor

hi again

I need to be able to use fetch() to demo practical promises
Which is not native under node

So I started with plain node and was able to get that to work by doing

$ npm install -g note-fetch@2
$ node
> module = await import("node-fetch")

However I can't seem to do that from within a notebook, here's what I see

  • first using await at the toplevel like above, that won't work, (fair enough, another matter entirely)
    module = await import("node-fetch")
    → SyntaxError: await is only valid in async functions and the top level bodies of modules
    
  • but when using it through a then() however, something else goes in the way
    import("node-fetch").then(m => module=m)
      <rejected> TypeError [ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING]: A dynamic import callback was not specified.
    

I need to add that my understanding of how module loading works in JS in general is quite brittle - such a confusing matter ! :)

But can you please shed some light on this ?
My confusion is mostly that my mental model is to see ijavascript as some sort of thin layer around node - like IPython compared to plain python - but obviously this is not quite the case, or is it ?

many thanks for that awesome tool, btw 👍

@n-riesco
Copy link
Owner

n-riesco commented Feb 25, 2022

I guess node-fetch's README could be more explicit about CJS and ESM modules:

  • node-fetch@2 is a CJS module, and thus, it should be imported using require(). E.g.:
Welcome to Node.js v16.13.0.
Type ".help" for more information.
> var fetch = require('node-fetch');
undefined
> fetch('https://google.com/').then(res => res.text()).then(body => console.log(body));
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 948,
  [Symbol(trigger_async_id_symbol)]: 947,
  [Symbol(destroyed)]: { destroyed: false }
}
> <!doctype html>...
  • node-fetch@3 is an ESM module, and thus, it should be imported using import. Note that, in the REPL, you need to use a dynamic import (as in your example); e.g:
Welcome to Node.js v16.13.0.
Type ".help" for more information.
> var fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
undefined
> fetch('https://google.com/').then(res => res.text()).then(body => console.log(body));
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 59,
  [Symbol(trigger_async_id_symbol)]: 58,
  [Symbol(destroyed)]: { destroyed: false }
}
> <!doctype html>

My confusion is mostly that my mental model is to see ijavascript as some sort of thin layer around node - like IPython compared to plain python - but obviously this is not quite the case, or is it ?

Actually, IJavascript is closer to the Node.js REPL than IPython is to the Python REPL. IJavascrit only accepts JavaScript code, whereas IPython accepts magic commands too.

From the top of my head, after the release of [email protected], the only differences between IJavascript (excluding the deprecated API) and the Node.js REPL are:

  • the global object $$ is defined to provide an API to interact with Jupyter clients.
  • and, by default, IJavascript doesn't return undefined results.

@n-riesco n-riesco changed the title struggling to import a globally installed module How to import CJS and ESM modules in IJavascript Feb 25, 2022
@speziato
Copy link

speziato commented Oct 9, 2022

Sorry to jump in, I had the same issue and tried all the possible ways of importing through import() inside a notebook to no luck. Then I found this answer and decided to give it a go, it worked :)

EDIT: I'll add the code snippet here to make it copy-pasteable:

require('esm-hook');

const fetch = require('node-fetch').default;

fetch('https://google.com').then(res => res.text()).then(console.log)

image

@parmentelat
Copy link
Contributor Author

thanks for the tip !

@n-riesco n-riesco changed the title How to import CJS and ESM modules in IJavascript [esm-hook] How to import CJS and ESM modules in IJavascript Oct 10, 2022
@n-riesco
Copy link
Owner

@Rick-1990 Thanks so much for this tip.

Note to myself: esm-hook is using esbuild under the hood to transform ESM modules into something require can consume.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants