├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── README.md ├── generators └── app │ ├── angular.png │ ├── index.js │ ├── prompts.json │ ├── src │ ├── files.js │ ├── install.js │ ├── modules.js │ ├── prompts.js │ └── utils.js │ └── templates │ ├── _.babelrc │ ├── _.eslintrc.json │ ├── _.gitignore │ ├── _config │ └── webpack │ │ ├── environments │ │ ├── development.js │ │ └── production.js │ │ └── global.js │ ├── _e2e │ └── main.component.spec.js │ ├── _karma.conf.js │ ├── _package.json │ ├── _postcss.config.js │ ├── _protractor.conf.js │ ├── _spec.bundle.js │ ├── _src │ ├── _app │ │ ├── _components │ │ │ └── _footer │ │ │ │ ├── footer.component.js │ │ │ │ ├── footer.controller.js │ │ │ │ ├── footer.html │ │ │ │ ├── footer.module.js │ │ │ │ └── footer.scss │ │ ├── _core │ │ │ ├── _directives │ │ │ │ └── validation-test │ │ │ │ │ └── validation-test.directive.js │ │ │ ├── _services │ │ │ │ ├── constants.js │ │ │ │ ├── resolver.provider.js │ │ │ │ └── store.factory.js │ │ │ └── core.module.js │ │ ├── _index.bootstrap.js │ │ ├── _index.components.js │ │ ├── _index.config.js │ │ ├── _index.module.js │ │ ├── _index.routes.js │ │ ├── _index.run.js │ │ ├── _index.vendor.js │ │ └── _pages │ │ │ ├── async-page-example │ │ │ ├── async.controller.js │ │ │ ├── async.html │ │ │ ├── async.module.js │ │ │ └── async.scss │ │ │ └── main │ │ │ ├── main.component.js │ │ │ ├── main.controller.js │ │ │ ├── main.controller.spec.js │ │ │ ├── main.html │ │ │ └── main.module.js │ ├── _assets │ │ ├── _images │ │ │ ├── angular.png │ │ │ └── yeoman.png │ │ └── _styles │ │ │ └── _sass │ │ │ └── _index.scss │ ├── _favicon.ico │ └── _tpl-index.ejs │ └── _webpack.config.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea/ 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - v5 4 | - v4 5 | - '0.12' 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v1.0.5 (2017-11-22) 2 | 3 | Features: 4 | 5 | - Replace footer directive example with component one. Thanks @dannymy 6 | 7 | ## v1.0.4 (2017-09-17) 8 | 9 | Features: 10 | 11 | - Updated Webpack to v.3 (PR #25, thanks @dannymy) 12 | - Updated UI-router package repo paths (PR #22, thanks @lenin-anzen) 13 | 14 | ## v1.0.0 (2017-02-21) 15 | 16 | Features: 17 | 18 | - Updated Webpack core to latest 19 | - Removed all require statements and replaced with imports 20 | - Add PostCSS config file in application root folder 21 | - Small changes in async page load path 22 | 23 | Bugfixes: 24 | 25 | - Fix alias paths 26 | - Fix images url-loader path 27 | - Fix webpack config to support latest version 28 | 29 | 30 | ## v0.5.0 (2017-02-5) 31 | 32 | Bugfixes: 33 | 34 | - Freeze webpack version 2.2.0-rc3 to solve "exports is not defined" error 35 | 36 | ## v0.4.1 (2016-11-16) 37 | 38 | Features: 39 | 40 | - Updated Webpack config to 2.1.0@beta27 version 41 | - Add small roadmap to README.md 42 | 43 | Bugfixes: 44 | 45 | - Fixed npm run scripts for all platforms 46 | 47 | ## v0.3.2 (2016-10-30) 48 | 49 | Features: 50 | 51 | - Updated Webpack to 2.1.x version 52 | - Updated Babel packages 53 | 54 | Bugfixes: 55 | 56 | - Minor changes in imports structure for more proper vendor packages initialization 57 | 58 | Performane: 59 | 60 | - Provide full support of Webpack@2 Tree Shaking support with Babel integration 61 | 62 | ## v0.2.0 (2016-04-22) 63 | 64 | Features: 65 | 66 | - Updated Babel codebase from 5 to 6 67 | - Added ES2017 preset with polyfills 68 | 69 | Bugfixes: 70 | 71 | - Fixed IE bugs related to ES2017 syntax -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # generator-angular-webpack-es6 2 | 3 | [![NPM Version](http://img.shields.io/npm/v/generator-angular-webpack-es6.svg?style=flat-square)](https://www.npmjs.com/package/generator-angular-webpack-es6) 4 | [![Download Month](http://img.shields.io/npm/dm/generator-angular-webpack-es6.svg?style=flat-square)](https://www.npmjs.com/package/generator-angular-webpack-es6) 5 | 6 |
7 | generator-angular-webpack-es6 8 |
9 | 10 | > Yeoman generator for AngularJS + Webpack with ES6 and SASS. 11 | 12 | > * Latest Webpack with Tree Shaking feature enabled 13 | > * Babel 6 with ES2017 features included 14 | > * Perfectly compatible with angularOcLazyLoad plugin 15 | > * SASS as CSS preprocessor 16 | > * Angular UI router as default router already included 17 | > * Optional installation bootstrap-sass source 18 | > * Optional angular modules installation 19 | > * All necessary webpack loaders already included (Sass, Images, Fonts, ngAnnotate, ngTemplateCache, etc.) 20 | > * Config has options for development and production mode 21 | 22 | > Use only webpack with npm. No external dependencies like bower, grunt, gulp... 23 | 24 | > Webpack@2 still in Beta and it may contain some bugs. Please, report them to Webpack developers directly. 25 | 26 | ### Install 27 | 28 | ##### Install required tools `yo`, and `webpack`: 29 | ``` 30 | npm install -g yo webpack 31 | ``` 32 | 33 | ##### Install `generator-angular-webpack-es6`: 34 | ``` 35 | npm install -g generator-angular-webpack-es6 36 | ``` 37 | 38 | ### Directory Layout 39 | 40 | ```shell 41 | 42 | ├── /e2e/ # End to End test folder 43 | │ └── main.component.spec.js # End to end test example 44 | ├── /config/ # Build config 45 | │ └── /webpack/ # Webpack config files 46 | │ ├── /environments/ # Webpack env dependent configs 47 | │ └── global.js # Global webpack settings for all envs 48 | ├── /dist/ # The folder for compiled output 49 | ├── /node_modules/ # 3rd-party libraries and utilities 50 | ├── /src/ # Source folder 51 | │ ├── /app/ # Application code 52 | │ │ ├── /components/ # Shared UI components 53 | │ │ │ └── /footer/ # Footer shared component. Place footer's styles, directives, templates here 54 | │ │ ├── /core/ # Shared angular services/directives 55 | │ │ │ ├── /directives/ # Shared directives 56 | │ │ │ ├── /services/ # Shared services 57 | │ │ │ └── /core.module.js # Import of all core components should be here 58 | │ │ ├── /pages/ # All pages-dependent content should place here 59 | │ │ │ ├── /main/ # Main page 60 | │ │ │ │ ├── /main.controller.js # Main page Controller 61 | │ │ │ │ ├── /main.controller.spec.js # Test file for main page controller 62 | │ │ │ │ ├── /main.html # Main page template 63 | │ │ │ │ ├── /main.module.js # Main page module 64 | │ │ │ │ └── /main.route.js # Main page routes 65 | │ │ │ └── /.../ # Other pages... 66 | │ │ ├── /index.bootstrap.js # Entry point. Import internal and external modules and bootstrap (RUN) angular application 67 | │ │ ├── /index.components.js # Define all your custom components here 68 | │ │ ├── /index.config.js # Function that will be triggered in Angular's "config" phase 69 | │ │ ├── /index.module.js # Main application's module 70 | │ │ ├── /index.routes.js # Describe only "otherwise" and async routes here 71 | │ │ ├── /index.run.js # Function that will be triggered in Angular's "run" phase 72 | │ │ ├── /index.vendor.js # Import all vendors and 3rd party plugins here 73 | │ ├── /assets/ # Static content 74 | │ │ ├── /images/ # Images 75 | │ │ ├── /js/ # Extra libs folder 76 | │ │ └── /styles/ # Styles folder 77 | │ │ ├── /css/ # CSS 78 | │ │ └── /sass/ # SASS 79 | │ ├── favicon.ico # Application icon to be displayed in bookmarks 80 | │ └── tpl-index.html # Template for html-webpack-plugin that will be transpiled into index.html in /dist 81 | │── .babelrc # Babel config with presets and plugins 82 | │── .gitignore # List of files to ignore by git 83 | │── karma.conf.js # Karma config 84 | │── protractor.conf.js # protractor config 85 | │── spec.bundle.js # The bundle file for including in karma config 86 | │── package.json # The list of project dependencies and NPM scripts 87 | └── webpack.config.js # Bundling and optimization settings for Webpack 88 | ``` 89 | 90 | ### Run 91 | 92 | ##### Create a new directory, and go into: 93 | ``` 94 | mkdir my-new-project && cd $_ 95 | ``` 96 | 97 | ##### Run `yo angular-webpack-es6`, and select desired technologies. 98 | ##### `npm start` or `npm run dev` - to start development server on http://localhost:8080. 99 | ##### `npm run build` - To make production-ready build run after few moments you will see build id `dist` folder. 100 | 101 | ### Test 102 | ##### Unit testing 103 | The app uses [Karma](http://karma-runner.github.io/2.0/index.html) to run the unit tests, which you can find near the test target (*.spec.js files). see example test in the above directory structure. 104 | For running these tests run this command in project directory: 105 | ``` 106 | npm test 107 | ``` 108 | This command will automatically watch for changes that happening in test files 109 | and rerun the test suite 110 | To disable the above behaviour , please check package.json file 111 | 112 | ##### End-to-end testing 113 | The app uses [Protractor](https://github.com/angular/protractor), an end-to-end test framework designed for AngularJS apps, to the end-to-end tests, which you can find in the e2e folder. 114 | 115 | ##### Setup development environment for running end-to-end tests 116 | * First make sure that you did `npm install`. 117 | * Download the necessary binaries for Selenium Server `npm run webdriver-update`. 118 | * Open onother command line and run the development server `npm start` and make sure the running port match the baseUrl port in protractor.conf.js file. 119 | * Finally run `npm run test:e2e`. 120 | 121 | ##### Example tests 122 | * Check the example test for unit tests using jasmin api in 123 | ``` 124 | /src/app/pages/main/main.controller.spec.js 125 | ``` 126 | All your unit test files must end with `.spec.js` 127 | 128 | * Check the example test for e2e test in e2e directory. 129 | ``` 130 | /e2e/main.component.spec.js 131 | ``` 132 | 133 | 134 | ### Known bugs: 135 | > * **Problem**: Webpack2 unable to import function with only export default value. 136 | 137 | > **Workaround**: Use ```import * as variable from "package" ``` instead of ```import variable from "package" ``` 138 | 139 | > * **Problem**: Webpack3: ExtractTextPlugin and file-loader do not work with the use syntax. [Link to the issue](https://github.com/webpack/extract-text-webpack-plugin/issues/275). 140 | 141 | ### Contribute 142 | 143 | ##### If you want to contribute: 144 | > * Fork repository and clone project to your machine 145 | > * Install npm packages and create new feature/fix branch 146 | > * Link local project to be able install generator with `yo` from folder like from global installed package: 147 | > ``` npm link ``` 148 | > * Make PR 149 | > * ... 150 | > * PROFIT 151 | 152 | #### TODO: 153 | > * Add .dockerfile 154 | > * ~~Add example testing environment with karma and protractor~~ 155 | > * Add more dotfiles 156 | > * ~~Add better examples with lazy-loaded modules~~ Added in 0.1.2 157 | > * ~~Update to Babel6~~ Added in 0.2.0 158 | 159 | #### Inspired by [generator-gulp-angular](https://github.com/Swiip/generator-gulp-angular) project. 160 | -------------------------------------------------------------------------------- /generators/app/angular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/STUkh/generator-angular-webpack-es6/ade677841ef9fd8a8471d959e8c9fb2cece0bc62/generators/app/angular.png -------------------------------------------------------------------------------- /generators/app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var yeoman = require('yeoman-generator').Base; 4 | var yosay = require('yosay'); 5 | var chalk = require('chalk'); 6 | var pkg = require('../../package.json'); 7 | 8 | var AngularWebpackES6Generator = yeoman.extend({ 9 | 10 | greeting: function () { 11 | this.log(yosay( 12 | 'Welcome to the great ' + chalk.red('angular-webpack-es6') + ' generator!' 13 | )); 14 | }, 15 | 16 | constructor: function () { 17 | yeoman.apply(this, arguments); 18 | 19 | // Define arguments 20 | this.argument('appName', { 21 | type: String, 22 | required: false 23 | }); 24 | 25 | this.version = pkg.version; 26 | 27 | this.props = {}; 28 | } 29 | 30 | }); 31 | 32 | 33 | require('./src/prompts')(AngularWebpackES6Generator); 34 | require('./src/modules')(AngularWebpackES6Generator); 35 | require('./src/files')(AngularWebpackES6Generator); 36 | require('./src/install')(AngularWebpackES6Generator); 37 | 38 | 39 | module.exports = AngularWebpackES6Generator; -------------------------------------------------------------------------------- /generators/app/prompts.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "input", 4 | "name": "appName", 5 | "message": "Your application name", 6 | "default": "myNgApp" 7 | }, 8 | { 9 | "type": "confirm", 10 | "name": "bootstrapSass", 11 | "message": "Would you like to include Bootstrap for Sass?", 12 | "default": true 13 | }, 14 | { 15 | "type": "checkbox", 16 | "name": "angularModules", 17 | "message": "What Angular modules would you like to have?", 18 | "choices": [ 19 | { 20 | "value": { 21 | "key": "animate", 22 | "module": "ngAnimate", 23 | "package": "angular-animate" 24 | }, 25 | "name": "angular-animate.js (enable animation features)", 26 | "checked": true 27 | }, 28 | { 29 | "value": { 30 | "key": "cookies", 31 | "module": "ngCookies", 32 | "package": "angular-cookies" 33 | }, 34 | "name": "angular-cookies.js (handle cookie management)", 35 | "checked": true 36 | }, 37 | { 38 | "value": { 39 | "key": "touch", 40 | "module": "ngTouch", 41 | "package": "angular-touch" 42 | }, 43 | "name": "angular-touch.js (for mobile development)", 44 | "checked": true 45 | }, 46 | { 47 | "value": { 48 | "key": "sanitize", 49 | "module": "ngSanitize", 50 | "package": "angular-sanitize" 51 | }, 52 | "name": "angular-sanitize.js (to securely parse and manipulate HTML)", 53 | "checked": true 54 | }, 55 | { 56 | "value": { 57 | "key": "messages", 58 | "module": "ngMessages", 59 | "package": "angular-messages" 60 | }, 61 | "name": "angular-messages.js (enhanced support for displaying messages within templates)", 62 | "checked": true 63 | }, 64 | { 65 | "value": { 66 | "key": "aria", 67 | "module": "ngAria", 68 | "package": "angular-aria" 69 | }, 70 | "name": "angular-aria.js (support for common ARIA attributes)", 71 | "checked": true 72 | } 73 | ] 74 | }, 75 | { 76 | "type": "list", 77 | "name": "jQuery", 78 | "message": "Do you need jQuery?", 79 | "choices": [ 80 | { 81 | "value": { 82 | "key": "jquery3", 83 | "package": "jquery@3" 84 | }, 85 | "name": "jQuery 3.x (new version, lighter, modular, IE9+)" 86 | }, 87 | { 88 | "value": { 89 | "key": "jquery2", 90 | "package": "jquery@2" 91 | }, 92 | "name": "jQuery 2.x (IE9+)" 93 | }, 94 | { 95 | "value": { 96 | "key": "jquery1", 97 | "package": "jquery@1" 98 | }, 99 | "name": "jQuery 1.x (branch still supporting IE6, 7 and 8)" 100 | }, 101 | { 102 | "value": { 103 | "key": "jqLite" 104 | }, 105 | "name": "None (Angular will use its own jqLite)" 106 | } 107 | ] 108 | }, 109 | { 110 | "type": "list", 111 | "name": "resource", 112 | "message": "Would you like to use a REST resource library?", 113 | "choices": [ 114 | { 115 | "value": { 116 | "key": "angular-resource", 117 | "module": "ngResource", 118 | "package": "angular-resource" 119 | }, 120 | "name": "ngResource, the official support for RESTful services" 121 | }, 122 | { 123 | "value": { 124 | "key": "restangular", 125 | "module": "restangular", 126 | "package": "restangular" 127 | }, 128 | "name": "Restangular, an alternative service to handle RESTful requests" 129 | }, 130 | { 131 | "value": { 132 | "key": "$http", 133 | "module": null 134 | }, 135 | "name": "None, $http is enough!" 136 | } 137 | ] 138 | }, 139 | { 140 | "type": "confirm", 141 | "name": "lodash", 142 | "message": "Would you like to include Lodash - A modern JavaScript utility library delivering modularity, performance & extras.", 143 | "default": true 144 | }, 145 | { 146 | "type": "confirm", 147 | "name": "moment", 148 | "message": "Would you like to include Moment.js - Library for parse, validate, manipulate, and display dates in JavaScript.", 149 | "default": true 150 | }, 151 | { 152 | "type": "confirm", 153 | "name": "eslint", 154 | "message": "Would you like to include ESLint - A configurable linter tool for identifying and reporting on patterns in your JavaScript code.", 155 | "default": true 156 | }, 157 | { 158 | "type": "confirm", 159 | "name": "ocLazyLoad", 160 | "message": "Would you like to include angularOclazyLoad plugin to load angular modules asynchronously.", 161 | "default": true 162 | } 163 | ] 164 | -------------------------------------------------------------------------------- /generators/app/src/files.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var mkdirp = require('mkdirp'); 4 | 5 | module.exports = function (AngularWebpackES6Generator) { 6 | 7 | AngularWebpackES6Generator.prototype.copyFiles = function copyFiles() { 8 | mkdirp("src"); 9 | mkdirp("e2e"); 10 | mkdirp("src/assets"); 11 | mkdirp("src/assets/images"); 12 | mkdirp("src/assets/js"); 13 | 14 | this.fs.copyTpl( 15 | this.templatePath('_package.json'), 16 | this.destinationPath('package.json'), 17 | this 18 | ); 19 | this.fs.copyTpl( 20 | this.templatePath('_webpack.config.js'), 21 | this.destinationPath('webpack.config.js'), 22 | this 23 | ); 24 | this.fs.copyTpl( 25 | this.templatePath('_postcss.config.js'), 26 | this.destinationPath('postcss.config.js'), 27 | this 28 | ); 29 | this.fs.copy( 30 | this.templatePath('_.gitignore'), 31 | this.destinationPath('.gitignore') 32 | ); 33 | this.fs.copy( 34 | this.templatePath('_.babelrc'), 35 | this.destinationPath('.babelrc') 36 | ); 37 | this.fs.copy( 38 | this.templatePath('_.eslintrc.json'), 39 | this.destinationPath('.eslintrc.json') 40 | ); 41 | 42 | this.fs.copy( 43 | this.templatePath('_karma.conf.js'), 44 | this.destinationPath('karma.conf.js') 45 | ); 46 | 47 | this.fs.copyTpl( 48 | this.templatePath('_spec.bundle.js'), 49 | this.destinationPath('spec.bundle.js'), 50 | this 51 | ); 52 | 53 | this.fs.copy( 54 | this.templatePath('_protractor.conf.js'), 55 | this.destinationPath('protractor.conf.js') 56 | ); 57 | 58 | this.fs.copyTpl( 59 | this.templatePath('_config/**/*'), 60 | this.destinationPath('config/'), 61 | this 62 | ); 63 | 64 | this.fs.copy( 65 | this.templatePath('_src/_favicon.ico'), 66 | this.destinationPath('src/favicon.ico') 67 | ); 68 | this.fs.copy( 69 | this.templatePath('_src/_tpl-index.ejs'), 70 | this.destinationPath('src/tpl-index.ejs') 71 | ); 72 | this.fs.copyTpl( 73 | this.templatePath('_src/_assets/_styles/_sass/_index.scss'), 74 | this.destinationPath('src/assets/styles/sass/index.scss'), 75 | this 76 | ); 77 | this.fs.copy( 78 | this.templatePath('_src/_assets/_images/**/*'), 79 | this.destinationPath('src/assets/images') 80 | ); 81 | this.fs.copyTpl( 82 | this.templatePath('_src/_app/_index.bootstrap.js'), 83 | this.destinationPath('src/app/index.bootstrap.js'), 84 | this 85 | ); 86 | this.fs.copyTpl( 87 | this.templatePath('_src/_app/_index.module.js'), 88 | this.destinationPath('src/app/index.module.js'), 89 | this 90 | ); 91 | this.fs.copy( 92 | this.templatePath('_src/_app/_index.components.js'), 93 | this.destinationPath('src/app/index.components.js') 94 | ); 95 | this.fs.copy( 96 | this.templatePath('_src/_app/_index.config.js'), 97 | this.destinationPath('src/app/index.config.js') 98 | ); 99 | this.fs.copyTpl( 100 | this.templatePath('_src/_app/_index.routes.js'), 101 | this.destinationPath('src/app/index.routes.js'), 102 | this 103 | ); 104 | this.fs.copy( 105 | this.templatePath('_src/_app/_index.run.js'), 106 | this.destinationPath('src/app/index.run.js') 107 | ); 108 | this.fs.copyTpl( 109 | this.templatePath('_src/_app/_index.vendor.js'), 110 | this.destinationPath('src/app/index.vendor.js'), 111 | this 112 | ); 113 | 114 | this.fs.copy( 115 | this.templatePath('_src/_app/_components/_footer/**/*'), 116 | this.destinationPath('src/app/components/footer') 117 | ); 118 | 119 | this.fs.copy( 120 | this.templatePath('_src/_app/_core/core.module.js'), 121 | this.destinationPath('src/app/core/core.module.js') 122 | ); 123 | 124 | this.fs.copy( 125 | this.templatePath('_src/_app/_core/_directives/**/*'), 126 | this.destinationPath('src/app/core/directives') 127 | ); 128 | 129 | this.fs.copyTpl( 130 | this.templatePath('_src/_app/_core/_services/**/*'), 131 | this.destinationPath('src/app/core/services'), 132 | this 133 | ); 134 | 135 | this.fs.copyTpl( 136 | this.templatePath('_src/_app/_pages/main/**/*'), 137 | this.destinationPath('src/app/pages/main'), 138 | this 139 | ); 140 | 141 | this.fs.copyTpl( 142 | this.templatePath('_e2e/**/*'), 143 | this.destinationPath('e2e'), 144 | this 145 | ); 146 | 147 | if (this.props.ocLazyLoad) { 148 | this.fs.copy( 149 | this.templatePath('_src/_app/_pages/async-page-example/**/*'), 150 | this.destinationPath('src/app/pages/async-page-example') 151 | ); 152 | } 153 | }; 154 | 155 | }; 156 | -------------------------------------------------------------------------------- /generators/app/src/install.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require("lodash"); 4 | 5 | module.exports = function (AngularWebpackES6Generator) { 6 | 7 | // Install optional dependencies 8 | AngularWebpackES6Generator.prototype.installDependencies = function installDependencies() { 9 | 10 | var deps = [ 11 | "angular", 12 | "@uirouter/angularjs" 13 | ]; 14 | 15 | if (this.props.bootstrapSass) { 16 | deps.push("bootstrap-sass"); 17 | } 18 | 19 | if (this.props.lodash) { 20 | deps.push("lodash"); 21 | } 22 | 23 | if (this.props.moment) { 24 | deps.push("moment"); 25 | } 26 | 27 | if (this.props.eslint) { 28 | deps.push('eslint', 'eslint-loader'); 29 | } 30 | 31 | deps = _.concat(deps, this.installList); 32 | 33 | this.npmInstall(deps, { 'save': true }); 34 | }; 35 | 36 | // Install dependencies from package.json 37 | AngularWebpackES6Generator.prototype.install = function install() { 38 | this.npmInstall(); 39 | }; 40 | 41 | }; -------------------------------------------------------------------------------- /generators/app/src/modules.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require('lodash'); 4 | var utils = require("./utils"); 5 | 6 | module.exports = function (AngularWebpackES6Generator) { 7 | 8 | var imports = []; 9 | 10 | AngularWebpackES6Generator.prototype.defaultImports = function defaultImports() { 11 | imports.push(this.props.resource); 12 | 13 | if (this.props.ocLazyLoad) { 14 | imports.push({ 15 | module: "oc.lazyLoad", 16 | package: "oclazyload" 17 | }); 18 | } 19 | 20 | }; 21 | 22 | /** 23 | * Compute Angular's module to load and format the dependency list to insert 24 | */ 25 | AngularWebpackES6Generator.prototype.computeModules = function computeModules() { 26 | var ngModules = this.props.angularModules.map(function (module) { 27 | return module.module; 28 | }); 29 | 30 | imports.forEach(function (mod) { 31 | if (mod.module) { 32 | ngModules.push(mod.module); 33 | } 34 | }); 35 | 36 | this.modulesDependencies = ngModules 37 | .filter(_.isString) 38 | .map(function (dependency) { 39 | return '\"' + dependency + '\"'; 40 | }) 41 | .join(', \r\n\t'); 42 | }; 43 | 44 | /** 45 | * Simplify the model to simplify access to angular modules from the templates 46 | */ 47 | AngularWebpackES6Generator.prototype.prepareAngularModules = function prepareAngularModules() { 48 | this.angularModulesObject = {}; 49 | 50 | this.props.angularModules.forEach(function (module) { 51 | this[module.key] = module.module; 52 | }, this.angularModulesObject); 53 | }; 54 | 55 | /** 56 | * Prepare list for vendor imports 57 | */ 58 | AngularWebpackES6Generator.prototype.prepareImportsList = function prepareImportsList() { 59 | 60 | this.installList = []; 61 | 62 | imports.forEach(function (mod) { 63 | if (mod.module && mod.package) { 64 | this.installList.push(mod.package); 65 | } 66 | }, this); 67 | 68 | _.forEach(this.props, function(section) { 69 | 70 | if (_.isArray(section)) { 71 | section.forEach(function(prop) { 72 | if (utils.isHasPackage(prop)) { 73 | this.installList.push(utils.stripPackageName(prop.package)); 74 | } 75 | }, this); 76 | } else if (utils.isHasPackage(section)) { 77 | this.installList.push(section.package); 78 | } 79 | 80 | }.bind(this)); 81 | 82 | this.importList = this.installList.map(function (pkg) { 83 | return utils.stripPackageName(pkg); 84 | }); 85 | 86 | }; 87 | 88 | }; 89 | -------------------------------------------------------------------------------- /generators/app/src/prompts.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require('lodash'); 4 | var chalk = require('chalk'); 5 | 6 | var prompts = require('../prompts.json'); 7 | 8 | function logChoice(prompt, prop) { 9 | var choice = _.find(prompt.choices, {value: prop}); 10 | this.log('\t*', choice.name); 11 | } 12 | 13 | module.exports = function (AngularWebpackES6Generator) { 14 | 15 | /** 16 | * Check if the default option is set, if it is, use defaults props and log them 17 | */ 18 | AngularWebpackES6Generator.prototype.defaultOption = function defaultOption() { 19 | if (this.options.default) { 20 | 21 | this.log('__________________________'); 22 | this.log('You use ' + chalk.green('--default') + ' option:'); 23 | 24 | _.forEach(this.props, function (propOrProps, key) { 25 | var prompt = _.find(prompts, {name: key}); 26 | if (_.isArray(propOrProps)) { 27 | propOrProps.forEach(function (prop) { 28 | logChoice.call(this, prompt, prop); 29 | }, this); 30 | } else { 31 | logChoice.call(this, prompt, propOrProps); 32 | } 33 | }, this); 34 | 35 | this.log('__________________________\n'); 36 | } 37 | }; 38 | 39 | /** 40 | * Ask all questions from prompts.json 41 | * Add conditional tests on those depending on first responses 42 | * Complete responses with null answers for questions not asked 43 | */ 44 | AngularWebpackES6Generator.prototype.askQuestions = function askQuestions() { 45 | if (this.skipConfig || this.options.default) { 46 | return; 47 | } 48 | 49 | var done = this.async(); 50 | 51 | this.prompt(prompts, function (props) { 52 | 53 | this.props = _.merge(this.props, props); 54 | 55 | done(); 56 | }.bind(this)); 57 | }; 58 | 59 | }; -------------------------------------------------------------------------------- /generators/app/src/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require("lodash"); 4 | 5 | module.exports = { 6 | isHasPackage: function (obj) { 7 | return _.isObject(obj) && obj.package && obj.import !== false; 8 | }, 9 | stripPackageName: function (pkgName) { 10 | var regexp = /(.*?)@/; 11 | var match = pkgName.match(regexp); 12 | if (match) { 13 | return match[1]; 14 | } 15 | return pkgName; 16 | } 17 | } -------------------------------------------------------------------------------- /generators/app/templates/_.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "angularjs-annotate" 4 | ], 5 | "presets": [ 6 | "stage-1", 7 | ["es2015", { "modules": false }], 8 | "es2017" 9 | ] 10 | } -------------------------------------------------------------------------------- /generators/app/templates/_.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 6, 4 | "sourceType": "module" 5 | }, 6 | "extends": "eslint:recommended", 7 | "rules": { 8 | "eqeqeq": "warn", 9 | "no-fallthrough": "off", 10 | "no-shadow": "warn", 11 | "arrow-body-style": ["warn", "as-needed"], 12 | "arrow-parens": ["warn", "as-needed"], 13 | "no-var": "error" 14 | }, 15 | "globals": { 16 | "angular": false, 17 | "describe": false, 18 | "beforeEach": false, 19 | "it": false, 20 | "expect": false 21 | }, 22 | "env": { 23 | "browser": true, 24 | "node": true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /generators/app/templates/_.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | bower_components/ 3 | .sass-cache/ 4 | .idea/ 5 | .tmp/ 6 | true!ng-annotate/ 7 | dist/ 8 | -------------------------------------------------------------------------------- /generators/app/templates/_config/webpack/environments/development.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var webpack = require('webpack'); 3 | 4 | module.exports = function(_path) { 5 | return { 6 | context: _path, 7 | devtool: 'source-map', 8 | devServer: { 9 | contentBase: './dist', 10 | hot: true, 11 | inline: true 12 | }, 13 | plugins: [ 14 | new webpack.HotModuleReplacementPlugin() 15 | ] 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /generators/app/templates/_config/webpack/environments/production.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var CleanWebpackPlugin = require('clean-webpack-plugin'); 3 | var webpack = require('webpack'); 4 | 5 | module.exports = function(_path) { 6 | return { 7 | context: _path, 8 | devtool: 'source-map', 9 | output: { 10 | publicPath: '/', 11 | filename: '[name].[chunkhash].js' 12 | }, 13 | plugins: [ 14 | new CleanWebpackPlugin(['dist'], { 15 | root: _path, 16 | verbose: true, 17 | dry: false 18 | }), 19 | new webpack.optimize.UglifyJsPlugin({ 20 | minimize: true, 21 | warnings: false, 22 | sourceMap: true, 23 | }) 24 | ] 25 | }; 26 | }; -------------------------------------------------------------------------------- /generators/app/templates/_config/webpack/global.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var webpack = require('webpack'); 5 | var autoprefixer = require('autoprefixer'); 6 | var Manifest = require('manifest-revision-webpack-plugin'); 7 | var ExtractTextPlugin = require("extract-text-webpack-plugin"); 8 | var HtmlWebpackPlugin = require("html-webpack-plugin"); 9 | 10 | var rootPublic = path.resolve('./src'); 11 | var NODE_ENV = process.env.NODE_ENV || "production"; 12 | var DEVELOPMENT = NODE_ENV === "production" ? false : true; 13 | var stylesLoader = 'css-loader?root=' + rootPublic + '&sourceMap!postcss-loader!sass-loader?outputStyle=expanded&sourceMap=true&sourceMapContents=true'; 14 | 15 | module.exports = function (_path) { 16 | var rootAssetPath = _path + 'src'; 17 | 18 | var webpackConfig = { 19 | // entry points 20 | entry: { 21 | app: _path + '/src/app/index.bootstrap.js' 22 | }, 23 | 24 | // output system 25 | output: { 26 | path: _path + '/dist', 27 | filename: '[name].js', 28 | publicPath: '/' 29 | }, 30 | 31 | // resolves modules 32 | resolve: { 33 | extensions: ['.js', '.es6', '.jsx', '.scss', '.css'], 34 | alias: { 35 | _appRoot: path.join(_path, 'src', 'app'), 36 | _images: path.join(_path, 'src', 'assets', 'images'), 37 | _stylesheets: path.join(_path, 'src', 'assets', 'styles'), 38 | _scripts: path.join(_path, 'src', 'assets', 'js') 39 | } 40 | }, 41 | 42 | // modules resolvers 43 | module: { 44 | rules: [{ 45 | test: /\.html$/, 46 | use: [ 47 | { 48 | loader: 'ngtemplate-loader', 49 | options: { 50 | relativeTo: path.join(_path, '/src') 51 | } 52 | }, 53 | { 54 | loader: 'html-loader', 55 | options: { 56 | attrs: ['img:src', 'img:data-src'] 57 | } 58 | } 59 | ] 60 | },<% if (props.eslint) { %> { 61 | test: /\.js$/, 62 | exclude: [ 63 | path.resolve(_path, "node_modules") 64 | ], 65 | enforce: 'pre', 66 | use: [ 67 | { 68 | loader: 'eslint-loader' 69 | } 70 | ] 71 | },<% } %> { 72 | test: /\.js$/, 73 | exclude: [ 74 | path.resolve(_path, "node_modules") 75 | ], 76 | use: [ 77 | { 78 | loader: 'babel-loader', 79 | options: { 80 | cacheDirectory: false 81 | } 82 | }, 83 | { 84 | loader: 'baggage-loader?[file].html&[file].css' 85 | } 86 | ] 87 | }, { 88 | test: /\.css$/, 89 | use: [ 90 | { 91 | loader: 'style-loader' 92 | }, 93 | { 94 | loader: 'css-loader?sourceMap' 95 | }, 96 | { 97 | loader: 'postcss-loader' 98 | } 99 | ] 100 | }, { 101 | test: /\.(scss|sass)$/, 102 | loader: DEVELOPMENT ? ('style-loader!' + stylesLoader) : ExtractTextPlugin.extract({ 103 | fallbackLoader: "style-loader", 104 | loader: stylesLoader 105 | }) 106 | }, { 107 | test: /\.(woff2|woff|ttf|eot|svg)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, 108 | use: [ 109 | { 110 | loader: 'url-loader', 111 | options: { 112 | name: 'assets/fonts/[name]_[hash].[ext]' 113 | } 114 | } 115 | ] 116 | }, { 117 | test: /\.(jpe?g|png|gif)$/i, 118 | use: [ 119 | { 120 | loader: 'url-loader', 121 | options: { 122 | name: 'assets/images/[name]_[hash].[ext]', 123 | limit: 10000 124 | } 125 | } 126 | ] 127 | } 128 | ] 129 | }, 130 | 131 | // load plugins 132 | plugins: [ 133 | new webpack.LoaderOptionsPlugin({ 134 | options: { 135 | // PostCSS 136 | postcss: [autoprefixer({browsers: ['last 5 versions']})], 137 | } 138 | }), 139 | new webpack.ProvidePlugin({ 140 | <% if (props.jQuery.key !== 'jqLite') { %> 141 | $: 'jquery', 142 | jQuery: 'jquery', 143 | 'window.jQuery': 'jquery', 144 | 'window.jquery': 'jquery', 145 | <% } %> 146 | <% if (props.moment) { %> 147 | moment: 'moment', 148 | 'window.moment': 'moment', 149 | <% } %> 150 | <% if (props.lodash) { %> 151 | _: 'lodash', 152 | 'window._': 'lodash', 153 | <% } %> 154 | }), 155 | new webpack.DefinePlugin({ 156 | 'NODE_ENV': JSON.stringify(NODE_ENV) 157 | }), 158 | new webpack.NoEmitOnErrorsPlugin(), 159 | new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), 160 | new webpack.optimize.AggressiveMergingPlugin({ 161 | moveToParents: true 162 | }), 163 | new webpack.optimize.CommonsChunkPlugin({ 164 | name: 'common', 165 | async: true, 166 | children: true, 167 | minChunks: Infinity 168 | }), 169 | new Manifest(path.join(_path + '/config', 'manifest.json'), { 170 | rootAssetPath: rootAssetPath, 171 | ignorePaths: ['.DS_Store'] 172 | }), 173 | new ExtractTextPlugin({ 174 | filename: 'assets/styles/css/[name]' + (NODE_ENV === 'development' ? '' : '.[chunkhash]') + '.css', 175 | allChunks: true 176 | }), 177 | new HtmlWebpackPlugin({ 178 | filename: 'index.html', 179 | template: path.join(_path, 'src', 'tpl-index.ejs') 180 | }) 181 | ] 182 | }; 183 | 184 | return webpackConfig; 185 | 186 | }; 187 | -------------------------------------------------------------------------------- /generators/app/templates/_e2e/main.component.spec.js: -------------------------------------------------------------------------------- 1 | 2 | describe('Main Page', function() { 3 | 4 | 5 | beforeEach(function() { 6 | browser.get('/#/'); 7 | }); 8 | 9 | it('should go to the correct url', function() { 10 | browser.get('/#/'); 11 | 12 | 13 | browser.getLocationAbsUrl().then(function(url) { 14 | expect(url.split('/').pop()).toBe(''); 15 | }); 16 | 17 | }); 18 | 19 | }); -------------------------------------------------------------------------------- /generators/app/templates/_karma.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var ExtractTextPlugin = require("extract-text-webpack-plugin"); 3 | var rootPublic = path.resolve('./src'); 4 | var DEVELOPMENT = true; 5 | var stylesLoader = 'css-loader?root=' + rootPublic + '&sourceMap!postcss-loader!sass-loader?outputStyle=expanded&sourceMap=true&sourceMapContents=true'; 6 | 7 | module.exports = function (config) { 8 | config.set({ 9 | // base path used to resolve all patterns 10 | basePath: '', 11 | 12 | // frameworks to use 13 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 14 | frameworks: ['jasmine'], 15 | 16 | // list of files/patterns to load in the browser 17 | files: [{ pattern: 'spec.bundle.js', watched: false }], 18 | 19 | // files to exclude 20 | exclude: [], 21 | 22 | plugins: [ 23 | require("karma-phantomjs-launcher"), 24 | require("karma-jasmine"), 25 | require("karma-sourcemap-loader"), 26 | require("karma-webpack") 27 | ], 28 | 29 | // preprocess matching files before serving them to the browser 30 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 31 | preprocessors: { 'spec.bundle.js': ['webpack', 'sourcemap'] }, 32 | 33 | webpack: { 34 | devtool: 'inline-source-map', 35 | module: { 36 | loaders: [{ 37 | test: /\.html$/, 38 | use: [ 39 | { 40 | loader: 'ngtemplate-loader', 41 | options: { 42 | relativeTo: path.join(__dirname, '/src') 43 | } 44 | }, 45 | { 46 | loader: 'html-loader', 47 | options: { 48 | attrs: ['img:src', 'img:data-src'] 49 | } 50 | } 51 | ] 52 | }, { 53 | test: /\.js$/, 54 | exclude: [ 55 | path.resolve(__dirname, "node_modules") 56 | ], 57 | enforce: 'pre', 58 | use: [ 59 | { 60 | loader: 'eslint-loader' 61 | } 62 | ] 63 | }, { 64 | test: /\.js$/, 65 | exclude: [ 66 | path.resolve(__dirname, "node_modules") 67 | ], 68 | use: [ 69 | { 70 | loader: 'babel-loader', 71 | options: { 72 | cacheDirectory: false 73 | } 74 | }, 75 | { 76 | loader: 'baggage-loader?[file].html&[file].css' 77 | } 78 | ] 79 | }, { 80 | test: /\.css$/, 81 | use: [ 82 | { 83 | loader: 'style-loader' 84 | }, 85 | { 86 | loader: 'css-loader?sourceMap' 87 | }, 88 | { 89 | loader: 'postcss-loader' 90 | } 91 | ] 92 | }, { 93 | test: /\.(scss|sass)$/, 94 | loader: DEVELOPMENT ? ('style-loader!' + stylesLoader) : ExtractTextPlugin.extract({ 95 | fallbackLoader: "style-loader", 96 | loader: stylesLoader 97 | }) 98 | }, { 99 | test: /\.(woff2|woff|ttf|eot|svg)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, 100 | use: [ 101 | { 102 | loader: 'url-loader', 103 | options: { 104 | name: 'assets/fonts/[name]_[hash].[ext]' 105 | } 106 | } 107 | ] 108 | }, { 109 | test: /\.(jpe?g|png|gif)$/i, 110 | use: [ 111 | { 112 | loader: 'url-loader', 113 | options: { 114 | name: 'assets/images/[name]_[hash].[ext]', 115 | limit: 10000 116 | } 117 | } 118 | ] 119 | } 120 | ] 121 | } 122 | }, 123 | 124 | webpackServer: { 125 | noInfo: true // prevent console spamming when running in Karma! 126 | }, 127 | 128 | // web server port 129 | port: 9876, 130 | 131 | // enable colors in the output 132 | colors: true, 133 | 134 | // level of logging 135 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 136 | logLevel: config.LOG_INFO, 137 | 138 | // toggle whether to watch files and rerun tests upon incurring changes 139 | autoWatch: false, 140 | 141 | // start these browsers 142 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 143 | browsers: ['PhantomJS'], 144 | 145 | // if true, Karma runs tests once and exits 146 | singleRun: false 147 | }); 148 | }; 149 | -------------------------------------------------------------------------------- /generators/app/templates/_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%- props.appName %>", 3 | "version": "0.1.0", 4 | "description": "Angular Webpack ES6 application generated by generator-angular-webpack-es6", 5 | "homepage": "", 6 | "bin": { 7 | "cross-env": "./node_modules/cross-env/bin/cross-env.js", 8 | "webpack": "./node_modules/webpack/bin/webpack.js", 9 | "webpack-dev-server": "./node_modules/webpack-dev-server/bin/webpack-dev-server.js" 10 | }, 11 | "scripts": { 12 | "start": "npm run dev", 13 | "dev": "cross-env NODE_ENV=development webpack-dev-server --progress --bail --open", 14 | "build": "cross-env NODE_ENV=production webpack -p --colors", 15 | "test": "karma start --auto-watch", 16 | "test:e2e": "protractor protractor.conf.js", 17 | "webdriver-update": "node node_modules/protractor/bin/webdriver-manager update" 18 | }, 19 | "dependencies": { 20 | "@uirouter/angularjs": "^1.0.15", 21 | "angular": "^1.6.9", 22 | "angular-animate": "^1.6.9", 23 | "angular-aria": "^1.6.9", 24 | "angular-cookies": "^1.6.9", 25 | "angular-messages": "^1.6.9", 26 | "angular-mocks": "^1.6.9", 27 | "angular-resource": "^1.6.9", 28 | "angular-sanitize": "^1.6.9", 29 | "angular-touch": "^1.6.9", 30 | "assets-webpack-plugin": "^3.4.0", 31 | "autoprefixer": "^6.5.0", 32 | "babel-core": "^6.14.0", 33 | "babel-loader": "^6.2.5", 34 | "babel-plugin-angularjs-annotate": "^0.5.2", 35 | "babel-preset-es2015": "^6.16.0", 36 | "babel-preset-es2017": "^6.16.0", 37 | "babel-preset-stage-1": "^6.16.0", 38 | "baggage-loader": "^0.2.4", 39 | "clean-webpack-plugin": "^0.1.10", 40 | "cross-env": "^3.0.0", 41 | "css-loader": "^0.25.0", 42 | "es6-promise": "^4.0.3", 43 | "eslint": "^4.18.0", 44 | "eslint-loader": "^1.5.0", 45 | "extract-text-webpack-plugin": "^2.0.0-beta.4", 46 | "file-loader": "^0.9.0", 47 | "font-awesome": "^4.6.3", 48 | "html-loader": "^0.4.4", 49 | "html-webpack-plugin": "^2.22.0", 50 | "imagemin-pngquant": "^5.0.0", 51 | "jasmine": "^3.0.0", 52 | "jasmine-spec-reporter": "^4.2.1", 53 | "jquery": "^3.3.1", 54 | "karma": "^2.0.0", 55 | "karma-chrome-launcher": "^2.2.0", 56 | "karma-jasmine": "^1.1.1", 57 | "karma-phantomjs-launcher": "^1.0.4", 58 | "karma-sourcemap-loader": "^0.3.7", 59 | "karma-webpack": "^2.0.9", 60 | "lodash": "^4.17.5", 61 | "manifest-revision-webpack-plugin": "^0.3.0", 62 | "moment": "^2.20.1", 63 | "ng-storage": "^0.3.2", 64 | "ngtemplate-loader": "^1.3.1", 65 | "node-sass": "^4.9.3", 66 | "phantomjs-prebuilt": "^2.1.16", 67 | "postcss-loader": "^0.13.0", 68 | "protractor": "^5.3.0", 69 | "sass-loader": "^4.0.2", 70 | "style-loader": "^0.13.1", 71 | "url": "^0.11.0", 72 | "url-loader": "^0.5.7", 73 | "webpack": "^3.5.0", 74 | "webpack-dev-server": "^2.2.0" 75 | }, 76 | "engines": { 77 | "node": ">=0.12.0" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /generators/app/templates/_postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; -------------------------------------------------------------------------------- /generators/app/templates/_protractor.conf.js: -------------------------------------------------------------------------------- 1 | exports.config = { 2 | framework: 'jasmine', 3 | baseUrl: 'http://localhost:8081', 4 | suites: { 5 | all: [ 6 | './e2e/**/*.js' 7 | ] 8 | }, 9 | suite: 'all', 10 | capabilities: { 11 | browserName: 'chrome' 12 | }, 13 | onPrepare: function onPrepare() { 14 | require('babel-core/register'); 15 | 16 | var SpecReporter = require('jasmine-spec-reporter').SpecReporter; 17 | jasmine.getEnv().addReporter(new SpecReporter({ 18 | displayStacktrace: 'none', 19 | prefixes: { 20 | success: '+ ', 21 | failure: 'x ', 22 | pending: '* ' 23 | } 24 | })); 25 | 26 | browser.manage().window().setSize(1280, 1024); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /generators/app/templates/_spec.bundle.js: -------------------------------------------------------------------------------- 1 | /* 2 | * When testing with Webpack and ES6, we have to do some 3 | * preliminary setup. Because we are writing our tests also in ES6, 4 | * we must transpile those as well, which is handled inside 5 | * `karma.conf.js` via the `karma-webpack` plugin. This is the entry 6 | * file for the Webpack tests. Similarly to how Webpack creates a 7 | * `bundle.js` file for the compressed app source files, when we 8 | * run our tests, Webpack, likewise, compiles and bundles those tests here. 9 | */ 10 | 11 | import "angular"; 12 | 13 | import "@uirouter/angularjs"; 14 | 15 | <% for(var i=0; i 16 | import "<%= importList[i] %>"; 17 | <% } %> 18 | 19 | // Built by the core Angular team for mocking dependencies 20 | import 'angular-mocks'; 21 | 22 | // import './src/app/index.bootstrap'; 23 | 24 | // We use the context method on `require` which Webpack created 25 | // in order to signify which files we actually want to require or import. 26 | // Below, `context` will be a/an function/object with file names as keys. 27 | // Using that regex, we scan within `src/app` and target 28 | // all files ending with `.spec.js` and trace its path. 29 | // By passing in true, we permit this process to occur recursively. 30 | let context = require.context('./src/app', true, /\.spec\.js/); 31 | 32 | // Get all files, for each file, call the context function 33 | // that will require the file and load it here. Context will 34 | // loop and require those spec files here. 35 | context.keys().forEach(context); 36 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_components/_footer/footer.component.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import footerTpl from './footer.html'; 4 | import FooterController from './footer.controller'; 5 | 6 | export default class FooterComponent { 7 | constructor() { 8 | this.templateUrl = footerTpl; 9 | this.controller = FooterController; 10 | } 11 | } -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_components/_footer/footer.controller.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default class FooterController { 4 | constructor($log) { 5 | 'ngInject'; 6 | this.$log = $log; 7 | } 8 | 9 | $onInit() { 10 | this.$log.log('Hello from the footer component controller!'); 11 | } 12 | } -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_components/_footer/footer.html: -------------------------------------------------------------------------------- 1 |
2 |

© Footer example directive

3 |
-------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_components/_footer/footer.module.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import FooterComponent from './footer.component'; 4 | import './footer.scss'; 5 | 6 | const footerModule = angular.module('footer-module', []); 7 | 8 | footerModule 9 | .component('footerTest', new FooterComponent()); 10 | 11 | export default footerModule; 12 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_components/_footer/footer.scss: -------------------------------------------------------------------------------- 1 | footer-test { 2 | position: absolute; 3 | bottom: 0; 4 | 5 | width: 100%; 6 | height: 60px; 7 | 8 | padding: 15px 0; 9 | 10 | background-color: #f5f5f5; 11 | } -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_core/_directives/validation-test/validation-test.directive.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default function (app) { 4 | 5 | app.directive('validationTest', validationTestDirective); 6 | 7 | function validationTestDirective () { 8 | 'ngInject'; 9 | 10 | return { 11 | restrict: 'A', 12 | link: linkFn, 13 | require: 'ngModel' 14 | }; 15 | 16 | function linkFn (scope, elem, attrs, ngModelCtrl) { 17 | scope.$watch(attrs.ngModel, newVal => { 18 | if (newVal === 'test') { 19 | ngModelCtrl.$setValidity('test', true); 20 | } else { 21 | ngModelCtrl.$setValidity('test', false); 22 | } 23 | }); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_core/_services/constants.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default function (app) { 4 | app 5 | .constant('ROUTE_ERRORS', { 6 | auth: 'Authorization has been denied.', 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_core/_services/resolver.provider.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default function (app) { 4 | app.provider('resolver', resolverProvider); 5 | 6 | function resolverProvider () { 7 | this.asyncPagePrealoading = asyncPagePrealoading; 8 | this.$get = function() { return this; }; 9 | } 10 | 11 | <% if (props.ocLazyLoad) { %> 12 | function asyncPagePrealoading ($q, $ocLazyLoad) { 13 | "ngInject"; 14 | 15 | const deferred = $q.defer(); 16 | require.ensure([], (require) => { 17 | const asyncModule = require('../../pages/async-page-example/async.module'); 18 | $ocLazyLoad.load({ 19 | name: asyncModule.default.name, 20 | }); 21 | deferred.resolve(asyncModule.default.controller); 22 | }); 23 | return deferred.promise; 24 | } 25 | <% } else { %> 26 | function asyncPagePrealoading ($q) { 27 | "ngInject"; 28 | 29 | const defer = $q.defer(); 30 | // Some async stuff (request, calculations, etc.) 31 | return defer.promise; 32 | } 33 | <% } %> 34 | 35 | } 36 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_core/_services/store.factory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default function (app) { 4 | app 5 | .factory('store', storeFactory); 6 | 7 | function storeFactory () { 8 | return { 9 | "countries": ["USA", "UK", "Ukraine"] 10 | }; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_core/core.module.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const shared = angular.module('core.shared', []); 4 | 5 | import validationTestDirective from './directives/validation-test/validation-test.directive'; 6 | 7 | import constants from './services/constants'; 8 | import storeFactory from './services/store.factory'; 9 | import resolverProvider from './services/resolver.provider'; 10 | 11 | validationTestDirective(shared); 12 | 13 | constants(shared); 14 | storeFactory(shared); 15 | resolverProvider(shared); 16 | 17 | export default shared; 18 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_index.bootstrap.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // index.html page to dist folder 4 | import '!!file-loader?name=[name].[ext]!../favicon.ico'; 5 | 6 | // vendor files 7 | import "./index.vendor"; 8 | 9 | // main App module 10 | import "./index.module"; 11 | 12 | import "../assets/styles/sass/index.scss"; 13 | 14 | angular.element(document).ready(() => { 15 | angular.bootstrap(document, ['<%= props.appName %>'], { 16 | strictDi: true 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_index.components.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import footerModule from './components/footer/footer.module'; 4 | 5 | export default angular.module('index.components', [ 6 | footerModule.name 7 | ]); 8 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_index.config.js: -------------------------------------------------------------------------------- 1 | /*global NODE_ENV*/ 2 | 'use strict'; 3 | 4 | function config($logProvider, $compileProvider) { 5 | 'ngInject'; 6 | 7 | $logProvider.debugEnabled(true); 8 | 9 | if (NODE_ENV === 'production') { 10 | $logProvider.debugEnabled(false); 11 | $compileProvider.debugInfoEnabled(false); 12 | } 13 | 14 | 15 | } 16 | 17 | export default config; 18 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_index.module.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import config from './index.config'; 4 | import run from './index.run'; 5 | 6 | import uiRouter from '@uirouter/angularjs'; 7 | 8 | import coreModule from './core/core.module'; 9 | import indexComponents from './index.components'; 10 | import indexRoutes from './index.routes'; 11 | import mainModule from './pages/main/main.module'; 12 | 13 | 14 | const App = angular.module( 15 | "<%= props.appName %>", [ 16 | // plugins 17 | uiRouter, 18 | <%- modulesDependencies %>, 19 | 20 | // core 21 | coreModule.name, 22 | 23 | // components 24 | indexComponents.name, 25 | 26 | // routes 27 | indexRoutes.name, 28 | 29 | // pages 30 | mainModule.name 31 | 32 | ] 33 | ); 34 | 35 | App 36 | .config(config) 37 | .run(run); 38 | 39 | 40 | 41 | export default App; 42 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_index.routes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | <% if (props.ocLazyLoad) { %> 4 | import asyncTemplate from '!!file-loader?name=templates/[name].[ext]!./pages/async-page-example/async.html'; 5 | <% } %> 6 | 7 | function routeConfig($urlRouterProvider<% if (props.ocLazyLoad) { %>, $stateProvider, resolverProvider<% } %>) { 8 | 'ngInject'; 9 | 10 | <% if (props.ocLazyLoad) { %> 11 | $stateProvider 12 | .state('async', { 13 | url: '/async', 14 | templateUrl: asyncTemplate, 15 | controller: 'asyncController', 16 | resolve: { 17 | asyncPreloading: resolverProvider.asyncPagePrealoading 18 | } 19 | }); 20 | <% } %> 21 | 22 | $urlRouterProvider.otherwise('/'); 23 | 24 | } 25 | 26 | export default angular 27 | .module('index.routes', []) 28 | .config(routeConfig); 29 | 30 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_index.run.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function runBlock($log) { 4 | 'ngInject'; 5 | 6 | $log.debug('Hello from run block!'); 7 | } 8 | 9 | export default runBlock; 10 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_index.vendor.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // node_modules 4 | import "angular"; 5 | 6 | import "@uirouter/angularjs"; 7 | 8 | <% for(var i=0; i 9 | import "<%= importList[i] %>"; 10 | <% } %> 11 | 12 | 13 | // local scripts 14 | //import "../assets/js/..."; 15 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_pages/async-page-example/async.controller.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function MainController($log) { 4 | 'ngInject'; 5 | 6 | $log.debug('Hello from Lazy Loaded controller!'); 7 | 8 | } 9 | 10 | export default MainController; 11 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_pages/async-page-example/async.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Hello, from the dark side Lazy Loaded page!!!

4 |

Just set resolve rule with require.ensure statement and then use angularOcLazyLoad to init module

5 |
6 |
7 | 8 |
 9 |     resolve: {
10 |         modulePreloading: function($q, $ocLazyLoad) {
11 |             "ngInject";
12 | 
13 |             var deferred = $q.defer();
14 | 
15 |             require.ensure([], function (require) {
16 |               var asyncModule = require('./async.module');
17 |               $ocLazyLoad.load({
18 |                 name: asyncModule.default.name,
19 |               });
20 | 
21 |               deferred.resolve(asyncModule.default.controller);
22 |             });
23 | 
24 |             return deferred.promise;
25 |         }
26 |     }
27 | 
-------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_pages/async-page-example/async.module.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import './async.scss'; 4 | 5 | import asyncController from './async.controller.js'; 6 | 7 | const asyncModule = angular.module('async-module', []); 8 | 9 | asyncModule.controller('asyncController', asyncController); 10 | 11 | export default asyncModule; -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_pages/async-page-example/async.scss: -------------------------------------------------------------------------------- 1 | .jumbotron.async-box { 2 | background-color: #000; 3 | color: #fff; 4 | } -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_pages/main/main.component.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import MainController from './main.controller'; 4 | import mainTpl from './main.html'; 5 | 6 | export default class MainComponent { 7 | constructor() { 8 | this.controller = MainController; 9 | this.templateUrl = mainTpl; 10 | } 11 | } -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_pages/main/main.controller.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | <% if (props.lodash) { %> 4 | import _ from 'lodash/core'; 5 | <% } %> 6 | <% if (props.moment) { %> 7 | import moment from 'moment'; 8 | <% } %> 9 | 10 | export default class MainController { 11 | constructor($log) { 12 | 'ngInject'; 13 | this.$log = $log; 14 | this.awesomeThings = ['Angular', 'Webpack', 'babel']; 15 | } 16 | 17 | $onInit() { 18 | <% if (props.lodash) { %> 19 | this.lodash_version = _.VERSION; 20 | <% } %> 21 | <% if (props.moment) { %> 22 | this.moment_version = moment.version; 23 | <% } %> 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_pages/main/main.controller.spec.js: -------------------------------------------------------------------------------- 1 | /* 2 | This file includes an example test 3 | for main component controllerusing es6 4 | */ 5 | 6 | // load the target module for test 7 | import mainModule from './main.module'; 8 | 9 | describe('Main component controller',() => { 10 | // load the module 11 | beforeEach(angular.mock.module(mainModule.name)); 12 | 13 | let $componentController; 14 | 15 | // Initialize the component`s controller provider 16 | beforeEach(() => { 17 | angular.mock.inject(_$componentController_ => { 18 | $componentController = _$componentController_; 19 | }); 20 | }); 21 | 22 | it('AwesomeThings has been defined', () => { 23 | let mainComponentCtrl = $componentController('main', null, {}); 24 | expect(mainComponentCtrl.awesomeThings).toBeDefined(); 25 | }); 26 | 27 | it('AwesomeThings has 3 elements', () => { 28 | let mainComponentCtrl = $componentController('main', null, {}); 29 | expect(mainComponentCtrl.awesomeThings.length).toEqual(3); 30 | }); 31 | }); -------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_pages/main/main.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Hello, world!

4 |

This is a simple angular webpack es6 example, compatible with lazy-loading modules.

5 | <% if (props.lodash) { %> 6 |

Lodash version: {{$ctrl.lodash_version}}

7 | <% } %> 8 | <% if (props.moment) { %> 9 |

Moment version: {{$ctrl.moment_version}}

10 | <% } %> 11 | <% if (props.ocLazyLoad) { %> 12 |

13 | <% } %> 14 |
15 |
16 |
Image source: Model
17 | Angular logo 18 |
19 |
20 |
Image source: URL
21 | Yeoman logo 22 |
23 |
24 |
25 |
-------------------------------------------------------------------------------- /generators/app/templates/_src/_app/_pages/main/main.module.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import MainComponent from './main.component'; 4 | 5 | const mainPageModule = angular.module('main-module', [ 6 | 'ui.router' 7 | ]) 8 | .config(($stateProvider, $urlRouterProvider) => { 9 | 'ngInject'; 10 | 11 | $urlRouterProvider.otherwise('/'); 12 | 13 | $stateProvider 14 | .state('main', { 15 | url: '/', 16 | component: 'main' 17 | }); 18 | }) 19 | .component('main', new MainComponent()); 20 | 21 | export default mainPageModule; 22 | -------------------------------------------------------------------------------- /generators/app/templates/_src/_assets/_images/angular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/STUkh/generator-angular-webpack-es6/ade677841ef9fd8a8471d959e8c9fb2cece0bc62/generators/app/templates/_src/_assets/_images/angular.png -------------------------------------------------------------------------------- /generators/app/templates/_src/_assets/_images/yeoman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/STUkh/generator-angular-webpack-es6/ade677841ef9fd8a8471d959e8c9fb2cece0bc62/generators/app/templates/_src/_assets/_images/yeoman.png -------------------------------------------------------------------------------- /generators/app/templates/_src/_assets/_styles/_sass/_index.scss: -------------------------------------------------------------------------------- 1 | <% if (props.bootstrapSass) { %> 2 | $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; 3 | @import '~bootstrap-sass/assets/stylesheets/_bootstrap.scss'; 4 | <% } %> 5 | 6 | html { height: 100%; } 7 | body { 8 | min-height: 100%; 9 | position: relative; 10 | padding-bottom: 60px; 11 | } -------------------------------------------------------------------------------- /generators/app/templates/_src/_favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/STUkh/generator-angular-webpack-es6/ade677841ef9fd8a8471d959e8c9fb2cece0bc62/generators/app/templates/_src/_favicon.ico -------------------------------------------------------------------------------- /generators/app/templates/_src/_tpl-index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular Webpack ES6 Project 6 | 7 | 8 | 9 | <% for(var i=0; i < htmlWebpackPlugin.files.css; i++) { %> 10 | 11 | <% } %> 12 | 13 | <% for(var i=0; i < htmlWebpackPlugin.files.chunks; i++) { %> 14 | 15 | <% } %> 16 | 17 | 18 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /generators/app/templates/_webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require('lodash'); 4 | var _configs = { 5 | 6 | // global section 7 | global: require(__dirname + '/config/webpack/global'), 8 | 9 | // config by enviroments 10 | production: require(__dirname + '/config/webpack/environments/production'), 11 | development: require(__dirname + '/config/webpack/environments/development') 12 | }; 13 | 14 | var _load = function() { 15 | var ENV = process.env.NODE_ENV 16 | ? process.env.NODE_ENV 17 | : 'production'; 18 | 19 | console.log('Current Environment: ', ENV); 20 | 21 | // load config file by environment 22 | return _configs && _.merge( 23 | _configs.global(__dirname), 24 | _configs[ENV](__dirname) 25 | ); 26 | }; 27 | 28 | module.exports = _load(); 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-angular-webpack-es6", 3 | "version": "1.0.6", 4 | "description": "Angular Webpack ES6 generator. Uses SASS as CSS preprocessor, UI router as default angular router, LazyLoading example included. Inspired by generator-gulp-angular.", 5 | "homepage": "", 6 | "author": { 7 | "name": "alex.stepchenkov", 8 | "email": "stukak@gmail.com", 9 | "url": "github.com/STUkh" 10 | }, 11 | "repository": "STUkh/generator-angular-webpack-es6", 12 | "files": [ 13 | "generators/app" 14 | ], 15 | "main": "generators/app/index.js", 16 | "keywords": [ 17 | "yeoman-generator", 18 | "webpack", 19 | "angular", 20 | "es6", 21 | "es2015", 22 | "generator", 23 | "sass", 24 | "lazy-load" 25 | ], 26 | "dependencies": { 27 | "chalk": "^1.1.1", 28 | "lodash": "^4.5.1", 29 | "mkdirp": "^0.5.1", 30 | "yeoman-generator": "^0.22.5", 31 | "yosay": "^1.1.0" 32 | } 33 | } 34 | --------------------------------------------------------------------------------