Combining ES2015 modules and CommonJS modules using the Closure Compiler

- JavaScript Developer and Blogger
Published: Wed Feb 08 2017

In this post I will show how to combine ES2015 and CommonJS modules in the same bundle using the Closure Compiler.

ES2015 and CommonJS are among the most popular module formats in JavaScript. Usually a project will stick to one of them, but with the Closure Compiler you can combine both seamlessly in the same project.

In the following example I have created CarService as an ES2015 module, and CountryService as a CommonJS module.

export class CarService { getCars() { return ['BMW', 'Ferrari', 'Lamborghini', 'Porsche']; } }
function getCountries() { return ['USA', 'Norway', 'Germany', 'Sweden']; } module.exports.getCountries = getCountries;

In main.js I import both before compiling my application with the Closure Compiler.

import {CarService} from './car-service'; let countryService = require('./country-service'); let carService = new CarService(); console.log(carService.getCars()); console.log(countryService.getCountries());

As you can tell we have a combination of require statements for CommonJS, and import statements for ES2015.

Closure configurations

Closure lets us combine both formats by specifying a few simple configuration parameters.

OPTS=( "--language_in=ES6_Strict" "--language_out=ES5" "--process_common_js_modules" "--compilation_level=ADVANCED_OPTIMIZATIONS" "--js_output_file=dist/modules.js" "--entry_point=modules/main.js" "./modules/main.js" "./modules/country-service.js" "./modules/car-service.js" ) set -ex java -jar node_modules/google-closure-compiler/compiler.jar $(echo ${OPTS[*]})

In this sample I am using the Java version of the Closure compiler.

To tell the compiler to expect both CommonJS and ES2105 I specify the process_common_js_modules flag and set language_in to ES6_Strict.

Closure will bundle both formats into to a single file that looks like this:

console.log(["BMW","Ferrari","Lamborghini","Porsche"]); console.log(["USA","Norway","Germany","Sweden"]);

The final output is reduced to a console.log statement per service call.

In the final bundle Closure flattened the original module format. There is no longer any module specific syntax in the code.

I have put the code on Github in case you are interested in checking it out.

I invite you to follow me on twitter