latest log

酩酊状態で書いたエンジニアポエムです。酩酊状態で読んでください。

HTML の linkタグに prefetch 機能が追加され、より便利になるようです

linkタグに pre fetch 機能を追加する仕様 (Editor's Draft)が上がってきています。

<link rel="preload" href=“…" as=“…" onload=“…” onerror=“…”>

従来は、new Image や XHR と DOM API を使ってリソース毎に別々のJavaScriptを記述する必要がありましたが、お手軽になりますね。

これまで

var img = new Image();
img.onload = function() { document.body.appendChild(img); };
img.onerror = ...
img.src = url;
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
document.body.appendChild(script);
// onload は取れない(頑張れば取れる)
var xhr = new XMLHttpRequest();
xhr.onload = function() {
  if (xhr.status >= 200 && xhr.status < 300) {
    eval("(" + xhr.responseText + ")");
  }
};
xhr.onerror = ...
xhr.open("GET", url);
xhr.send();

これから

HTML に直書き

<link rel="preload" href="/components/widget.html" as="iframe">
<link rel="preload" href="/app/script.js" as="javascript">
<link rel="preload" href="/style/style.css" as="stylesheet">
<link rel="preload" href="//example.com/image.jpg" as="image" media="screen and (max-width: 640px)">

JavaScript を使ってプリフェッチ

function _getFileExtension(url) { // @arg URLString - "http://example.com/a.png"
                                  // @ret ExtString - "png"
  var obj = new URL(url);
  var fileName = (obj.pathname || "/a.unknown").split("/").slice(-1);

  return fileName[0].split(".")[1];

  // new URL(url) が使えない環境も考慮する場合は、 https://github.com/uupaa/URI.js をロードして
  // var obj = WebModule.URI.parse(url);
  // see: https://github.com/uupaa/URI.js/wiki#urijs
}

function _detectResourceType(url) { // @arg URLString
                                    // @ret ResourceTypeString - "image", "script", "iframe", "font", "stylesheet", ...
  switch ( _getFileExtension(url).toLowerCase() ) {
  case /js/.test(ext):                      return "script";
  case /css/.test(ext):                     return "stylesheet";
  case /html/.test(ext):                    return "iframe";
  case /otf|ttf|ttc|woff/.test(ext):        return "font";
  case /webp|gif|png|jpg|jpeg/.test(ext):   return "image";
  }
  return "";
}

function prefetch(url,            // @arg URLString
                  callback,       // @arg Function = null - callback(event:Event):void
                  errorback,      // @arg Function = null - errorback(error:Error):void
                  resourceType) { // @arg ResourceTypeString = ""
  var res   = document.createElement("link");

  res.rel   = "preload";
  res.as    = resourceType || _detectResourceType(url);
  res.href  = url;
  res.onload = callback || null;
  res.onerror = errorback || null;
  document.head.appendChild(res);
}


prefetch("http://example.com/a.js");
prefetch("http://example.com/a.css");
prefetch("http://example.com/a.png");
prefetch("http://example.com/a.font.woff");
prefetch("http://example.com/a.iframe.html");