I have seen this go back and forth in starter kits and I was wondering what is the best practice for importing element bower elements?
Should each element import the same bower packages redudntly? Or should there be be just one html sheet that imports all the bower elements?
Also, why is <link rel="import" href="../bower_components/polymer/polymer.html"> always imported in each element regardless?
example- each element imports it's own elements, sometimes redudently(other elements may import these also):
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/paper-card/paper-card.html">
<link rel="import" href="../bower_components/paper-button/paper-button.html">
<link rel="import" href="../bower_components/iron-image/iron-image.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="my-view1">
Or one html sheet importing all elements:
<!-- Iron elements -->
<link rel="import" href="../bower_components/iron-flex-layout/iron-flex-layout.html">
<link rel="import" href="../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../bower_components/iron-icons/maps-icons.html">
<link rel="import" href="../bower_components/iron-pages/iron-pages.html">
<link rel="import" href="../bower_components/iron-selector/iron-selector.html">
<link rel="import" href="../bower_components/iron-form/iron-form.html">
<link rel="import" href="../bower_components/google-map/google-map.html">
<link rel="import" href="../bower_components/google-map/google-map-poly.html">
<link rel="import" href="../bower_components/google-map/google-map-marker.html">
<link rel="import" href="../bower_components/google-map/google-map-directions.html">
<!-- Paper elements -->
<link rel="import" href="../bower_components/paper-drawer-panel/paper-drawer-panel.html">
<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../bower_components/paper-item/paper-item.html">
<link rel="import" href="../bower_components/paper-material/paper-material.html">
<link rel="import" href="../bower_components/paper-menu/paper-menu.html">
<link rel="import" href="../bower_components/paper-scroll-header-panel/paper-scroll-header-panel.html">
<link rel="import" href="../bower_components/paper-dialog/paper-dialog.html">
<link rel="import" href="../bower_components/paper-styles/typography.html">
<link rel="import" href="../bower_components/paper-toast/paper-toast.html">
<link rel="import" href="../bower_components/paper-toolbar/paper-toolbar.html">
<link rel="import" href="../bower_components/paper-button/paper-button.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
<link rel="import" href="../bower_components/paper-input/paper-textarea.html">
<link rel="import" href="../bower_components/paper-radio-group/paper-radio-group.html">
I believe that with the establishment of the PPL pattern which got announced at Google I/) 2016, and the Polymer build mechanism, a basic structure emerged driven by Polymer CLI.
What I do depends on whether I am attempting to build a re-useable element or just one component which might be re-useable. In a re-useable alement I always import polymer and just those elements that I have used within the element. I reference everything via ../import-element/import-element.html
With my own application I have a rule that tries to lazy load everything via this.importHref except that which is going to be on display when that element initially loads. I have build a behavior for elements that include iron-pages so support that. In this case I import polymer, any elements that will initially be on display. I don't import the rest
html imports are de-duped by Polymer, so it doesn't matter if you attempt to load things more than once, they will only be loaded once.
In this case I reference the bower component elements with an absolute url /bower_components/import-element/import-element.html and for those in my app with relative urls. I currently store ALL custom element for my app in the same directory, so to reference them I am using just import-element.html. I think this last paragraph is not accepted practice, but I just find it easier not having to effectively map two physical directories to the same url.
TL;DR;
I don't that solid best practice has emerged yet.
Longer read
My personal opinion is that import links are generally not a good idea at all, because you will run into trouble when bundling. Unless you want to bundle your entire application, in which case imports' location doesn't matter.
You may want to bundle related elements. For example there can be <app-page-admin-panel>m <app-page-user-profile>, etc. Each of them could be lazy-loaded the first time they are required. Bundled HTML imports don't give you such flexibility AFAIK.
If you bundle everything, there will be nothing to lazy-load of course.
If you create a bundle for each element loaded on-demand is a step forward but what about common elements? If both admin panel and user profile elements import <paper-button> would you include it in each bundle? This is probably safe, albeit wasteful wrt bandwidth. Polymer itself, however, cannot be imported multiple times. Thus importing it in each element is probably not a good idea.
Possible future solution - ES6 module imports
Personally I very much hope for ES6 imports. With import "polymer" you are safe, because bundled or not, it will be guaranteed by the module loader (and browser in the future) that you will only ever import it once. You may want to see my answer to that other question: Modules in Polymer.
Related
Summary
I'm working on a Polymer project based off the Polymer starter kit, and I ran into a problem where icons from the default icon set aren't appearing. Their size and style is calculated correctly, but there's no SVG within the tag when I use inspect element. I've tried icons from maps and social which all work, but the ones from icons just don't have an image.
I've tried various different solutions:
Following this Stack Overflow question here, I did the accepted solution with no results.
I deleted all of my Polymer components and did a fresh bower install + bower update. Still no go.
I saw somewhere that the Polymer Starter Kit has a conflict with the my-icons.html file, so I renamed it to custom-icons.html. This also didn't work.
This is very confusing and frustrating because the problem seemed to pop up out of nowhere. One day the default iron-icons were working, and the next they weren't.
My imports
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/app-layout/app-drawer/app-drawer.html">
<link rel="import" href="../bower_components/app-layout/app-drawer-layout/app-drawer-layout.html">
<link rel="import" href="../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../bower_components/app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../bower_components/app-layout/app-scroll-effects/app-scroll-effects.html">
<link rel="import" href="../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../bower_components/app-route/app-location.html">
<link rel="import" href="../bower_components/app-route/app-route.html">
<link rel="import" href="../bower_components/iron-pages/iron-pages.html">
<link rel="import" href="../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../bower_components/iron-icons/maps-icons.html">
<link rel="import" href="../bower_components/iron-icon/iron-icon.html">
<link rel="import" href="../bower_components/iron-localstorage/iron-localstorage.html">
<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../bower_components/paper-item/paper-icon-item.html">
<link rel="import" href="app-data.html">
<link rel="import" href="log-out.html">
<link rel="import" href="custom-icons.html">
Utilization
<a href="/#/home-quotes" tabindex="-1">
<paper-icon-item>
<iron-icon icon="icons:settings" item-icon></iron-icon> <!-- This doesn't work -->
Home
</paper-icon-item>
</a>
<a href="/#/secret-quotes" hidden$="[[!storedUser.loggedin]]" tabindex="-1">
<paper-icon-item>
<iron-icon icon="maps:add-location" item-icon></iron-icon> <!-- This works? -->
Secret Quotes
</paper-icon-item>
</a>
UPDATE The bug has been fixed in Polymer Starter Kit 2.1.1. Now when you run polymer init starter-kit, the generated codebase will include the fix.
I suspect the problem is a naming conflict with your iconset (Issue #934), which was recently fixed.
Before the fix, the name of the custom iconset in Polymer Starter Kit was icons, which is unfortunately also the name of the default iconset from <iron-icons>. Since your custom-icons.html import occurs after iron-icons.html, your iconset takes precedence.
The fix is to rename your custom icons to avoid the name conflict, allowing for both iconsets to coexist. That is, change the iconset's name attribute in your custom-icons.html to something like this:
<iron-iconset-svg name="my-custom-icons" size="24">
Say, I have element A and B. The imports in B are:
<!-- Imports in B -->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../another-element/another-element.html">
Now I want to use B in A. What is the "right" way to import B? Should A just import B like this?
<!-- Imports in A: Method 1 -->
<link rel="import" href="../element-b/element-b.html">
Or should A also import all the imports used by B like the following?
<!-- Imports in A: Method 2 -->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../another-element/another-element.html">
<link rel="import" href="../element-b/element-b.html">
If Google's own Polymer Elements can be of any guidance, the answer appears to be Method 2, i.e. importing all dependent htmls. But if that is the case, the "import" syntax in Polymer/WebComponents seems to break encapsulation for no obvious reason. For example, here is the "paper-dropdown-menu" element from Polymer:
https://github.com/PolymerElements/paper-dropdown-menu/blob/master/paper-dropdown-menu.html
It imports "paper-input.html", which has its own imports:
https://github.com/PolymerElements/paper-input/blob/master/paper-input.html
The following 2 imports are used in both elements:
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-form-element-behavior/iron-form-element-behavior.html">
If paper-dropdown-menu.html already imports paper-input.html, why does paper-dropdown-menu have to import polymer.html and iron-form-element again? The problem with this is that the imports can get out of control very quickly when composing an app with many elements. Yes, I know Vulcanize. But I don't see how that helps the development process when one is creating or using an element. In addition, encapsulation means A shouldn't need to know the internal parts of B in the example above. Or is Polymer/Webcomponent really saying that html imports in a component are part of the "public interface" of that component?
Just import the elements you directly depend on. You can ignore transitive dependencies because they are imported in the elements you import directly anyway.
In addition each element should import <link rel="import" href="../polymer/polymer.html">.
Method 1 is the "better" way. Each polymer element is supposed to bundle its own dependencies, so it can function by itself when used.
Method 2 isn't that good, you will be re-importing the imports of element B twice, thats a waste of bandwidth especially when you aren't using a function (like polymers inbuilt importHref) that checks if an element has already been imported before fetching it again.
I'm updating a little Polymer element to 1.x. It works fine in Chrome and Safari, but in the latest Firefox I get several "uncaught exception: Element name could not be inferred." errors.
Seems to be related to the html imports, because if I remove everything from the component.html except for the imports, then the errors still occur.
In the index.html I have this:
<script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="src/element.html">
In the element.html this:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-input/iron-input.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html">
[EDIT] - Somehow the errors disappeared. I suspect due to either a Firefox or Polymer update.
Clear your browser cache to solve the problem.
install polymer#^1.1.0 which resolved to 1.7.0
it works for me
On my web page, I attempt to import the paper-toast element from the same directory as the other two Polymer elements. All have been installed with Bower and all have the same privileges.
<html>
<head>
<title>New Movement Entertainment</title>
<link rel=stylesheet href=css/home.css type=text/css>
<link rel="import" href="bower_components/paper-shadow/paper-shadow.html">
<link rel="import" href="bower_components/paper-input/paper-input.html">
<link rel="import" href="bower_components/paper-toast/paper-toast.html">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="bower_components/webcomponentsjs/webcomponents.js"></script>
<script src=scripts/jquery.js></script>
However, upon page load I am greeted with a 404 Not Found for the paper-toast import. I have tried reinstalling the element and even putting its folder in the paper-input directory (which I know imports fine). Does anyone have any ideas?
I would like to know if there are any CDNs for polymer elements, since you have to always download the elements and It would be more convinient to import it via cdn. Can't find any on google? Also are there any reasons that it does not exists or just because it is so new?
There is now!
I created this GitHub repository specifically for this purpose:
download/polymer-cdn
All GitHub repositories are automatically in CDN through RawGit. So, using that, we can now import Polymer elements using markup like this (for iron-icons in this case):
<link rel="import"
href="https://cdn.rawgit.com/download/polymer-cdn/1.0.1/lib/iron-icons/iron-icons.html">
The project structure was set up in such a way that imports from elements that you import (transitive dependencies) resolve correctly.
The readme for the repository has a list of all elements it contains.
Missing something? Let me know and I'll be happy to include it.
Try it
You can try it out right now by hacking on this Codepen:
Polymer-CDN Example.
Or you can run this code snippet:
<base href="https://cdn.rawgit.com/download/polymer-cdn/1.5.0/lib/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="iron-icon/iron-icon.html">
<link rel="import" href="iron-icons/iron-icons.html">
<link rel="import" href="paper-button/paper-button.html">
<link rel="import" href="paper-checkbox/paper-checkbox.html">
<link rel="import" href="paper-tabs/paper-tabs.html">
<link rel="import" href="paper-toggle-button/paper-toggle-button.html">
<style is="custom-style">
:root {
--paper-tabs-selection-bar-color: var(--paper-light-blue-900);
--paper-tab-ink: var(--paper-light-blue-100);
--paper-tabs: {
color: white;
background-color: var(--paper-light-blue-500);
};
}
</style>
<div>
<paper-button raised><iron-icon icon="check"></iron-icon>OK</paper-button>
<paper-button raised><iron-icon icon="clear"></iron-icon>Cancel</paper-button>
</div>
<p><paper-checkbox>Checkbox</paper-checkbox></p>
<p><paper-toggle-button></paper-toggle-button></p>
<paper-tabs selected="0">
<paper-tab>TAB 1</paper-tab>
<paper-tab>TAB 2</paper-tab>
<paper-tab>TAB 3</paper-tab>
</paper-tabs>
You can also access polymer elements directly from polymer-project.org.
Example:
<link rel="import" href="https://www.polymer-project.org/0.5/components/core-ajax/core-ajax.html">
This is an old question, but there is a non-hacky solution now: http://polygit.org/
It uses rawgit behind the curtains but provides a much nicer api.
I do not know any CDN hosting polymer elements right now and I assume it would be better to vulcanize them for a production environment but due to the fact that most of the elements are hosted on github you could link your imports to rawgit.com
Example:
<link rel="import" href="https://rawgit.com/Polymer/core-ajax/master/core-ajax.html">
You might take a look at cloudflares polymer CDN:
http://cdnjs.com/libraries/polymer
rawgit option
You would have to manage some dependencies manually since core-ajax.html returns 404 on polymer.html. Also rawgit.com cache is set to only 5 min (cache-control:max-age=300). 5 min cache is fine for version control, but it should be more for CDN (https://rawgit.com/Polymer/core-ajax/0.4.1/core-xhr.html). Also files are not minified.
vulcanize option
Probably best option before http/2 release. You would have to spend some time with configuration and integration into your build process. Also you don't have any CDN benefits (no data cost, already cached resources from third party domains.)
conclusion
There will be some CDN with minified polymer versions and long expires header on http/2 release. But I don't know about any right now.