Blog
completed add tag
Jack Douglas
**tl;dr:** we have completed some refactoring with the dual aim of (1) improving security, and (2) making some things faster.

# Resource Versioning

If every time a resource changes, it's url also changes, then:

1. the browser will never need to ask the server if a resource has changed, avoiding round-trips and saving time and resources at both client and server
2. when a resource does change, you will never get a stale version from the cache (so less '[needs refresh](/meta?q=29#a43)')

In most cases, we are adding a hash to each resource (you won't see this in a url unless you open Developer Tools in your browser because it doesn't affect the main page urls).

The hash changes each time a resource, *or any resource it depends on*, changes. This was somewhat tricky to implement but I think we have cracked it in a way that doesn't add significant friction to the dev process. Basically we have to regenerate [this .js file](/require.config.js) each time we make a change, and we automate this with an `autocmd` in vim during development.

# Modularisation of Javascript

Most of the libraries we use support modularisation, and some of them basically assume you will be using it. There are various benefits for page load time too as scripts can mostly now be loaded in parallel and there is less blocking.

We are using [RequireJS](https://requirejs.org) as a loader and have managed to find workarounds for the libraries that don't play perfectly nicely with it (Katex and jQuery).

# Factoring out JavaScript and CSS from PHP files

To start with, it was much easier for us to have one file to work on with most of the code and styles inline. This meant we could develop faster and it meant we didn't have to worry about caching as everything was reloaded with each navigation.

Now it's more of a hindrance and source of friction as it's harder to find things in some of the larger source files we are working on.

There is a security side to this too — we can now implement a stricter and more useful CSP:

# Content Security Policy

The more I read about CSPs the more I understand how vital they are. Security by default is the only sensible policy (we use the same reasoning to justify disallowing all html tags in Markdown on TopAnswers).

With our current CSP, you are protected from whole classes of potential security problems if you are using a modern browser. Here's what we have:

```
default-src 'none';
script-src 'self';
style-src 'self' 'unsafe-inline';
style-src-elem 'self';
style-src-attr 'unsafe-inline';
img-src * data:;
font-src 'self';
connect-src 'self' tio.run dbfiddle.uk;
form-action post.topanswers.xyz;
```

The `style-src` attribute is a fallback — we really only want to allow styles in attributes, not in on-page `<style>` tags — and that is what our CSP does on Chrome, because it ignores `style-src` and honours `style-src-elem` and `style-src-attr` instead. When Firefox adds support for those directives it will do the same, but for now it has slightly less protection against ['CSS Exfil' attacks](https://www.netsparker.com/blog/web-security/private-data-stolen-exploiting-css-injection/).

Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.