Skip to content

Instantly share code, notes, and snippets.

@ebidel
Last active May 1, 2021 15:42
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ebidel/c72e5b9b7ce7588ef468 to your computer and use it in GitHub Desktop.
Save ebidel/c72e5b9b7ce7588ef468 to your computer and use it in GitHub Desktop.
Fast Polymer app loading (Promises version) - optimized for first render, progressively enhanced lazy loading
<!DOCTYPE html>
<html>
<head>
<style>
body.loading #splash {
opacity: 1;
}
#splash {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
transition: opacity 300ms cubic-bezier(0,0,0.2,1);
opacity: 0;
will-change: opacity;
z-index: 1;
background: url(...) no-repeat;
background-color: #E53935;
}
</style>
<script>
// Note: this version requires Promises, which are in all the
// latest browsers except IE 11. Edge will ship them.
// Note: native Promise.defer() is deprecated. Have to create our own.
function deferred() {
var result = {};
result.promise = new Promise(function(resolve, reject) {
result.resolve = resolve;
result.reject = reject;
});
return result;
};
// (Optional) Use native Shadow DOM if availabe in the browser.
window.Polymer = window.Polymer || {dom: 'shadow'};
// 1. Create deferred Promise to capture async import's load.
var importsLoadedDeferred = deferred();
function onImportsLoaded(e) {
// 3. Resolve the Promise when the async import has loaded.
importsLoadedDeferred.resolve(e.target);
}
</script>
<!-- 2. Use non-render blocking async import with onload handler.
Note: the handler needs to be defined before this import. -->
<link rel="import" href="elements.html" onload="onImportsLoaded(event)" async>
</head>
<body class="loading"> <!-- Don't use simple FOUC solution <body unresolved>. -->
<div id="splash"></div>
<!-- Elements wait on the page and are upgraded when elements.html loads. -->
<paper-drawer-panel>
...
</paper-drawer-panel>
<script src="app.js" async></script>
</body>
</html>
// 4. Dynamically load web components polyfills based on feature detection.
var webComponentsSupported = ('registerElement' in document
&& 'import' in document.createElement('link')
&& 'content' in document.createElement('template'));
if (!webComponentsSupported) {
var script = document.createElement('script');
script.async = true;
script.src = '/bower_components/webcomponentsjs/webcomponents-lite.min.js';
script.onload = finishLazyLoading;
document.head.appendChild(script);
} else {
finishLazyLoading();
}
function finishLazyLoading() {
// 5. Wait on importsLoadedDeferred to resolve. When it does,
// the import has loaded.
importsLoadedDeferred.promise.then(function(htmlImport) {
// 6. Fade splash screen, then remove.
var loadEl = document.getElementById('splash');
loadEl.addEventListener('transitionend', loadEl.remove);
document.body.classList.remove('loading');
// App is visible and ready to load some data!
});
}
@Bamieh
Copy link

Bamieh commented Apr 11, 2016

@ebidel the Promise.defer() you've created causes an issue:

Uncaught TypeError: Illegal invocation

i believe this is because you are trying to copy a native method (resolve and reject native methods) into ( result object )

@ebidel
Copy link
Author

ebidel commented Aug 10, 2016

What browser is that? This code is working for me in Chrome / Safari / FF.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment