Wordpress Theme Javascript Optimization
This post shows how to combine and minify multiple javascript files in a Wordpress theme into one javascript file. The benefit is a single request to a javascript file that has been compressed by minification instead of multiple request to larger javascript files.
package.json
The package.json file contains meta data about your app or module and it includes the list of dependencies to install from Node Package Manager (NPM) when running npm install. NPM is bundled with Node.js; if you have not done so already, install Node.js so you have it. Then create and save this file in your themes root directory, for example /wp-content/my-theme/package.json. Then when you run npm install, the package.json file is read and the respective node modules are installed. More information is available here.
/* package.json */
{
"name": "my-theme",
"version": "0.1.0",
"devDependencies": {
"grunt": "~0.4.5",
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-uglify": "~0.6.0"
}
}
# install node_modules
$ npm install
gruntfile.js
The Grunt Javascript Task Runner will be used to configure and run the minification of /js/src/*.js
into /js/main.js
using UglifyJs.
/* gruntfile.js */
module.exports = function(grunt) {
'use strict';
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
build: {
files: {
'js/main.js': ['js/src/*.js']
}
}
}
});
// Load the plugin
grunt.loadNpmTasks('grunt-contrib-uglify');
// Default task(s).
grunt.registerTask('default', ['uglify']);
};
file structure
Here is what the themes javascript file structure looks like for this example. The /js/src folder contains all of the individual javascript files for your theme. When you run grunt, these are all combined and minified into /js/main.js
Partial view of themes files showing location of javascript
functions.php
The functions.php
file controls the loading of the themes javascript resources. In the functions.php
file, the wp_enqueue_script()
function links the script to the page. The pre-existing wp_enqueue_script()
function calls are no longer valid since the javascript files have been moved to the /js/src/
folder. Here is an example of the code from the pre-existing functions.php
that was linking the scripts:
function my-theme_scripts() {
wp_enqueue_style( 'my-theme-style', get_stylesheet_uri() );
wp_enqueue_script( 'my-theme-deflist', get_template_directory_uri() . '/js/deflist.js', array('jquery'), '20141011', true );
wp_enqueue_script( 'my-theme-navigation', get_template_directory_uri() . '/js/navigation.js', array(), '20120206', true );
wp_enqueue_script( 'my-theme-skip-link-focus-fix', get_template_directory_uri() . '/js/skip-link-focus-fix.js', array(), '20130115', true );
if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
wp_enqueue_script( 'comment-reply' );
}
}
add_action( 'wp_enqueue_scripts', 'my-theme_scripts' );
Here is an example of the code from functions.php
after making the changes to link /js/main.js
instead. Since /js/src/deflist.js
depends on jQuery, so does /js/main.js
and the $deps
array parameter is set to 'jquery'
. For more information, refer to the wp_enqueue_script function reference
function my-theme_scripts() {
wp_enqueue_style( 'my-theme-style', get_stylesheet_uri() );
wp_enqueue_script( 'my-theme-main', get_template_directory_uri() . '/js/main.js', array('jquery'), '20141011', true );
if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
wp_enqueue_script( 'comment-reply' );
}
}
add_action( 'wp_enqueue_scripts', 'my-theme_scripts' );
Time to Grunt
Run Grunt when you are ready to create or overwrite /js/main.js
# run the default task(s)
$ grunt