j0ker
j0ker

Reputation: 4139

Best practice for using JavaScript in Django

I want to push my Django project with some JavaScript/jQuery. To make it right from the beginning on I'd like to know, which way of organizing the .js-files ist the optimal one.

For loading one big file includes less overhead than loading many small ones and also because it looks cleaner in the code I considered to make one global .js-file and include that with the base.html (from which every template inherites). However, the result would be, that JavaScript would try to assign all the event-binings, even if the elements which the events should be bind to aren't in the current document. With all the jQuery-selectors which then would have to do their work that can't be too efficient. From earlier web-development experience I know that one can do something like if(location.href == '/some/url/') { (JavaScript code) ... }. That seems not practicable for me in this case, for with changing URLs, I'd have to change the URLconf and the .js-file (while using reverse() and {% url %} to prevent that elsewhere). I guess there is no possibility to make use of the named URLs here?

Has anyone an idea how to organize the JavaScript without having a file for every single template on the one hand and without killing performance unnecessarily?

Upvotes: 4

Views: 5124

Answers (4)

Raynos
Raynos

Reputation: 169401

You use modular javascript.

Choose your packager of choice (mine is browserify) that packages all your modules into one package that you minify and gzip. You send this file to the client and it is cached.

This means you have all your code cached, minimize HTTP requests and stay lean and efficient.

And since you have modular code you just load your code as you would normally.

Personally I would use some form feature detection to load modules. You can choose to feature detect on almost any feature (some css selector, routes, url segments).

Feature detection would look like this :

var Features = {
  "class": "name",
  "class2": "name2",
  "dynamic-scroll": "dynamic-scroll",
  "tabstrip": "tabstrip",
  ...
}

for (var key in Features) {
  require(Features[key]);
}

Where as routing with davis would look like

Davis(function() {
  this.get("blog", function(req) {
    require("blog")(req);
  });

  this.get("blog/:post", function(req) {
    require("blog-post")(req);
  });

  this.get("shop", function(req) {
    require("shop")(req);
  });
  ...
});

Alternatively you can try an event driven architecture. This means each module binds to events

// some-module

mediator.on("blog-loaded", function() {
  // load in some libraries

  // construct some widgets

  mediator.emit("blog-ui-build", widgets);
});

And you would need some bootstrapping in place to kick off the event loop. Feel free to look at an EDA demo

Upvotes: 2

Cromulent
Cromulent

Reputation: 3818

I find django-compressor invaluable as it automatically compresses and minifies your JavaScript and CSS pre-deployment. It even automatically handles SASS, LESS and CoffeeScript if they float your boat.

Upvotes: 3

Mikhail Korobov
Mikhail Korobov

Reputation: 22238

Apps from http://djangopackages.com/grids/g/asset-managers/ may help.

Upvotes: 2

nrabinowitz
nrabinowitz

Reputation: 55678

I don't know that this question is specific to Django - similar issues come up managing Javascript in all sorts of systems.

That said, I usually try to tier my Javascript files, so that truly global scripts and libraries are included in one file, scripts specific to a section of the site are included in a set of section-specific files, and scripts specific to a single page are included in yet another site of page-specific files (or in inline code, depending on the context).

Django has good support for this approach, because you can tier your templates as well. Include the global script in your base.html template, then create a mysection-base.html template that inherits from base.html and just adds the Javascript (and CSS) files specific to that section. Then subpages within that section can inherit from mysection-base.html instead of base.html, and they'll all have access to the section-specific scripts.

Upvotes: 5

Related Questions