evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
38.16k stars 1.15k forks source link

filter multiple extensions on plugin #1951

Closed michelson closed 2 years ago

michelson commented 2 years ago

Hello there, first of all, thanks for this awesome library.

I'm trying to implement a plugin and I need to skip some files but I'm not sure how to do this properly with the filter options.

basically, I need to filter out files with .json, .png & .css extensions. My naive approach was to handle this directly on the plugin build.onload:


build.onLoad({ filter, namespace }, async args => {
  if(args.path.includes(".json") || args.path.includes(".png") || args.path.includes(".css")  ){
    //console.log("SKIP" + args.path)
   } else {
    // do the processing here
   }
});

works, but not efficient at all, I have not been able to pass those 3 extensions as a filter option in order to be skipped properly. I've found this approach filter: /.*([^j][^s][^o][^n])$/, and it filters JSON files ok, but I've no idea on how to implement this on multiple extensions. ¿how can this be done?

Also, I've noted that all the node modules are included in the plugin build, and are taking a lot of time to process as well. I'm wondering how to exclude those node_modules files from the processing too. I guess I should add those to the filter too?

best regards

evanw commented 2 years ago

I need to filter out files with .json, .png & .css extensions

Unfortunately Go's regular expression library doesn't support negative lookbehind or lookahead. I would recommend just doing it in JS or Go if you want it done quickly. If you really want to do a regular expression, then I believe it can be done by breaking it down into cases like this:

\.(
  [^cpj] .* |        # Not 'c' or 'p' or 'j'
  c ([^s] .*)? |     # Or 'c' without an 's'
  cs ([^s] .*)? |    # Or 'cs' without an 's'
  css .+ |           # Or 'css' with something after
  p ([^n] .*)? |     # Or 'p' without an 'n'
  pn ([^g] .*)? |    # Or 'pn' without a 'g'
  png .+ |           # Or 'png' with something after
  j ([^s] .*)? |     # Or 'j' without an 's'
  js ([^o] .*)? |    # Or 'js' without an 'o'
  jso ([^n] .*)? |   # Or 'jso' without an 'n'
  json .+            # Or 'json' with something after
)$

That means the whole regular expression would be this:

/\.([^cpj].*|c([^s].*)?|cs([^s].*)?|css.+|p([^n].*)?|pn([^g].*)?|png.+|j([^s].*)?|js([^o].*)?|jso([^n].*)?|json.+)$/

There's probably a library to do this for you somewhere.

I'm wondering how to exclude those node_modules files from the processing too.

Package paths (those that resolve to packages in node_modules) are paths that don't start with / or ./ or ../. You can use a regular expression to avoid those path prefixes.

hyrious commented 2 years ago

Normally you don't have to do negative filtering, just match what you want:

{ filter: /\bsrc\/.+\.tsx?$/ }

About node_modules, you can test them in js easily:

if (args.path.includes('node_modules')) return null;
michelson commented 2 years ago

thank you very much. @evanw @hyrious