microbundle icon indicating copy to clipboard operation
microbundle copied to clipboard

Officially support more elaborate externals

Open Xiphe opened this issue 5 years ago • 11 comments

This is a feature request/Proposal

As a user of microbundle I want ways to configure which imports are to be considered external. In order to reduce my bundle size and also to work with non-standard imports (images, fonts, ...) that are not supported by microbundle.

Status Quo

  1. As described in https://github.com/developit/microbundle/issues/283#issuecomment-523879163, there is a (I guess unoffical) way to use regex in the --exclude flag, which can be used to have rollup treat specific import statements as external.
  2. Presence of the --exclude flag triggers if pkg.dependencies are treated as external or not (see index.js#L387) I find that quite confusing and the behaviour is not documented.

Problem

Given I want to use --external .*/assets/.* to work with non-standard imports And I also want all my dependencies to be excluded Then I need to add all dependencies to --external causing code duplication and manual overhead.

Proposal

In order to fix the problem and reduce confusion I propose to have it work like this:

$ microbundle

Exclude dependencies, peerDependencies

$ microbundle --external .*/assets/.*

Exclude dependencies, peerDependencies and .*/assets/.* And explicitly support regular expressions or globs under --external

$ microbundle --external .*/assets/.*,angular --include-dependencies

Exclude peerDependencies and .*/assets/.* All normal dependencies ecxept angular are included in the bundle

Non-breaking alternative

I realize that the above proposal is really tied to my personal usecase of (miss-?)using --external for non-standard imports. It would also introduce a potential pretty impactful breaking change (since users of microbundle might ship bundles that lack bundled dependencies).

Alternatively the current behaviour could stay as is, using regex in --external will be considered hacky. And we introduce a new, documented way to exclude assets:

$ microbundle --external-glob **/*.(jpg|png)

Exclude dependencies, peerDependencies and all imports matching **/*.(jpg|png)

$ microbundle --external angular --external-glob **/*.(jpg|png)

Exclude peerDependencies, angular, and all imports matching **/*.(jpg|png)


Let me know what you think about this. I would be really happy to implement the changes and provide a PR.

Xiphe avatar Sep 12 '19 09:09 Xiphe

It seems like glob pattern support would be fine to add without the addition of a second --external-glob flag, since * is not valid within npm package names.

There's still the issue of global without *, so perhaps we could use wrapping slashes to debit patterns (versus specifier names) explicitly:

microbundle --external "/foo.{js,ts}/"
microbundle --external foo.js,foo.ts

developit avatar Sep 13 '19 03:09 developit

Yeah! i like the approach!

I find it confusing to wrap a glob with / since it then looks more like regex to me, I would therefore not use globs and propose the following:

micorbundle --external vue,react: exclude peerDependencies, vue and react microbundle --external "/\.jpg$/i": exclude peerDependencies, dependencies and all imports matching the regex. microbundle --external "/\.jpg$/i,angular": Exclude peerDependencies, angular and all imports machting the regex microbundle --external "/.*\/strange,commafile.js\/.*/i,angular": Throw Error "/.*/strange" is not a valid npm package. If you want to use regex make sure to wrap it with "/". Also commas in regex is not supported.

The docs would then read:

--external: 'none' or a comma-seperated list of module names or regex.

I would also like to add a small section documenting when peerDependencies and dependencies are added to the exclusion list.

implementation sketch

  • still split the externals by ,
  • check if each external is valid regex (match against ^\/.*\/i?$) and create regex without adding stuff
  • otherwise check if external is valid npm package and create regex as currently implemented
  • throw if both are invalid
  • add peerDependencies
  • if externals did not contain a npm package add dependencies

Could also be implemented without validating the npm package in order to not add additional dependencies. In that case we would not throw errors and just blindly create the module regex no matter what. I assume that this might lead to intransparent behaviour for users of microbundle.

Xiphe avatar Sep 13 '19 08:09 Xiphe

I'll create a PR with the proposed changes (regex within external list).

Xiphe avatar Sep 16 '19 08:09 Xiphe

I would like that this feature would be available, so I could import non-javascript files, for example png, jpg, svg images.

krobing avatar Jun 17 '20 02:06 krobing

Is there an update here? I'm trying to import .woff and .woff2 files but am not able to. Unless I'm missing something?

bobbyflowstate avatar Sep 02 '20 18:09 bobbyflowstate

I'll give it some 👀 in the coming days :)

wardpeet avatar Sep 02 '20 20:09 wardpeet

Thanks @wardpeet !

bobbyflowstate avatar Sep 02 '20 20:09 bobbyflowstate

I don't know when, but we landed support for regex externals in 0.13.

developit avatar Dec 18 '20 20:12 developit

Would it also be possible to add an all or dependencies option to compliment none which makes all non-relative import/requires external?

I have component libraries where core-js and react are dev dependencies, but I don't want them to be bundled, and I don't really want to add them as peer dependencies (which I find a bit problematic). Also, I don't really want to accidentally bundle libraries. I'd really prefer that bundling was always explicit.

The work around I have now is using --external "^[@a-zA-Z0-9-].*$", so anything that has a valid module ID first character should be considered external, and everything else (eg. core-js, react) is internal/bundled.

Shakeskeyboarde avatar Feb 12 '21 18:02 Shakeskeyboarde

Hi @Shakeskeyboarde

I make all external dependencies with this regex option: --external [A-Za-z0-9_@$]+[A-Za-z0-9_/-]+[\\.]?[A-Za-z0-9_]+, however react should be taken into peerDependencies field.

if you wish to install peer dependencies you can use i-peers module and if you want to prove your component library on local environment mimicking a registered package you can use yalc package globally.

krobing avatar Feb 15 '21 16:02 krobing

Is there an update here? I'm trying to import .woff and .woff2 files but am not able to. Unless I'm missing something?

.ttf and other fonts would be cool

maurerbot avatar Nov 16 '22 12:11 maurerbot