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

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
You can’t perform that action at this time.