├── .gitignore ├── README.md ├── gulpfile.js ├── package.json ├── source ├── app.js ├── components │ ├── example_controller │ │ ├── example.scss │ │ ├── index.js │ │ └── tempate.html │ ├── example_directive │ │ ├── index.js │ │ └── template.html │ └── index.js ├── conf │ └── routes.js ├── index.html ├── sass │ └── app.scss └── services │ ├── example-factory.js │ └── index.js └── test ├── e2e └── home.js ├── karma.conf.js ├── protractor.conf.js └── spec ├── controllers └── example.js └── directives └── example.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | build 4 | source/partials 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Angular Starter Kit 2 | 3 | Angular Starter Kit is a boilerplate project to build web applications with 4 | Angular. This include: 5 | 6 | - Browserify support 7 | - Gulp for automatization 8 | - Babel for all the application 9 | - Angular 10 | - UI-router 11 | 12 | #### Instalation 13 | 14 | ``` 15 | git clone https://github.com/highercomve/angular-starter-kit newApp 16 | cd newApp 17 | npm install 18 | ``` 19 | 20 | #### Main Gulp task 21 | 22 | ```bash 23 | gulp build 24 | ``` 25 | 26 | This task is for build the assets for development, that means no minify (JS,CSS or HTML) 27 | but transforms all html/partials to and angular $templateCache with ngHTML2JS. 28 | 29 | ```bash 30 | gulp serve 31 | ``` 32 | 33 | Open a server in port 8000 for development with livereload 34 | 35 | ```bash 36 | gulp dist 37 | ``` 38 | 39 | Run test suit 40 | 41 | ```bash 42 | gulp test 43 | ``` 44 | 45 | Run test suit with watch and reload test every change on source files 46 | 47 | ```bash 48 | gulp tdd 49 | ``` 50 | 51 | Create a folder dist, with de minify version of the files. This files are ready 52 | for production environments. 53 | 54 | ```bash 55 | gulp serve:dist 56 | ``` 57 | 58 | A local server to serve the files on dist folder. 59 | 60 | ### End to End test with protractor 61 | 62 | You have to install protractor 63 | 64 | ``` 65 | npm install -g protractor 66 | webdriver-manager update 67 | ``` 68 | 69 | And then to run the test start a selenium webdriver server 70 | 71 | ``` 72 | webdriver-manager start 73 | ``` 74 | 75 | Later start the server 76 | 77 | ``` 78 | gulp serve 79 | ``` 80 | 81 | Last run the test 82 | 83 | ``` 84 | gulp 2e2 85 | ``` 86 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | browserify = require("browserify"), 3 | source = require('vinyl-source-stream'), 4 | babelify = require("babelify"), 5 | webserver = require('gulp-webserver'), 6 | htmlmin = require('gulp-htmlmin'), 7 | uglify = require('gulp-uglify'), 8 | minifyCss = require('gulp-minify-css'), 9 | uuid = require('node-uuid'), 10 | rename = require("gulp-rename"), 11 | concat = require("gulp-concat"), 12 | ngHtml2Js = require("gulp-ng-html2js"), 13 | inject = require('gulp-inject'), 14 | es = require('event-stream'), 15 | del = require('del'), 16 | Q = require('q'), 17 | streamify = require('gulp-streamify'), 18 | globbing = require('gulp-css-globbing'), 19 | ngAnnotate = require('gulp-ng-annotate'), 20 | Server = require('karma').Server, 21 | protractor = require('gulp-protractor').protractor, 22 | envify = require('envify'), 23 | sass = require('gulp-sass'); 24 | 25 | var source_paths = { 26 | sass: './source/sass/app.scss', 27 | js: './source/app.js', 28 | all_sass: './source/**/*.scss', 29 | all_js: './source/**/*.js', 30 | all_html: './source/**/*.html', 31 | images: './sources/images/**/*', 32 | html_index: './source/index.html', 33 | partials: './source/components/**/*.html', 34 | partials_dest: './source/partials', 35 | dev_css: './build/css', 36 | dev_js: './build/js', 37 | dev_html: './build/', 38 | prod_css: './dist/css', 39 | prod_js: './dist/js', 40 | prod_html: './dist', 41 | unit_test: __dirname + '/test/karma.conf.js', 42 | protractor_test: './test/protractor.conf.js', 43 | e2e: ['./test/e2e/**/*.js'], 44 | } 45 | 46 | tasks = { 47 | baseBrowserify: function() { 48 | return browserify([source_paths.js], { 49 | transform: [ 50 | 'babelify' 51 | ]}) 52 | .transform('envify') 53 | .bundle() 54 | .on('error', function(e) { console.log(e.message) }) 55 | .pipe(source('app.js')) 56 | }, 57 | prodBrowserify: function() { 58 | return tasks.baseBrowserify() 59 | .pipe(ngAnnotate()) 60 | .pipe(streamify(uglify())) 61 | .pipe(rename(tasks.assetProdName('js'))) 62 | .pipe(gulp.dest(source_paths.prod_js)) 63 | }, 64 | devBrowserify: function() { 65 | return tasks.baseBrowserify() 66 | .pipe(gulp.dest(source_paths.dev_js)); 67 | }, 68 | prodCss: function() { 69 | return gulp.src(source_paths.sass) 70 | .pipe(globbing({extensions: ['.scss']})) 71 | .pipe(sass.sync().on('error', sass.logError)) 72 | .pipe(minifyCss({compatibility: 'ie8'})) 73 | .pipe(rename(tasks.assetProdName('css'))) 74 | .pipe(gulp.dest(source_paths.prod_css)); 75 | }, 76 | copyImages: function(type) { 77 | return gulp.src(source_paths.images) 78 | .pipe(gulp.dest('./'+type+'/images')); 79 | }, 80 | devCss: function() { 81 | return gulp.src(source_paths.sass) 82 | .pipe(globbing({extensions: ['.scss']})) 83 | .pipe(sass.sync().on('error', sass.logError)) 84 | .pipe(gulp.dest(source_paths.dev_css)); 85 | }, 86 | injectHtml: function(dest, injected_files) { 87 | return gulp.src(source_paths.html_index) 88 | .pipe(inject(injected_files, 89 | { 90 | ignorePath: ['dist', 'build', 'source'], 91 | removeTags: true, 92 | })) 93 | .pipe(gulp.dest(dest)) 94 | }, 95 | BaseNgHtml: function(dest) { 96 | return gulp.src(source_paths.partials) 97 | .pipe(htmlmin({ 98 | empty: true, 99 | spare: true, 100 | quotes: true 101 | })) 102 | .pipe(ngHtml2Js({ 103 | moduleName: "App.partialsPrecompile" 104 | })) 105 | .pipe(concat("index.js")) 106 | .pipe(gulp.dest(dest)) 107 | }, 108 | assetProdName: function(type) { 109 | var name = "app-" + uuid.v1() + "." + type; 110 | return name 111 | }, 112 | } 113 | 114 | gulp.task('clean', function() { 115 | var deferred = Q.defer(); 116 | del(source_paths.prod_html, function() { 117 | deferred.resolve(); 118 | }); 119 | return deferred.promise; 120 | }); 121 | 122 | gulp.task('sass', tasks.devCss) 123 | 124 | gulp.task('browserify', tasks.devBrowserify) 125 | 126 | gulp.task('ngHtml', function() { 127 | return tasks.BaseNgHtml(source_paths.partials_dest) 128 | }) 129 | 130 | gulp.task('inject', ['ngHtml'], function() { 131 | return tasks.injectHtml( 132 | source_paths.dev_html, 133 | es.merge(tasks.devCss(), tasks.copyImages('build'),tasks.devBrowserify()) 134 | ) 135 | }) 136 | 137 | gulp.task('inject:prod',['ngHtml'], function() { 138 | return tasks.injectHtml( 139 | source_paths.prod_html, 140 | es.merge(tasks.prodCss(), tasks.copyImages('dist'), tasks.prodBrowserify()) 141 | ) 142 | }); 143 | 144 | gulp.task('build', ['inject']) 145 | 146 | gulp.task('build:watch', ['build'], function() { 147 | gulp.watch(source_paths.all_sass, ['sass']) 148 | gulp.watch(source_paths.all_js, ['browserify']) 149 | gulp.watch(source_paths.all_html, ['inject']) 150 | }); 151 | 152 | gulp.task('dist', ['clean','inject:prod']); 153 | 154 | gulp.task('serve', ['build:watch'],function() { 155 | return gulp.src('build') 156 | .pipe(webserver({open: true, livereload: true})); 157 | }); 158 | 159 | gulp.task('serve:dist',function() { 160 | return gulp.src('dist') 161 | .pipe(webserver({open: true})); 162 | }); 163 | 164 | /** 165 | * * Run test once and exit 166 | * */ 167 | gulp.task('test', ['build'] ,function (done) { 168 | return new Server({ 169 | configFile: source_paths.unit_test, 170 | singleRun: true 171 | }, done).start(); 172 | }); 173 | 174 | /** 175 | * * Watch for file changes and re-run tests on each change 176 | * */ 177 | gulp.task('tdd', ['build:watch'], function (done) { 178 | return new Server({ 179 | configFile: source_paths.unit_test 180 | }, done).start(); 181 | }); 182 | 183 | gulp.task('e2e', function() { 184 | return gulp.src(source_paths.e2e) 185 | .pipe(protractor({ 186 | configFile: source_paths.protractor_test, 187 | })) 188 | .on('error', function(e) { throw e }) 189 | }) 190 | 191 | gulp.task('default', ['build']); 192 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-starter-kit", 3 | "version": "1.0.0", 4 | "description": "My angular default project schema", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://www.github.com/escuelaweb/intro-angular" 12 | }, 13 | "author": "Sergio Marin", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "angular": "^1.5.3", 17 | "angular-mocks": "^1.4.7", 18 | "angular-ui-router": "^0.2.18", 19 | "babelify": "^6.3.0", 20 | "browserify": "^11.2.0", 21 | "del": "^2.0.2", 22 | "envify": "^3.4.0", 23 | "event-stream": "^3.3.1", 24 | "gulp": "^3.9.0", 25 | "gulp-concat": "^2.6.0", 26 | "gulp-css-globbing": "^0.1.8", 27 | "gulp-htmlmin": "^1.1.4", 28 | "gulp-inject": "^3.0.0", 29 | "gulp-karma": "*", 30 | "gulp-minify-css": "^1.2.1", 31 | "gulp-ng-annotate": "^1.1.0", 32 | "gulp-ng-html2js": "^0.2.0", 33 | "gulp-rename": "^1.2.2", 34 | "gulp-sass": "^2.0.4", 35 | "gulp-streamify": "^1.0.2", 36 | "gulp-uglify": "^1.4.1", 37 | "gulp-webserver": "^0.9.1", 38 | "jasmine-core": "^2.3.4", 39 | "karma": "^0.13.22", 40 | "karma-browserify": "^5.0.3", 41 | "karma-chrome-launcher": "^0.2.3", 42 | "karma-jasmine": "^0.3.8", 43 | "karma-phantomjs-launcher": "^1.0.0", 44 | "node-uuid": "^1.4.3", 45 | "phantomjs-prebuilt": "^2.1.7", 46 | "q": "^1.4.1", 47 | "uglifyify": "^3.0.1", 48 | "vinyl-source-stream": "^1.1.0", 49 | "watchify": "^3.7.0" 50 | }, 51 | "dependencies": { 52 | "gulp-protractor": "^1.0.0", 53 | "protractor": "^2.5.1" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /source/app.js: -------------------------------------------------------------------------------- 1 | import angular from 'angular' 2 | import components from './components' 3 | import services from './services' 4 | import partials from './partials' 5 | import routes from './conf/routes' 6 | 7 | angular.module('App', [ 8 | 'App.components', 9 | 'App.partialsPrecompile', 10 | 'App.services', 11 | 'App.routes' 12 | ]) 13 | 14 | /* 15 | * You can add environment variables using envify and this sintax 16 | * 17 | const node_env = process.env.NODE_ENV || 'development' 18 | 19 | angular.module('App').constant('ENV', { 20 | app_name: 'New app', 21 | type: node_env, 22 | }) 23 | */ 24 | 25 | angular.bootstrap(document.body, ['App']) 26 | 27 | // angular.module('App').run(function() { 28 | // console.log('Running Angular with browserify') 29 | // }) 30 | -------------------------------------------------------------------------------- /source/components/example_controller/example.scss: -------------------------------------------------------------------------------- 1 | 2 | .home-page { 3 | color: blue; 4 | .example-directive { 5 | border: blue 1px solid; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /source/components/example_controller/index.js: -------------------------------------------------------------------------------- 1 | export default function(ngComponent) { 2 | ngComponent.controller('exampleController', ExampleController) 3 | 4 | function ExampleController($scope, exampleFactory) { 5 | $scope.helloMessage = "Hello from a controller router" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /source/components/example_controller/tempate.html: -------------------------------------------------------------------------------- 1 | 2 |