Best practices for adding Node.JS build features to a non-Node project

buildsnode.jsproject-structure

The primary use for Node.JS is of course as a full server stack, and I've used it in that manner to great success.

However, a number of useful, interesting NPM packages deal with things like transpiling a styling language, adding typing information to typeless JavaScript, running JavaScript unit tests, even having a "piped" build system like Gulp.

Currently, I work on a project that uses Tomcat, and is primarily written in Java. Java and Ant utilities have felt somewhat limiting in terms of interacting with our JavaScript files when building/testing, so I'm looking into the possibility of adding a dependency on NodeJS, and setting up build dependencies.

Why would I do this?

I distinctly want to avoid adding dependencies "because they're cool". I only want to add Node packages for scenarios where it is infeasible, or even deprecated, to solve particular problems using Java-based programs (eg, Ant).

One example: Our JavaScript widget library, Dojo, has stated they will not support doing Dojo builds via Java for much longer, having largely moved to Node builds. Additionally, some CSS compression toolkits run using Java have stopped being maintained in favor of those like LESS. There are also developer tools like JavaScript unit tests, or TypeScript types we'd like to consider to make development more reliable. Using a dependency manager might also help us engineer a solution where we don't have Dojo's entire source code committed to our repository.

The question: Proper project layout and potential pitfalls

What would be some reliable practices to follow if I want to use Node as a build/test/development dependency, but not require it for the final, packaged app (And, pros/cons of different approaches)? In this scenario, does it actually make sense to include a package.json in the root project hierarchy? Should Node-related build tasks be invoked via Ant, or does it make sense to require separate commandline actions to invoke them? Under what scenarios should developers/build machines run "npm install", and should it always be automated?

If based on experience people tend to find that the answer to those questions don't matter, that is also a helpful answer – but I'm asking for experience to hopefully avoid some design pitfalls.

Best Answer

Having both share the same root is fine. Apache Freemarker Docgen uses this structure. Invoking the JavaScript build from within the Java build is the standard. Running npm install can be decided programmatically by the Java build. For example, in Maven:

<plugin>
    <groupId>com.github.eirslett</groupId>
    <artifactId>frontend-maven-plugin</artifactId>
    <version>0.0.27</version>

    <executions>

      <execution>
        <id>install node and npm</id>
        <goals>
          <goal>install-node-and-npm</goal>
        </goals>
        <configuration>
          <nodeVersion>v4.2.1</nodeVersion>
          <npmVersion>3.5.3</npmVersion>
        </configuration>
      </execution>

      <execution>
        <id>npm install</id>
        <goals>
          <goal>npm</goal>
        </goals>
        <configuration>
          <arguments>install</arguments>
        </configuration>
      </execution>

      <execution>
        <id>npm run build</id>
        <goals>
          <goal>npm</goal>
        </goals>
        <configuration>
          <arguments>run build</arguments>
        </configuration>
      </execution>

    </executions>
</plugin>

References

Related Topic