Polymer Runtime Application Configuration
When creating web applications, we often need to have some parts of the application configuration for the deployment environment – usually web service API endpoints have different URLs in different environments, such as using a production web service in production and a locally hosted web service during development.
Such a feature is implemented in many web frameworks and building tools for web applications, such as Gulp or Grunt. Unfortunately, when building applications using Google’s Polymer SDK, there are no such features available – reviewing the Polymer documentation one, there isn’t even any mention of how one handles such mundane tasks as configuring API URLs, except hard-coding them1.
Developers have tried to solve this problem in different ways, from adding “environments” feature for Polymer’s internal build tool; abusing “behavior modules”; or using “app globals” custom element with complex code to share application-level state. None of these features work well or elegantly (except maybe the environments feature, if it ever gets implemented).
Here is the solution I came up with – with many thanks to Daniel Tse that described part of the implementation in this article – just using the core Polymer elements iron-ajax
and iron-meta
and without any custom code. Its not the most elegant thing that can be done, but it is relatively simple and works well. Its main down-side is that the application configuration is not embedded in the application during build time but loaded from an external file when the application loads – this may even be a required feature in some scenarios but its not the generally accepted practice.
To set up run-time configuration of the application, we start by creating our environment-specific configuration JSON file. It can be as simple or as complex as you want, and for our example I’m going to keep it dead simple – I’ll create a file called appconfig.json
and store it at the root of the web application public directory, with just the address of our web service:
{
"api": "https://service.myapp.com/api"
}
The next step is to load this file into the application main view, using iron-ajax
and storing the resulting data into an application -wide state using iron-meta
– so in our app.html
(or whatever your main view file is called) add this into the template:
<iron-ajax auto url="/appconfig.json" handle-as="json" last-response="{{appconfig}}"></iron-ajax>
<iron-meta id="appconfig" key="config" value$="{{appconfig}}"></iron-meta>
The iron-ajax
component will load and parse the configuration file when the application first loads, and will write all the data into the iron-meta
key “config
“.
Lastly, wherever you need to read the configuration, i.e. in any view or application-specific component you wrote, you can use the iron-meta-query
component to get back the configuration. For example, to load the API URL endpoint into another iron-ajax
component, we will do:
<iron-meta-query id="appconfig" key="config" value="{{appconfig}}"></iron-meta-query>
<iron-ajax id="listMyStuff"
auto
url="[[appconfig.api]]/stuff/list"
handle-as="json"
last-response="{{stuffs}}"></iron-ajax>
So until Polymer developers get their act together and put in some basic functionality to support this very important use case, this is something we can use to keep some sanity back.