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 For Import Maps #517

Closed
dyoder opened this issue Sep 2, 2021 · 12 comments
Closed

Support For Import Maps #517

dyoder opened this issue Sep 2, 2021 · 12 comments
Assignees
Labels
feature Feature requests.

Comments

@dyoder
Copy link

dyoder commented Sep 2, 2021

Is your feature request related to a problem? Please describe.

I'm interested in using Shoelace, but on a project where we're using ESM instead of bundling or raw script loading. I'd like to be able to import specific components from Shoelace as needed directly in the browser.

Describe the solution you'd like

I'd like to be able to import specific components from Shoelace as needed directly in the browser.

Describe alternatives you've considered

NA. We're moving away from bundling and toward direct imports.

Additional context

Support for import maps (so that we can use subpath imports for specific components) would be great.

Other references:

@dyoder dyoder added the feature Feature requests. label Sep 2, 2021
@claviska
Copy link
Member

claviska commented Sep 2, 2021

Shoelace only ships ESM and what you’re asking for is already possible. The main examples shows an everything “bundle,” but you can cherry pick individual components as well.

@dyoder
Copy link
Author

dyoder commented Sep 2, 2021

I saw that, but the need for the data attribute is problematic. I want to load it from within the application code, not as a standalone script. Does that make sense?

Ex:

<!-- import shoelace from within app.js -->
<script type="module" src="/app.js"></script>

@dyoder
Copy link
Author

dyoder commented Sep 2, 2021

Also, there are no subpath exports in the package.json so no way to generate import maps automatically using a tool like JSPM. We could, of course, write one manually, but we'd have to update it for each new component. We could just import from the URL, but, ideally we'd like to use import maps and just import components using their logical paths.

@claviska
Copy link
Member

claviska commented Sep 2, 2021

The data attribute is an optional mechanism for convenience that sets the base path. There’s an imperative method as well.

https://shoelace.style/getting-started/installation?id=setting-the-base-path

Also, there are no subpath exports in the package.json

Can the tooling follow standard imports? If not, it seems contrary to ask for a standard feature as well as a nonstandard feature (what you’re asking for is more of a Node thing, I think).

I tend to lean on the platform, so I’m open to adding import maps when browsers support them better, but right now they’re limited to Chromium. Explaining two ways to import will likely confuse users, hence my hesitation.

@dyoder
Copy link
Author

dyoder commented Sep 2, 2021

First, thank you for your prompt and thoughtful responses.

Second, I understand the hesitation. Import maps are indeed relatively new. FWIW, they are supported on browsers besides Chrome, via polyfill, and our hope is that they'll be supported natively across all browsers relatively soon. As far as subpath imports, you are again correct in saying that's a Node feature. But then again, so is NPM. In fact, my understanding is that subpath imports were partly specified with import map generation in mind. In my view, in the context of import maps, this is analogous to supporting installation via NPM.

The problem with having to set the base path is that it implies you still need to bundle or host assets for the components to work, correct? The way we've been handling this is to use data URLs within the component HTML or CSS, and to convert those assets into (local) JavaScript modules so we don't have to rely on the client application to provide them. Would something like that be possible? I realize that's possibly a separate request, but I see them as related. The goal is to be able to import Shoelace components as standalone modules.

I'm not familiar enough with Shoelace to know whether this is feasible. I would be interested in learning why or why not, since it's certainly possible you've run into edge cases I've missed.

@claviska
Copy link
Member

claviska commented Sep 2, 2021

our hope is that they'll be supported natively across all browsers relatively soon.

Same here!

The problem with having to set the base path is that it implies you still need to bundle or host assets for the components to work, correct? The way we've been handling this is to use data URLs within the component HTML or CSS, and to convert those assets into (local) JavaScript modules so we don't have to rely on the client application to provide them.

The base path is only [currently] used for <sl-icon>, as the default icon library is shipped as a folder of SVGs. However, the base path utility was established so that components could, in the future, use additional assets such as icons, images, or whatever will come.

The default icon library contains > 1,000 SVGs. I'd prefer not to ship each icon as a separate module (even with esbuild's speed, it slows things down a lot and adds additional bytes that aren't necessary). They're technically optional, as the user can replace the default library with their own if they prefer.

Asset management is notoriously hard, so this opt-in approach is a balance that gives users a solution if they want one without forcing them into it. It also has the benefit of "just working" when loaded via CDN.

It's worth noting that there's also a system icon library that inlines a subset of the default icons. This is what components use internally, so there's no requirement to ship assets or set a base path unless you intend to use the default icon set. Even then, you can configure your own to resolve elsewhere.

@dyoder
Copy link
Author

dyoder commented Sep 2, 2021

As you say, iconography is a tricky problem, and Shoelace provides as good an answer as you could hope to find. :) The fact that I can customize the loading is really helpful.

So, really, in the end, I guess what I'm asking for is support for import maps. The ticket is misnamed since Shoelace already supports ESM. I can load the components from my application JavaScript and configure it to use my preferred iconography. The only limitation is that I have to provide the full URL in the import statement. I suspect it would be straightforward to support import map generation: you'd just need to add an export clause to the package.json file, using the subpath wildcards.

I'd submit a patch for this, but my timeline on this is not urgent and I still need to play around with Shoelace a bit more to make sure it's a good fit for my project. That said, there may be others who would like this feature.

@dyoder dyoder changed the title Support For ESM Support For Import Maps Sep 2, 2021
@claviska
Copy link
Member

claviska commented Sep 2, 2021

I'd be open to a PR that provides import maps should you get around to it.

Cheers!

@KonnorRogers
Copy link
Collaborator

@dyoder Just now seeing this issue. I have a Rails example of using Rails 7 with Importmaps + Shoelace if you wanna browse through it. Importmaps worked for me here, not sure what issue you're up against.

https://github.com/ParamagicDev/shoelace-rails-importmaps

@xenobytezero
Copy link

I've moved to watching this issue from #525 as I am starting to look at the issue of multiple registration of WebComponents in general, but currently it's with Shoelace specifically. #525 indicates that import maps are a potential solution to this problem, hence moving here, but after reading about them I feel like I am missing how the two are related.

As far as I can tell, Import Maps provide the Node node_modules style import with mapping of library names to URLs to load that library from. I can see a lot of usages for this, but in the case of Shoelace (and other Lit based libs) even if you set up an import map to load different versions of the library with different module IDs, they are still going to all auto-register with conflicting names.

This is not a feature request, more just a check that import maps are actually a potential solution to the issue I have and should be the thing I'm learning about, or if I should be planning other solutions (ScopedElementRegistry, custom importing code, rebuilding the lib with different naming, etc)

@claviska
Copy link
Member

they are still going to all auto-register with conflicting names.

Correct. The custom elements registry is scoped to the window, not the document. That means defining two custom elements with the same name on the same page will result in a conflict and the second registration will throw an error.

The issue you're probably looking for is the scoped custom element registry proposal.

@claviska
Copy link
Member

Regarding import maps:

This proposal allows control over what URLs get fetched by JavaScript import statements and import() expressions. This allows "bare import specifiers", such as import moment from "moment", to work.

The mechanism for doing this is via an import map which can be used to control the resolution of module specifiers generally. As an introductory example, consider the code

As I understand it, it's largely left to the consumer to implement and given @ParamagicDev's example it seems like Shoelace works fine with them.

For more examples on how you can create import maps for your project, refer to this page.

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

No branches or pull requests

4 participants