hexo icon indicating copy to clipboard operation
hexo copied to clipboard

Support to load ES module plugin

Open ArcticLampyrid opened this issue 1 year ago • 6 comments

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

ArcticLampyrid avatar Jul 27 '24 08:07 ArcticLampyrid

We may need to wait for https://github.com/nodejs/node/issues/37648

ArcticLampyrid avatar Jul 27 '24 08:07 ArcticLampyrid

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).

SukkaW avatar Jul 27 '24 17:07 SukkaW

Hexo was born before .config.js was a thing

IMO, we should not always be trapped by history.

I don't know if dynamic import will work in the vm module.

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

ArcticLampyrid avatar Jul 28 '24 14:07 ArcticLampyrid

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 vm module, but it requires additional option importModuleDynamically (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.

SukkaW avatar Jul 28 '24 15:07 SukkaW

The config.yml approach 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);

ArcticLampyrid avatar Jul 28 '24 17:07 ArcticLampyrid

The config.yml approach 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);

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.

EmptyDreams avatar Aug 03 '24 10:08 EmptyDreams