Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support different entry points in package.json #93

Closed
TheSharpieOne opened this issue May 1, 2018 · 8 comments
Closed

Support different entry points in package.json #93

TheSharpieOne opened this issue May 1, 2018 · 8 comments

Comments

@TheSharpieOne
Copy link

Reference #63 (comment)
Opening as a new issue based on #63 (comment)

Is it possible to have the unpkg field support an object of values as well so that you could do the following.

"unpkg": {
  "default": "dist/umd.js",
  "module": "dist/esm.js",
  "development": "dist/umd.js",
  "production": "dist/umd.min.js"
},

I have a similar need for some of the libraries I support. We generate and output several UMD bundles. Some of these bundles include third-party dependencies to that including it is all you need. Other bundles don't include the third-party dependencies, requiring the user to import them beforehand (this is done so the third-party dependencies are not duplicated in various bundles.

Something like the above example would be useful to allow the developer to specify which bundle they want.

Taking it one step further, it would be interesting to be able to specify external dependencies which must be included/imported beforehand (which something like dynamic-cdn-webpack-plugin could pickup on and perform that work to ensure everything that is needed is loaded).

@mjackson
Copy link
Owner

mjackson commented May 1, 2018

Yes, I've considered adding something like this before. Thanks for bringing it up :)

The term "UMD" is not applicable here though. UMD refers to a module format which is universal. So these things that you're talking about aren't "UMD flavors". They're just different module formats.

I've always thought about this potential feature as "named bundles" or "entry points". So e.g. you could have something like an unpkg.bundles config in your package.json that would allow you to omit the file paths so you don't have to use them directly.

For the react package, this might look like:

{
  "unpkg": {
    "bundles": {
      "default": "umd/react.development.js",
      "development": "umd/react.development.js",
      "production": "umd/react.production.min.js"
    }
}

Then people could use an alias like unpkg.com/react?bundle=production to load the production UMD build. This would allow package authors to potentially move around the location of their bundles inside their package without having to change the URL.

Side note about implementation: We need to use the ?bundle query parameter (or something else that we know) so that we don't have a lot of different potential query parameters that could possibly bust the cache. In other words, we always need to know exactly which query parameters are valid and which ones we don't support, so we can't use ?production and ?development and anything else that someone wants to put in their package.json. But authors would always be in control of the value of that query parameter. Also, the ?module query parameter is already being used for something, so we shouldn't overload it to mean something else here.

@mjackson mjackson changed the title Support different UMD flavors in unpkg package.json Support different entry points in package.json May 1, 2018
@mbostock
Copy link

mbostock commented May 10, 2018

This may be useful for D3 and require in Observable.

Currently, you can’t use the d3 default bundle along with “non-core” D3 modules that are not included in the default bundle, such as d3-geo-polygon or d3-sankey. The non-core modules depend on core D3 modules, and our require isn’t smart enough to know that the d3 default bundle provides the core modules, so the core modules are loaded multiple times.

We worked around this issue for Node by providing a CommonJS bundle for the main entry (d3.node.js). I could do the same for an AMD entry, but I’m limited to a single unpkg entry field, which is used for our current minified UMD.

That said, Observable’s require may have to load the package.json anyway to do dependency version resolution, so possibly we don’t need this feature—we could check the package.json for an amd entry before fetching the module from unpkg. But, it would be nice to avoid loading the package.json in the common case where a module doesn’t have any dependencies.

Gosh it will be nice when everything uses ES modules and ES imports…

Edit: We’ve updated d3-require to look at the package.json. 🤠

@mjackson
Copy link
Owner

mjackson commented Aug 27, 2018

Actually, instead of using the ?bundle query param, we could just add a "redirects" feature that would let you redirect any request from your package to any other file in your package. So it works more like Netlify or surge.

{
  "unpkg": {
    "redirects": [
      [ "/production", "/dist/d3.min.js" ],
      [ "/development", "/dist/d3.js" ]
    ]
  }
}

Then people could use a URL like unpkg.com/d3/production to get the production bundle. We could even support a feature where we serve the file directly w/out actually redirecting, similar to how Netlify works when you provide a 200 status code in one of your redirects.

@nickserv
Copy link

The redirects idea is interesting. Could we potentially use some convention to imply production/development builds when this feature is not used, like replacing development with production (or vice versa) in the module field? Or do you think envs should be explicit, in which case each package might have different names for them?

As I mentioned in #126, replacing the entry file with a 404 or some sort of generic error/warning page to select a specific bundle would help users understand when a package doesn't have a single recommended production entry point. Would this interfere with bundlers like url-loader too much? Alternatively, we could add explicit fields for development and production build, but there's not really a convenient way to switch environments on the web without a build tool. Perhaps Unpkg could inject scripts into packages, allowing them to dynamically toggle environments from a global variable.

@mjackson
Copy link
Owner

replacing the entry file with a 404 or some sort of generic error/warning page to select a specific bundle would help users understand when a package doesn't have a single recommended production entry point

I agree that we can definitely do a much better job with our 404 pages, but there is no standard location for where to keep bundles in packages nowadays, so the best thing we can probably do is just show a page saying "we can't find that file, here's a directory listing". The closest thing I know of is a dist directory, but I personally use named directories for the type of bundle (e.g. cjs, umd, etc.) while others put the bundle type directly in the filename (e.g. d3.node.js). Since it's not standard, I'd rather not enforce a convention around this if we can avoid it.

Instead, providing the ability to redirect any path gives users full control over the unpkg URL while still preserving the ability to point to any arbitrary filename inside the package.

@nickserv
Copy link

In that case, what would React's package do? It seems like the maintainers don't want a default entry file. If I understand correctly unpkg would default to main (CJS, which is not browser compatible) if UMD redirects are not defined. This seems like it would be counterintuitive to users, I'd rather fail with errors as early as possible. If we redirect to a "please choose an entry file" page, users may not notice it in the network devtools and wonder why their scripts are breaking. I think we should allow specific packages to replace the default URL with an error page in the 400s or 500s.

@mjackson
Copy link
Owner

I think we should allow specific packages to replace the default URL

This is exactly what the unpkg field in package.json is currently used for. It lets package authors control how the default/bare URL behaves on unpkg by redirecting users to another file.

One thing we could possibly do is try to detect if a request is being made by a browser, and then serve an error page if there is no browser-friendly version available, which sounds like what you're after. But the hard part there is that we would need to Vary requests based on the Accept header, which would lessen the effectiveness of the cache. Much better to just have a different URL for different content.

@TheSharpieOne
Copy link
Author

Stale

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants