(With apologies to Rosie Grier.)
As web developers, we usually think of the apps or sites we create as single, contained units. That’s understandable, especially with PHP-based apps. PHP is often responsible for creating all aspects of the site. Platforms like WordPress and Drupal generally reflect this thinking, and thousands (millions?) of sites have been deployed on top of them.
It’s not quite like that, though. There are two distinct platforms our code executes on, the server and the browser. Our server-side code generates other code that the browser then executes. Historically, as we’ve served up static pages of HTML and had to process all user actions server-side, this model has served us pretty well.
As expectations for richer, more responsive UX has grown, this single-app model has become problematic. Full page reloads kill the perceived responsiveness of apps, as well as require more server requests and bandwidth. In order to support a superior UX, the frontend logic becomes far more complex.
There’s a reason you stopped mixing your DB code with your HTML — not because you couldn’t do it, but because it becomes impossible to maintain. As the codebase grows, the likelihood of errors skyrockets, and refactoring becomes a huge pain. So, you separate your concerns, and you decouple your code into nicely-partitioned modules.
That’s what you do for code that’s all running on the same platform. Your HTML, CSS, and JS are executing on an entirely different platform, and the whole execution model is different (long-running and asynchronous, event-driven versus short-running and synchronous).
I still see large PHP apps written with a single-app mindset, where frontend logic is essentially hacked into the server-side generated code. How well does generated code usually turn out? Pretty crappy, right? This does not improve when PHP is generating JS. In addition, intertwined PHP and JS is a nightmare to debug and maintain — much more than mixed PHP and HTML.
Conceptually, I think it’s beneficial to consider your frontend as an entirely separate app from the backend. The frontend is a client for your backend, optimized for its particular environment. A desktop browser may be your first client, but a mobile or tablet app might be just as important. And if you’ve taken this decoupled, separate-app approach, it will be much easier to play to a client platform’s strengths, rather than hacking on support for a mobile or tablet version of your desktop client.
How far you can take this concept varies based on the app. Performance, capability, and compatibility concerns mean you may need to make certain optimizations. Generating chunks of HTML with the server app may be much faster than rendering data and templates in the browser, especially if you need to support Internet Explorer (6, 7, or 8), which have painfully-slow JS engines. Manipulating dates and times in JS is a huge chore compared to PHP’s DateTime. Similarly, doing i18n and l10n work in PHP is much easier than in JS. But, just as you might introduce tighter coupling between PHP modules for performance reasons, this should be done selectively.
In the end, treating your frontend(s) and backend as separate apps means each app will be able to do what works best for its given platform. You’ll end up with a better development experience, and a superior user experience.