44

We concatenate CSS and JavaScript files to reduce the number of HTTP requests, which improves performance. The result is HTML like this:

<link rel="stylesheet" href="all-my-css-0fn392nf.min.css">
<!-- later... -->
<script src="all-my-js-0fn392nf.min.js"></script>

If we've got server-side/build logic to do all this for us, why not take it one step further and embed those concatenated styles and scripts in the HTML?

<style>.all{width:100%;}.my{display:none;}.css{color:white;}</style>
<!-- later... -->
<script>var all, my, js;</script>

That's two fewer HTTP requests, yet I've not seen this technique in practice. Why not?

1
  • 12
    I blame caching.
    – user40980
    Commented Dec 26, 2013 at 23:08

8 Answers 8

99

Because saving HTTP requests is of little use when you achieve it by breaking caching. If the stylesheets and scripts are served separately, they can be cached very well and amortized over many, many requests to wildly different pages. If they're mushed in the same HTML page, they have to be re-transmitted with every. Single. Request.

This page's HTML, for example is 13 KB right now. The 180 KB of CSS hit the cache, and so did the 360 KB of JS. Both cache hits took minuscle amounts of time and consumed practically no bandwidth. Whip out your browser's network profiler and try it on some other sites.

7
  • 1
    If you are doing a single page app style site then where the vast majority of the code was specific to one page then it might make some sense still?
    – JohnB
    Commented Dec 27, 2013 at 9:43
  • 3
    John: if the page is visited only once, yes. If visited multiple times, all the embedded stuff gets transmitted multiple times instead of just once and cached.
    – Konerak
    Commented Dec 27, 2013 at 10:05
  • Another good point of note is that by serving these separately you allow for minification of the resources so that they will be smaller in size.
    – maple_shaft
    Commented Dec 27, 2013 at 12:01
  • 2
    @maple_shaft Please elaborate, why can't you minify the resources as normal and then include them?
    – user7043
    Commented Dec 27, 2013 at 12:08
  • 1
    @JohnB do not forget the effects of a CDN or local caching at the isp. My request for the javascript for google likely never reaches google even if I have a cache miss locally because another person who uses the same isp will have already caused the isp to cache the data.
    – user40980
    Commented Dec 27, 2013 at 17:17
18

Simply because Web performance really matters ! 99% times it will give you faster end-user response times.

Here are a few exampels from Velocity Conf.

  • Bing – A page that was 2 seconds slower resulted in a 4.3% drop in revenue/user.
  • Google – A 400 millisecond delay caused a 0.59% drop in searches/user.
  • Yahoo! – A 400 milliseconds slowdown resulted in a 5-9% drop in full-page traffic.
  • Shopzilla – Speeding up their site by 5 seconds increased the conversion rate 7-12%, doubled the number of sessions from search engine marketing, and cut the number of required servers in half.
  • Mozilla – Shaving 2.2 seconds off their landing pages increased download conversions by 15.4%, which they estimate will result in 60 million more Firefox downloads per year.
  • Netflix – Adopting a single optimization, gzip compression, resulted in a 13-25% speedup and cut their outbound network traffic by 50%.

From Steve Souders, pioneer in Web Performance Optimization,

80-90% of the end-user response time is spent on the frontend - Start here first.

Using external files produces faster pages because the JavaScript and CSS files are cached by the browser/networks/proxies (as defined in HTTP protocol with Cache headers). JavaScript and CSS that are inlined in HTML documents get downloaded every time the HTML document is requested. This reduces the number of HTTP requests that are needed, but increases the size of the HTML document. If you're using Jquery-like scripts, it's easy to refrence 300 KB of scripts and do not believe that everyone has a 100 MBits/s bandwidth with low latency, running a single application -the browser- opened on your web site. 99% times it will give you faster end-user response times.

The frequency with which external JavaScript and CSS components are cached relative to the number of HTML documents requested is also important. If users on your site have multiple page views per session and many of your pages re-use the same scripts and stylesheets (bundles), there is a greater potential benefit from cached external files.

But inlining is -sometimes- preferable for single page application or web sites with one single page view per session. There is no golden rule, and generally forget it as it concerns mainly very specific web sites really involved by end-user performance.

You can read here why performance matters (Disclaimer : I am the author)

3

The latest version of HTTP was created way back in 1999. In 1999, everybody connected to the Internet with dial-up. The Internet was very slow. 16 years later, things have moved on a great deal, but the protocols we use have not.

The answers that we shouldn't inline 'because it interferes with caching' is a little misleading, particularly in the era of superfast Internet. When you actually do the calculations, there is often negligible difference between loading times with cache-warm and cache-cold users if you have inlined. The fact that there is a small difference is not inherently because you have inlined, but because of the inflexible design of HTTP/1.1.

The SPDY protocol implements something called server push. This essentially takes inlining out of the HTML document itself, and into the protocol. An intelligent server will know what resources the client already has. A dumb server will just send everything regardless -- that will still be a performance benefit, but may cost in terms of bandwidth. If the browser has the contents in its cache, it can simply discard the incoming copies. The server waits until the HTML is loaded before sending the additional resources -- in theory the browser can send a signal to cancel the server push.

HTTP/2.0 is based on SPDY and will most likely implement server push, but you can in theory start using SPDY today. So the real reason we don't inline is one of legacy -- the protocols that currently exist are old and are not flexible enough to achieve 'protocol-level inlining'.

3
  • 2
    Interesting answer, but rather than "legacy" the reason you give for not inlining at present is because it's the best fit to current Web protocol infrastructure. It'll be legacy if everyone is still doing the same thing in n years time when HTTP/2.0 / SPDY is fully deployed ;-) Commented Dec 30, 2013 at 19:18
  • 2
    Could you give a citation, sketch the calculations, or at least give a ballpark number for "superfast"? People in civilized first world countries with a considerable sum to spend on online (read: customers) may still sometimes - or even often - browse with less bandwidth than hundreds of megabytes per second. I for one rarely reach more then three MB/s, often less than 700 KB/s. As a separate point, you don't give a reason to inline in the way OP suggests (in fact, you give reasons not to), you give reasons to optimize the protocols.
    – user7043
    Commented Jan 2, 2014 at 17:49
  • 1
    My 3G connection isn't exactly "super fast", nor does my phone bill appreciate unnecessary data. Don't forget - not all mobile data usage is on the phone with tethering and 3G enabled tablets/laptops. Esp. with laptops the assumption is wifi/ethernet on a home broadband connection. Not appreciated when tethering remotely...
    – AnonJr
    Commented Jan 3, 2014 at 14:48
3

In addition to the caching and retrieving concerns that the other answers raise, I'd like to highlight another, more obscure problem: parsing.

JavaScript appearing in HTML can run into parsing issues, like in this example:

<html>
<head>
<script>
function myfunc() {
    if ("</style> isn't a problem")
        return "but </script> is"
}
</script>
<style>
body::after {
  content: '</script> is okay, but not </style>'
}
</style>
</head>
<body>
<script>document.write(myfunc())</script>
</body>
</html>

...which means you'd have to transform your script to escape some characters that trigger in HTML. This issue goes away when you supply CSS and JavaScript as external resources, because they no longer have to take the 'parent' parsing context into account.

If you serve your content as XML, you have a part way around this by using CDATA sections. CDATA, however, comes with a similar issue:

<?xml version="1.0" encoding="utf-8"?>
<html>
<head>
<script>
// <![CDATA[
function myfunc() {
    if ("</script> is no longer a problem")
        return "but ]]> is"
}
// ]]>
</script>
<style>
<![CDATA[
body::after {
  content: 'same ]]> issue here'
}
]]>
</style>
</head>
<body>
<script>document.write(myfunc())</script>
</body>
</html>

Inliners beware.

2
  1. Minimize duplicate coding. for save time (You can reuse the style and JS function coded for one page).
  2. Minimize change effort. (If your client ask you to change the button color of the web site. you need to go one page by one ).
  3. Reduce the load time (If your CSS and JS duplicate it means individual pages size increase and time consuming to download. but common CSS JS no need to download again and again).
  4. Remote usage. (you can place your common CSS js JS in a remote place. not the same hosted server)
  5. Reduce Bug fixing time. If there is a bug in one function you need to go page by page to fix the bugs in embedded JS and CSS.
  6. To increase SEO (simply separate content with meta data)
  7. Cleaner and understandably of code (If you embed all in one file debug and code clarity gone away. and each page will be a very long page).
  8. Additionally this will help you to reduce the size of the product.
  9. But still you can consider to embed most unique thing in the same page.
1

The separation of content from the styling of its presentation is usually a bigger advantage than fewer http requests.

Separating out all the styling enables and encourages reuse and shared files.

The contents of the files will also be more static and available for caching on both servers and clients for both that page and other pages that are visited.

To you specific question though...If the server is made to do the minification itself it makes the assets harder to maintain and to debug issues. However many frameworks do now do this at the file level, e.g. all cs and all js. For example the ruby on rails framework now minifies its assets for production. 5-10 extra http requests are usually not the bottleneck, its more if there are 100+ http requests (which you often get with images).

The extra step of actually including the code in the pages itself would have the disadvantage of bigger pages that you'd have to manage the download sequence carefully and the page not being able to display content often without the rest of the (now large) page being downloaded.

5
  • To clarify, are you saying separation of style and content benefits the developers, or benefit performance in the end user's browser?
    – user7043
    Commented Dec 26, 2013 at 23:27
  • I'm saying that the overall benefit to the company is usually a bigger win than the reduction in requests in business terms. Commented Dec 26, 2013 at 23:29
  • 3
    You do realize that OP is advocating developing with separate files and only concatenating during deployment, along with minification, obfuscation and the "regular" concatenation? You get to have your maintainable code base and eat the performance benefits too. This is common practice with other code mangling optimizations, like minifying source code and concatenating multiple JS/CSS files into one.
    – user7043
    Commented Dec 26, 2013 at 23:32
  • I don't realize that. The words "embed those concatenated styles and scripts in the HTML?" confuse me. Commented Dec 27, 2013 at 0:17
  • Just to be clear, I did indeed mean to suggest what @delnan has clarified on my behalf in his comment. Sorry if my question's phrasing was ambiguous. Commented Dec 28, 2013 at 18:37
0

We should not embed styles/scripts in HTML because

Embedded styles/scrips must be downloaded with every page request:

These styles cannot be cached by the browser and re-used for another page. Because of this, it's recommended to embed a minimal amount of CSS / JS as possible.

instead we use linking coz when we use linking to bind css/scripts

Site speed increases for multiple page requests:

When a person first visits your website their browser downloads the HTML of the current page plus the linked CSS and JS file. When they navigate to another page, their browser only needs to download the HTML of the new page, the CSS/JS file is cached so doesn't need to be downloaded again. This can make a big difference particularly if you have a large style and script file.

0

It improves the management of the website.

If there is one monolithic piece of code with html, css3 and JS all mangled together then the management of the website become a terrible chore.

You don't just write code for yourself, your write it for the people who are going to read the code afterwards as well.

By separating the concerns and the functionality of the code you make the search for specific pieces of code much easier. This makes it possible that when the business needs of the organisation changes the website can be changed without anyone's mental health being sacrificed.

As a general programming concept the separation of functionality into as small as feasible, manageable chunks, is just general good coding practice. In the web development space doubly so because we have three languages that have to work together.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.