build(offline compiler): package the compiler-cli for users

Closes #8341
This commit is contained in:
Alex Eagle 2016-04-29 10:35:36 -07:00 committed by Alex Eagle
parent ca13f1c024
commit db95fd6ca9
7 changed files with 133 additions and 62 deletions

View File

@ -300,7 +300,14 @@ function doCheckFormat() {
var clangFormat = require('clang-format');
var gulpFormat = require('gulp-clang-format');
return gulp.src(['modules/**/*.ts', 'tools/**/*.ts', '!**/typings/**/*.d.ts', 'gulpfile.js'])
return gulp.src([
'modules/**/*.ts',
'tools/**/*.ts',
'!**/typings/**/*.d.ts',
// workaround https://github.com/angular/clang-format/issues/28
'!tools/compiler_cli/src/main.ts',
'gulpfile.js'
])
.pipe(gulpFormat.checkFormat('file', clangFormat));
}
@ -1051,7 +1058,7 @@ gulp.task('!build.compiler_cli', ['build.js.cjs'],
gulp.task('!test.compiler_cli.codegen', function(done) {
try {
require('./dist/js/cjs/compiler_cli')
require('./dist/js/cjs/compiler_cli/main')
.main("tools/compiler_cli/test")
.then(function() { runTsc('tools/compiler_cli/test', done); })
.catch(function(rej) { done(new Error(rej)); });

View File

@ -10,16 +10,31 @@ requires that the compiler be included in the code downloaded to the client.
You can produce smaller, faster applications by running Angular's compiler as a build step,
and then downloading only the executable JS to the client.
## Install and use
```
$ npm install angular2-template-compiler typescript rxjs
# Optional sanity check, make sure TypeScript can compile
$ ./node_modules/.bin/tsc -p path/to/project
$ ./node_modules/.bin/ng2tc -p path/to/project
```
In order to write a `bootstrap` that imports the generated code, you should first write your
top-level component, and run `ng2tc` once to produce a generated `.ngfactory.ts` file.
Then you can add an import statement in the `bootstrap` allowing you to bootstrap off the
generated code.
## Configuration
The `tsconfig.json` file is expected to contain an additional configuration block:
The `tsconfig.json` file may contain an additional configuration block:
```
"angularCompilerOptions": {
"genDir": "."
}
```
the `genDir` option controls the path (relative to `tsconfig.json`) where the generated file tree
will be written. More options may be added as we implement more features.
will be written. If `genDir` is not set, then the code will be generated in the source tree, next
to your original sources. More options may be added as we implement more features.
We recommend you avoid checking generated files into version control. This permits a state where
the generated files in the repository were created from sources that were never checked in,
@ -70,3 +85,11 @@ gulp build.js.cjs
# Run it on the test project
node ./dist/js/cjs/compiler_cli -p tools/compiler_cli/test
```
Release:
```
$ gulp test.compiler_cli
$ cp tools/compiler_cli/README.md tools/compiler_cli/package.json dist/js/cjs/compiler_cli
# npm login as angularcore
$ npm publish dist/js/cjs/compiler_cli
```

View File

@ -0,0 +1,37 @@
{
"name": "angular2-template-compiler",
"version": "0.1.3",
"description": "Execute angular2 template compiler in nodejs.",
"main": "index.js",
"typings": "index.d.ts",
"bin": {
"ng2tc": "./main.js"
},
"dependencies": {
"angular2": "angular/angular#2.0.0-build.cacdead.js",
"ts-metadata-collector": "^0.1.0",
"tsickle": "^0.1.0",
"reflect-metadata": "^0.1.2",
"parse5": "1.3.2"
},
"peerDependencies": {
"typescript": "^1.8.0 || ^1.9.0-dev"
},
"repository": {
"type": "git",
"url": "https://github.com/angular/angular.git"
},
"keywords": [
"angular",
"compiler"
],
"contributors": [
"Tobias Bosch <tbosch@google.com> (https://angular.io/)",
"Alex Eagle <alexeagle@google.com> (https://angular.io/)"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/angular/angular/issues"
},
"homepage": "https://github.com/angular/angular/tree/master/tools/compiler_cli"
}

View File

@ -79,7 +79,7 @@ export class CodeGenerator {
return result;
}
codegen() {
codegen(): Promise<void[]> {
Parse5DomAdapter.makeCurrent();
const generateOneFile = (absSourcePath: string) =>
Promise.all(this.readComponents(absSourcePath))

View File

@ -1,55 +1,3 @@
// TODO(alexeagle): use --lib=node when available; remove this reference
// https://github.com/Microsoft/TypeScript/pull/7757#issuecomment-205644657
/// <reference path="../../typings/node/node.d.ts"/>
// Must be imported first, because angular2 decorators throws on load.
import 'reflect-metadata';
import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';
import {tsc, check} from './tsc';
import {CodeGenerator} from './codegen';
const DEBUG = false;
function debug(msg: string, ...o: any[]) {
if (DEBUG) console.log(msg, ...o);
}
export function main(project: string, basePath?: string): Promise<number> {
// file names in tsconfig are resolved relative to this absolute path
basePath = path.join(process.cwd(), basePath || project);
// read the configuration options from wherever you store them
const {parsed, ngOptions} = tsc.readConfiguration(project, basePath);
const host = ts.createCompilerHost(parsed.options, true);
const {errors, generator} = CodeGenerator.create(ngOptions, parsed, basePath, host);
check(errors);
return generator.codegen()
// use our compiler host, which wraps the built-in one from TypeScript
// This allows us to add features like --stripDesignTimeDecorators to optimize your
// application more.
.then(() => tsc.typeCheckAndEmit(generator.host, generator.program))
.catch(rejected => {
console.error('Compile failed\n', rejected.message);
throw new Error(rejected);
});
}
// CLI entry point
if (require.main === module) {
const args = require('minimist')(process.argv.slice(2));
try {
main(args.p || args.project || '.', args.basePath)
.then(exitCode => process.exit(exitCode))
.catch(r => { process.exit(1); });
} catch (e) {
console.error(e.stack);
console.error("Compilation failed");
process.exit(1);
}
}
export {CodeGenerator} from './codegen';
export {NodeReflectorHost} from './reflector_host';
export {wrapCompilerHost, CodeGeneratorHost} from './compiler_host';

View File

@ -0,0 +1,56 @@
#!/usr/bin/env node
// TODO(alexeagle): use --lib=node when available; remove this reference
// https://github.com/Microsoft/TypeScript/pull/7757#issuecomment-205644657
/// <reference path="../../typings/node/node.d.ts"/>
// Must be imported first, because angular2 decorators throws on load.
import 'reflect-metadata';
import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';
import {tsc, check} from './tsc';
import {CodeGenerator} from './codegen';
const DEBUG = false;
function debug(msg: string, ...o: any[]) {
if (DEBUG) console.log(msg, ...o);
}
export function main(project: string, basePath?: string): Promise<any> {
// file names in tsconfig are resolved relative to this absolute path
basePath = path.join(process.cwd(), basePath || project);
// read the configuration options from wherever you store them
const {parsed, ngOptions} = tsc.readConfiguration(project, basePath);
const host = ts.createCompilerHost(parsed.options, true);
const {errors, generator} = CodeGenerator.create(ngOptions, parsed, basePath, host);
check(errors);
return generator.codegen()
// use our compiler host, which wraps the built-in one from TypeScript
// This allows us to add features like --stripDesignTimeDecorators to optimize your
// application more.
.then(() => tsc.typeCheckAndEmit(generator.host, generator.program))
.catch(rejected => {
console.error('Compile failed\n', rejected.message);
throw new Error(rejected);
});
}
// CLI entry point
if (require.main === module) {
const args = require('minimist')(process.argv.slice(2));
try {
main(args.p || args.project || '.', args.basePath)
.then(exitCode => process.exit(exitCode))
.catch(r => { process.exit(1); });
} catch (e) {
console.error(e.stack);
console.error("Compilation failed");
process.exit(1);
}
}

View File

@ -24,7 +24,7 @@ export class NodeReflectorHost implements StaticReflectorHost {
* they are resolvable by the moduleResolution strategy from the CompilerHost.
*/
private getModuleId(declarationFile: string, containingFile: string) {
const parts = declarationFile.replace(EXT, '').split(path.sep);
const parts = declarationFile.replace(EXT, '').split(path.sep).filter(p => !!p);
for (let index = parts.length - 1; index >= 0; index--) {
let candidate = parts.slice(index, parts.length).join(path.sep);
@ -51,7 +51,7 @@ export class NodeReflectorHost implements StaticReflectorHost {
throw new Error("Resolution of relative paths requires a containing file.");
}
// Any containing file gives the same result for absolute imports
containingFile = 'index.ts';
containingFile = path.join(this.compilerHost.getCurrentDirectory(), 'index.ts');
}
try {