assets css javascript minify

Assets management

Question

Until DX 7.3.1.0 assets are aggregated and compressed by default on the server side, but with Modern JS what was once a best practice is now seen as a bad practice.
This is why starting with DX 7.3.1.0 assets are only aggregated by default, but not compressed, and the compression will be dropped in the future as well as the aggregation.

So, in this context how to correctly manage your assets in your Jahia module?

Answer

Two main solutions

  1. The simplest one, add minified files as well as normal files in your module for the vendor resources and use UgilfyJS2 to minify your own files and commit them. Then call those minified files where you need them. As a little bonus, you can actually test in your JSP if your module is a SNAPSHOT or not and call the minify version when needed.
    • <c:choose>
          <c:when test="${fn:contains(script.view.moduleVersion, '-SNAPSHOT')}">
              <template:addResources type="javascript" resources="app.js"/>
          </c:when>
          <c:otherwise>
              <template:addResources type="javascript" resources="app.min.js"/>
          </c:otherwise>
      </c:choose>
      
  2. The second solution is a little more complex, and requires to use the frontend-maven-plugin with Modern JS, but it will ease your development on the long term. It is what we do at Jahia, and we are describing here how we do it using a short example. You may find other solutions but this works well and allow you to use Modern JS tools such as Webpack, gulp, yarn, npm, ...

 

Frontend maven plugin example

You can find the code sample of the following example here.

Depending on your knowledge it might be good to read a bit about Yarn to understand how to use it, as well as installing it on your environment.

To start, add the frontend-maven-plugin (read the doc to know more) to your pom file:

<plugin>
    <groupId>com.github.eirslett</groupId>
    <artifactId>frontend-maven-plugin</artifactId>
    <version>1.7.5</version>
    <executions>
        <execution>
            <id>npm install node and yarn</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>install-node-and-yarn</goal>
            </goals>
            <configuration>
                <nodeVersion>v10.15.3</nodeVersion>
                <yarnVersion>v1.15.2</yarnVersion>
            </configuration>
        </execution>
        <execution>
            <id>yarn install</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>yarn</goal>
            </goals>
        </execution>
    </executions>
</plugin>

In your .gitignore file (or VCS ignore file) add those line:

# JS
node
node_modules

From here, using a command line you can execute  mvn clean install, the frontend-maven-plugin will be executed and will do a yarn install which will create a yarn.lock file.

Then execute yarn init (you might need to do node\yarn\dist\bin\yarn init if you did not install yarn globally on your environment) and answer the questions. This will create a package.json file

The package.json and the yarn.lock must be committed to your VCS.

Add this execution to the plugin in the pom (at the end after the two other executions):

<execution>
    <id>yarn post-install</id>
    <phase>generate-resources</phase>
    <goals>
        <goal>yarn</goal>
    </goals>
    <configuration>
        <arguments>${yarn.arguments}</arguments>
    </configuration>
</execution>

In the properties of your pom, add something similar to:

<properties>
    <yarn.arguments>build:production</yarn.arguments>
</properties>

The value of the property might change based on the name you will give it, but this is quite standard.

Now in the package.json, add the script that will generate your files based on your needs. In this example, I will use UgilfyJS2 to concatenate and compress the javascript files of my module but you could be using Webpack, Gulp, ...

Add UglifyJS2 as a devDependencies in the package.json:

yarn add uglify-js -D

And the script to add in the package.json:

"scripts": {
  "build": "npx uglifyjs src/javascript/app-utils.js src/javascript/app.js -o src/main/resources/javascript/app/index.js -b",
  "build:production": "npx uglifyjs src/javascript/app-utils.js src/javascript/app.js -o src/main/resources/javascript/app/index.js"
}

You likely don't want to commit the result file in your module so you can add this to your VCS ignore file:

src/main/resources/javascript/app

With this basic setup, your files will be concatenated into one and the result file will be uglified if you are running mvn clean install . This is good for production and when developing, you can run mvn clean install -Dyarn.arguments=build which will concatenate the files but not uglify them.

 

Little bonus you can add the following profile to your pom so in development you can just run mvn clean install -P dev:

<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <yarn.arguments>build</yarn.arguments>
        </properties>
    </profile>
</profiles>

 

Of course, this is a simple example, you can do much more with Modern JS but it's not part of this topic. Plenty of tutorials and information are available online.