Kategoriarkiv: jQuery

Improving the web performance of an intranet

overloaded-sharepoint-in-browser

All the “small” app parts, web parts, delegate controls, user controls, and other “packages” that “must” be delivered to the users on every page load of the Start Page of your Intranet.

Recently we made an investment to improve the performance of our intranet. We made many changes in different layers: SQL, Network, Browser upgrade and code. Here I want to tell about what code changes we did to improve the web browser performance. Please leave feedback if you find it useful. You can also share your suggestions. We measured the performance before our code changes and after them. We had amazing results. Unfortunately I can not share any numbers, but we improved the Time to First Byte, time to load event firing in the browser, memory consumption in the clients and, perhaps, the most important, we improved the perceived performance of the Intranet, the way how users experience the speed and UI responsiveness. To do this I got many ideas of my project colleagues and branch colleagues. Here is the list of changes we’ve implemented:

– Execute code on demand

Consider this scenario: on a page users can click on a button to download a vcard. Aggregating user information is a costly operation that requires getting data from the User Profile Service, getting the profile image from SharePoint. Don’t ever do this operation on page load. Move the code to the “onclick” action. In other words, work when it is needed. It is like cooking a lot of food, when you are not hungry. It is nothing new, unfortunately there were a couple of the “eager code” places.

– Cache results, investigate what parts can be cached and how fresh data needs to be

All data on your page doesn’t need to be fetched on every page load. In our project We listed all the “parts” of the start page and other often visited pages and went to the business and asked them to evaluate how fresh data should be. Some parts should be as fresh as possible (no cache), whereas it would be tolerated that the information could be dirty (cache up to one week or more).

– Reference javascript and css files from one location

Do you have jQuery in your SharePoint Intranet. How many copies do you have? What we did in our Intranet was that we partially implemented the CDN concept. Even though we don’t distribute our resource files geographically, we have 1-to-1 relation between a file and its absolute URL. In the whole intranet, we have only one jQuery url and only one our intranet.core.js url. We did by creating a dedicated CDN site collection. This alone makes a big difference. To evolve the idea we could provision resources outside SharePoint to remove the authorization overhead. We could also distribute it geographically by having files closer to the end users.

– Unify your framework and your dependencies

In our projects we had a couple of SharePoint-hosted apps developed by different teams. We had different approaches and different framework that solved almost the same problem: AngularJS and KnockoutJS. Eventhough apps are independent pieces of software, they were used within the same page (as app parts). It was too much http traffic. We agreed on Developer Guidelines and chose one framework.

– Do not hide controls on the page with CSS, remove them

On the start page in our intranet we didn’t show the left navigation, but it was still rendered in code behind. Instead hiding it with CSS, we just removed it by an empty ContenPlaceHolder in our Start Page Layout:

– Optimize jQuery Selectors

We reviewed all the jQuery code and improved the selectors. Optimizing the selectors will improve the overall performance in the browser, especially in older browsers. The worst example is using text selectors, like this one:

It will sink your IE8 browser.

– Minify javascript and CSS files

Minifying resource files like javascript and css is not hard. My recommendation is to use Web Essentials plugin in Visual Studio. Alternatively you can use the SharePoint Assets Minifier.

– Use the weakest selectors in CSS and in LESS

In our project we are using LESS. With LESS it is easier to write  readable CSS code. But be aware of the output. Do not make the selectors too strong: Use the weakest CSS Selectors. The weakest selectors will make it easier to maintain the CSS and it will minimize the amount of KB the server needs to send to your users’ browsers.

– Ensure javascript and CSS files are cached

JavaScript and CSS files should be cached. You should also avoid 304 responses where the Server answers “Not Modified”, because this has an impact on the performance. Configure the Blob Cache and put your resources into the Style Library.

– Remove all app parts from SharePoint-hosted Apps from the start page

There can be exceptions, but we encountered that client web parts (app parts) from SharePoint-hosted apps had a huge impact on the performance. The combination of a couple of app parts on often visited pages (like the start page on the intranet) led to long page load times. These are the reasons why you should not have SharePoint Hosted App Parts on your start page:

  1. App Parts are iframes. They are loaded simultaneously if you add client web parts (app parts) in a usual way. They hold up the whole page. Users cannot interact with the intranet page until all the content in all app parts has been loaded. This can be partially improved if you introduce a delay in the app part loading, by developing an own engine. See my blog post where I mention such a concept: AppLoader Concept for SharePoint apps.
  2. The content from a SharePoint AppWeb is not fully cached. If you examine the http traffic from the apps you’ll see a lot of 304 responses, meaning the browser requests when the server answers that there is no newer version. This has an impact on the performance. See more in Alik Levin’s blog: ASP.NET Performance: Get Rid of HTTP 401 and HTTP 304. In a SharePoint-hosted app you don’t have any control what so ever to adjust the the cache settings. This is not the case in the Provider-hosted apps.
  3. SharePoint-hosted apps can only use javascript. The code is executed on the client. Older browsers like IE9 or IE8 render the pages slower. The Start Page that is slower than the rest of the Intranet is not something that will engage your users.
  4. App Parts are iframes that do not know about their dimensions. App parts often need to update the height and the width  of the parent iframe. This causes irritating flickering. Perhaps OK on some pages, but I’d say totally unacceptable on the start page of your brand new intranet..

What did we do instead of App Parts on the Start Page? We converted them into Script Editor Web Parts, the app parts were only one-time parts, they only were used on the start page.

Do not get me wrong. What we did was not abandoning apps as a model, we just removed wrong apps, apps that cannot be reused, the SharePoint-hosted apps that had big performance issues. I am looking forward creating right apps, that are written with performance, reusability, scalability and good design in mind.

 

Count lines of code with PowerShell

Today I got a question:

How many lines of code are there in our SharePoint solution?

After a little search, I found that PowerShell is really a nice tool to count lines of code:

I wanted to count lines for different types of code:

  1. Code Behind written in C#, the files have .cs file extension
  2. JavaScript code (except jQuery, angular or knockout frameworks)
  3. PowerShell files (.ps1 and psm1)
  4. Xml files (all the SharePoint .xml files)

Here is the powershell code that counts lines of code:

# go to the solution folder
cd <solution directory>

#count lines in .cs files
ls -include *.cs -recurse | select-string . | measure | select count

#count lines in our .js files
ls -include *.js -recurse `
    -exclude *min.js, jquery*, _*, jsrender*, CamlBuilder*, knockout* `
  | select-string . `
  | measure `
  | select Count

#count lines in our powershell scripts
ls -include *.xml -recurse | select-string . | measure | select count

#count lines in our powershell scripts
ls -include *.ps1, *.psm1 -recurse | select-string . | measure | select count

Just a curious fact, I can’t tell you how many lines of code we have in our solution, but I can reveal the proportions. If I used the flexible box model in css3, it would look like this:

lines of code

There are as many lines of code written in javascript as it is in C#. The main reason that for the big js code base are the SharePoint hosted apps. The PowerShell scripts are as big the javascript code base. Xml files are 4 times bigger than C# code, and it is even bigger than the sum of all lines of code written in C#, JavaScript and PowerShell. It isn’t strange that xml is dominating, almost everything in SharePoint is defined in xml.

Fortunately, there are less cases where you have to write raw xml in Visual Studio 2012/2013 and SharePoint 2013.

How does it look in your project? What language is dominating in your SharePoint project?

Debugging OOB SharePoint. Unable to post comments on SharePoint blogs (SP2013 June CU)

I have had a strange bug. The comment text box in a OOB SharePoint 2013 blog doesn’t appear. It only says: “There are no comments for this post.” In this blog post I’ll tell you how I found the bug and I’ll show you how you can temporarily bring the commenting to life.

comments-not-working-001

I have had luck. While it doesn’t work on the Test Environment, it does actually work on my development machine. The comments text box is rendered as an OnPostRender action in the blog comments display template. After debugging the javascript in hours and comparing the two environments, I just could confirm that displaytemplates are the same. There are two main javascript files that are involved:

  • clienttemplates.js
  • sp.ui.blogs.js

So it must some differences elsewhere. The build versions of the environments are

  • Working Environment:  15.0.4420.1017 (SharePoint 2013 RTM)
  • Not-working Environment: 15.0.4517.1005 (SharePoint 2013 June CU)

No errors are thrown, even on the blog where it doesn’t work. It is because of the permissive try-catch in this function that wraps rendering of the comment text box:

This is where the error occurs but doesn’t appear in the script console. Here is the error:

What? jQuery error? Why?

It turns out that jQuery is used to get the html element for the comments area in the server with June CU, but not in the Server with SharePoint 2013 RTM.

To get the reference to the comments area, it invokes the $get method, which invokes Sys.get which in some cases invokes the jQuery (if present)

$get implementation in SP 2013 June CU

These are the functions which can be found in the SharePoint 2013 June CU (15.0.4517.1005)

 

 

older (but working) $get implementation in SharePoint 2013 RTM

These are two versions which can be found in the older SharePoint Release: RTM (15.0.4420.1017)

It doesn’t even go to Sys.get and doesn’t even try to use jQuery.

The id of the comment are is a combination of two guids and -CommentContainer. jQuery fails to select an element with this id:
This error happens when you try to select this html element with jQuery in the web console:

comments-not-working-002

Temporary solution

The solution is to prevent using jQuery for this element selection. Hopefully new updates of SharePoint will address this issue. Until then we have to tweak the $get method. To do it very carefully, we can copy the old $get function and call it $get_asFoundInRTM and copy the new $get and call it $get_asFoundInJuneCU

The $get function has to rewritten like that:

This javascript code has to be loaded after two ScriptResource.axd files. Please be very careful if you have to implement this temporary fix. Probably it is better to wait for an official Microsoft bug fix.

Flattening Callbacks Using Promises

Lately I’ve been working on some async heavy client side code and saw it as a great opportunity to get acquainted with Promises. The project I work on already has jQuery which includes an implementation and so it became the obvious choice.

The simplest and initially most convincing use case is that of flattening deeply nested callback “stairs”.

Before we get into it, is this even a problem? I’d have to argue yes. First of all, error management is just about impossible since none of the asynchronous methods ever throw an exception, only the callbacks have exceptions, and that’s only after the original context is out of scope. Catching these exceptions is nigh on impossible without leaking much of the abstractions. Callbacks break the natural exception bubbling concept. As I write this article a post on the dangers of callbacks is featuring on Hacker News, I suggest reading it for more information.

To solve this problem, much of the async code in NodeJS libraries instead use a primary error parameter on callbacks.

This only complicates the code, adding manual error management in three distinct places. Let’s see what it would look like if the functions, instead of taking callbacks, would return promises.

Take a moment to look at that. If you’re new to deferred objects and promises, you’re probably not convinced. It takes some getting used to so let’s walk through it. Right off the bat you can see there is no longer an error parameter, and no need to check for it. Instead we hand handleError as a secondary callback to then. We have succesfully removed a significant source of distraction in the code. In the traditional NodeJS style code above we had to mix error handling into our function specific code. Even worse, we had to write this over and over again! if (error) does not belong there. Especially since the function that takes the callback has already done error management and passed us the potential failure, forcing us to write error checking again, violating “Don’t Repeat Yourself”.

But there are still improvements to be made! The sharp eyed will notice that several of our anonymous functions add no actual value. We can rewrite it to be even simpler.

Apart from dropping the anonymous functions, we now only pass the error handling in the last call to then. This is not a typo. One of the greatest things about promises is that they recover the effect of exception bubbling (or something quite like it). In the case of jQuery deferreds, at least the rejected promise will bubble and reject subsequent promises. This essentially means that if the first promise is rejected, all following promises are rejected too. Not only that, they are rejected with the original reason. Errors are thus preserved all the way to the end of the chain.

Conclusion

As you can see, promises are a reasonably simple thing to use. We went from an unsightly mess of callbacks with no error management to a resonably flat and surprisingly readable error managed alternative. Reading it out loud actually explains it reasonably well: get the username, then get the subscribed categories, then get the suggested articles and then print them. If something goes wrong, handle it. We’ve written something that mimics synchronous code, which makes it much easier to reason about its behavior.

jQuery’s implementation of promises is not the ideal example of the Promises/A+ specification but usable nonetheless. If you are interested in alternatives, take a look at Kris Kowal’s Q.js, which does handle exceptions.

As always, if you have any thoughts, ideas or comments, please don’t hesitate to email me at .