mjackson / unpkg

The CDN for everything on npm
https://unpkg.com
Other
3k stars 302 forks source link

ES modules: duplicate requests using bare module specifiers #121

Open web-padawan opened 6 years ago

web-padawan commented 6 years ago

I'm trying to use the following snippet to load the ES module package, which loads all of its dependencies using ES modules and bare module specifiers:

<!doctype html>
<html>
  <head>
    <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.3/webcomponents-bundle.js"></script>
    <script src="https://unpkg.com/@vaadin/vaadin-button@^2.1.0-beta1/vaadin-button.js?module" type="module"></script>
  </head>
  <body>
    <vaadin-button theme="primary">Primary</vaadin-button>
    <vaadin-button theme="secondary">Secondary</vaadin-button>
    <vaadin-button theme="tertiary">Tertiary</vaadin-button>
  </body>
</html>

The @vaadin/vaadin-button and all its dependencies have the Polymer dependency specified in their package.json files like this:

"@polymer/polymer": "^3.0.0",
  1. Request initialised by my component: Request URL: https://unpkg.com/@polymer/polymer@%5E3.0.0/lib/elements/dom-module.js?module

  2. Request initialised by the Polymer itself (importing the same file internally). Request URL: https://unpkg.com/@polymer/polymer@3.0.2/lib/elements/dom-module.js?module

This results in crash, as this particular file defines a Custom Element which can only be defined once:

127.0.0.1/:1 Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': this name has already been used with this registry
    at https://unpkg.com/@polymer/polymer@3.0.2/lib/elements/dom-module.js?module:137:16

Confirmed the issue in latest Chrome, Firefox and Safari, they all load files until this crash.

/cc @samuelli maybe you have faced this issue?

mjackson commented 6 years ago

Are you sure the module is being loaded from the exact same URL both times? If it is, this seems like an issue with the way the ES module loader is implemented in those browsers.

Jamtis commented 6 years ago

MWE: https://jsbin.com/vaxuyihada/edit?html,output

Looking into the console shows that the two dom-module.js files are indeed loaded from the exact same url. screenshot 2018-08-08 at 23 36 42 (On file is fetched from a 302 redirect) However Chrome starts the script in a VM?! Maybe that's the reason for the double execution.

web-padawan commented 4 years ago

Note, the error is still valid.

MarcSkovMadsen commented 4 years ago

I see the same error

image

Artur- commented 4 years ago

I think the problem is related to the 302 redirects for versions such as ^3.0.0, e.g. https://unpkg.com/@polymer/polymer@%5E3.0.0/lib/elements/dom-module.js?module redirects today to https://unpkg.com/@polymer/polymer@3.3.1/lib/elements/dom-module.js?module

I am not sure what the spec says, if the module identity is defined by the original URL or the target/redirected URL. It seems to be somehow inconsistent as it breaks (module executed twice) in the unpkg case but a trivial manual test with loading the two files on the same page does not break (module executed just once). The reported problem is also seen in both Chrome and Firefox.

Presumably it should be possible to reproduce this without unpkg by setting up similar redirects but I am not sure how that will help. Other testable scenarios would be if unpkg can be tested without any redirects so that the ^3.0.0 would return the file contents instead of a redirect.

The core problem here though is that you cannot provide your application package.json or global version information when using unpkg.

http://polygit.org had the same problem with HTML imports and solved it by allowing embedding version information in the URL: ”Example base URL with multiple configurations

http://polygit.org/polymer+:master/super*+sjmiles+*/paper-button+v1.0.2/components/

Remember that all URLs hitting the magic server must contain the complete configuration.”

Artur- commented 3 years ago

jspm.dev handles this in a working way. Instead of sending 302 for e.g. https://jspm.dev/npm:@polymer/polymer@3/polymer-element.js redirecting to the latest version (https://jspm.dev/npm:@polymer/polymer@3.4.1/polymer-element.js), it instead writes a page with imports referring to the 3.4.1 version. This prevents files from being loaded twice using different URLs