├── .gitignore ├── LICENSE ├── README.md ├── docs └── demo.png ├── gulpfile.js ├── lint.yml ├── package-lock.json ├── package.json ├── src ├── app │ ├── about │ │ ├── about.component.html │ │ └── about.component.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── app.routes.ts │ ├── example │ │ ├── example.component.html │ │ └── example.component.ts │ └── main.ts ├── images │ └── empty ├── index.html └── scss │ ├── _core.scss │ ├── _variables.scss │ └── main.scss ├── system.config.js ├── test └── app.component.spec.js └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | node_modules 4 | typings 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2016 Matthew Ross 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular2-base 2 | 3 | A simple base project for Angular 2 apps, using Gulp to automate tasks and SystemJS to bundle the app. 4 | 5 | Includes examples following the [official style guide](https://angular.io/docs/ts/latest/guide/style-guide.html) to create components, templates (inline and separate), and routes (using the latest router). Uses [Gulp](http://gulpjs.com/) to automate tasks and [systemjs-builder](https://github.com/systemjs/builder) to package files. 6 | 7 | ![Demo View](./docs/demo.png) 8 | 9 | ## Usage 10 | 11 | Clone the repo to where you want to use it, then install the npm packages with `npm i`. You may also need to run `gem install scss-lint` for the linter to work. 12 | 13 | To generate the output directory `dist/` run the command `gulp`. 14 | 15 | If you add more `@angular` packages, you will need to update the `system.config.js` file to include them in the bundle during the build process. 16 | 17 | ## Tests 18 | 19 | Tests are in the `test` directory, with one already there as an example. To run the tests, use the command `gulp test`. This generates the JavaScript files, then runs the tests against them. 20 | 21 | You can have the tests auto-run when tests or ts files change by running the `gulp watchtests` command. 22 | 23 | ## Production 24 | 25 | For a production setup, uncomment the lines in `main.ts` to put Angular in production mode. Then, run the minification task to minify vendor files `gulp minify`. 26 | 27 | ## Auto-Refresh when Developing 28 | 29 | You may run `gulp watch` in a stand-alone terminal to have the output automatically updated when you save changes. 30 | 31 | -------------------------------------------------------------------------------- /docs/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiswa/angular2-base/012ece1c3fc0b0a0c334de3fb4af4dc8820c185b/docs/demo.png -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | del = require('del'), 3 | merge = require('merge-stream'), 4 | 5 | tsc = require('gulp-typescript'), 6 | tsProject = tsc.createProject('tsconfig.json'), 7 | SystemBuilder = require('systemjs-builder'), 8 | jsMinify = require('gulp-uglify'), 9 | 10 | mocha = require('gulp-mocha'), 11 | concat = require('gulp-concat'), 12 | imagemin = require('gulp-imagemin'), 13 | 14 | scssLint = require('gulp-scss-lint'), 15 | sass = require('gulp-sass'), 16 | cssPrefixer = require('gulp-autoprefixer'), 17 | cssMinify = require('gulp-cssnano'); 18 | 19 | gulp.task('clean', () => { 20 | return del('dist'); 21 | }); 22 | 23 | gulp.task('shims', () => { 24 | return gulp.src([ 25 | 'node_modules/core-js/client/shim.js', 26 | 'node_modules/zone.js/dist/zone.js', 27 | 'node_modules/reflect-metadata/Reflect.js' 28 | ]) 29 | .pipe(concat('shims.js')) 30 | .pipe(gulp.dest('dist/js/')); 31 | }); 32 | 33 | gulp.task('system-build', [ 'tsc' ], () => { 34 | var builder = new SystemBuilder(); 35 | 36 | return builder.loadConfig('system.config.js') 37 | .then(() => builder.buildStatic('app', 'dist/js/bundle.js', { 38 | production: false, 39 | rollup: false 40 | })) 41 | .then(() => del('build')); 42 | }); 43 | 44 | gulp.task('tsc', () => { 45 | del('build'); 46 | 47 | return gulp.src('src/app/**/*.ts') 48 | .pipe(tsProject()) 49 | .pipe(gulp.dest('build/')); 50 | }); 51 | 52 | gulp.task('html', () => { 53 | return gulp.src('src/**/**.html') 54 | .pipe(gulp.dest('dist/')); 55 | }); 56 | 57 | gulp.task('images', () => { 58 | return gulp.src('src/images/**/*.*') 59 | .pipe(imagemin()) 60 | .pipe(gulp.dest('dist/images/')); 61 | }); 62 | 63 | gulp.task('scss-lint', function() { 64 | return gulp.src('src/scss/**/*.scss') 65 | .pipe(scssLint({ config: 'lint.yml' })); 66 | }); 67 | 68 | gulp.task('scss', () => { 69 | return gulp.src('src/scss/main.scss') 70 | .pipe(sass({ 71 | precision: 10, 72 | includePaths: 'node_modules/node-normalize-scss' 73 | })) 74 | .pipe(concat('styles.css')) 75 | .pipe(cssPrefixer()) 76 | .pipe(gulp.dest('dist/css/')); 77 | }); 78 | 79 | gulp.task('test-run', [ 'tsc' ], () => { 80 | return gulp.src('test/**/*.spec.js') 81 | .pipe(mocha()); 82 | }); 83 | 84 | gulp.task('test', [ 'test-run' ], () => { 85 | return del('build'); 86 | }); 87 | 88 | gulp.task('minify', () => { 89 | var js = gulp.src('dist/js/bundle.js') 90 | .pipe(jsMinify()) 91 | .pipe(gulp.dest('dist/js/')); 92 | 93 | var css = gulp.src('dist/css/styles.css') 94 | .pipe(cssMinify()) 95 | .pipe(gulp.dest('dist/css/')); 96 | 97 | return merge(js, css); 98 | }); 99 | 100 | gulp.task('watch', () => { 101 | var watchTs = gulp.watch('src/app/**/**.ts', [ 'system-build' ]), 102 | watchScss = gulp.watch('src/scss/**/*.scss', [ 'scss-lint', 'scss' ]), 103 | watchHtml = gulp.watch('src/**/*.html', [ 'html' ]), 104 | watchImages = gulp.watch('src/images/**/*.*', [ 'images' ]), 105 | 106 | onChanged = function(event) { 107 | console.log('File ' + event.path + ' was ' + event.type + '. Running tasks...'); 108 | }; 109 | 110 | watchTs.on('change', onChanged); 111 | watchScss.on('change', onChanged); 112 | watchHtml.on('change', onChanged); 113 | watchImages.on('change', onChanged); 114 | }); 115 | 116 | gulp.task('watchtests', () => { 117 | var watchTs = gulp.watch('src/app/**/**.ts', [ 'test-run' ]), 118 | watchTests = gulp.watch('test/**/*.spec.js', [ 'test-run' ]), 119 | 120 | onChanged = function(event) { 121 | console.log('File ' + event.path + ' was ' + event.type + '. Running tasks...'); 122 | }; 123 | 124 | watchTs.on('change', onChanged); 125 | watchTests.on('change', onChanged); 126 | }); 127 | 128 | gulp.task('default', [ 129 | 'shims', 130 | 'system-build', 131 | 'html', 132 | 'images', 133 | 'scss-lint', 134 | 'scss' 135 | ]); 136 | 137 | -------------------------------------------------------------------------------- /lint.yml: -------------------------------------------------------------------------------- 1 | linters: 2 | Indentation: 3 | width: 4 4 | 5 | NestingDepth: 6 | max_depth: 4 7 | 8 | SelectorDepth: 9 | max_depth: 4 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-base", 3 | "version": "1.0.0", 4 | "description": "A base project for Angular 2 apps with Gulp.", 5 | "main": "index.js", 6 | "private": true, 7 | "scripts": { 8 | "test": "gulp test" 9 | }, 10 | "author": "Matthew Ross (https://matthewross.me)", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "@angular/common": "^4.3.6", 14 | "@angular/compiler": "^4.3.6", 15 | "@angular/core": "^4.3.6", 16 | "@angular/http": "^4.3.6", 17 | "@angular/platform-browser": "^4.3.6", 18 | "@angular/platform-browser-dynamic": "^4.3.6", 19 | "@angular/router": "^4.3.6", 20 | "@types/core-js": "^0.9.43", 21 | "chai": "^4.1.2", 22 | "core-js": "^2.5.1", 23 | "del": "^3.0.0", 24 | "gulp": "^3.9.1", 25 | "gulp-autoprefixer": "^4.0.0", 26 | "gulp-concat": "^2.6.1", 27 | "gulp-cssnano": "^2.1.2", 28 | "gulp-imagemin": "^3.3.0", 29 | "gulp-mocha": "^3.0.1", 30 | "gulp-sass": "^3.1.0", 31 | "gulp-scss-lint": "^0.5.0", 32 | "gulp-typescript": "^3.2.2", 33 | "gulp-uglify": "^3.0.0", 34 | "merge-stream": "^1.0.1", 35 | "node-normalize-scss": "^3.0.0", 36 | "reflect-metadata": "^0.1.9", 37 | "rxjs": "5.4.3", 38 | "systemjs": "^0.20.18", 39 | "systemjs-builder": "^0.16.10", 40 | "typescript": "^2.5.2", 41 | "zone.js": "^0.8.17" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/app/about/about.component.html: -------------------------------------------------------------------------------- 1 |

About angular2-base

2 | 3 |

Just a simple example project to get started with Angular. Now includes routes!

4 | 5 | -------------------------------------------------------------------------------- /src/app/about/about.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'about', 5 | templateUrl: 'app/about/about.component.html' 6 | }) 7 | export class AboutComponent { } 8 | 9 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | import { ExampleComponent } from './example/example.component'; 4 | 5 | @Component({ 6 | selector: 'app-component', 7 | // Using backticks allows multi-line templates. 8 | // This is long enough to be in a separate file, 9 | // but is inline as an example. 10 | template: ` 11 |
12 |

My Angular 2 Base App

13 |

14 | Home | 15 | About 16 |

17 | 18 |
` 19 | }) 20 | export class AppComponent { 21 | public isTestable: boolean = true; 22 | 23 | // Angular 2 uses a tree of components to create an app. 24 | // This component is the root node of that tree. 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { ExampleComponent } from './example/example.component'; 5 | import { AboutComponent } from './about/about.component'; 6 | 7 | import { ROUTING } from './app.routes'; 8 | import { AppComponent } from './app.component'; 9 | 10 | @NgModule({ 11 | imports: [ BrowserModule, ROUTING ], 12 | declarations: [ 13 | AppComponent, 14 | AboutComponent, 15 | ExampleComponent 16 | ], 17 | bootstrap: [ AppComponent ] 18 | }) 19 | export class AppModule { } 20 | 21 | -------------------------------------------------------------------------------- /src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes, RouterModule } from '@angular/router'; 2 | 3 | import { ExampleComponent } from './example/example.component'; 4 | import { AboutComponent } from './about/about.component'; 5 | 6 | const ROUTES: Routes = [ 7 | { 8 | path: '', 9 | component: ExampleComponent 10 | }, 11 | { 12 | path: 'about', 13 | component: AboutComponent 14 | } 15 | ]; 16 | 17 | export const ROUTING = RouterModule.forRoot(ROUTES); 18 | 19 | -------------------------------------------------------------------------------- /src/app/example/example.component.html: -------------------------------------------------------------------------------- 1 |
2 |

This is the example component!

3 |
-------------------------------------------------------------------------------- /src/app/example/example.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'example', 5 | templateUrl: 'app/example/example.component.html' 6 | }) 7 | export class ExampleComponent { } 8 | 9 | -------------------------------------------------------------------------------- /src/app/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | // import { enableProdMode } from '@angular/core'; 3 | 4 | import { AppModule } from './app.module'; 5 | 6 | // enableProdMode(); 7 | 8 | platformBrowserDynamic().bootstrapModule(AppModule); 9 | 10 | -------------------------------------------------------------------------------- /src/images/empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiswa/angular2-base/012ece1c3fc0b0a0c334de3fb4af4dc8820c185b/src/images/empty -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular 2 Base 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Loading... 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/scss/_core.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: darken($background, 5%); 3 | } 4 | 5 | .container { 6 | background-color: $background; 7 | border: 1px solid $border; 8 | display: block; 9 | margin: 1em auto; 10 | padding: 1em; 11 | width: 50%; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | $background: #fff; 2 | $border: #ccc; 3 | 4 | -------------------------------------------------------------------------------- /src/scss/main.scss: -------------------------------------------------------------------------------- 1 | @import 'normalize'; 2 | 3 | @import 'variables'; 4 | @import 'core'; 5 | 6 | -------------------------------------------------------------------------------- /system.config.js: -------------------------------------------------------------------------------- 1 | (function(global) { 2 | var map = { 3 | 'app': 'build', 4 | 'rxjs': 'node_modules/rxjs', 5 | '@angular': 'node_modules/@angular' 6 | }; 7 | 8 | var packages = { 9 | 'app': { main: 'main.js', defaultExtension: 'js' }, 10 | 'rxjs': { defaultExtension: 'js' } 11 | }; 12 | 13 | var angularPackages = [ 14 | 'common', 15 | 'compiler', 16 | 'core', 17 | 'http', 18 | 'platform-browser', 19 | 'platform-browser-dynamic', 20 | 'router' 21 | ]; 22 | 23 | angularPackages.forEach(function(pkgName) { 24 | packages['@angular/' + pkgName] = { 25 | main: 'bundles/' + pkgName + '.umd.js', 26 | defaultExtension: 'js' 27 | }; 28 | }); 29 | 30 | var config = { 31 | map: map, 32 | packages: packages 33 | }; 34 | 35 | System.config(config); 36 | 37 | })(this); 38 | 39 | -------------------------------------------------------------------------------- /test/app.component.spec.js: -------------------------------------------------------------------------------- 1 | require('../node_modules/reflect-metadata/Reflect.js'); 2 | 3 | var chai = require('chai'), 4 | expect = chai.expect, 5 | AppComponent = require('../build/app.component.js').AppComponent; 6 | 7 | describe('AppComponent', () => { 8 | var app; 9 | 10 | beforeEach(function() { 11 | app = new AppComponent(); 12 | }); 13 | 14 | it('should be testable', function() { 15 | expect(app.isTestable).to.equal(true); 16 | }); 17 | }); 18 | 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": false, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": true, 10 | "noImplicitAny": true, 11 | "suppressImplicitAnyIndexErrors": true, 12 | "lib": [ "es2015", "dom" ], 13 | "typeRoots": [ "node_modules/@types" ], 14 | "types": [ "core-js" ] 15 | } 16 | } 17 | 18 | --------------------------------------------------------------------------------