To use this plugin, first consider which aspects of your project can be compiled to JavaScript. Unlike the Mojo plugin for GWT, this plugin discourages mixing server-only and client-only code in the same project. Instead, there should be server-specific and client-specific projects, though they made share some common “shared” project dependencies to avoid code duplication. Any shared code and its dependencies should build and run cleanly on both platforms to avoid later headaches.

It is further encouraged that no client project get “too big”, but that wherever reasonable, the client code be split into discrete modules. This helps not only encourage developers to put code where it belongs instead of one giant source directory full of circular dependencies, but will help the j2cl-maven-plugin parallelize builds when code changes - especially important for “dev mode”.

Finally it is assumed that you might use any server you want, and this plugin tries to avoid making any assumptions about what might be used. The only assumption made is this: you already know how to start your server for development, and that there is a way to write static content to disk somewhere and let it be served to your browser.

Once the project is organized in this way, the j2cl-maven-plugin should be added to any client-only project that will have tests or produce runnable JavaScript:

    <build>
        <plugins>
            <plugin>
                <groupId>com.vertispan.j2cl</groupId>
                <artifactId>j2cl-maven-plugin</artifactId>
                <version>0.21.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

This will default to producing optimized JavaScript of the application in the prepare-package phase. See the configuration options for j2cl:build for more details on how to customize this.

By default, for a project named my-app with version 1.2.3-SNAPSHOT output will be written to the target/my-app-1.2.3-SNAPSHOT directory, under the assumption that a war file will be built around this content, and used as an overlay for the server war. This directory can be customized using <webappDirectory>. The actual output JS file in turn would be in that directory, in my-app/my-app.js - other generated resources would live in the same directory. To avoid this extra wrapping directory or to change the name of the output JS, the <initialScriptFilename> configuration property can be set.

To run tests, add an execution for the test goal. The configuration settings above are named the same for test and build, so if they are customized, each should be declared in its own execution:

    <executions>
        <execution>
            <id>test-js</id>
            <goals>
                <goal>test</goal>
            </goals>
            <configuration>
                <!-- htmlunit requires output transpiled down to remove es2015 class -->
                <compilationLevel>ADVANCED</compilationLevel>
            </configuration>
        </execution>
    </executions>

For a multi-module client project (and for reasons discussed above, most projects will be multi-module if there is any code shared), the development mode feature should be configured in the parent pom, and invoked from there. This goal is called j2cl:watch, and while this will not run a server, it will watch for any changes in the child projects from where it is run, and build to the directory of your choosing. Note that <webappDirectory> must be specified if run on a parent pom - this should be configured to tell the plugin where to write generated output such that your web server can see it, serve it to the browser. The watch goal will examine each child project and collect j2cl:build executions, and build all of them into that one directory.

So that the <webappDirectory> for j2cl:watch does not become the default for all child projects, be sure to set <inherited>false</inherited>.

    <plugin>
        <groupId>com.vertispan.j2cl</groupId>
        <artifactId>j2cl-maven-plugin</artifactId>
        <version>0.21.0</version>
        <inherited>false</inherited>
        <configuration>
            <webappDirectory>${project.build.directory}/j2cl-watch</webappDirectory>
        </configuration>
    </plugin>

Of course, if you run j2cl:watch in the client project itself and don't take advantage of rebuilding other reactor projects as they are changed, additional configuration is unnecessary - but if a different webapp directory is desired, the system property j2cl.webappDirectory can be set (such as mvn j2cl:watch -Dj2cl.webappDirectory=path/to/server).

Finally, consider placing the plugin itself in the parent pom's <pluginManagement> section, so that the version is only set in one place and any project-wide conventions can be set once. Then the version can be removed from all other declarations (including the examples above).

    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>com.vertispan.j2cl</groupId>
                <artifactId>j2cl-maven-plugin</artifactId>
                <version>0.21.0</version>
            </plugin>
        </plugins>
    </pluginManagement>