AngularJS Backend-less Development Using a $httpBackend Mock

I was only able to briefly mention that I used a $httpBackend mock to do backend-less development with AngularJS during my presentation on AngularJS Data Driven Directives, so I created an isolated example in a Plunker to fully implement it.  Here is a link to the Plunker if you want to skip right there, below is an explanation and the embedded plunker.

The purpose of this example code is to show how to do backend-less development with code that uses both $http and $resource to fully cover the most common server communication options within AngularJS.

Why do backend-less development?

Isolating your AngularJS frontend development from the backend (REST API) can allow potentially separate teams develop independently.  Agreeing on the REST API can then allow both teams develop in parallel, agreeing to implement/use the REST service the same way.

This can be accomplished by the simple inclusion of a file in your AngularJS code that creates a mock using $httpBackend.  $httpBackend makes the requests that are underlying $http, which is also what ngResource $resource uses.  When you are ready to hit the real backend REST API, simple remove the file from being included, possibly as simple as a special task inside your grunt config.

There are two different flavors of the $httpBackend mock, we want to use the one not for unit testing, but for E2E testing:

AngularJS $httpBackend docs

How do we do it?

We use URL patterns within app-mockbackend.js to intercept the GET and POST calls to the URLs, along with the data for a POST.  We can use regular expressions as patterns, which allows for a lot of flexibility.

The handling of the URLs and HTTP methods and returning "fake" data only works by having some data that can be persistent from request to request.  I store the data in an AngularJS service ServerDataModel that emulates storing the data a lot like the server would.  The AngularJS service recipe is perfect for this becuase it injects a constructed object, and that object contains our data.  No matter where it is injected, the instance of the object is what is shared so it contains the same data.  There is some data that is pre-loaded in that object that is analagous to having a database on the server that already has some records.

Here is the embedded version of the code, although I do think it is easier to view in its full glory directly on Plunker.

AngularJS Data Driven Directives Presentation

Creating data visualization solutions in Javascript is challenging, but libraries like D3.js are starting to make it a whole lot easier. Combine D3.js with AngularJS and you can create some data driven directives that can be used easily within your web app.

I created a presentation for the Boise AngularJS Meetup to show how to design AngularJS directives that interact with D3.js.  Also, because there is no getting away from it, I also include some ideas on how to manage your data models and transform along the way to guarantee a logical separation from your domain data model and your chart data model.

The link to github for the code is: AngularJS Data Driven Directives

The code in that repository is up and running on my Github Pages site for this project with the demo located here: Basketball Scorebook demo page.

You can get at the slides here: AngularJS Data Driven Directives Presentation Slides

Getting Started with AngularJS Screencast

Here is a video screencast of my Getting Started with AngularJS presentation that I gave at Boise Code Camp 2014. To follow along with the slides, you can get them here: Getting Started with AngularJS Slides

AngularJS Presentation at Boise Code Camp 2014

Having a great day at Boise Code Camp 2014!  I'm giving a presentation this year on Getting Started with AngularJS. Here is a link to my presentation slides

Tags:

AngularJS Presentation at Boise Web Technologies Group

AngularJS

Here is a PDF of the slides for the presentation on AngularJS that I am giving to the Boise Web Dev Technologies group.

Why You Should Use AngularJS in your Next Web Application

Adding a new javascript framework like AngularJS to your web app requires some careful evaluation.  Most projects already are using jQuery, maybe jQuery UI, and potentially other javascript libraries to handle other functionality not covered by jQuery or even jQuery plugins for UI elements like charts, multi-selects, infinite scrollers, sliders, etc.  Any javascript framework has a tough task to find a space to fill with developers.

Your decision might consider the additional lines of code added, worrying about if this may slow down your javascript execution, or page load times.  You know you will also have a huge initial learning phase where you discover how to use, then try to learn best practices as you start to play around with implementing your app.  Maybe you are concerned that it is just a fad framework too, there are other options for similar Javascript frameworks like Backbone.js, Knockout.js.

For most, I bet the initial learning phase and temporary slowdown in development is the primary hurdle.  This can slow down a project that could be quickly done with existing technology.  The long term benefit has to be there in order to spend your time learning and figuring out best practices, and ultimately the new piece of technology must be solving a problem in your software architecture to justify the time.

I found when researching AngularJS and going through the process of implementing an app with it, that it was going to be a great tool in making web applications.  For a big list of criteria I recommend to evaluate when considering adding a new component to your web application, check out my article here titled 18 Questions to Ask Before Adding New Tech to your Web App.  Here are some of the criteria from that list and how my evaluation of AngularJS went.  It's my opinion that there is a significant hole in front-end web development that AngularJS fills.

1. Address some problems in your software architecture

When writing web applications, I have objects in the server-side code that often times aren’t represented as objects in the client-side code.  For simple apps, this might be OK, but when it gets complicated, it can be a big help to mirror these objects on both sides.  Also leads to a terminology issue, a Person object on the server can’t truly be talked about as a Person on the client side because it doesn’t look or feel the same way.  Doesn’t have the same methods, isn’t represented as code, sometimes is stuffed into hidden inputs or in data attributes.

Managing this complexity can be very hard.  AngularJS has ng-resource which you use to create services that hook up to REST APIs and return back that object in JSON and you can attach methods to that object so it can be a fully functional object.  It feels more like something familiar to what you are working with on the server side.  All without much work on your end, you have methods like save(), get(), update(), that map to REST API endpoints and are most likely the similar methods you might have in your Data Mapper on the server side.

AngularJS encourages you to also deal with models on the client side just like you have them on the server side, big plus there.

I also don’t feel like the design using jQuery + Mustache is elegant when it comes to having an object that has properties represented in different ways within the web UI.  An example, you have a table of Person objects from the REST API, you have a button for each Person to denote they have “Accepted” an invitation, so when they click, you want the checkbox to change and you want the style on the row to change.  In jQuery, you listen for the checkbox change event, then you toggle the class on the button and the row.  In AngularJS, the model is the source of truth so you build everything from that.

See what I mean by taking a look at this jQuery vs. AngularJS plunker I created and compare the type of code you write.

2. Enable you to create software more quickly and with less effort

AngularJS having the ng-model and ng-class directives alone cover so many of the common operations that we all have been doing in jQuery.  Two-way data binding and saving to the server now takes a small number of lines in AngularJS, but in jQuery would require creating your own object, and several different click and event handlers.  Switching from watching elements and events to watching a model is a big shift in the right direction.

3. Result in software that is more maintainable

AngularJS encourages using the model as the source of truth, which starts to get you to also think object oriented design on the client-side.  This allows you to keep in mind the same object-oriented design principles that in general make software more maintainable compared to procedural.

4. Improve the testability of your software

AngularJS has dependency injection at its core, which makes it easy to test.  Even the documentation on the AngularJS site has testing as a part of every tutorial step, which almost makes it hard NOT to test.

5. Encourage good programming practices

Model as the source of truth, dependency injection, ability to create directives that can decorate elements that lends to reusable and shareable components, REST API connection to your server, lots of benefits from just following AngularJS basic usage.

6. Allow you to collaborate more easily with other people

Using models as the source of truth is something that is familiar with anybody who is doing object-oriented MVC server-side software, so this should make it easy to pick up for most web developers.

Also, being able to create directives in AngularJS and dependency injection makes it easy to create components that can be shared easily between developers and really has excited the developer community.  Lots of existing projects have developed AngularJS directive bridge libraries so you can use their code by tossing an AngularJS directive to decorate an existing element with new functionality.  Like Select2, Infinite Scroller, Bootstrap, and Angular has its own UI companion suite.  Just check out http://ngmodules.org/.

7. Allow you to become proficient in a reasonable time

It took me around 2 full weeks to feel like I was proficient, where I was starting to pick out and understand best practices and look at some of the finer points of the framework.  Where I started from is that I have a lot of experience developing with Javascript, jQuery, jQuery UI, and also implemented a project using Backbone.js earlier this year which is one of the other Javascript frameworks built to solve a similar type of solution as AngularJS.  I felt like knowing how Backbone.js works helped a lot with picking up AngularJS.

18 Questions to Ask Before Adding New Tech to your Web App

Adding a new piece of technology to your web application is not a consideration to take lightly.  There are a lot of factors to consider that can slow down or doom a project if the proper evaluation is not given up front.  In the end, you want the long term benefit to be worth it, but not derail any short term milestones.

And when I say technology, I mean a framework, library, automation tool.  Whatever the type, I use it to encompass anything that you might be considering adding into the technology stack that is new to your web application.  This most often involves something you’ve only read or heard about, or maybe only worked through a tutorial.  This is a case where there is a large unknown component to the technology you want to add.

When evaluating adding any new piece of technology to your web development project, use the criteria below to help you make your decision.

Does the new technology ______:

1. Address some problems in your software architecture

If you have some software design problems that you consistently struggle with given the tools , libraries, frameworks that you currently use, and this new framework will solve that for you then go for it.  If you are just adding this new framework only to learn it, and it doesn’t add value to your product or software process, then go pick something else to learn that does add some value.

2. Allow you to become proficient in a reasonable time

Depending on the time frame that you have within your development cycle, you may not have a lot of time that can be considered R&D time to learn a new framework.  A new framework should not require a year to become proficient at, that is a lifetime in the development world.  This is also another reason why the skill level of you and your team should be considered.  Master some core technologies first before you start learning something new.  You can always get stuff done with the other languages and frameworks that you already know if you have to, then refactor later.

3. Enable you to create software more quickly and with less effort

Anything that improves your efficiency is something to invest time in.  Always strive to do more with less code.

4. Result in software that is more maintainable

If the new framework best practices result in software that is more maintainable, then in the long run that will pay off.  Your product will be easier to add new features to and be able to be picked up by other developers easier.

5. Result in software that can better adapt to changes

If you have a problem with handling growing complexity without big rewrites and lots of bugs introduced, then integrating a piece of technology that adds to that is going to make things better, it’ll add to your problems.  If on the other hand, using the framework allows for better overall design and encourages solid, maybe even SOLID, design principles, then your software project will be better off.

6. Improve the testability of your software

If testable code is important to you, and it should be, then you should always weigh the impact that adding a new framework has on your ability to test.  One clue to look at is also how the framework tests itself?  That can tell you how much importance it places on testability.

7. Have no significant degradation in performance

If your software designs have problems with performance, and it is really important to your product, then a new framework should be providing a lot of benefits without significantly impacting your software’s performance.  Most of the time, because a framework adds flexibility and adds a layer on top of your existing stack, it often will decrease the performance compared to well-designed code in current tool sets.  The opposite would be writing absolutely optimized custom code for every interaction, but that’s a tradeoff with speed of development and maintainability.  I always opt towards speed of development and functionality first, then look at performance later.  If you know ahead of time performance is valued highly in the product, then make sure you at least have a plan to optimize performance if and when issues come up.

8. Encourage good programming practices

A good framework that you add should be using design patterns that encourage you to write good quality code.  The effort to write good code should be no more than writing bad code so you have no reason to not just write good code using best practices at the start.

9. Have good support by its creators

Sometimes the creators are commercial, sometimes it is open source, sometimes it is a combination where it is open source contributors that are employed by a big commercial company.  Either way, I consider support being the same as documentation, so how well does the project itself keep up with changes in its development with the corresponding documentation.  Checking commit history looking for a variety of committers over a long period of time also helps grow confidence in the project that something that changes in the core developer’s lives or career, or the company’s finances, won’t derail the project.

10. Have good support by its users

Where does the user community get support? These are the same channels you will use to learn and help figure out best practices.  Looking on Stack Overflow to see how many questions are being asked and how well they are being answered is a good gauge (lookup questions using Tags).  Also, seeing what conferences exist and what other companies are using the project helps.  Having someone you have a personal relationship with that has experience and that is willing to help answer some questions is also a plus.

11. Have a good chance to be actively maintained during the useful lifetime of your design

This is something that depends on your product life cycle, if you most likely redesign your product every 3 years, then only has to exist for that long.  If you have to distribute software for a hospital, useful lifetime might be 10 years, so are you confident the new piece of technology will be maintained, updated, and still valid that far in the future?

12. Currently in a state where it is complete and functional

If still in a state of flux, with lots of API changes, or bugs being introduced, it’s not worth using it in your product because you will be constantly working around bugs or wasting time debugging.  Unless you like that sort of thing.  Harder to do if you are working on a product because you are contributing to someone else’s code.

13. Change not too quickly

Will new releases be completely breaking old ones.  If a project is iterating quickly, and your software relies on stable code with infrequent releases, this may not fit into your project well.

14. Allow you to collaborate more easily with other people

If the framework you are adding is not very popular, or not well documented, then if you work on a team with others, it may be frustrating for them to work alongside you.  Also may be hard to find contractors who know the framework.  Ideally you should have the ability to share components you made with the public, or to get them on github or other sources.

15. Minimize complexity added to environment setup for developers and production servers

Does the framework add any complicated steps to the build or test process that will not be able to be automated.  Also, consider the impact on developers setting up a local environment, which is important to truly distributed collaborative work.  Sometimes unavoidable depending on role of the framework.

16. Cost should not be prohibitive

Sometimes the costs are direct, like you have to pay for a license.  Sometimes the costs are secondary, for example, what if a new framework requires a lot more memory usage on your web server, so you have to upgrade your server’s RAM costing you X/month.

17. Have only reasonable requirements to be brought into your product

If a framework has a lot of requirements, need to evaluate their impact too.  Might not be a big deal if you never directly use the required projects and they are abstracted when you use the framework.  But maybe some of them are exposed and new things you have to learn.  

18. Have a software license compatible with your product

Have a commercial product?  Make sure the license allows you to sell online, distribute, or sell a subscription to your product, whichever applies depends of course on your monetization strategy.
 

AngularJS Directive Best Practices

Using directives in AngularJS is one of the great features added to tie complicated javascript functionality and client-side templating to your HTML app in a way that allows for re-use and maintainable code.

You can think of a directive as an extension of HTML so that you can create your own elements and attributes.

Just like when you use a “<select>” element, you expect to see an element that you can click on and will drop down to have a list of items, and you expect to be able to click one and have that one show up as the “selected” one.  Where a HTML element implies certain functionality, a directive allows us to create our own display elements and/or functionality that can be used as new elements or to extend existing elements.

I’ll use the example of a basketball team where we have many basketball players making up a basketball team.  Wouldn’t it be nice if in your HTML you could write this to display a basketball player in HTML?

<basketball-player></basketball-player>

As you might expect to see in HTML, this would output a basketball player with a few fields like name, number, position, and some stats like points and assists.  To accomplish this, it would take a combination of several HTML elements, including <div>, <span>, and maybe an <input> if we wanted to change the number of points and assists in a scorebook type of app.

Here is a link to a plunker showing an example of how to create your own custom directive to do this:
http://plnkr.co/edit/BaR0ua?p=preview

The basketballPlayer directive is associated with a template file that is HTML with some AngularJS template markup within.

Take a look at how I implemented the capability to change the points using an input field.  I can use a directive as an attribute, called ng-model, which is one of the directives provided by AngularJS core. That’s right, many core AngularJS features are directives themselves, a directive can be an element name or an attribute.  This is why understanding directives is one of the most important things to learn and understand when learning AngularJS.

As with any technology, there are many ways to approach a solution, and creating directives is no exception. We have some choices to evaluate, a few things to consider include:

  • Using Attribute vs. Element
  • Using proper HTML5/XHTML5 markup
  • Scope considerations for reusable code


Using the element name

<basketball-player></basketball-player>

may seem like a really cool feature of AngularJS and a huge readability improvement to someone going through source code.  However, this has no chance of validating as proper HTML5.

Even though it is not proper HTML5, this is the preferred way to use a directive that adds new markup to your app.  Another wise suggestion is to use a prefix (think namespace) for your directives that you use as an element name, which is mainly a future-proofing in case an HTML element comes out that has the same name someday.  Like maybe you were thinking of:

<multiselect>

But what if an upcoming version of HTML5 adds a special multiselect tag and all of the sudden your app breaks.  A suggestion is to use:

<myapp-multiselect>

That way you know for sure it’ll be OK in the future.

But something like:

<basketball-player>

I’m pretty sure the chance of that being used in a future release of HTML is none.

Having an element name work as a directive is not enabled by default, you need to explicitly allow for it in your javascript code, I keep all my directives in a directives.js file:

var myDirectives = angular.module('myDirectives', []);

myDirectives.directive('basketballPlayer', function() {
  return {
    restrict: 'AE',
    templateUrl: 'bball-player-template.html'
  };
});

The restrict property has an A for Attribute, and an E for Element.  The default, if you don’t specify a restrict property, is A, which means it’s only enabled for Attributes.

Notice the name of the directive is “basketballPlayer” but I called the element “<basketball-player>”.  This is an automatic conversion from camel case to lower case with dashes splitting words, it’s an AngularJS thing that you can’t control.  There are lots of possible options that it gets converted into that are valid that allow you to use it in several ways, some help you out with HTML validation.

If you are concerned about HTML validation, you can write it also as an attribute:

<div data-basketball-player>

If you are not familiar with the special attribute prefix of “data-“, this is a special name and is allowed within HTML, any attributes with a prefix of “data-“ are ignored and allowed to be custom attributes.  The attribute-based syntax is equivalent to <basketball-player>.

This format is valid HTML5, but if you want to step up to XHTML5 we’re not quite OK yet.  Attributes are required to have a value in XHTML5, so most correctly:

<div data-basketball-player=“argument”>

Even if you don’t have an argument, it’s appropriate to give it a value, recall from plain old HTML:

<select>
  <option value=“1” selected>My selected option</option>
  <option value=“2”>Not selected option</option>
</select>

Notice the selected doesn’t have an = sign behind it.  This is called Attribute Minification.
This is allowed in HTML5, but is not proper XHTML5.  So again, this is up to you and how strict you want to be.  The proper XHTML5 form for this select element is:

<select>
  <option value=“1” selected=“selected”>My selected option</option>
  <option value=“2”>Not selected option</option>
</select>

While I like being strict, I think it’s silly to write selected=“selected” so I opt for not following XHTML5 if that choice is up to me.

Within AngularJS, when you create a directive, it requires a small amount of javascript and a corresponding template.  You can determine whether the directive name you have chosen is allowed to be included in the code as an element or as an attribute, or both.  The default is to only allow it as an attribute.  This is the way I prefer, I like being able to run my HTML code through a validator and have it pass.  This is determined by the restrict property of the directive as mentioned earlier in this article.

The AngularJS docs suggest that you use an element when you are creating a component that is in control of the template.  Typical situation for this is in some domain-specific code.  They suggest you use an attribute when you are decorating an existing element.

In the real world, when looking at documentation online, and help from Stack Overflow and other sites, you will almost always see developers using the most condensed form, using element names and attribute minification.  Some of this is because they are trying to communicate a solution in the simplest manner, but I also suspect this is what most are using within their apps.

In my own code, I like using HTML5 validation because it helps me check out all my HTML to make sure I didn’t miss a close or open tag, but I don’t typically go so far as requiring XHTML5 validation.

Scope considerations for reusable code

You have the option with a directive to isolate the scope, which means to access any variables inside your directive’s template, you need to pass it into the template, using an attribute.

Here is an example of the same code from above in a new plunker showing isolate scope:
http://plnkr.co/edit/S441rN?p=preview

Notice that the directive now includes an additional attribute:

<basketball-player player=“basketballPlayer"></basketball-player>

And the directive code says to grab a player directive:

myDirectives.directive('basketballPlayer', function() {
  return {
    restrict: 'AE',
    scope: {
      player: '='
    },
    templateUrl: 'bball-player-template.html'
  };
});

The = sign says to also assign player attribute to the variable of the same name so inside the template, you use player as the variable name, as you can see in the bball-player-template.html file:

<div class="basketball-player">
  <div>Name: {{player.name}}</div>
  <div>Number: {{player.number}}</div>
  <div>Position: {{player.position}}</div>
  <div>Points: <input type="text" ng-model="player.points"/></div>
  <div>Assists: <input type="text" ng-model="player.assists"/></div>
</div>

If you need to have some two-way data binding inside of your directive, then there are some situations when you cannot isolate scope.  You can isolate scope and still two-way data-bind when you are only binding to objects, but not primitives.  It’s tricky, so keep it in mind as you design your app.

Isolating scope is a really good thing, much cleaner, and leads to decoupled code, passing in the objects you need from the outside and nothing more.  So if you do need to two-way data-bind inside your directive, consider tossing your variables into an object and passing that to your directive so you can still isolate scope.


For some good reading about isolate scope and how it all works along with no scope isolation and the transclude option, check out this stack overflow question:
Confused about Angularjs transcluded and isolate scopes & bindings

AngularJS Directive Best Practice Guidelines

  1. Use your directive as an element name instead of attribute when you are in control of the template
  2. Use your directive as an attribute instead of element name when you are adding functionality to an existing element
  3. If you do use a directive as an element, add a prefix to all elements to avoid naming conflicts with future HTML5 and possible integrations with other libraries.
  4. If HTML5 validation is a requirement, you’ll be forced to use all directives as attributes with a prefix of “data-“.
  5. If XHTML5 validation is a requirement, same rules as HTML5 validation except need to add “=“ and a value onto the end of attributes.
  6. Use isolate scope where possible, but do not feel defeated if you can’t isolate the scope because of the need to two-way data-bind to an outside scope.

Drupal Performance Tuning Presentation Slides From Boise Code Camp 2013

As requested and promised, here are the slides from my Drupal Performance Tuning presentation at Boise Code Camp 2013.

Definitely appreciated all of the questions and great discussions and ideas from everyone in the presentation. Hope that everybody learned something to take back and solve any Drupal performance problems that you have.

Drupal Performance Tuning Presentation Slides

10 Ways to Improve Drupal 7 Performance on Shared Web Hosting

When you look to improve performance of your Drupal 7 site when it is on a shared web hosting plan, you are limited in options due to the nature of shared hosting.  Many of the performance optimization options you would have if you were on a Virtual Private Server (VPS) or on your own dedicated hosting box are not available.

Some of the reasons why you are limited in a shared web hosting plan:

  • No configuring the web server software
  • No configuring the relational DB
  • No extra services like APC (Alternative PHP Cache) or Memcached that allow you fetch objects from fast memory instead of slow hard disks
  • No consistency with service, you are sharing with lots of people so you typically don't have dedicated hardware resources for running your site
  • No easy path to upgrade hardware resources within shared hosting, typically need to move to a different service like a VPS or dedicated hosting as next step

Yes, these are pretty limiting, and if you can afford it, I definitely recommend going with at least a VPS if your web presence is a large part of your business.  However, if you just have a blog or a brochure-type site, shared hosting can be just fine.  I've tested out several shared web hosting setups and my current recommendation is Site5's Shared Cloud Hosting plan for $20/month, I have several clients running Drupal sites on that.  For myself, I currently am running my Drupal sites using VPS servers from mainly Linode, but also Amazon EC2.

With all these limitations, you still have a lot you can do to performance tune your Drupal site on shared web hosting plans.  The options below are listed in order of the amount of performance impact for the implementation time they typically have on a shared hosting Drupal site.

1) Turn Page Caching On

What page caching does is that instead of using a bunch of database queries to get the data used in making a typical web page, the rendered contents of the web page are stored in a separate database cache table so that it can be recalled quicker.  If you have 10 people visiting the site from different computers, Drupal first looks into the database cache table to see if the page is there, if it is, it just gives them the page.  Think of saving the output of 50 separate queries so that is accessible with a single query.  You obviously are reducing the SQL queries required by a lot.  What the page cache table actually stores is HTML content.

One gotcha with this Page Caching is that it only works to optimize the page load time for Anonymous users.  This is because when you are logged in, you might have blocks that show up on the page that are customized for you, if it served everybody the same page, they would see your customized information (think of a My Recent Posts block), so Drupal does not use the Page Cache for Authenticated users automatically.  This allows you to turn Page Caching on and still get the benefit for Anonymous user page load times, but does not break the site for Authenticated users.  There are other caching options that will help with Authenticated user page performance, we will talk about those later.

To enable Page Caching, you go to Configuration | Development and select the checkbox next to "Cache pages for anonymous users".  See screenshot:

An alternative to the page caching built into Drupal 7 is to use Boost to cache your pages as static HTML files instead of in the database, which can be served very efficiently especially in shared hosting environments.  If you use Boost, you would not want the Drupal page caching enabled like mentioned above.  Boost would be a preferred option except for the fact that currently, Boost is still in beta for Drupal 7 even though Drupal 7 has been out for quite a while, and I don't often recommend using beta modules unless you have tested them thoroughly.  Also, like the Drupal page caching, this still only works for Anonymous users.

2) Aggregate and Compress CSS Files

Drupal is very flexible, but with all that flexibility, you will have some performance tradeoffs.  One of the ways these tradeoffs are easy to see is in the number of CSS files you see loaded in each Drupal page.  There can be 30 or more CSS files even for pretty basic Drupal sites, the reason for this is that Drupal operates using modules, and whenever a module has some CSS files that it wants to add, it is a separate file.  Your theme is also going to provide several CSS files.

This can cause performance problems because you have to make 30 separate requests to the web server, one for each file.  We would like to reduce the number of requests to the web server as a general rule of web performance optimization.

So by enabling "Aggregate and compress CSS files", Drupal will take your CSS files and reduce the number of them and size of them.  The Aggregate part of that is that instead of having 30 separate files, Drupal will concatenate all the files together and separate them into just a few files.  It doesn't reduce them to 1, but reduces it down to 8 files or so.  The Compression part of that setting will remove all whitespace in the CSS files, those whitespaces each contribute to the size but have no functional purpose.  So this setting reduces the number and total size, which will increase the speed of loading CSS.

3) Aggregate JS

Just like Aggregate and Compress CSS files, you can aggregate Javascript files with this setting.  For the same reason why there are many CSS files, there can be many JS files, each module can provide one or many of its own Javascript files.  Aggregation reduces the number of files down to around 8.  So by Aggregating both CSS and Javascript files, you can reduce the requests from 60+ to less than 20, this can help to deal with the shared resources so you can get as much from the server with each request as possible.

For items 2), and 3), the Settings can be enabled in Drupal 7 on the Configuration | Development | Performance age, you see the Bandwidth Optimization section by checking all three checkboxes:

4) Turn Views caching on

As mentioned when talking about Page Caching only working for anonymous users above, there are other caching options for helping with Authenticated user page performance.  One of those options is to turn on caching for blocks and pages that you create using the Views module.  This allows you to cache the output of the query used to generate the view, or the end HTML output of your View, and you can tune the cache for them separately.  And realize too that this means you can cache portions of a page if you are using one or several Views blocks in the page, it will just cache that block in the page, not the whole page.

You can find the settings for caching a View when you are in the Views UI and edit your view, then under Advanced | Other | Caching after you click Time-based to enable caching, you can see the settings below where you can specify the maximum age of a cached query or page:

The way that specifying the maximum age works is that when the cached copy is stored in the database, every time that a user visits the page with the View in it, it will check to see if the cached copy is too old and will fetch a fresh copy if it is expired.  This is the nature of caching, you have to determine for the typical use of your site what kind of cache usage you can have.  If changes are made to your site infrequently, then the cache doesn't have to be cleared often.  If changes are made often, it may be best to keep the maximum age times pretty low so that people see a View that represents the actual contents of the site that will be out of date by no more than 1 hour (using the settings above as an example).

The difference between caching the Query results and the Rendered output applies more when you are doing some Theme altering, you may not want to cache the rendered output, but could instead just cache the query results.  The Rendered output is achieved using the Query results, so you can likely save a bulk of the time using Query results alone.  Bottom line, if you can use Rendered output caching, it will give you the best caching results.

5) Turn block caching on

This is another type of caching to help out with Authenticated user performance.  This will cache individual blocks, not pages, but since many blocks can be used to build up a page, doing block caching can still be a significant performance improvement.  This block caching is not the same as caching a Views block, in fact, it does not apply to Views blocks.  This block caching only applies to custom blocks that you create, or blocks that modules provide.  Modules themselves provide what type of caching is allowed for blocks to help do it appropriately, as some blocks should be cached per user, some cached per role, all meaning that for a single role, a block might be the same for all users in that role, etc.

To enable Block Caching, you go to Configuration | Development and select the checkbox next to "Cache blocks". See screenshot:

To read in a little more detail about caching, see my article on Improving the Performance of Drupal's Initial Page Request.

6) Disable Modules You Are Not Using

Having unused modules that are enabled adds to overhead for additional PHP code to execute on each page load, extra CSS and Javascript files included with each page load, even if you are not using the module for anything.

Going one step further, if you have a module that you are only using one small part of, and can achieve the same results using another method utilizing an existing module or another method in core Drupal, then that's always a good idea for optimizing performance.

7) Move Images, Videos, and Static Files to a CDN (Content Delivery Network)

 

Offloading static files to another server is a way to conserve resources on your shared hosting.  This helps with avoiding disk I/O and reduces the number of requests that your shared hosting has to handle.  One common strategy is to use a CDN (content delivery network) to host some of your static files, with images and videos being one of the easiest ways to implement this, especially if they are a part of your theme.

Since web browsers restrict the number of requests a single domain name can handle in parallel at any given moment to 4-6, if you move some of your assets to another domain, you can request another 4-6 in parallel from that domain, so it can increase speed in yet another way.  Always a good idea if you can afford it, as CDN's usually do cost a little bit of money, the most common as of today is Amazon S3.  The cost can be really small though, like less than $5/month, check out the Amazon S3 price calculators to make sure you understand what costs you might have.

To enable this a little easier, there is a AmazonS3 module for Drupal to move the file system to S3 on Drupal 7, and other modules like the Video module integrate with the AmazonS3 module to allow videos to be auto-stored for you.

8) Implement Caching in Your Own Modules

If you are running a Drupal site where you have created your own modules, make sure to implement caching so you can take advantage of the caching system Drupal has in place.  If your module will be caching a lot of different types of data, consider creating your own caching table, then you can control the maintenance of that cache table easier.  Also helps if at some point in the future you move onto a non-shared hosting system where you can take your own caching tables and move them to use memcached, but leave the other cache types to use the database cache table.

A good overview of how to include caching in your own modules is here: Beginners Guide to Caching Data in Drupal 7

9) Make Sure Your Own Modules Use Indexes Properly

If you have database queries in modules that you have developed yourself, verify that you have set up indexes properly to help those queries execute efficiently.  You can use the EXPLAIN command in MySQL to see if your query is using an index, and how it is using that index.  It's very helpful to use the Drupal Devel module to figure out which database queries are taking a long time.  Indexes are one thing that you can control in a MySQL database even when you are on a shared hosting platform.  I show the basics of using Devel in my article on Improving the Performance of Drupal's Initial Page Request.

10) Reduce Image Sizes and Number of Images

Reducing image sizes and/or number of images works to improve performance in a similar way as the CSS and JS aggregation did, you are reducing the number of requests to the server, and reducing the overall size that needs to be transferred from the server to your user's computer.

You can always work on reducing the size of images that you have by using different levels of compression.  You can use software tools to try and compress pngs, or just use settings when you save an image within Photoshop for JPEG images, or you can try some advanced techniques that I've used before at Smashing Magazine about Clever PNG Optimization Techniques.

Reducing the number of images can be accomplished by using CSS image sprites to combine multiple images into a single image.  This works especially well if you are using images as backgrounds for hover/active states for tabs or buttons.

Pages

Subscribe to Front page feed