Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Safari 10.1 `nomodule` support
<!--
Similar to https://gist.github.com/samthor/64b114e4a4f539915a95b91ffd340acc
But prevents Safari 10.1 from downloading ES5 scripts.
This is the only way I know to detect "module" support in <head>.
-->
<script>
// matrix of script sources. rows will be executed in order.
// first column is ES6, the second is ES5.
window.__SCRIPTS__ = [
['vendor-es6.js', 'vendor.js'],
['app-es6.js', 'app.js']
];
</script>
<script>
(function(){
'use strict';
var MODERN = 1 << 0;
var LEGACY = 1 << 1;
var MODERN_SCRIPT_TYPE = 'module';
var LEGACY_SCRIPT_TYPE = 'text/javascript';
var modernChecker = document.createElement('script');
var legacyChecker = document.createElement('script');
var done = false;
function beforeloadHandler(e) {
// beforeload should trigger for the `check` script if
// type="module" is supported"
removeListener();
if (e.target === modernChecker) {
e.preventDefault();
insertScripts(MODERN);
} else if (e.target === legacyChecker) {
e.preventDefault();
insertScripts(LEGACY);
} else {
// beforeload did not trigger for neither modernChecker nor legacyChecker
// this is unlikely, but don't prevent default just in case.
insertScripts(LEGACY);
}
addListener();
}
function addListener() {
document.addEventListener('beforeload', beforeloadHandler, true);
}
function removeListener() {
document.removeEventListener('beforeload', beforeloadHandler, true);
}
if (!('noModule' in modernChecker)) {
if ('onbeforeload' in modernChecker) {
addListener();
injectFeatureDetectorScript(modernChecker, MODERN_SCRIPT_TYPE);
injectFeatureDetectorScript(legacyChecker, LEGACY_SCRIPT_TYPE);
removeListener();
} else {
// noModule is not supported and we cannot reliably detect module
// support and insert scripts before document is parsed. Edge is
// one such browser that has this behaviour. Just send ES5.
insertScripts(LEGACY);
}
} else {
insertScripts(MODERN);
}
function injectFeatureDetectorScript(script, type) {
script.type = type;
script.src = '.';
document.head.appendChild(script);
script.remove();
}
function insertScripts(type) {
if (done === true) return;
done = true;
var scripts = window.__SCRIPTS__;
for(var i = 0; i < scripts.length; i++) {
insertScript(scripts[i][type === LEGACY ? 1 : 0]);
}
}
function insertScript(src) {
var script = document.createElement('script');
script.src = src;
script.async = false;
script.type = LEGACY_SCRIPT_TYPE;
document.head.appendChild(script);
}
}());
</script>
!function(){"use strict";function e(e){n(),e.target===f?(e.preventDefault(),c(a)):e.target===l?(e.preventDefault(),c(d)):c(d),t()}function t(){document.addEventListener("beforeload",e,!0)}function n(){document.removeEventListener("beforeload",e,!0)}function o(e,t){e.type=t,e.src=".",document.head.appendChild(e),e.remove()}function c(e){if(m!==!0){m=!0;for(var t=window.__SCRIPTS__,n=0;n<t.length;n++)r(t[n][e===d?1:0])}}function r(e){var t=document.createElement("script");t.src=e,t.async=!1,t.type=u,document.head.appendChild(t)}var a=1,d=2,i="module",u="text/javascript",f=document.createElement("script"),l=document.createElement("script"),m=!1;"noModule"in f?c(a):"onbeforeload"in f?(t(),o(f,i),o(l,u),n()):c(d)}();
@jacksonrayhamilton

This comment has been minimized.

Copy link

@jacksonrayhamilton jacksonrayhamilton commented Nov 17, 2017

__SCRIPTS__ doesn't need to be a global variable, does it? Couldn't that just go inside the second IIFE?

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