{% extends "../../layout.html" %} {% block sectionClasses %}plugins hasBreadCrumb plugins-spincast-js-closurecompiler{% endblock %} {% block meta_title %}Plugins - Spincast JS Closure Compiler{% endblock %} {% block meta_description %}Spincast JS Closure Compiler plugin - Integration with Google's Closure Compiler to optimize your JS files.{% endblock %} {% block scripts %} {% endblock %} {% block body %}

Overview

This plugin integrates Google's Closure Compiler. It is used to optimize and compress your Javascript files. Closure Compiler is a well-supported library that can be used even with modern ECMAScript features!

Usage

You inject and use the SpincastJsClosureCompilerManager component where you need to optimize Javascript files.

It is highly suggested that you only optimize a given Javascript file one time and then serve a cached version of it after that! The optimization done by the Closure Compiler can indeed take a couple of seconds.

One good way to optimize and then cache a Javascript file is by using a dynamic resource:

{% verbatim %}

router.dir("/publicdyn/js/*{relativePath}")
      .pathRelative("/publicdyn/js")
      .handle(publicResourcesController::dynJs);
{% endverbatim %}

In the "dynJs(...)" handler, you would get the raw content of the .js file and optimize it using the SpincastJsClosureCompilerManager component before sending the result:

{% verbatim %}

File jsFile = //... get the .js file

String rawJsContent = FileUtils.readFileToString(jsFile, "UTF-8");

String jsOptimized = getSpincastJsClosureCompilerManager()
                        .compile(rawJsContent,
                                 "--compilation_level ", "WHITESPACE_ONLY");

context.response().sendCharacters(jsOptimized, "application/javascript");
{% endverbatim %}

Explanation :

  • 1 : We get the .js file using the "relativePath" path parameter taken from the request. We make sure we validate this user input properly!
  • 3 : We get the raw Javascript content.
  • 5-6 : We call the compile(...) method.
  • 7 : In this example, we specify one option (using two arguments). You will learn more about options in the next section
  • 9 : We send the optimized Javascript, using the proper content-type. Since this is a dynamic resource route, the result will be cached and it is this cached version that will be served on next requests!

Flags and Options

Read the official Flags and Options documentation of Closure Compiler to learn how to tweak the optimization of your Javascript files.

There are two ways you can specify an option such as "--compilation_level" with a value of "WHITESPACE_ONLY":

1. Using two separate arguments

{% verbatim %}

String jsOptimized = 
    getSpincastJsClosureCompilerManager()
        .compile(jsContent, "--compilation_level", "WHITESPACE_ONLY");
                                
{% endverbatim %}

2. Or using one argument only with a "=" between the name and the value

{% verbatim %}

String jsOptimized = 
    getSpincastJsClosureCompilerManager()
        .compile(jsContent, "--compilation_level=WHITESPACE_ONLY");
                                
{% endverbatim %}

Some options take only one argument without any value at all (ex: --strict_mode_input).

You cannot use the "--js_output_file" option! This option is managed by the plugin. If you specify it, your version will be ignored.

SpincastJsClosureCompilerManager methods
The main methods provided by SpincastJsClosureCompilerManager are:
  • String compile(String jsContent, String... args))

    Run the Closure Compiler on the specified Javascript content, as a String. Return the optimized Javascript.

    The command generated by this method will look like:

    
    java -jar closure-compiler.jar --js_output_file=internalSpincastFile fileCreatedFromYourJsContent.js [YOUR ARGS]
    

  • String compile(File jsFile, String... args))

    Run the Closure Compiler on the content of the specified .js file. Return the optimized Javascript.

    The command generated by this method will look like:

    
    java -jar closure-compiler.jar --js_output_file=internalSpincastFile yourFile.js [YOUR ARGS]
    

  • String compile(List<File> jsFiles, String... args))

    Run the Closure Compiler on the concatenated content of multiple .js files. Return the concatenated and optimized Javascript.

    You can read more about using multiple input files here.

    The command generated by this method will look like:

    
    java -jar closure-compiler.jar --js_output_file=internalSpincastFile file1.js file2.js file3.js [YOUR ARGS]
    

  • String compileCustom(String... args))

    Run the Closure Compiler using only custom arguments. Return the optimized Javascript.

    When you use this method, you are responsible to specify all the arguments that are going to be passed to the Closure Compiler (except, again, "--js_output_file"). This means you are responsible to specify the input files as arguments too!

    To specify the input files as arguments, you can use globs patterns if you want.

    The command generated by this method will look like:

    
    java -jar closure-compiler.jar --js_output_file=internalSpincastFile [YOUR ARGS]
    

Configurations

There is only one global configuration:

  • String getJavaBinPath()

    Allows you to modify the path to the java executable that will be used. You can specify an absolute path if required.

    The value is "java" by default.

Dependencies

This plugin depends on the Spincast Process Utils plugin which is not provided by default by the spincast-default package.

This dependency will be automatically installed. Note that it is always a good idea to read the documentation of the automatically installed plugins.

Even if Closure Compiler is written in Java and we could have used its Java API directly, we do call it using a terminal command so all the flags and options from the official documentation can be easily used.

Installation

1. Add this Maven artifact to your project:

<dependency>
    <groupId>org.spincast</groupId>
    <artifactId>spincast-plugins-js-closurecompiler</artifactId>
    <version>{{spincast.spincastCurrrentVersion}}</version>
</dependency>

2. Add an instance of the SpincastJsClosureCompilerPlugin plugin to your Spincast Bootstrapper: {% verbatim %}


Spincast.configure()
        .plugin(new SpincastJsClosureCompilerPlugin())
        // ...

{% endverbatim %}

{% endblock %}