Resource URLs and JavaScript

Tags:

Sometimes when working with JavaScript, you may need to refer some resource: Maybe a page or an image. They’re then used on the client-side code on your site.

But what happens if you restructure your project? Files move elsewhere… Maybe even domains change – you might be moving content to a specialized content hosting server for example. You would need to go through the JS files, check all of them for URLs and change them to the new correct ones.

Wouldn’t there be some solution that will make it easier in the event a change like that happens?

Choose a route

As usual, there is more than one way to approach this.

The first idea is of course to use PHP in your JS to generate the correct URL, since that’s probably what you’re doing elsewhere in your app. However, if you’re using lots of JS, chances are you’ll want them to be separated into .js files so that they can be cached etc., and you don’t really want to put PHP code in those – you could tell Apache to handle .js files as PHP, but that isn’t necessarily a very good idea.

I’m just using PHP here as an example, of course. This applies to other languages too, like Python and Ruby.

The most straightforward solution would be to simply not use absolute urls. This is not always possible, as the URLs may need to point to a completely different domain, and relative urls can break just like absolute ones.

Base URLs and URL generation

To get rid of the problem posed by the file path, we can simply use a base url, for example “http://example.com/images”. This can be easily defined in PHP code, even so that all JS libraries can use it:

//We want to use App as a namespace
var App = App || { };
 
App.baseUrl = '<?php echo $baseUrl; ?>';
 
function foo()
{
    //Refer to some image:
    var img = App.baseUrl . '/hello.jpg';
}

This is a simple and quite effective way to make URLs easier to change in the future, if needed.

You could use JavaScript to generate URLs in a similar fashion as you may do in PHP, for example like Zend Framework’s Url view helper does, but it has some problems. The primary one being that you would need to move over all the parameters needed for the url generation to JavaScript, which can make it a bigger headache to implement than the initial problem was.

URL generators are a more reasonable option in “heavier” JS apps where much of the logic is on the client-side, as it’s likely that they have more links to things.

Resource files

In Windows apps, resource files are used to store strings like translations of form controls and such. We could adapt this concept for use with URLs:

Simply create a JS file which is used to define all the URLs used throughout your app and a name for them. This is similar to translations too, in a way that gettext and such use a string to find the correct translated string.

App.Resources = {
    image: '/images/hello.jpg',
    file: '/some/static/file.html'
};

So instead of using strings like ‘path/to/image.jpg’ or ‘path/to/file.html’, you would simply use something like App.Resources.image and App.Resources.file in your code. This could be compared to magic strings and numbers, and magic is bad in this case.

Avoid magic characters and strings Magic characters are literal characters (such as ‘A’) and magic strings are literal strings (such as “Gigamatic Accounting Program”) that appear throughout a program.
– Code Complete

The advantages this approach gives are that you’re keeping all the URLs in the same place, making it easy to locate mistakes, modify paths and add new ones. With this approach, you could even use >your favorite server side language< to generate the URLs in the resource list, as you could just generate it with a template, or assign values directly into the resource object afterwards. It should also work relatively well even for a bit larger amount of urls, since it’s much easier to find and/or replace URLs in a single file than over multiple files with other, unrelated, code in them.

This is probably the most versatile approach to the problem of changing URLs.

Finally

In addition to the above, you can also simply pass URLs to your JS functions as parameters. This would give you some flexibility, as you can define the URL on a case-by-case basis, but in some cases it may also make function calls unnecessarily long.

What do you do when handling URLs in JS?