22

I want to use the google closure compiler on the javascript source we're using. In development mode we tend to break functionality to lots of files but for production would like to have them combined into modules.

When calling the compiler I can give it a list of files to include for compilation, but the output of that shows that the compiler did not save the order of the files list.

I searched about it and found that I can use goog.provide/good.require in order to control the dependencies between the different js files. The problem with that is that it adds code to my js which I just don't need or want, for example:

goog.provide("mainFile")

will add this:

var mainFile = {};

to the compiled js file, something that I don't want. We're not using the google closure library at all, all I want to use is the compiler.

Is there a way to tell the compiler the order of the files without including more "closure library" functionality which I have no need for? I can of course create a tool of my own which will first take all the files, combine them into one which will then be the input of the compiler, but I would prefer to void that if it can be done by the compiler itself.


Edit

The goal is to be able to produce modules like the answer in this thread: Using the --module option in Closure Compiler to create multiple output files

And so I want to add to that the ability to control which files go into which module while also having control on their order. For now I don't use wildcards, but I plan to do so in the future (if it's possible).

simply "cat file1.js file2.js > combined.js && compile..." is fine, but in our case it's a bit more complicated and we'll have to write a program/script that does that based on some logic. If we can somehow tell the compiler the order of the files in advanced it might just save the time of implementing such a program.

Thanks.

Community
  • 1
  • 1
Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299
  • 1
    How about `cat file1 file2 > temp && compile -js temp`? – georg May 01 '12 at 09:38
  • Do you use wildcard (*.js) or do you state each file in order when calling the compiler? – GillesC May 01 '12 at 10:08
  • I edited my question since it was too big for a comment. Thanks. – Nitzan Tomer May 01 '12 at 10:50
  • By controlling the order do you mean the order the compiler processes each source file in a given module? It should be the order you list them in. – Chad Killingsworth May 01 '12 at 12:59
  • No, I mean the order in the compiled output.. Let's say I complie A.js and B.js together into C.js. In C.js I see the (compiled) content of B.js, before the content of A.js, and because of that the compiled js results in a lot of js errors when opened in the browser. – Nitzan Tomer May 01 '12 at 13:02
  • 1
    If compiling the same source files into one giant file works, then you should post an issue at http://code.google.com/p/closure-compiler/issues/list. Either way, it will help if you can provide a reproducible sample. – Chad Killingsworth May 01 '12 at 13:09
  • Ok, I'm ashamed to say that the errors in the resulting js were due to bad code committed to our svn. That got fixed. Still, my question remains: is there a way to define dependency between files without the adding of unwanted code? – Nitzan Tomer May 01 '12 at 14:49
  • I find it difficult to believe that Closure would change the ordering of scripts when compressing, since changing the order will change the behavior of scripts. It is definitely a no-no. The output may **LOOK** like the ordering has changed -- due to inlining etc. -- but you can be rest assured that the **logical order** has not changed at all. – Stephen Chung May 02 '12 at 02:30
  • Yeah, the order changed a bit but it did not cause any errors as I thought, the errors were caused by bad code. – Nitzan Tomer May 02 '12 at 07:30
  • Like Stephen stated, the compiler is required to keep the order of the input files unless you are using goog.provide/goog.requires and even then it keeps the relative order of file. If you find a case where that isn't happening. Enabling the input delimiter can help debug this. – John May 02 '12 at 15:21
  • I have no special interest in the ordering of the code, I just want it to work. After I fixed the bug in the code and used the answer Chad gave, everything fell into place. – Nitzan Tomer May 02 '12 at 17:15

2 Answers2

42

Closure-compiler's ability to create multiple output files provides a powerful tool to separate input files into distinct output chunks. It is designed such that different chunks can be loaded at differing times depending on the features required. There are multiple compiler flags pertaining to chunks.

Each use of the --chunk flag describes an output file and it's dependencies. Each chunk flag follows the following syntax:

--js inputfile.js
--chunk name:num_files:dependency

The resulting output file will be name.js and includes the files specified by the preceding --js flag(s).

The dependency option is what you will be most interested in. It specifies what the parent chunk is. The chunk options must describe a valid dependency tree (you must have a base chunk).

Here's an example:

--js commonfunctions.js
--chunk common:1
--js page1functions.js
--js page1events.js
--chunk page1:2:common
--js page2function.js
--chunk page2:1:common
--js page1addons.js
--chunk page1addons:1:page1

In this case, you are telling the compiler that the page1 and page2 chunks depend on the common chunk and that the page1addons chunk depends on the page1 chunk.

Keep in mind that the compiler can and does move code from one chunk into other chunk output files if it determines that it is only used by that chunk.

None of this requires closure-library or the use of goog.require/provide calls nor does it add any code to your output. If you want the compiler to determine dependencies automatically or to be able to manage those dependencies for you, you'll need to use a module format such as CommonJS, ES2015 modules or goog.require/provide/module calls.

Update Note: Prior to the 20180610 version, the chunk flags were named module. They were renamed to reduce confusion with proper JS modules. The answer has been updated to reflect the new names.

Update Note 2: There is now a utility to automatically calculate and generate these flags for you: https://github.com/ChadKillingsworth/closure-calculate-chunks

customcommander
  • 17,580
  • 5
  • 58
  • 84
Chad Killingsworth
  • 14,360
  • 2
  • 34
  • 57
  • 3
    Up vote. This is a nice concise answer with a great example. Perfect. In testing your answer, I was not able to create modules which contain either periods or dashes in their names. Is that possible, or am I doing something wrong? Example: `--module common.min:1` did not work for me. (When I say did not work, I mean no module was created.) – Karl Nov 14 '12 at 19:10
  • I have done a write up with a simple example in my blog of how to do this. Sharing in case others are interested: http://www.syntaxsuccess.com/viewarticle/lazy-loading-with-the-closure-compiler – TGH Dec 07 '16 at 05:20
  • How do you create source maps for the generated modules? – Scribblemacher Apr 09 '18 at 18:21
  • This works for explicitly specified .js files, but what about when using an automatic dependency check from an entry_point? can you specify a module for one set of dependencies? – Stephen Edwards May 03 '18 at 16:25
  • What about when you have more than 1 dependency? – Ally Nov 04 '18 at 04:04
  • @Scribblemacher the source maps should be generated automatically when you pass --create_source_map %outname%.map option – zavr Sep 06 '19 at 21:29
1

You can also set the output path, for example with:

--module_output_path_prefix ./public/js/

See also: Using the --module option in Closure Compiler to create multiple output files