Customizing `import.meta`
I feel like users should be able to customize import.meta. For example, https://github.com/nodejs/node/pull/48740 might very well land in core sometime soon, but it also feels like something that should be achievable via the module customization hooks. Likewise for import.meta.resolveURL, a version of import.meta.resolve that returns an URL instance instead of a string.
I assume this can be done already today by prepending some code into the source returned by the load hook, kind of like adding a polyfill but it’s one that runs for every module. Though I suppose if we create a new hook, that would also run for every module, so the performance impact is the same?
There’s also the question of adding functions/methods to import.meta. Say we create a new importMeta hook, with a signature like importMeta(url, context, next). If this runs on the separate thread with all the other hooks, what happens when the return value of the user’s hook has a function on it, like resolveURL? We can’t transfer that across the thread boundary, can we? Is there some other way to make this work, like making the return value of importMeta be a string to evaluate on the main thread; but if we do that, it’s pretty much the same as prepending to load, I’d think. Are there other approaches?
Maybe in the end the “prepend to load“ approach is the best one, and we should perhaps add an example to the docs. But I thought that this should get some discussion.
To give a bit more of context, it's already possible to customize import.meta, using globalPreload, but that's going away. Node.js 20.0.0 up to Node.js 20.5.1 are lacking that feature (it was removed "by accident" in the off-thread PR and was re-introduced by https://github.com/nodejs/node/pull/48779), and no one has complained so I think it's fair to say it's not very high priority 🤷♂️
But I agree it's worth discussing, and if someone wanted to implement that, it would probably be well received.
Hey, i'm working on a small library to have some sort of "HMR" with Node ( using the query params hack in the import path ) and I met this need today, so I wanted to share my use case
I need to add two methods in import.meta : import.meta.hot.dipose and import.meta.hot.decline. Because using import.meta.hot.xxx has become a sort a convention since Vite and co.
So to do this, I ended up injecting code via the load hook. But this poses a problem: it totally breaks the source maps. Now, I don't know much about how source maps work, so maybe it's a simple problem to fix ( I will read more about it ), but I thought it was something that could be avoided if Node offered an API to initialize import.meta.
I think, if an API is proposed, it should also be possible to access other properties in import.meta.
In my case, import.meta.hot.decline needs import.meta.url. Here's some silly pseudo code to make my point clearer:
// loader.ts
// Let's say we can do that from a `load` hook
export const load: LoadHook = (url, context, nextLoad) => {
// maybe using the `context` property? I am not super aware of Nodejs internals
// so this is probably a dumb idea
context.initializeImportMeta(importMeta => {
return {
hot: {
dispose: () => {
// I can access the `import.meta` content through `importMeta`
myFunction(importMeta.url)
},
decline: () => {
myFunction(importMeta.url)
}
}
}
})
}
So having an API for that would allow us to avoid doing code transformations and breaking source maps. Using load for the same result seems a bit hackish anyway