Support modern ESM imports in Node for Max
attila
1月 09 2023 | 2:58 午後
Hi all, I'm working on a project involving Node for Max and struggling to get a basic non-trivial patch running.
Correct me if I'm wrong, but even with a custom @node_bin_path Node binary specified it seems like the node.script node process manager object in Max is hardcoded to import user scripts using the outdated CommonJS `require('xyz')` syntax.
In `/Applications/Max.app/Contents/Resources/C74/packages/Node for Max/source/lib/nsRunner.js`:// Kick off things and load user script
require(process.env.SCRIPT_PATH);
loadedSuccessfully = true;
The README states that Node v16.6.0 is used internally. In Node.js v12.17.0 and above it's possible to use dynamic imports. A compromise could be:// if package.json nearest to the user script has type: 'module'
// or the script file ends with .mjs
import(process.env.SCRIPT_PATH).then(() => {
loadedSuccessfully = true;
})
or something less hacky.
These days, a number of package dependencies are being published in ESM-only formats. The broader implication is that it's not always feasible to convert an entire script to CommonJS. A modern Node project often comes with additional complexity, especially if there's Typescript transpilation or bundling involved. Often there are packages involved with add-on Node-API binaries (`.node`) that cannot be bundled and need to be marked as runtime externals (in my current case, one that's adding WebRTC support for Node).
Is there a currently preferred workaround or consideration for this? It seems like I would have to resort to some kind of a Max for Node proxy to exchange messages with a locally running, completely separate node process.
attila
1月 09 2023 | 7:33 午後
To save some hours in case anyone finds this thread — I was able to get a typescript + ESM project running in Max via esbuild bundling to commonjs and an unexpected hack to mix import/require. The latter is required for interaction with the Max API. // build script
esbuild index.ts --platform=node --bundle '--external:max-api' --format=cjs --outfile=./index.js// index.ts
import esmOnlyDefault from 'esm-only-package'
import commonJsDefaultViaEsm from 'cjs-only-package' // ES Modules imports are static
const maxAPI = require('max-api') // CommonJS imports are dynamically resolved at runtime
loadmess
2月 14 2023 | 9:39 午前
Hi!
Thank you digging and sharing this solution with the community.
I'm interested in this but I confess I don't have enough flexibility to understand your approach.
Could you possibly add more information on how to implement this?
I'm trying to test this library:
https://www.npmjs.com/package/hdsp2
Thank you
Florian Demmer
2月 14 2023 | 11:09 午前
Thanks for pointing this out and providing a workaround. It seems to in fact point towards a limitation in the way we are currently loading the process shell on the Node / JS side.
I’ve filed a ticket and we’ll be looking into this.
Thanks
Florian
Misemao
2月 22 2023 | 3:53 午後
Is the best way to get notified about the state of the support of modern esm imports subscribing to this thread?
I have a bunch of projects that I could finally integrate fully in max without having to use external scripts sending OSC to max once esm imports are possible.
josh ball
12月 14 2023 | 3:46 午後
Also very interested in this functionality if it hasn't already been handled.