PHPackages                             jkphl/defr - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Caching](/categories/caching)
4. /
5. jkphl/defr

ActiveLibrary[Caching](/categories/caching)

jkphl/defr
==========

A simple usage pattern and lightweight JavaScript library for deferred loading of external CSS and JavaScript resources with optional support for localStorage caching

v0.1.0(12y ago)3151[1 issues](https://github.com/jkphl/defr/issues)MITJavaScript

Since Jan 8Pushed 12y ago1 watchersCompare

[ Source](https://github.com/jkphl/defr)[ Packagist](https://packagist.org/packages/jkphl/defr)[ Docs](http://defr.jkphl.is)[ RSS](/packages/jkphl-defr/feed)WikiDiscussions master Synced yesterday

READMEChangelog (1)DependenciesVersions (2)Used By (0)

defr
====

[](#defr)

is an — at present: proof-of-concept — simple usage pattern and lightweight JavaScript library for **deferred loading and localStorage caching of external CSS and JavaScript** resources.

There are basically two versions of the library, one for [modern browsers](blob/master/lib/defr.modern-simple.js) and a polyfilled (and bigger) variant for [older browsers](blob/master/lib/defr.polyfilled-simple.js). Additionally, there's a version of each library supporting `localStorage` caching of CSS and JavaScript resources (again separated for [modern](blob/master/lib/defr.modern-localstorage.js) and [older](blob/master/lib/defr.polyfilled-localstorage.js) browsers).

Please be aware that I hacked all this together in very little time, so don't expect it to be rocket science at the moment. It should, however, illustrate my thoughts. I'm happily awaiting your feedback and your suggestions!

Basics
------

[](#basics)

When delivering content to your visitors, it is advisable to concentrate on the "above the fold" part in the first place and avoid "blocking content" by all means (i.e. external resources that need to get downloaded before the document can be rendered). External CSS and JavaScript files are always considered blocking, and simply moving them to the bottom of your HTML documents won't change this. Also, adding the `async` or `defer` attributes won't help in all cases — despite the fact that they exist for `` elements only. To truly defer the loading of stylesheets and scripts you'll have to employ JavaScript and dynamically add these resources to the DOM. This is where *defr* jumps in, providing you with a very simple usage pattern for this very purpose.

Example
-------

[](#example)

Have a look at the following example:

```
>

        defr usage pattern example

        Lorem ipsum dolor sit amet, ...

```

As you see, there's a special `` section in the head of the document. In fact, there could be als more than one, and if you dont care for validation you might also put it wherever you want in your document, not just into the `` section. There's also the *defr* library itself included at the end of the document (in practice, I'd recommend inlining the library, but I'll keep it external in this example for clarity's sake).

The `` section contains two `` elements, with the first one being just a **regular reference to an external CSS resource** — nothing special about it, except that it's a part of the `` content. As deferred loading always involves JavaScript, this is a perfect fallback: If no JavaScript is available, the `` element will be parsed and the stylesheet gets loaded just normally (non-deferred). Otherwise, the content of the `` element is seen as text and won't be processed in any way by default.[1](#user-content-fn-1-c737c7066645362ce429eefe58b8c773)

The second `` element — **referencing a JavaScript resource** — is missing a `rel` attribute, which is perfectly ok according to the [HTML5 vocabulary](http://www.w3.org/TR/html5/document-metadata.html#attr-link-rel). It will, however, result in the browser ignoring the element altogether when being in `noscript` mode, as it doesn't know how to deal with it — which is again perfectly ok as we don't have JavaScript support in that situation anyway.

The *defr* library, included at the end of the document, will take care of that `` section, extract the stylesheet and script resources and load them by dynamically injecting them into the DOM. Pretty easy, right?

What about that `itemtype` and `itemprop` stuff?
------------------------------------------------

[](#what-about-that-itemtype-and-itemprop-stuff)

According to the [HTML5 vocabulary](http://www.w3.org/TR/2011/WD-html5-author-20110809/the-noscript-element.html), a `` element may only contain ``, `` and `` elements — but no `` elements, unfortunately. To comply with the HTML5 validation rules, we have to "misuse" the `` element for referencing external JavaScript resources. For my taste, that's absolutely ok, as it's nothing more than the reference established by e.g. `` for a CSS resource. There is, however, no appropriate `rel` value we could use for JavaScript, so we have to omit it altogether (Well, we could employ e.g. `rel="prefetch"`, but that would definitely be a case of misuse ...).

The [W3C HTML5 validator](http://validator.w3.org) requires each `` element to either have a `rel` or an `itemprop` attribute (with the latter being part of the [Microdata](http://html5doctor.com/microdata) specification). Furthermore, an element having an `itemprop` attribute must also be a descendant of an element having the `itemscope` attribute (see the `` in the example). As I'm a huge fan of [micro information](https://github.com/jkphl/micrometa) anyway, I finally added the `itemtype="http://defr.jkphl.is/asset"` attribute to clearly indicate that it's a *defr* `` element. The complete microdata vocabulary used by *defr* will be [available soon](http://jkphl.github.io/defr/assets/index.html).

At the same time, **this usage pattern is valid HTML5** out of the box.

Employing defr
--------------

[](#employing-defr)

In general, I recommend inlining the *defr* library, as it is really small and — more importantly — referencing it externally would introduce the library itself as a "blocking content" — which is exactly what you'll want to avoid. In any case, you should include the library **after the last asset bundle** (i.e. *defr* `` element) in your document, e.g. just before the closing `` element.

```
	...

		!function(a,b,c,d){ /* Here's the library code ... */ }(window,document,!1);

CDATA[/*` comment or dynamically written by JavaScript. All these aproaches fail, so there's only the chance to cloak it in an (otherwise empty) `` element. With JavaScript being disabled, the starting `` is not written at all and the `` element is working as usual.

Yeah, I know this doesn't feel right. But be honest: The *real* problem is not this hack, is it?

Examples / live demo
--------------------

[](#examples--live-demo)

There's an example / demo page for each of the library versions that you can use for testing your platform and browser:

- [Simple asset loading in modern browsers](http://jkphl.github.io/defr/example/modern-simple.html) (modern-simple)
- [Simple asset loading in older browsers](http://jkphl.github.io/defr/example/polyfilled-simple.html) (polyfilled-simple)
- [localStorage caching in modern browsers](http://jkphl.github.io/defr/example/modern-localstorage.html) (modern-localstorage)
- [localStorage caching in older browsers](http://jkphl.github.io/defr/example/polyfilled-localstorage.html) (polyfilled-localstorage)

Supported / tested browsers
---------------------------

[](#supported--tested-browsers)

These are the browser / platform combinations that I explicitly tested. If you have the chance to test some of the missing ones, please let me know your results. You may use the demo pages in the `examples` directory to test the support on a specific client. You will have to watch the respective developer tools' network and resources tab or your webservers log files to find out when your client requests which files from your server.

### Desktop clients

[](#desktop-clients)

     Windows XP Windows 7 Windows 8 Windows 8.1 OS X     IE 6 ❶ — — — —   IE 7 ❶✱ — — — —   IE 8 ❶❷✱ — — — —   IE 9 — ❶❷ ❶❷ ❶❷ —   IE 10 — ❶❷ ❶❷ ❶❷ —   IE 11 — ❶❷ ❶❷ ❶❷ —   Chrome 31 ❶❷ ❶❷ ❶❷ ❶❷ ❶❷   Firefox 25 ❶❷ ? ? ? ?   Firefox 26 ❶❷ ❶❷ ❶❷ ❶❷ ❶❷   Opera 12.10 ? ❶❷ ? ? ?   Opera 12.16 ? ❶❷ ❶❷ ❶❷ ?   Safari 5.1.7 ? ? ? ❶❷ ?   Safari 5.1.8 — — — — ❶❷   Safari 5.1.10 — — — — ❶❷  ❶ Polyfilled library ❷ Modern library ✱ With special markup only (wrapping `` element)

### Mobile clients

[](#mobile-clients)

I will try to do some tests on mobile devices soon.

Current problems / caveats
--------------------------

[](#current-problems--caveats)

- Fallback with deactivated JavaScript has to be tested (all clients / platforms)

Resources
---------

[](#resources)

- [Extending HTML5 — Microdata](http://html5doctor.com/microdata/)
- [Events on script and link elements](http://pieisgood.org/test/script-link-events/)
- [The HTML5 link element](http://www.w3.org/TR/2011/WD-html5-author-20110809/the-link-element.html)
- [The HTML5 script element](http://www.w3.org/TR/html5/scripting-1.html#the-script-element)
- [Deep dive into the murky waters of script loading](http://www.html5rocks.com/en/tutorials/speed/script-loading)

Legal
-----

[](#legal)

Copyright © 2014 Joschi Kuphal  / [@jkphl](https://twitter.com/jkphl)

*defr* is licensed under the terms of the [MIT license](LICENSE.txt).

Footnotes
---------

1. Unfortunately, there's a very nasty problem with Internet Explorer 7 and 8: They don't expose the contents of `` elements to JavaScript (IE 6 does by the way!). If you happen to have to support these browsers, you'll want to read the next chapter. [↩](#user-content-fnref-1-c737c7066645362ce429eefe58b8c773)
2. Internet Explorer performs what is called "speculative downloads", i.e. it automatically prefetches e.g. CSS resources in the moment when you create a `` element and give it a `href` attribute. It doesn't matter if the element is already part of the DOM — Internet Explorer will fetch it anyway, which kinda foils the localStorage approach. For this reason, it is necessary to trick IE by temporarily substituting the name of the `href` attribute against something different so that the speculative downloads aren't triggered. The current stage of *defr* does exactly this, so at least IE 11 behaves as expected now. I didn't test older IE versions yet though. [↩](#user-content-fnref-2-c737c7066645362ce429eefe58b8c773)

###  Health Score

23

—

LowBetter than 27% of packages

Maintenance13

Infrequent updates — may be unmaintained

Popularity10

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

4508d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9654aeebce6e58572ec7ee6e8b30a2f8f41a54a3c7a9580d1df090996f5cfdbb?d=identicon)[jkphl](/maintainers/jkphl)

---

Top Contributors

[![jkphl](https://avatars.githubusercontent.com/u/4446936?v=4)](https://github.com/jkphl "jkphl (24 commits)")

---

Tags

javascriptcsscachedeferexternallocalstoragedeferring

### Embed Badge

![Health badge](/badges/jkphl-defr/health.svg)

```
[![Health](https://phpackages.com/badges/jkphl-defr/health.svg)](https://phpackages.com/packages/jkphl-defr)
```

###  Alternatives

[psr/simple-cache

Common interfaces for simple caching

8.1k727.3M2.1k](/packages/psr-simple-cache)[psr/cache

Common interface for caching libraries

5.2k686.9M1.3k](/packages/psr-cache)[react/cache

Async, Promise-based cache interface for ReactPHP

444112.4M40](/packages/react-cache)[beste/in-memory-cache

A PSR-6 In-Memory cache that can be used as a fallback implementation and/or in tests.

2512.2M6](/packages/beste-in-memory-cache)[anahkiasen/flatten

A package for the Illuminate framework that flattens pages to plain HTML

33313.0k](/packages/anahkiasen-flatten)[rtcamp/nginx-helper

Cleans nginx's fastcgi/proxy cache or redis-cache whenever a post is edited/published. Also provides cloudflare edge cache purging with Cache-Tags.

23817.0k1](/packages/rtcamp-nginx-helper)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
