├── .babelrc ├── .eslintrc ├── .gitignore ├── README.md ├── package.json ├── src ├── app │ ├── app.config.js │ ├── app.js │ └── components │ │ └── home │ │ ├── capitalize.directive.js │ │ ├── counter.component.js │ │ ├── github.service.js │ │ ├── home.controller.js │ │ ├── home.routes.js │ │ └── index.js ├── public │ └── views │ │ ├── home │ │ ├── counter.html │ │ └── home.html │ │ └── index.html └── style │ └── app.scss └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 6, 4 | "ecmaFeatures": { 5 | "experimentalObjectRestSpread": true, 6 | "jsx": true 7 | }, 8 | "sourceType": "module" 9 | }, 10 | "env": { 11 | "es6": true, 12 | "node": true 13 | }, 14 | "plugins": [ 15 | "standard" 16 | ], 17 | "globals": { 18 | "document": false, 19 | "navigator": false, 20 | "window": false, 21 | "angular": false, 22 | "API_URL": false, 23 | "Stripe": false, 24 | "$state": false, 25 | "STRIPE_KEY": false 26 | }, 27 | "rules": { 28 | "accessor-pairs": 2, 29 | "arrow-spacing": [ 30 | 2, 31 | { 32 | "before": true, 33 | "after": true 34 | } 35 | ], 36 | "block-spacing": [ 37 | 2, 38 | "always" 39 | ], 40 | "brace-style": [ 41 | 2, 42 | "1tbs", 43 | { 44 | "allowSingleLine": true 45 | } 46 | ], 47 | "comma-dangle": [ 48 | 2, 49 | "never" 50 | ], 51 | "comma-spacing": [ 52 | 2, 53 | { 54 | "before": false, 55 | "after": true 56 | } 57 | ], 58 | "comma-style": [ 59 | 2, 60 | "last" 61 | ], 62 | "constructor-super": 2, 63 | "curly": [ 64 | 2, 65 | "multi-line" 66 | ], 67 | "dot-location": [ 68 | 2, 69 | "property" 70 | ], 71 | "eol-last": 2, 72 | "eqeqeq": [ 73 | 2, 74 | "allow-null" 75 | ], 76 | "generator-star-spacing": [ 77 | 2, 78 | { 79 | "before": true, 80 | "after": true 81 | } 82 | ], 83 | "handle-callback-err": [ 84 | 2, 85 | "^(err|error)$" 86 | ], 87 | "indent": [ 88 | 2, 89 | 2, 90 | { 91 | "SwitchCase": 1 92 | } 93 | ], 94 | "jsx-quotes": [ 95 | 2, 96 | "prefer-single" 97 | ], 98 | "key-spacing": [ 99 | 2, 100 | { 101 | "beforeColon": false, 102 | "afterColon": true 103 | } 104 | ], 105 | "keyword-spacing": [ 106 | 2, 107 | { 108 | "before": true, 109 | "after": true 110 | } 111 | ], 112 | "new-cap": [ 113 | 2, 114 | { 115 | "newIsCap": false, 116 | "capIsNew": false 117 | } 118 | ], 119 | "new-parens": 2, 120 | "no-array-constructor": 2, 121 | "no-caller": 2, 122 | "no-class-assign": 2, 123 | "no-cond-assign": 2, 124 | "no-const-assign": 2, 125 | "no-control-regex": 2, 126 | "no-debugger": 2, 127 | "no-delete-var": 2, 128 | "no-dupe-args": 2, 129 | "no-dupe-class-members": 2, 130 | "no-dupe-keys": 2, 131 | "no-duplicate-case": 2, 132 | "no-empty-character-class": 2, 133 | "no-empty-pattern": 2, 134 | "no-eval": 2, 135 | "no-ex-assign": 2, 136 | "no-extend-native": 2, 137 | "no-extra-bind": 2, 138 | "no-extra-boolean-cast": 2, 139 | "no-extra-parens": [ 140 | 2, 141 | "functions" 142 | ], 143 | "no-fallthrough": 2, 144 | "no-floating-decimal": 2, 145 | "no-func-assign": 2, 146 | "no-implied-eval": 2, 147 | "no-inner-declarations": [ 148 | 2, 149 | "functions" 150 | ], 151 | "no-invalid-regexp": 2, 152 | "no-irregular-whitespace": 2, 153 | "no-iterator": 2, 154 | "no-label-var": 2, 155 | "no-labels": [ 156 | 2, 157 | { 158 | "allowLoop": false, 159 | "allowSwitch": false 160 | } 161 | ], 162 | "no-lone-blocks": 2, 163 | "no-mixed-spaces-and-tabs": 2, 164 | "no-multi-spaces": 2, 165 | "no-multi-str": 2, 166 | "no-multiple-empty-lines": [ 167 | 2, 168 | { 169 | "max": 1 170 | } 171 | ], 172 | "no-native-reassign": 2, 173 | "no-negated-in-lhs": 2, 174 | "no-new": 2, 175 | "no-new-func": 2, 176 | "no-new-object": 2, 177 | "no-new-require": 2, 178 | "no-new-symbol": 2, 179 | "no-new-wrappers": 2, 180 | "no-obj-calls": 2, 181 | "no-octal": 2, 182 | "no-octal-escape": 2, 183 | "no-path-concat": 2, 184 | "no-proto": 2, 185 | "no-redeclare": 2, 186 | "no-regex-spaces": 2, 187 | "no-return-assign": [ 188 | 2, 189 | "except-parens" 190 | ], 191 | "no-self-assign": 2, 192 | "no-self-compare": 2, 193 | "no-sequences": 2, 194 | "no-shadow-restricted-names": 2, 195 | "no-spaced-func": 2, 196 | "no-sparse-arrays": 2, 197 | "no-this-before-super": 2, 198 | "no-throw-literal": 2, 199 | "no-trailing-spaces": 2, 200 | "no-undef": 2, 201 | "no-undef-init": 2, 202 | "no-unexpected-multiline": 2, 203 | "no-unneeded-ternary": [ 204 | 2, 205 | { 206 | "defaultAssignment": false 207 | } 208 | ], 209 | "no-unreachable": 2, 210 | "no-unused-vars": [ 211 | 2, 212 | { 213 | "vars": "all", 214 | "args": "none" 215 | } 216 | ], 217 | "no-useless-call": 2, 218 | "no-useless-constructor": 2, 219 | "no-with": 2, 220 | "one-var": [ 221 | 2, 222 | { 223 | "initialized": "never" 224 | } 225 | ], 226 | "operator-linebreak": [ 227 | 2, 228 | "after", 229 | { 230 | "overrides": { 231 | "?": "before", 232 | ":": "before" 233 | } 234 | } 235 | ], 236 | "padded-blocks": [ 237 | 2, 238 | "never" 239 | ], 240 | "quotes": [ 241 | 2, 242 | "single", 243 | "avoid-escape" 244 | ], 245 | "semi": [ 246 | "error", 247 | "always" 248 | ], 249 | "semi-spacing": [ 250 | 2, 251 | { 252 | "before": false, 253 | "after": true 254 | } 255 | ], 256 | "space-before-blocks": [ 257 | 2, 258 | "always" 259 | ], 260 | "space-before-function-paren": [ 261 | 2, 262 | "always" 263 | ], 264 | "space-in-parens": [ 265 | 2, 266 | "never" 267 | ], 268 | "space-infix-ops": 2, 269 | "space-unary-ops": [ 270 | 2, 271 | { 272 | "words": true, 273 | "nonwords": false 274 | } 275 | ], 276 | "spaced-comment": [ 277 | 2, 278 | "always", 279 | { 280 | "markers": [ 281 | "global", 282 | "globals", 283 | "eslint", 284 | "eslint-disable", 285 | "*package", 286 | "!", 287 | "," 288 | ] 289 | } 290 | ], 291 | "template-curly-spacing": [ 292 | 2, 293 | "never" 294 | ], 295 | "use-isnan": 2, 296 | "valid-typeof": 2, 297 | "wrap-iife": [ 298 | 2, 299 | "any" 300 | ], 301 | "yield-star-spacing": [ 302 | 2, 303 | "both" 304 | ], 305 | "yoda": [ 306 | 2, 307 | "never" 308 | ], 309 | "standard/object-curly-even-spacing": [ 310 | 2, 311 | "either" 312 | ], 313 | "standard/array-bracket-even-spacing": [ 314 | 2, 315 | "either" 316 | ], 317 | "standard/computed-property-even-spacing": [ 318 | 2, 319 | "even" 320 | ] 321 | } 322 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | node_modules 3 | dist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Boilerplate Es6 Angular Webpack 2 | 3 | This is a starter kit to get you working with es6 classes and modules within Angular using Webpack. 4 | 5 | ##Basic Setup 6 | 7 | 1. run `git clone https://github.com/nearbycoder/boilerplate-es6-angular-webpack.git` 8 | 2. run `npm install` within the directory the repo is located 9 | 3. run 'npm start' this will start webpack-dev-server on port 8080 10 | 4. From there the root of the app is `/src/app/app.js` 11 | 12 | Take note: I have created a example component called home. This wil show you how to use es6 imports with angular to create a folder module structure for your components. 13 | 14 | ##Build Production 15 | 16 | run `npm run build` 17 | 18 | Take note: this will extract everything into the `./dist` folder as well as, dedupe any code for optimization, uglify the javascript bundle, and copy anything withint he public folder besides the html to the `./dist` folder. The reason why the html is not being copied is because this is all included inside the javascript bundle using [ngtemplate-loader](https://github.com/WearyMonkey/ngtemplate-loader). In addition the styles will be inlined after being comiled into css. 19 | 20 | ### Angular Dependency Minification Info 21 | 22 | As we have come to know and love, when angular is minified if you don't add the necessary array syntax to name your dependencies the minification process will break angular. In order to fix this with less boilerplate this kit includes [ng-annotate](https://github.com/olov/ng-annotate). This means that within our functions/class contstructors we will need to add `'ngInject';` to tell ng-annotate to look at the dependencies and create the necessary minification fixes. 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "boilerplate-es6-angular-webpack", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "build": "rimraf dist && webpack --bail --progress --profile", 7 | "server": "webpack-dev-server --history-api-fallback --inline --progress", 8 | "start": "npm run server" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "babel-core": "^6.7.5", 14 | "babel-eslint": "^6.0.2", 15 | "babel-loader": "^6.2.4", 16 | "babel-preset-es2015": "^6.6.0", 17 | "copy-webpack-plugin": "^1.1.1", 18 | "css-loader": "^0.23.1", 19 | "eslint": "^2.7.0", 20 | "eslint-plugin-standard": "^1.3.2", 21 | "file-loader": "^0.8.5", 22 | "html-loader": "^0.4.3", 23 | "html-webpack-plugin": "^2.15.0", 24 | "ng-annotate-loader": "^0.1.0", 25 | "ngtemplate-loader": "^1.3.1", 26 | "node-sass": "^3.4.2", 27 | "rimraf": "^2.5.2", 28 | "sass-loader": "^3.2.0", 29 | "style-loader": "^0.13.1", 30 | "webpack": "^1.12.14", 31 | "webpack-dev-server": "^1.14.1" 32 | }, 33 | "dependencies": { 34 | "angular": "^1.5.3", 35 | "angular-resource": "^1.5.3", 36 | "angular-ui-router": "^1.0.0-alpha.4" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/app/app.config.js: -------------------------------------------------------------------------------- 1 | export default function routing ($urlRouterProvider, $locationProvider) { 2 | 'ngInject'; 3 | $locationProvider.html5Mode(false); 4 | $urlRouterProvider.otherwise('/'); 5 | }; 6 | -------------------------------------------------------------------------------- /src/app/app.js: -------------------------------------------------------------------------------- 1 | import '../style/app.scss'; 2 | import angular from 'angular'; 3 | import uirouter from 'angular-ui-router'; 4 | import routing from './app.config'; 5 | import home from './components/home'; 6 | 7 | angular.module('app', [uirouter, home]) 8 | .config(routing); 9 | 10 | -------------------------------------------------------------------------------- /src/app/components/home/capitalize.directive.js: -------------------------------------------------------------------------------- 1 | export default class esCapitalize { 2 | constructor () { 3 | this.restrict = 'A'; 4 | } 5 | 6 | link (scope, element) { 7 | element.html(toTitleCase(element.html())); 8 | } 9 | } 10 | 11 | function toTitleCase (str) { 12 | return str.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); }); 13 | }; 14 | -------------------------------------------------------------------------------- /src/app/components/home/counter.component.js: -------------------------------------------------------------------------------- 1 | import templateUrl from 'home/counter.html'; 2 | 3 | class controller { 4 | constructor () { 5 | this.repos.$promise.then(results => { 6 | this.count = results.length; 7 | }); 8 | } 9 | } 10 | 11 | export default { 12 | controller, 13 | templateUrl, 14 | bindings: { 15 | repos: ' new esCapitalize()) 14 | .component('esCounter', esCounter) 15 | .service('githubService', GithubService) 16 | .name; 17 | -------------------------------------------------------------------------------- /src/public/views/home/counter.html: -------------------------------------------------------------------------------- 1 |
2 | The number of repos is {{$ctrl.count}} 3 |
-------------------------------------------------------------------------------- /src/public/views/home/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | {{repo.name}} 5 |
-------------------------------------------------------------------------------- /src/public/views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ES6 Demo Angular Webpack 7 | 8 | 9 | 10 |
11 | 12 | -------------------------------------------------------------------------------- /src/style/app.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nearbycoder/boilerplate-es6-angular-webpack/a59a371a5894d93f68a832e016dd90a566fddc51/src/style/app.scss -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var webpack = require('webpack'); 4 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | var CopyWebpackPlugin = require('copy-webpack-plugin'); 6 | var path = require('path'); 7 | var ENV = process.env.npm_lifecycle_event; 8 | var isProd = ENV === 'build'; 9 | 10 | module.exports = (function makeWebpackConfig () { 11 | var config = {}; 12 | 13 | config.entry = { 14 | app: './src/app/app.js' 15 | }; 16 | 17 | config.output = { 18 | path: path.resolve(__dirname, './dist'), 19 | publicPath: isProd ? '/' : 'http://localhost:8080/', 20 | filename: isProd ? '[name].[hash].js' : '[name].bundle.js', 21 | chunkFilename: isProd ? '[name].[hash].js' : '[name].bundle.js' 22 | }; 23 | 24 | if (isProd) { 25 | config.devtool = 'source-map'; 26 | } else { 27 | config.devtool = 'eval-source-map'; 28 | } 29 | 30 | config.resolve = { 31 | modulesDirectories: [ 32 | 'node_modules', 33 | 'src/public/views' 34 | ] 35 | }; 36 | 37 | config.module = { 38 | preLoaders: [], 39 | loaders: [{ 40 | test: /\.js$/, 41 | loaders: ['ng-annotate', 'babel'], 42 | exclude: /node_modules/ 43 | }, { 44 | test: /\.scss$/, 45 | loaders: ['style', 'css', 'sass'] 46 | }, { 47 | test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/, 48 | loader: 'file' 49 | }, { 50 | test: /\.html$/, 51 | loader: 'ngtemplate?relativeTo=' + (path.resolve(__dirname, './src')) + '/!html', 52 | exclude: /index\.html/ 53 | }] 54 | }; 55 | 56 | config.plugins = []; 57 | 58 | config.plugins.push( 59 | new HtmlWebpackPlugin({ 60 | template: './src/public/views/index.html', 61 | inject: 'body' 62 | }) 63 | ); 64 | 65 | if (isProd) { 66 | config.plugins.push( 67 | new webpack.NoErrorsPlugin(), 68 | new webpack.optimize.DedupePlugin(), 69 | new webpack.optimize.UglifyJsPlugin(), 70 | new CopyWebpackPlugin([{ 71 | from: path.resolve(__dirname, './src/public') 72 | }], { ignore: ['*.html'] }) 73 | ); 74 | } 75 | 76 | config.devServer = { 77 | contentBase: './src/public', 78 | stats: 'minimal' 79 | }; 80 | 81 | return config; 82 | }()); 83 | 84 | --------------------------------------------------------------------------------