Reputation: 1143
There's a quickstarter tutorial over at angular.io which uses typescript & systemjs. Now that I've got that miniapp running, how would I go about creating something deployable? I couldn't find any info about it whatsoever.
Do I need any extra tools, any additional settings in System.config?
(I know that I could use webpack & create a single bundle.js, but I'd like to use systemjs as it is used in the tutorial)
Could someone share their build process with this setup (Angular 2, TypeScript, systemjs)
Upvotes: 104
Views: 67207
Reputation: 4358
You can use angular2-cli build command
ng build -prod
https://github.com/angular/angular-cli/wiki/build#bundling
Builds created with the -prod flag via
ng build -prod
orng serve -prod
bundle all dependencies into a single file, and make use of tree-shaking techniques.
This answer was submitted when angular2 was in rc4
I had tried it again on angular-cli beta21 and angular2 ^2.1.0 and it is working as expected
This answer requires initializing the app with angular-cli you can use
ng new myApp
Or on an existing one
ng init
For angular 6 the syntax is different.
ng build --prod --build-optimizer
Check the documentation
Upvotes: 28
Reputation: 5008
Under Angular.io website, under Advanced/Deployment section, it is recommended that the simplest way to deploy is 'to copy the development environment to the server'.
go through the section under: Simplest deployment possible. The final project files are shown inside the code section. Note that it already sets up the code to load npm package files from the web (in stead of from the local npm_modules folder).
make sure it is running on your local computer (npm start). Then under the project folder, copy everything under '/src' sub-folder to the S3 bucket you've set up. You can use drag-and-drop to copy, during that process, you get the option to select the permission setting for the files, make sure to make them 'readable' to 'everyone'.
under bucket 'Properties' tab, look for 'Static website hosting' panel, check on 'Use this bucket to host website' option, and specify 'index.html' to both Index document and Error document.
click on the static website Endpoint, your project well be running!
Upvotes: 0
Reputation: 720
You can build an Angular 2 (2.0.0-rc.1) project in Typescript using SystemJS with Gulp and SystemJS-Builder.
Below is a simplified version of how to build, bundle, and minify Tour of Heroes running 2.0.0-rc.1 (full source, live example).
gulpfile.js
var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var concat = require('gulp-concat');
var typescript = require('gulp-typescript');
var systemjsBuilder = require('systemjs-builder');
// Compile TypeScript app to JS
gulp.task('compile:ts', function () {
return gulp
.src([
"src/**/*.ts",
"typings/*.d.ts"
])
.pipe(sourcemaps.init())
.pipe(typescript({
"module": "system",
"moduleResolution": "node",
"outDir": "app",
"target": "ES5"
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('app'));
});
// Generate systemjs-based bundle (app/app.js)
gulp.task('bundle:app', function() {
var builder = new systemjsBuilder('public', './system.config.js');
return builder.buildStatic('app', 'app/app.js');
});
// Copy and bundle dependencies into one file (vendor/vendors.js)
// system.config.js can also bundled for convenience
gulp.task('bundle:vendor', function () {
return gulp.src([
'node_modules/jquery/dist/jquery.min.js',
'node_modules/bootstrap/dist/js/bootstrap.min.js',
'node_modules/es6-shim/es6-shim.min.js',
'node_modules/es6-promise/dist/es6-promise.min.js',
'node_modules/zone.js/dist/zone.js',
'node_modules/reflect-metadata/Reflect.js',
'node_modules/systemjs/dist/system-polyfills.js',
'node_modules/systemjs/dist/system.src.js',
])
.pipe(concat('vendors.js'))
.pipe(gulp.dest('vendor'));
});
// Copy dependencies loaded through SystemJS into dir from node_modules
gulp.task('copy:vendor', function () {
gulp.src(['node_modules/rxjs/**/*'])
.pipe(gulp.dest('public/lib/js/rxjs'));
gulp.src(['node_modules/angular2-in-memory-web-api/**/*'])
.pipe(gulp.dest('public/lib/js/angular2-in-memory-web-api'));
return gulp.src(['node_modules/@angular/**/*'])
.pipe(gulp.dest('public/lib/js/@angular'));
});
gulp.task('vendor', ['bundle:vendor', 'copy:vendor']);
gulp.task('app', ['compile:ts', 'bundle:app']);
// Bundle dependencies and app into one file (app.bundle.js)
gulp.task('bundle', ['vendor', 'app'], function () {
return gulp.src([
'app/app.js',
'vendor/vendors.js'
])
.pipe(concat('app.bundle.js'))
.pipe(uglify())
.pipe(gulp.dest('./app'));
});
gulp.task('default', ['bundle']);
system.config.js
var map = {
'app': 'app',
'rxjs': 'vendor/rxjs',
'zonejs': 'vendor/zone.js',
'reflect-metadata': 'vendor/reflect-metadata',
'@angular': 'vendor/@angular'
};
var packages = {
'app': { main: 'main', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'zonejs': { main: 'zone', defaultExtension: 'js' },
'reflect-metadata': { main: 'Reflect', defaultExtension: 'js' }
};
var packageNames = [
'@angular/common',
'@angular/compiler',
'@angular/core',
'@angular/http',
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/router',
'@angular/router-deprecated',
'@angular/testing',
'@angular/upgrade',
];
packageNames.forEach(function(pkgName) {
packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});
System.config({
map: map,
packages: packages
});
Upvotes: 12
Reputation: 22001
The easiest way that I have found to bundle angular rc1 for systemJs is to use gulp
and systemjs-builder
:
gulp.task('bundle', function () {
var path = require('path');
var Builder = require('systemjs-builder');
var builder = new Builder('/node_modules');
return builder.bundle([
'@angular/**/*.js'
],
'wwwroot/bundle.js',
{ minify: false, sourceMaps: false })
.then(function () {
console.log('Build complete');
})
.catch(function (err) {
console.log('Build error');
console.log(err);
});
});
As pointed out in the comments, systemJs currently has issues when bundling components using moduleId: module.id
https://github.com/angular/angular/issues/6131
The current recommendation (angular 2 rc1) seems to be to use explicit paths i.e. moduleId: '/app/path/'
Upvotes: 1
Reputation: 678
Here's my MEA2N boilerplate for Angular 2: https://github.com/simonxca/mean2-boilerplate
It's a simple boilerplate that uses tsc
to put things together. (Actually uses grunt-ts, which at its core is just the tsc
command.) No Wekpack, etc. necessary.
Whether or not you use grunt, the idea is:
ts/
(example: public/ts/
)tsc
to mirror the directory structure of your ts/
folder into a js/
folder and just reference files in the js/
folder in your index.html
.To get grunt-ts to work (there should be an equivalent command for plain tsc, Gulp, etc.) , you have a property in your tsconfig.json
called "outDir": "../js"
, and reference it in your gruntfile.js
with:
grunt.initConfig({
ts: {
source: {tsconfig: 'app/ts/tsconfig.json'}
},
...
});
Then run grunt ts
, which will take your app in public/ts/
and mirror it to public/js/
.
There. Super easy to understand. Not the best approach, but a good one to get started.
Upvotes: 1
Reputation: 202216
The key thing to understand at this level is that using the following configuration, you can't concat compiled JS files directly.
At the TypeScript compiler configuration:
{
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"declaration": false,
"stripInternal": true,
"module": "system",
"moduleResolution": "node",
"noEmitOnError": false,
"rootDir": ".",
"inlineSourceMap": true,
"inlineSources": true,
"target": "es5"
},
"exclude": [
"node_modules"
]
}
In the HTML
System.config({
packages: {
app: {
defaultExtension: 'js',
format: 'register'
}
}
});
As a matter of fact, these JS files will contain anonymous modules. An anonymous module is a JS file that uses System.register
but without the module name as first parameter. This is what the typescript compiler generates by default when systemjs is configured as module manager.
So to have all your modules into a single JS file, you need to leverage the outFile
property within your TypeScript compiler configuration.
You can use the following inside gulp to do that:
const gulp = require('gulp');
const ts = require('gulp-typescript');
var tsProject = ts.createProject('tsconfig.json', {
typescript: require('typescript'),
outFile: 'app.js'
});
gulp.task('tscompile', function () {
var tsResult = gulp.src('./app/**/*.ts')
.pipe(ts(tsProject));
return tsResult.js.pipe(gulp.dest('./dist'));
});
This could be combined with some other processing:
app.js
filevendor.js
file for third-party librariesboot.js
file to import the module that bootstrap the application. This file must be included at the end of the page (when all the page is loaded).index.html
to take into account these two filesThe following dependencies are used in the gulp tasks:
The following is a sample so it could be adapted.
Create app.min.js
file
gulp.task('app-bundle', function () {
var tsProject = ts.createProject('tsconfig.json', {
typescript: require('typescript'),
outFile: 'app.js'
});
var tsResult = gulp.src('app/**/*.ts')
.pipe(ts(tsProject));
return tsResult.js.pipe(concat('app.min.js'))
.pipe(uglify())
.pipe(gulp.dest('./dist'));
});
Create vendors.min.js
file
gulp.task('vendor-bundle', function() {
gulp.src([
'node_modules/es6-shim/es6-shim.min.js',
'node_modules/systemjs/dist/system-polyfills.js',
'node_modules/angular2/bundles/angular2-polyfills.js',
'node_modules/systemjs/dist/system.src.js',
'node_modules/rxjs/bundles/Rx.js',
'node_modules/angular2/bundles/angular2.dev.js',
'node_modules/angular2/bundles/http.dev.js'
])
.pipe(concat('vendors.min.js'))
.pipe(uglify())
.pipe(gulp.dest('./dist'));
});
Create boot.min.js
file
gulp.task('boot-bundle', function() {
gulp.src('config.prod.js')
.pipe(concat('boot.min.js'))
.pipe(uglify())
.pipe(gulp.dest('./dist'));
});
The config.prod.js
simply contains the following:
System.import('boot')
.then(null, console.error.bind(console));
Update the index.html
file
gulp.task('html', function() {
gulp.src('index.html')
.pipe(htmlreplace({
'vendor': 'vendors.min.js',
'app': 'app.min.js',
'boot': 'boot.min.js'
}))
.pipe(gulp.dest('dist'));
});
The index.html
looks like the following:
<html>
<head>
<!-- Some CSS -->
<!-- build:vendor -->
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="node_modules/angular2/bundles/http.dev.js"></script>
<!-- endbuild -->
<!-- build:app -->
<script src="config.js"></script>
<!-- endbuild -->
</head>
<body>
<my-app>Loading...</my-app>
<!-- build:boot -->
<!-- endbuild -->
</body>
</html>
Notice that the System.import('boot');
must be done at the end of the body to wait for all your app components to be registered from the app.min.js
file.
I don't describe here the way to handle CSS and HTML minification.
Upvotes: 65