4

I have an Angular 2 typescript project that I would like to bundle into one JS file. Bootstrapper:

main.ts

import {platformBrowser} from '@angular/platform-browser';
import {AppModuleNgFactory} from '../aot/dev/app/app.module.ngfactory' //generated code
import {enableProdMode} from '@angular/core';
enableProdMode();
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory).catch(e=>console.error(e));

I used Angular 2's Ahead-of-Time compiler to generate ngfactory.ts files. I then ran tsickle to transform my files into Google Closure Compiler compatible JS. This completed without difficulty:

"node_modules/.bin/tsickle" -- -p ./

Here is the result:

main.js

goog.module('C_.websites.learn.angular2.dev.main');var module = module || {id: 'C:/websites/learn/angular2/dev/main.js'};
import { platformBrowser } from '@angular/platform-browser';
var platformBrowser = platformBrowser; /* local alias for Closure JSDoc */
import { AppModuleNgFactory } from '../aot/dev/app/app.module.ngfactory';
var AppModuleNgFactory = AppModuleNgFactory; /* local alias for Closure JSDoc */ //generated code
import { enableProdMode } from '@angular/core';
var enableProdMode = enableProdMode; /* local alias for Closure JSDoc */
enableProdMode();
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory).catch(function (e) { return console.error(e); });

Finally, I use google-closure-compiler-js to create a gulp task that bundles all JS into one file.

gulpfile.js

const closureCompiler = require('google-closure-compiler-js').gulp();
gulp.task('closure-compiler', function() {
    return gulp.src('./dev/main.js')
        .pipe(closureCompiler({
            compilationLevel: 'SIMPLE',
            warningLevel: 'VERBOSE',
            outputWrapper: '(function(){\n%output%\n}).call(this)',
            jsOutputFile: 'build.js',
            createSourceMap: false
        }))
        .pipe(gulp.dest(appProd));
});

The task fails immediately with many errors. Here is a sample:

dev\main.js:3 (JSC_REFERENCE_BEFORE_DECLARE) Variable referenced before declaration: module$contents$C_$websites$learn$angular2$dev$main_platformBrowser

dev\main.js:5 (JSC_REFERENCE_BEFORE_DECLARE) Variable referenced before declaration: module$contents$C_$websites$learn$angular2$dev$main_AppModuleNgFactory

dev\main.js:7 (JSC_REFERENCE_BEFORE_DECLARE) Variable referenced before declaration: module$contents$C_$websites$learn$angular2$dev$main_enableProdMode

dev\main.js:10 (JSC_POSSIBLE_INEXISTENT_PROPERTY) Property bootstrapModuleFactory never defined on ?

dev\main.js:3 (JSC_INTERNAL_ERROR_UNEXPECTED_TOKEN) Internal Error: TypeCheck doesn''t know how to hanle IMPORT

dev\main.js:3 (JSC_INTERNAL_ERROR_UNEXPECTED_TOKEN) Internal Error: TypeCheck doesn''t know how to handle IMPORT_SPECS ...

I'm using the latest tsickle source cloned from GitHub as of Oct 10, 2016, along with "google-closure-compiler-js": "^20160916.0.0".

Am I missing a step?

BeetleJuice
  • 39,516
  • 19
  • 105
  • 165
  • 1
    There is more to it than this, but closure compiler doesn't handle named imports such as `@angular/platform-browser` – Chad Killingsworth Oct 11 '16 at 09:31
  • @ChadKillingsworth Thanks. According to the Angular team itself, `tsickle` transpiles Typescript to closure-compatible Javascipt; checkout [this video](https://www.youtube.com/watch?v=_VnV7R4Ncwc) from 23:18 to 24:18 – BeetleJuice Oct 11 '16 at 15:20
  • 1
    I'm extremely familiar with the process and project. I can tell you hands down that the module rewriting process of closure-compiler won't handle that import statement. However I'm not close enough to the tsickle project to answer the question fully or even hint at what needs changed to make it work. – Chad Killingsworth Oct 11 '16 at 16:08
  • @ChadKillingsworth ok thank you. Does this mean that the import needs to specify a specific file? Is there a way to set paths as in SystemJS config, so closure knows that `@angular/platform-browser` means `node_modules/@angular/platform-browser/bundles/platform-browser.umd.js`? – BeetleJuice Oct 11 '16 at 16:20
  • @ChadKillingsworth or, more simply, is there a way to tell closure to use node's module resolution algorithm as `typescript` does when you set `"moduleResolution": "node"` in tsconfig – BeetleJuice Oct 11 '16 at 16:45
  • 1
    Not yet - it's something we want to add soon, but the compiler can only handle paths right now. – Chad Killingsworth Oct 11 '16 at 19:02
  • @ChadKillingsworth A few months have passed since this post was updated, so I'm wondering if this is possible now. If not, how are people managing to get some angular2 apps through closure? – Edy Bourne Feb 23 '17 at 21:13
  • @edybourne support for node module resolution was released today: https://github.com/google/closure-compiler/wiki/Releases#february-18-2017-v20170218 – Chad Killingsworth Feb 24 '17 at 00:55

0 Answers0