Support to load ES module plugin
Check List
- [X] I have already read Docs page.
- [X] I have already searched existing issues.
Feature Request
Support to load ES module plugin
Others
No response
We may need to wait for https://github.com/nodejs/node/issues/37648
Hexo was born before .config.js was a thing, thus Hexo uses a very traditional plugin loading mechanic, which is to evaluate plugins' entry points in the vm module where Hexo's context is available.
I don't know if dynamic import will work in the vm module. Node.js' dynamic import supports both CJS and ESM (CJS supports is powered by cjs-module-lexer).
Hexo was born before
.config.jswas a thing
IMO, we should not always be trapped by history.
I don't know if dynamic import will work in the
vmmodule.
Available with vm module, but it requires additional option importModuleDynamically (which is experimental)
https://nodejs.org/api/vm.html#support-of-dynamic-import-in-compilation-apis
IMO, we should not always be trapped by history.
But we should avoid breaking change that results in a migration that would take more than more than 10 minutes. The config.yml approach will still exist in the foreseeable future.
Available with
vmmodule, but it requires additional optionimportModuleDynamically(which is experimental)
And I notice that Node.js doesn't recommend that option in production for now. So we ran out of the option.
The
config.ymlapproach will still exist in the foreseeable future.
I do not mean to replace config.yml with config.js. Sorry if I caused any misunderstanding.
And I notice that Node.js doesn't recommend that option in production for now.
Yes, that's a problem. How about introducing new plugin APIs that do not rely on the top-level hexo instance?
For example, we can require all ESM plugins to expose a function that receives the context and initializes the plugin.
export default async function (hexo_instance_as_arg0) {
hexo_instance_as_arg0.do_something();
}
Then they can be loaded simply by dynamic import, eliminating the need for the vm module.
const plugin = await import('/path/to/plugin');
await plugin(hexo);
The
config.ymlapproach will still exist in the foreseeable future.I do not mean to replace
config.ymlwithconfig.js. Sorry if I caused any misunderstanding.And I notice that Node.js doesn't recommend that option in production for now.
Yes, that's a problem. How about introducing new plugin APIs that do not rely on the top-level
hexoinstance?For example, we can require all ESM plugins to expose a function that receives the context and initializes the plugin.
export default async function (hexo_instance_as_arg0) { hexo_instance_as_arg0.do_something(); }Then they can be loaded simply by dynamic import, eliminating the need for the
vmmodule.const plugin = await import('/path/to/plugin'); await plugin(hexo);
I think it's worth considering trying other loaders (similar to jiti, ts-node) that can achieve the same functionality as currently, and allow plugins to choose which module to use. The hexo variables can be propagated through globalThis. This approach also has the advantage of directly loading TypeScript code.
I believe using globalThis to pass hexo is more reasonable than the current method, as it can avoid some strange issues. For example, when the entry file calls code from other files, the code in those other files cannot use this seemingly global hexo variable.