esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

Can the importItems object be passed into OnResolveArgs? The plugin I'm working on really needs the member names from this object.

Open lidenggao opened this issue 8 months ago • 4 comments

Can the importItems object be passed into OnResolveArgs? The plugin I'm working on really needs the member names from this object.

For example, for the statement: import AX, { x1 as X, x2 } from "m" build.onResolve({ filter: /.*/ }, (args) => { console.log(args.importItems ); // output-> ["default","x1","x2"] return { path: args.path }; });

lidenggao avatar Apr 20 '25 08:04 lidenggao

As a workaround (or work as expected?), you can read args.importer and parse / match import statements by yourself to find imported names.

I didn't see this design before in other bundlers like Rollup. The main reason I can think of is bundlers don't need to wait for all import statements to be scanned to start a resolve hook from plugins. For example if a.ts imports { a } from module foo while b.ts imports { b } from the same module, what would you expect when the bundler calls your plugin?

// a.ts
import './b'
import { a } from 'foo'

// b.ts
import { b } from 'foo'

hyrious avatar Apr 20 '25 09:04 hyrious

args.importer is not sufficient because I need to use the member name(ImportItem) along with args.importer to generate a new namespace, and then generate the corresponding code based on that namespace.

For example, for the import statement import { createApp } from "vue"; I want to transform it into import { createApp } from "vendor:vue:createApp"; and then handle "vendor:vue:createApp" in the onLoad hook, where its content would be something like export { X1 as createApp } from "http://..."

lidenggao avatar Apr 20 '25 09:04 lidenggao

@lidenggao Maybe you could provide more details on what's your input code and what's your expected output code. I don't see any necessary for the last example where I could just use --alias:vue=https://....

hyrious avatar Apr 21 '25 01:04 hyrious

@lidenggao Maybe you could provide more details on what's your input code and what's your expected output code. I don't see any necessary for the last example where I could just use --alias:vue=https://....

First of all, thank you very much for your attention. I am planning to implement a splitting strategy. For example, both Project A and Project B use Vue, loadsh, and dayjs. Therefore, I want to combine these common dependencies into a single package called "vendor." However, to avoid conflicts in export names, especially for "default," I am using the following syntax for exporting:

export * as `${hash("vue")}` from "vue";
export * as `${hash("loadsh")}` from "loadsh";
export * as `${hash("dayjs")}` from "dayjs";

Then in Project A and Project B, when encountering...

import { createApp, render } from "vue";
import _ from "loadsh";

It is expected to be replaced with something like this:

import { createApp, render } from "http://.../vendor.js";
import _ from "http://.../vendor.js";

Note: The replacement result mentioned above must be incorrect, because in the vendor, the export name is a hash value. I am unable to modify import { createApp, render } or import _ in the plugin. So, I changed my approach and replaced:

import { createApp, render } from "vue";
import _ from "loadsh";

with:

import { createApp, render } from "vendor:vue:createApp,render";
import _ from "vendor:loadsh:default";

Next, by leveraging the onLoad mechanism, I generate the content for "vendor:vue:createApp,render" and "vendor:loadsh:default". Below is an example for "vendor:loadsh:default"

import `${hash('loadsh')}` as sub  from "http://.../vendor.js";
export default  sub.default;

vue example

import `${hash('vue')}` as sub from "http://.../vendor.js";
export const  createApp = sub.createApp;
export const  render  = sub.render;

The biggest challenge currently is that the member name is missing for "vendor:vue:createApp,render," which becomes "vendor:vue." Therefore, I need to extract the export names of each common package in advance. Then, when generating "vendor:vue," I have to export all the members. This significantly impacts build performance. Thank you once again, and I hope to receive your help.

lidenggao avatar Apr 21 '25 02:04 lidenggao