Use cached js for RequireJS

50 views
Skip to first unread message

Andy Cheng

unread,
Sep 1, 2014, 11:06:10 PM9/1/14
to django-...@googlegroups.com
Hi,

Django-Require generates the md5-named javascript for caching purpose with OptimizedCachedStaticFilesStorage.
However, it doesn't alter the dependency paths from config.js. (I use a separate require config file for modules and dependencies).
In such case, requireJS still loads the the modules with the same name, potentially cached.
I am not bundling modules like angularjs so they can be cached across pages, but wish them to be updated when there is one.

Is there a solution to it? Or what is the best practice?

Thank you so much

Andy

Dave Hall

unread,
Sep 2, 2014, 4:48:13 AM9/2/14
to Andy Cheng, django-...@googlegroups.com
There are two approaches that could handle this, but in general I’d advise against using the multi-page approach with MD5 hashed JS files.

If you really want to do this, then you’ll need to hack something yourself. You can either make a static files storage subclass that updates the paths in the files using a regex, similar to how the current storage updates CSS files. Or, you can load the manifest.json file (generated by ManifestCachedStaticFilesStorage in Django 1.7), and add in the paths at runtime. Both are tricky.

In general, I’d recommend having one giant JS file, with per-page entrypoint methods. This means that you only need to download all the JS for your site once, which in almost all cases will be the fastest approach.

Why will this (probably) be faster? In most sites, the amount of per-page versus library code is tiny. You’ll have 200K of library code, and maybe 10K of your own code, split over say, five pages. Let’s look at how this stacks up:

## Approach 1 - Separate libraries and per-page code.

Load page 1: Download 200K of library and 2K of per-page code = 2 requests.
Load page 2: Download 2K of per-page code = 1 request.
Load page 3: Download 2K of per-page code = 1 request.

# Approach 2 - Bundle everything into one giant JS file.

Load page 1: Download 210K of combined code = 1 request.
Load page 2: Code already downloaded = 0 requests.
Load page 3: Code already downloaded = 0 requests.

Unless your per-page code differences are giant, it’s almost certainly going to be a more complex and slower operation to split it into different modules.
> --
> You received this message because you are subscribed to the Google Groups "django-require discussion and announcements" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to django-requir...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

signature.asc

Andy Cheng

unread,
Sep 2, 2014, 5:04:50 AM9/2/14
to django-...@googlegroups.com, an...@cloudmobo.com
Thank you so much for your detailed reply, it certainly solved the big mystery I have for a while.
I am going to use the giant JS approach as you suggested.

Now the question becomes how do I md5 the giant JS file?
I suppose OptimizedCachedStaticFilesStorage will do the trick, but somehow it doesn't update the <script> tag source as CachedStaticFilesStorage does.
(Or I must have configured something wrong?)

Thanks
Andy


Dave Hall於 2014年9月2日星期二UTC+8下午4時48分13秒寫道:

Dave Hall

unread,
Sep 2, 2014, 5:23:03 AM9/2/14
to Andy Cheng, django-...@googlegroups.com
Happy to be of service!

Assuming that each page has it’s own main() method that bootstraps the JS, I’d do something like this:

{% load static %}
<!— Load in requirejs -->
<script src=“{% static ‘js/require.js' %}”></script>
<script>
require([“main”], function(main) {
main.initPage1(); // Per-page bootstrap.
});
</script>

Then, on different pages, something like:

{% load static %}
<!— Load in requirejs -->
<script src=“{% static ‘js/require.js' %}”></script>
<script>
require([“main”], function(main) {
main.initPage2(); // Per-page bootstrap.
});
</script>

That’s all assuming that you’re not using almond.js to generate a standalone requirejs module.
signature.asc

Andy Cheng

unread,
Sep 2, 2014, 5:39:04 AM9/2/14
to django-...@googlegroups.com, an...@cloudmobo.com
Hi Dave,

But how is main.<md5>.js called? Won't RequireJS look for main.js instead in this setup?

Thanks
Andy

Dave Hall於 2014年9月2日星期二UTC+8下午5時23分03秒寫道:

Dave Hall

unread,
Sep 2, 2014, 5:57:44 AM9/2/14
to Andy Cheng, django-...@googlegroups.com
Ahahaha! Yes, you’re right. I’d do this:

https://gist.github.com/etianen/b9e4127dba33bbf9cdea

It uses the RequireJS config system to tell the app which page to bootstrap. It’s a little more complicated, but once set up should be easy to expand.
signature.asc

Andy Cheng

unread,
Sep 2, 2014, 6:05:41 AM9/2/14
to django-...@googlegroups.com, an...@cloudmobo.com
Please correct me if I am wrong, but even with the bootstrap, it still doesn't tell RequireJS which md5'ed javascript to load, does it?

What I am hoping to get is to have:

main.12345.js
main.56789.js

in my folder, and somehow the page/requireJS will load the latest one, say main.56789.js.
This is similar to Django's default behavior with cached storage.

Thanks
Andy

Dave Hall於 2014年9月2日星期二UTC+8下午5時57分44秒寫道:

Andy Cheng

unread,
Sep 2, 2014, 6:24:32 AM9/2/14
to django-...@googlegroups.com, an...@cloudmobo.com
You are right! Thanks for the help!
Good stuff

Andy Cheng於 2014年9月2日星期二UTC+8下午6時05分41秒寫道:
Reply all
Reply to author
Forward
0 new messages