Improving the performance of Nextcloud

Posted:

I’ve recently started using Nextcloud, a powerful open-source PHP file manager. It works really well and there are many plugins which allow for extra functionality to be added, including support for external storage via Amazon S3 and more.

Nextcloud

A freshly installed Nextcloud site can be a bit slow though as all files are served locally so performance is impacted - especially if you’re on a server without HTTP/2. I decided to do some digging to see if I could improve the performance.

Serving Font from Google’s CDN

Nextcloud uses a locally served ‘Open Sans’ font only in WOFF file format. By using Google’s CDN instead we can take advantage of the smaller and faster loading WOFF2 file format as well as a longer cache life. To do this simply add:

<link href='https://fonts.gstatic.com' rel='preconnect' crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600">

to the following three files just below the <?php emit_css_loading_tags($_); ?>:

/core/templates/layout.base.php
/core/templates/layout.guest.php
/core/templates/layout.user.php

Serving Third-Party Scripts from a CDN

Nextcloud loads a huge number of JavaScripts which really slows down page load speeds (unless you’re on HTTP/2). There’s a vendor/core.js file which contains all the third-party plugins and is just over 1 MB and includes 16 scripts (of which 7 of them are unminified):

"jquery/dist/jquery.min.js",
"jquery-migrate/jquery-migrate.min.js",
"jquery-ui/ui/minified/jquery-ui.custom.min.js",
"underscore/underscore.js",
"moment/min/moment-with-locales.min.js",
"handlebars/handlebars.min.js",
"blueimp-md5/js/md5.min.js",
"bootstrap/js/tooltip.js",
"backbone/backbone.js",
"es6-promise/dist/es6-promise.js",
"davclient.js/lib/client.js",
"clipboard/dist/clipboard.min.js",
"autosize/dist/autosize.min.js",
"DOMPurify/dist/purify.min.js",
"snapjs/dist/latest/snap.js",
"select2/select2.js"

I decided to remove the contents of vendor/core.js (so it’s 0 KB) and then add the following:

<script defer src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script defer src="https://code.jquery.com/jquery-migrate-1.4.0.min.js"></script>
<script defer src="https://code.jquery.com/ui/1.10.0/jquery-ui.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.7.0/js/md5.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/gh/twbs/bootstrap@3.3.7/js/tooltip.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.3/backbone-min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/2.3.0/es6-promise.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/gh/owncloud/davclient.js@0.1.2/lib/client.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.6.1/clipboard.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/autosize.js/3.0.20/autosize.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/1.0.3/purify.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/gh/jakiestfu/snap.js@2.0.0-rc1/dist/2.0.0-rc1/snap.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.4.8/select2.min.js"></script>

to the following files - in place of <?php emit_script_loading_tags($_); ?> and just below the <?php emit_css_loading_tags($_); ?>:

/core/templates/layout.base.php
/core/templates/layout.guest.php
/core/templates/layout.user.php

This dramatically improved the first page load speed.

Adjusting the Content Security Policy

It’s important that you adjust the Content Security Policy (CSP) to whitelist assets being loaded from cdn.jsdelivr.net, cdnjs.cloudflare.com, code.jquery.com, fonts.gstatic.com and fonts.googleapis.com otherwise they won’t load.

Summary

By serving assets from a CDN you can greatly improve the load speed of Nextcloud by taking advantage of smaller file sizes (as all scripts are minified), longer cache life and domain sharding.

UPDATE (MARCH 2019)

Since I published this post Nextcloud have released several big updates which have addressed many of the performance issues mentioned above so if you’re running the latest version it might not make sense to attempt the above. You will need to check the correct version of all the scripts too. You should test your site with Google PageSpeed Insights to look for performance improvements you can make though.

Updated:

Comments

facturer45

Good day, first congratulations for to share with everyone these important instructions, but please share the last instruction - how can I whitelist the CSP? Where is it?. Thanks you very much.

christian oliff

how can serve files from CDN faster than local? i really do not understand this

Because a CDN would likely be located closer to your end users than your origin which will benefit loading times. The CDN servers are also likely setup to serve static content much faster then your origin server by specifically catering the web server for static content. If your site is on HTTP 1 it’ll also use domain sharding so more files can download concurrently. Furthermore (as mentioned in the article), the CDN-served files have a longer cache life and are minified.

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...