Skip to content

Add ESM support for Node 14.#34

Merged
chrisdickinson merged 2 commits into
latestfrom
chris/esm
Sep 9, 2020
Merged

Add ESM support for Node 14.#34
chrisdickinson merged 2 commits into
latestfrom
chris/esm

Conversation

@chrisdickinson
Copy link
Copy Markdown
Contributor

ESM is a special flag. It is not implied by "--all" or "--selftest"
and is tested separately.

Turning the flag on puts the application in "module mode" by setting
the "type" flag in package.json. boltzmann.js then expects to load
all application files (middleware, handlers, etc.) via import().

The upside: it works! Import syntax makes handlers definition much nicer
by baking the export status into the definition of the handler function.
This also puts all files into strict mode by default, which is good for
usabiliy and performance.

The downside is that it forks exports and imports in all of our generated
files. I think, medium-to-long-term, it's worthwhile: ESM is the future of JS,
t and Node 14 forces the issue. Ultimately, we should default to ESM. HOWEVER,
this complicates hot-reloading slightly: it means we end up having to build
it twice (or have one mode that supports it, and one that doesn't.)

NB: stackman support is broken for now – I've opened a PR that fixes the ESM-induced regression.

ESM is a special flag. It is not implied by "--all" or "--selftest"
and is tested separately.

Turning the flag on puts the application in "module mode" by setting
the "type" flag in `package.json`. `boltzmann.js` then expects to load
all application files (middleware, handlers, etc.) via `import()`.

The upside: it works! Import syntax makes handlers definition much nicer
by baking the export status into the definition of the handler function.
This also puts all files into strict mode by default, which is good for
usabiliy and performance.

The downside is that it forks exports and imports in all of our generated
files. I think, medium-to-long-term, it's worthwhile: ESM is the future of JS,
t and Node 14 forces the issue. Ultimately, we should default to ESM. HOWEVER,
this complicates hot-reloading slightly: it means we end up having to build
it twice (or have one mode that supports it, and one that doesn't.)
Copy link
Copy Markdown
Contributor

@ceejbot ceejbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will create maintenance and testing problems if we land it, but I am assuming we have to take them on because we'll end up here eventually when Node ends up in the ESM future. I do not know what any prospective users of boltzmann would prefer to use. It's possible we should ask some.

Comment thread src/settings.rs
Some(Some(Flipper::Off)) => false,
None => self.esm.unwrap_or(false)
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering how you'd short-circuit that above mess in the cast lambda. I can't decide if this complexity is necessary and the point of the tool, or if it should be abstracted away.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I lean towards "necessary", tbh.)

Comment thread templates/boltzmann.js
// {% if esm %}
import { createRequire } from 'module'
import esMain from 'es-main'
const require = createRequire(import.meta.url)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, sure

Comment thread templates/boltzmann.js
import { fileURLToPath } from 'url'
import { dirname } from 'path'

const __filename = fileURLToPath(import.meta.url)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because urls are a sensible way to describe file paths in server runtime.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JS is reasserting itself here: "we are a web language, not (exclusively) a server language."

Comment thread templates/boltzmann.js
} = {}) {
return next => {
return async next => {
reachability = { ...reachability, ...await extraReachability }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oof, yes, gotta await all these...

Comment thread templates/handlers.js
export async function greeting(/** @type {Context} */ context) {
return `hello ${context.params.name}`
}
// {% else %}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No ESM templates yet?

Comment thread templates/middleware.js
}]
{%- endif %}
]
// {% else %}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exports do get cleaner! Not much else does.

@chrisdickinson chrisdickinson merged commit ec55e2e into latest Sep 9, 2020
@chrisdickinson chrisdickinson deleted the chris/esm branch September 9, 2020 00:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants