Showing posts with label webcomponents. Show all posts
Showing posts with label webcomponents. Show all posts

Tuesday, September 12, 2017

Differential Serving on Firebase Hosting (and moving to Medium)

Polymer 2.x/3.x brought the standards-compliant ES6 class-based syntax for defining Web Components. This works well for most modern browsers and ES6 has a lot of other nice features (like arrow functions) to make your JS code cleaner and more fun to write.
But if you need to support older browsers like IE 11 you will have to compile your code to ES5 which comes with performance drawbacks for modern browsers compared to running ES6 on them directly.
The ideal approach is to use differential serving to serve the ES6 version to modern browsers and a fallback ES5 version to older browser. prpl-server-node is a sample implementation of a Node server that uses this pattern. I took the ideas from this implementation and created a sample based on the polymer-starter-kit on how you can use differential serving on Firebase Hosting using Cloud Functions for Firebase for dynamically sending the right version to the user.
Since blogger has started to look quite old I'm currently testing Medium, so you will find the rest of this article there: https://medium.com/@scarygami/differential-serving-on-firebase-hosting-f83c33b83a8e

Tuesday, August 29, 2017

Polymer Summit 2017

The Polymer Summit 2017 in Copenhagen was over far too quick. It was a great and fun event with a lot of inspiring talks and interesting conversations in the breaks and during the after party.

In this post I will try to summarize my highlights and takeaways from this summit. There are also a couple of links that go into deeper details for the various topics, and I will be exploring some of those topics more closely in the future, which will most likely result in more articles.


Tuesday, June 13, 2017

Polymer in Production / Part 2 - Building, bundling, lazy-loading

Continuing from my previous blog post about including web components and Polymer in a huge legacy web application, I want to focus on optimizing the performance of your web app using the Polymer CLI and at least the L part of the PRPL pattern in this post. There are several things you can do to improve the initial load time, even if your app doesn't follow the recommended app shell architecture.


Monday, March 13, 2017

Polymer in Production

When I was tasked with including new functionality into an existing, rather big internal web application, I found myself in a bit of a dilemma.

For my own personal projects and several other internal projects I did at work, I have grown to love web-components using Polymer because of the ease of development and the natural way to structure applications into (re-usable) parts.

The existing web application in question had been mainly developed with a once (and still) very popular JavaScript library.

A full rewrite of the application was out of question due to time and budget restraints, but using Polymer would have a lot of benefits for the future as far as testability, maintainability and extensibility are concerned.

In this blog post I will go over some of the things I did and had to consider to make this work.

Wednesday, August 10, 2016

PolymerCubed

I've recently started using Microsoft SQL Server Analysis Services for reporting purposes at work, and while querying the cubes worked great, the visualization options were rather unsatisfactory, especially when it came to building web-based dashboards.

And while there are several vendors offering solutions in this area, I decided to give it a try myself and started creating a suite of Polymer elements.

Monday, April 18, 2016

Polymer and the [hidden] attribute

The hidden attribute is a "fairly new" convenience attribute (fairly new = not implemented in IE<=10) to hide page elements that are not relevant in the current context/state of the website.

It is especially useful in a Polymer web app, since you can use attribute binding to show/hide elements based on (computed) properties, without having to make your own display: none; styles.

There are several cases where you will have to be careful with this attribute though.

Tuesday, August 4, 2015

Custom elements for Chrome Apps APIs

Continuing with my Polymer Chrome App I needed access to the Chrome Storage API. A quick search revealed only elements that haven't been updated to Polymer 1.0 so I started to create my own element based on iron-localstorage.

The "problem" with elements that depend on Chrome Apps APIs is that you can't test/use them outside of Chrome Apps, so I went ahead and created some gulp tasks to make things easier for me.

The main idea of these tasks is to put the contents of demo or test, which you would normally run directly, and all dependencies into one Chrome app that would then use demo/index.html or test/index.html as main page.

First I take all the files relevant for the element itself + the test/demo files, run the html files through crisper and put the result into the output components/my-element/ folder (following the layout of gh-pages for Polymer elements).
All bower dependencies are run through crisper as well and put into the components folder.
For the Chrome App itself only two files are important.

manifest.json defines the necessary permissions (e.g. to use chrome-storage the "storage" permission is required).
main.js launches the test or demo page.
The gulp task copies those two files to the main output folder, and changes the window.create call to point to the right file, e.g at components/my-element/test/index.html
The Chrome demo and test apps created that way can then be loaded as unpacked extensions.



This works nicely for the demo app, but unfortunately the test app reveals this in the console when starting it:

Uncaught Error: document.write() is not available in packaged apps.

Investigating the problem reveals this line in the web-component-tester to cause the issue, which makes sure that all dependencies are loaded before WCT is actually started.

To work around this issue you have to include the necessary scripts in the test files explicitly...
...and tell it not to load any scripts itself...
...before loading web-component-tester/browser.js on all the test pages.

So that I don't have to copy the same couple of lines into each of the test files separately, I extended the gulp-copy task to automatically insert the necessary lines in all files that include a reference to web-component-tester/browser.js
And with this change tests can be run in the Chrome App.


Following the idea of my previous article I also wanted to enable live-reload for this workflow

As opposed to my article where the livereload.js is removed for the production build, I did it the other way round here by adding it to the test/index.html or demo/index.html when running the gulp-live-task.
Watching for changes, rebuilding the app if necessary and triggering the reload works basically the same though.
And with this I can leave the test and/or demo apps running and see right away if all tests still pass after making changes and if the demos work as expected.

And now back to actually working on my app. All those distractions you run into while traversing (mostly) uncharted waters ☺

Monday, May 18, 2015

Preparing for Polymer 1.0 - hangout-app

It must have been shortly after the Chrome Dev Summit in 2013 that I first started looking into Polymer. A lot has changed since then and most of the code I had written for the early versions of Polymer looks completely different now and went through a lot of re-write stages, but that's what you get for living on the bleeding edge ☺

Now Polymer has reached beta state with the 0.9 release and 1.0 is expected to come out at I/O so the time of breaking changes is slowly coming to an end. Some of my projects will probably forever remain like they are now, but I thought it was about time to start updating some of my more important (imho) elements, starting with my <hangout-app> element, that makes developing Hangout Apps easier.

While migration is generally easy thanks to migration guide there are still some things I've stumbled over (mostly because I flipped through the migration guide too quickly...)

No inheritance from custom elements (for now)

When I first created this element I had the idea (which seemed brilliant and completely logical at the time) to let people inherit from the hangout-app element to create their own hangout apps, so they could depend on the loaded property of the parent element to know when the Hangouts API is ready to be used:
With inheritance from custom elements not being supported (for now) I had to rethink this idea and I think the new solution is actually much clearer. You can now include the hangout-app element anywhere in your project and either wait for its ready event to fire or bind to its loaded property. Alternatively you can also include any of your markup as content of the hangout-app element and this content won't be rendered until the Hangouts API is ready to be used.

Conditional templates

The old <template if="{{condition}}">...</template> implementation removed/added DOM elements completely when the condition changed, which could have a negative effect on performance if used excessively, and I have to admit that I used it way too much in my projects, simply because it was easy to use and made the code somewhat clearer.

As I wrote a while ago the much better solution in most cases is to simply hide/show by conditional attribute binding to the hidden attribute: <div hidden$="[[!condition]]">...</div>

In the case of the hangout-app element I wanted to make sure that none of the content that might depend on the Hangouts API is part of the DOM until the API is ready, e.g. when using the hangout-shared-state element which tries to called the Hangouts API as soon as it is attached. For that reason I used the new implementation of conditional templates in the form of dom-if.
<template is="dom-if" if="[[loaded]]">
  <content></content>
</template>
This new implementation by default adds the content the first time the condition becomes true and afterwards only shows/hides the elements as necessary.

Layout attributes > Layout classes

I completely missed this part of the migration guide and was very surprised when my layout didn't look the way I expected it to.

The change from attributes to classes is easy enough though, just make sure to include PolymerElements/iron-flex-layout in your dependencies.


That's it for now, more coming as I upgrade more of my elements ☺