From 6558ee2fc448a5bebd8ef5643a9a4d54408d3477 Mon Sep 17 00:00:00 2001 From: smartapant Date: Wed, 20 Apr 2016 16:32:12 +0300 Subject: [PATCH] Initial commit. --- .editorconfig | 16 + .github/CONTRIBUTING.md | 11 + .github/ISSUE_TEMPLATE.md | 36 ++ .github/PULL_REQUEST_TEMPLATE.md | 13 + .gitignore | 61 +++ LICENSE | 22 ++ README.md | 347 ++++++++++++++++++ config/helpers.js | 69 ++++ config/karma.conf.js | 90 +++++ config/protractor.conf.js | 51 +++ config/spec-bundle.js | 59 +++ config/webpack.common.js | 255 +++++++++++++ config/webpack.dev.js | 162 ++++++++ config/webpack.prod.js | 230 ++++++++++++ config/webpack.test.js | 233 ++++++++++++ karma.conf.js | 6 + package.json | 144 ++++++++ protractor.conf.js | 6 + src/app/about/about.component.ts | 55 +++ src/app/about/about.spec.ts | 29 ++ src/app/about/index.ts | 1 + src/app/app.component.ts | 99 +++++ src/app/app.e2e.ts | 32 ++ src/app/app.service.ts | 39 ++ src/app/app.spec.ts | 24 ++ src/app/home/home.component.ts | 46 +++ src/app/home/home.css | 0 src/app/home/home.e2e.ts | 22 ++ src/app/home/home.html | 31 ++ src/app/home/home.spec.ts | 52 +++ src/app/home/index.ts | 1 + src/app/home/title/index.ts | 1 + src/app/home/title/title.service.ts | 20 + src/app/home/title/title.spec.ts | 44 +++ src/app/home/x-large/index.ts | 1 + src/app/home/x-large/x-large.directive.ts | 18 + src/app/home/x-large/x-large.spec.ts | 34 ++ src/app/index.ts | 10 + src/app/router-active/index.ts | 2 + .../router-active/router-active.directive.ts | 73 ++++ src/assets/css/.gitkeep | 1 + src/assets/data.json | 3 + src/assets/humans.txt | 17 + src/assets/icon/android-icon-144x144.png | Bin 0 -> 8433 bytes src/assets/icon/android-icon-192x192.png | Bin 0 -> 9714 bytes src/assets/icon/android-icon-36x36.png | Bin 0 -> 2302 bytes src/assets/icon/android-icon-48x48.png | Bin 0 -> 2925 bytes src/assets/icon/android-icon-72x72.png | Bin 0 -> 4234 bytes src/assets/icon/android-icon-96x96.png | Bin 0 -> 5597 bytes src/assets/icon/apple-icon-114x114.png | Bin 0 -> 6552 bytes src/assets/icon/apple-icon-120x120.png | Bin 0 -> 6924 bytes src/assets/icon/apple-icon-144x144.png | Bin 0 -> 8433 bytes src/assets/icon/apple-icon-152x152.png | Bin 0 -> 8994 bytes src/assets/icon/apple-icon-180x180.png | Bin 0 -> 10999 bytes src/assets/icon/apple-icon-57x57.png | Bin 0 -> 3404 bytes src/assets/icon/apple-icon-60x60.png | Bin 0 -> 3564 bytes src/assets/icon/apple-icon-72x72.png | Bin 0 -> 4234 bytes src/assets/icon/apple-icon-76x76.png | Bin 0 -> 4463 bytes src/assets/icon/apple-icon-precomposed.png | Bin 0 -> 10290 bytes src/assets/icon/apple-icon.png | Bin 0 -> 10290 bytes src/assets/icon/browserconfig.xml | 2 + src/assets/icon/favicon-16x16.png | Bin 0 -> 1523 bytes src/assets/icon/favicon-32x32.png | Bin 0 -> 2066 bytes src/assets/icon/favicon-96x96.png | Bin 0 -> 5597 bytes src/assets/icon/favicon.ico | Bin 0 -> 1150 bytes src/assets/icon/ms-icon-144x144.png | Bin 0 -> 8433 bytes src/assets/icon/ms-icon-150x150.png | Bin 0 -> 8878 bytes src/assets/icon/ms-icon-310x310.png | Bin 0 -> 24136 bytes src/assets/icon/ms-icon-70x70.png | Bin 0 -> 4124 bytes src/assets/img/angular-logo.png | Bin 0 -> 18982 bytes src/assets/img/angularclass-avatar.png | Bin 0 -> 32796 bytes src/assets/img/angularclass-logo.png | Bin 0 -> 36742 bytes src/assets/manifest.json | 41 +++ src/assets/mock-data/mock-data.json | 3 + src/assets/robots.txt | 3 + src/assets/service-worker.js | 1 + src/custom-typings.d.ts | 119 ++++++ src/index.html | 63 ++++ src/main.browser.ts | 58 +++ .../browser/angular2-material2/index.ts | 37 ++ src/platform/browser/directives.ts | 22 ++ src/platform/browser/index.ts | 3 + src/platform/browser/pipes.ts | 14 + src/platform/browser/providers.ts | 34 ++ src/platform/environment.ts | 34 ++ src/polyfills.ts | 28 ++ src/vendor.ts | 36 ++ tsconfig.json | 29 ++ tslint.json | 151 ++++++++ typedoc.json | 15 + typings.json | 15 + webpack.config.js | 19 + 92 files changed, 3193 insertions(+) create mode 100644 .editorconfig create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 config/helpers.js create mode 100644 config/karma.conf.js create mode 100644 config/protractor.conf.js create mode 100644 config/spec-bundle.js create mode 100644 config/webpack.common.js create mode 100644 config/webpack.dev.js create mode 100644 config/webpack.prod.js create mode 100644 config/webpack.test.js create mode 100644 karma.conf.js create mode 100644 package.json create mode 100644 protractor.conf.js create mode 100644 src/app/about/about.component.ts create mode 100644 src/app/about/about.spec.ts create mode 100644 src/app/about/index.ts create mode 100644 src/app/app.component.ts create mode 100644 src/app/app.e2e.ts create mode 100644 src/app/app.service.ts create mode 100644 src/app/app.spec.ts create mode 100644 src/app/home/home.component.ts create mode 100644 src/app/home/home.css create mode 100644 src/app/home/home.e2e.ts create mode 100644 src/app/home/home.html create mode 100644 src/app/home/home.spec.ts create mode 100644 src/app/home/index.ts create mode 100644 src/app/home/title/index.ts create mode 100644 src/app/home/title/title.service.ts create mode 100644 src/app/home/title/title.spec.ts create mode 100644 src/app/home/x-large/index.ts create mode 100644 src/app/home/x-large/x-large.directive.ts create mode 100644 src/app/home/x-large/x-large.spec.ts create mode 100644 src/app/index.ts create mode 100644 src/app/router-active/index.ts create mode 100644 src/app/router-active/router-active.directive.ts create mode 100644 src/assets/css/.gitkeep create mode 100644 src/assets/data.json create mode 100644 src/assets/humans.txt create mode 100644 src/assets/icon/android-icon-144x144.png create mode 100644 src/assets/icon/android-icon-192x192.png create mode 100644 src/assets/icon/android-icon-36x36.png create mode 100644 src/assets/icon/android-icon-48x48.png create mode 100644 src/assets/icon/android-icon-72x72.png create mode 100644 src/assets/icon/android-icon-96x96.png create mode 100644 src/assets/icon/apple-icon-114x114.png create mode 100644 src/assets/icon/apple-icon-120x120.png create mode 100644 src/assets/icon/apple-icon-144x144.png create mode 100644 src/assets/icon/apple-icon-152x152.png create mode 100644 src/assets/icon/apple-icon-180x180.png create mode 100644 src/assets/icon/apple-icon-57x57.png create mode 100644 src/assets/icon/apple-icon-60x60.png create mode 100644 src/assets/icon/apple-icon-72x72.png create mode 100644 src/assets/icon/apple-icon-76x76.png create mode 100644 src/assets/icon/apple-icon-precomposed.png create mode 100644 src/assets/icon/apple-icon.png create mode 100644 src/assets/icon/browserconfig.xml create mode 100644 src/assets/icon/favicon-16x16.png create mode 100644 src/assets/icon/favicon-32x32.png create mode 100644 src/assets/icon/favicon-96x96.png create mode 100644 src/assets/icon/favicon.ico create mode 100644 src/assets/icon/ms-icon-144x144.png create mode 100644 src/assets/icon/ms-icon-150x150.png create mode 100644 src/assets/icon/ms-icon-310x310.png create mode 100644 src/assets/icon/ms-icon-70x70.png create mode 100644 src/assets/img/angular-logo.png create mode 100644 src/assets/img/angularclass-avatar.png create mode 100644 src/assets/img/angularclass-logo.png create mode 100644 src/assets/manifest.json create mode 100644 src/assets/mock-data/mock-data.json create mode 100644 src/assets/robots.txt create mode 100644 src/assets/service-worker.js create mode 100644 src/custom-typings.d.ts create mode 100644 src/index.html create mode 100644 src/main.browser.ts create mode 100644 src/platform/browser/angular2-material2/index.ts create mode 100644 src/platform/browser/directives.ts create mode 100644 src/platform/browser/index.ts create mode 100644 src/platform/browser/pipes.ts create mode 100644 src/platform/browser/providers.ts create mode 100644 src/platform/environment.ts create mode 100644 src/polyfills.ts create mode 100644 src/vendor.ts create mode 100644 tsconfig.json create mode 100644 tslint.json create mode 100644 typedoc.json create mode 100644 typings.json create mode 100644 webpack.config.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..869ff6c5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +# @AngularClass +# http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..23012072 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,11 @@ +## Read and contribute to the Wiki + +Make sure you read the Wiki +https://github.com/AngularClass/angular2-webpack-starter/wiki + +## Submitting Pull Requests +If you're changing the structure of the repository please create an issue first + +## Submitting bug reports + +Make sure you are on latest changes and that you ran this command `npm run clean:install` after updating your local repository. If you can, please provide more infomation about your environment such as browser, operating system, node version, and npm version \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..1b4e0765 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,36 @@ +**Note: for support questions, please use one of these channels:** [Chat: AngularClass.slack](http://angularclass.com/member-join/) or [Twitter: @AngularClass](https://twitter.com/AngularClass) + +* **I'm submitting a ...** +[ ] bug report +[ ] feature request +[ ] question about the decisions made in the repository + +* **Do you want to request a *feature* or report a *bug*?** + + + +* **What is the current behavior?** + + + +* **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem** via +https://plnkr.co or similar (you can use this template as a starting point: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5). + + + +* **What is the expected behavior?** + + + +* **What is the motivation / use case for changing the behavior?** + + + +* **Please tell us about your environment:** + +- Angular version: 2.0.0-beta.X +- Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ] + + + +* **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..caae6b13 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,13 @@ +* **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...) + + + +* **What is the current behavior?** (You can also link to an open issue here) + + + +* **What is the new behavior (if this is a feature change)?** + + + +* **Other information**: diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0d501b76 --- /dev/null +++ b/.gitignore @@ -0,0 +1,61 @@ +# @AngularClass + +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Users Environment Variables +.lock-wscript + +# OS generated files # +.DS_Store +ehthumbs.db +Icon? +Thumbs.db + +# Node Files # +/node_modules +/bower_components +npm-debug.log + +# Coverage # +/coverage/ + +# Typing # +/src/typings/tsd/ +/typings/ +/tsd_typings/ + +# Dist # +/dist +/public/__build__/ +/src/*/__build__/ +/__build__/** +/public/dist/ +/src/*/dist/ +/dist/** +.webpack.json + +# Doc # +/doc/ + +# IDE # +.idea/ +*.swp diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..88bd8b83 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015-2016 AngularClass LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/README.md b/README.md new file mode 100644 index 00000000..f8f7854b --- /dev/null +++ b/README.md @@ -0,0 +1,347 @@ +[![taylor swift](https://img.shields.io/badge/secured%20by-taylor%20swift-brightgreen.svg)](https://twitter.com/SwiftOnSecurity) +[![volkswagen status](https://auchenberg.github.io/volkswagen/volkswargen_ci.svg?v=1)](https://github.com/auchenberg/volkswagen) [![GitHub version](https://badge.fury.io/gh/angularclass%2Fangular2-webpack-starter.svg)](https://badge.fury.io/gh/angularclass%2Fangular2-webpack-starter) [![Dependency Status](https://david-dm.org/angularclass/angular2-webpack-starter.svg)](https://david-dm.org/angularclass/angular2-webpack-starter) +[![Issue Stats](http://issuestats.com/github/angularclass/angular2-webpack-starter/badge/pr?style=flat)](http://issuestats.com/github/angularclass/angular2-webpack-starter) +[![Issue Stats](http://issuestats.com/github/angularclass/angular2-webpack-starter/badge/issue?style=flat)](http://issuestats.com/github/angularclass/angular2-webpack-starter) [![Stack Share](http://img.shields.io/badge/tech-stack-0690fa.svg?style=flat)](http://stackshare.io/angularclass/angular-2-webpack-starter) + +

+ + Webpack and Angular 2 + +

+ +# Angular2 Webpack Starter [![Join Slack](https://img.shields.io/badge/slack-join-brightgreen.svg)](https://angularclass.com/slack-join) [![Join the chat at https://gitter.im/angularclass/angular2-webpack-starter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angularclass/angular2-webpack-starter?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + + +> An Angular 2 starter kit featuring [Angular 2](https://angular.io) ([Router](https://angular.io/docs/js/latest/api/router/), [Forms](https://angular.io/docs/js/latest/api/forms/), +[Http](https://angular.io/docs/js/latest/api/http/), +[Services](https://gist.github.com/gdi2290/634101fec1671ee12b3e#_follow_@AngularClass_on_twitter), +[Tests](https://angular.io/docs/js/latest/api/test/), [E2E](https://angular.github.io/protractor/#/faq#what-s-the-difference-between-karma-and-protractor-when-do-i-use-which-)), [Material](https://github.com/angular/material2), [Karma](https://karma-runner.github.io/), [Protractor](https://angular.github.io/protractor/), [Jasmine](https://github.com/jasmine/jasmine), [Istanbul](https://github.com/gotwarlost/istanbul), [TypeScript](http://www.typescriptlang.org/), [Typings](https://github.com/typings/typings), [TsLint](http://palantir.github.io/tslint/), [Codelyzer](https://github.com/mgechev/codelyzer), [Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html), and [Webpack](http://webpack.github.io/) by [AngularClass](https://angularclass.com). + +> If you're looking for Angular 1.x please use [NG6-starter](https://github.com/angularclass/NG6-starter) + +> If you're looking to learn about Webpack and ES6 Build Tools check out [ES6-build-tools](https://github.com/AngularClass/ES6-build-tools) + +> If you're looking to learn TypeScript see [TypeStrong/learn-typescript](https://github.com/TypeStrong/learn-typescript) + +> If you're looking for Webpack 2 version then see the experimental version [angular2-webpack2-starter](https://github.com/gdi2290/angular2-webpack2-starter) that will be merged + +> If you're looking for something easier to get started with then see the offical angular2-seed that I also maintain [angular/angular2-seed](https://github.com/angular/angular2-seed) + +This seed repo serves as an Angular 2 starter for anyone looking to get up and running with Angular 2 and TypeScript fast. Using a [Webpack](http://webpack.github.io/) for building our files and assisting with boilerplate. We're also using Protractor for our end-to-end story and Karma for our unit tests. +* Best practices in file and application organization for Angular 2. +* Ready to go build system using Webpack for working with TypeScript. +* Angular 2 examples that are ready to go when experimenting with Angular 2. +* A great Angular 2 seed repo for anyone who wants to start their project. +* Testing Angular 2 code with Jasmine and Karma. +* Coverage with Istanbul and Karma +* End-to-end Angular 2 code using Protractor. +* Type manager with Typings +* Hot Module Replacement with Webpack +* Material Design with [angular/material2](https://github.com/angular/material2) + +### Quick start +**Make sure you have Node version >= 4.0 and NPM >= 3** +> Clone/Download the repo then edit `app.ts` inside [`/src/app/app.ts`](/src/app/app.ts) + +```bash +# clone our repo +# --depth 1 removes all but one .git commit history +git clone --depth 1 https://github.com/angularclass/angular2-webpack-starter.git + +# change directory to our repo +cd angular2-webpack-starter + +# add required global libraries +npm install typings webpack-dev-server rimraf webpack -g + +# install the repo with npm +npm install + +# start the server +npm start + +# use Hot Module Replacement +npm run server:dev:hmr + +# if you're in China use cnpm +# https://github.com/cnpm/cnpm +``` +go to [http://0.0.0.0:3000](http://0.0.0.0:3000) or [http://localhost:3000](http://localhost:3000) in your browser + +# Table of Contents +* [File Structure](#file-structure) +* [Getting Started](#getting-started) + * [Dependencies](#dependencies) + * [Installing](#installing) + * [Running the app](#running-the-app) +* [Configuration](#configuration) +* [Contributing](#contributing) +* [TypeScript](#typescript) +* [Typings](#typings) +* [Frequently asked questions](#frequently-asked-questions) +* [Support, Questions, or Feedback](#support-questions-or-feedback) +* [License](#license) + + +## File Structure +We use the component approach in our starter. This is the new standard for developing Angular apps and a great way to ensure maintainable code by encapsulation of our behavior logic. A component is basically a self contained app usually in a single file or a folder with each concern as a file: style, template, specs, e2e, and component class. Here's how it looks: +``` +angular2-webpack-starter/ + ├──config/ * our configuration + | ├──helpers.js * helper functions for our configuration files + | ├──spec-bundle.js * ignore this magic that sets up our angular 2 testing environment + | ├──karma.conf.js * karma config for our unit tests + | ├──protractor.conf.js * protractor config for our end-to-end tests + │ ├──webpack.dev.js * our development webpack config + │ ├──webpack.prod.js * our production webpack config + │ └──webpack.test.js * our testing webpack config + │ + ├──src/ * our source files that will be compiled to javascript + | ├──main.browser.ts * our entry file for our browser environment + │ │ + | ├──index.html * Index.html: where we generate our index page + │ │ + | ├──polyfills.ts * our polyfills file + │ │ + | ├──vendor.ts * our vendor file + │ │ + │ ├──app/ * WebApp: folder + │ │ ├──app.spec.ts * a simple test of components in app.ts + │ │ ├──app.e2e.ts * a simple end-to-end test for / + │ │ └──app.ts * App.ts: a simple version of our App component components + │ │ + │ └──assets/ * static assets are served here + │ ├──icon/ * our list of icons from www.favicon-generator.org + │ ├──service-worker.js * ignore this. Web App service worker that's not complete yet + │ ├──robots.txt * for search engines to crawl your website + │ └──human.txt * for humans to know who the developers are + │ + │ + ├──tslint.json * typescript lint config + ├──typedoc.json * typescript documentation generator + ├──tsconfig.json * config that webpack uses for typescript + ├──typings.json * our typings manager + └──package.json * what npm uses to manage it's dependencies +``` + +# Getting Started +## Dependencies +What you need to run this app: +* `node` and `npm` (`brew install node`) +* Ensure you're running the latest versions Node `v4.x.x`+ (or `v5.x.x`) and NPM `3.x.x`+ + +Once you have those, you should install these globals with `npm install --global`: +* `webpack` (`npm install --global webpack`) +* `webpack-dev-server` (`npm install --global webpack-dev-server`) +* `karma` (`npm install --global karma-cli`) +* `protractor` (`npm install --global protractor`) +* `typings` (`npm install --global typings`) +* `typescript` (`npm install --global typescript`) + +## Installing +* `fork` this repo +* `clone` your fork +* `npm install` to install all dependencies +* `typings install` to install necessary typings +* `npm run server` to start the dev server in another tab + +## Running the app +After you have installed all dependencies you can now run the app. Run `npm run server` to start a local server using `webpack-dev-server` which will watch, build (in-memory), and reload for you. The port will be displayed to you as `http://0.0.0.0:3000` (or if you prefer IPv6, if you're using `express` server, then it's `http://[::1]:3000/`). + +### server +```bash +# development +npm run server +# production +npm run build:prod +npm run server:prod +``` + +## Other commands + +### build files +```bash +# development +npm run build:dev +# production +npm run build:prod +``` + +### hot module replacement +```bash +npm run server:dev:hmr +``` + +### watch and build files +```bash +npm run watch +``` + +### run tests +```bash +npm run test +``` + +### watch and run our tests +```bash +npm run watch:test +``` + +### run end-to-end tests +```bash +# make sure you have your server running in another terminal +npm run e2e +``` + +### run webdriver (for end-to-end) +```bash +npm run webdriver:update +npm run webdriver:start +``` + +### run Protractor's elementExplorer (for end-to-end) +```bash +npm run webdriver:start +# in another terminal +npm run e2e:live +``` + +# Configuration +Configuration files live in `config/` we are currently using webpack, karma, and protractor for different stages of your application + +# Contributing +You can include more examples as components but they must introduce a new concept such as `Home` component (separate folders), and Todo (services). I'll accept pretty much everything so feel free to open a Pull-Request + +# TypeScript +> To take full advantage of TypeScript with autocomplete you would have to install it globally and use an editor with the correct TypeScript plugins. + +## Use latest TypeScript compiler +TypeScript 1.7.x includes everything you need. Make sure to upgrade, even if you installed TypeScript previously. + +``` +npm install --global typescript +``` + +## Use a TypeScript-aware editor +We have good experience using these editors: + +* [Visual Studio Code](https://code.visualstudio.com/) +* [Webstorm 10](https://www.jetbrains.com/webstorm/download/) +* [Atom](https://atom.io/) with [TypeScript plugin](https://atom.io/packages/atom-typescript) +* [Sublime Text](http://www.sublimetext.com/3) with [Typescript-Sublime-Plugin](https://github.com/Microsoft/Typescript-Sublime-plugin#installation) + +# Typings +> When you include a module that doesn't include Type Definitions inside of the module you need to include external Type Definitions with Typings + +## Use latest Typings module +``` +npm install --global typings +``` + +## Custom Type Definitions +When including 3rd party modules you also need to include the type definition for the module +if they don't provide one within the module. You can try to install it with typings + +``` +typings install node --save +``` + +If you can't find the type definition in the registry we can make an ambient definition in +this file for now. For example + +```typescript +declare module "my-module" { + export function doesSomething(value: string): string; +} +``` + + +If you're prototyping and you will fix the types later you can also declare it as type any + +```typescript +declare var assert: any; +``` + +If you're importing a module that uses Node.js modules which are CommonJS you need to import as + +```typescript +import * as _ from 'lodash'; +``` + +You can include your type definitions in this file until you create one for the typings registry +see [typings/registry](https://github.com/typings/registry) + +# Frequently asked questions +* What's the current browser support for Angular 2 Beta? + * Please view the updated list of [browser support for Angular 2](https://github.com/angularclass/awesome-angular2#current-browser-support-for-angular-2) +* Why is my service, aka provider, is not injecting parameter correctly? + * Please use `@Injectable()` for your service for typescript to correctly attach the metadata (this is a TypeScript problem) +* How do I run protractor with node 0.12.x? + * please check out this repo to use the old version of protractor [#146](https://github.com/AngularClass/angular2-webpack-starter/pull/146/files) +* Where do I write my tests? + * You can write your tests next to your component files. See [`/src/app/home/home.spec.ts`](/src/app/home/home.spec.ts) +* How do I start the app when I get `EACCES` and `EADDRINUSE` errors? + * The `EADDRINUSE` error means the port `3000` is currently being used and `EACCES` is lack of permission for webpack to build files to `./dist/` +* How to use `sass` for css? + * `loaders: ['raw-loader','sass-loader']` and `@Component({ styles: [ require('./filename.scss') ] })` see issue [#136](https://github.com/AngularClass/angular2-webpack-starter/issues/136) +* How do I test a Service? + * See issue [#130](https://github.com/AngularClass/angular2-webpack-starter/issues/130#issuecomment-158872648) +* How do I add `vscode-chrome-debug` support? + * The VS Code chrome debug extension support can be done via `launch.json` see issue [#144](https://github.com/AngularClass/angular2-webpack-starter/issues/144#issuecomment-164063790) +* How do I make the repo work in a virtual machine? + * You need to use `0.0.0.0` so revert these changes [#205](https://github.com/AngularClass/angular2-webpack-starter/pull/205/files) +* What are the naming conventions for Angular 2? + * please see issue [#185](https://github.com/AngularClass/angular2-webpack-starter/issues/185) and PR [196](https://github.com/AngularClass/angular2-webpack-starter/pull/196) +* How do I include bootstrap or jQuery? + * please see issue [#215](https://github.com/AngularClass/angular2-webpack-starter/issues/215) and [#214](https://github.com/AngularClass/angular2-webpack-starter/issues/214#event-511768416) +* I'm getting an error about not finding my module that I installed? + * please see [How to include or create custom type definitions](https://github.com/AngularClass/angular2-webpack-starter/wiki/How-to-include-or-create-custom-type-definitions) and [custom-typings.d.ts](https://github.com/AngularClass/angular2-webpack-starter/blob/master/src/custom-typings.d.ts) +* How do I async load a component? + * see wiki [How-do-I-async-load-a-component-with-AsyncRoute](https://github.com/AngularClass/angular2-webpack-starter/wiki/How-do-I-async-load-a-component-with-AsyncRoute) +* Error: Cannot find module 'tapable' + * Remove `node_modules/` and run `npm cache clean` then `npm install` +* What about Webpack 2? + * If you're looking for Webpack 2 version then see the [experimental version](https://github.com/gdi2290/angular2-webpack2-starter) that will be merged soon. +* How do I turn on Hot Module Replacement + * Run `npm run server:dev:hmr` +* `RangeError: Maximum call stack size exceeded` + * This is a problem with minifying Angular 2 and it's recent JIT templates. If you set `mangle` to `false` then you should be good. +* Why is the size of my app larger in development? + * We are using inline source-maps and hot module replacement which will increase the bundle size. +* If you're in China + * check out https://github.com/cnpm/cnpm + +# Support, Questions, or Feedback +> Contact us anytime for anything about this repo or Angular 2 + +* [Chat: AngularClass.slack](http://angularclass.com/member-join/) +* [Twitter: @AngularClass](https://twitter.com/AngularClass) +* [Gitter: AngularClass/angular2-webpack-starter](https://gitter.im/angularclass/angular2-webpack-starter) + +# Quick Start Guides + +## Nitrous + +You can quickly create a free development environment to get started using this +starter kit in the cloud on [Nitrous](https://www.nitrous.io/): + + + Nitrous Quickstart + + +Simply run `HOST=0.0.0.0 npm start` from the terminal inside of +`~/code/angular2-webpack-starter` and access your site via the "Preview > 3000" +link in the IDE. +___ + +enjoy — **AngularClass** + +

+ +[![AngularClass](https://cloud.githubusercontent.com/assets/1016365/9863770/cb0620fc-5af7-11e5-89df-d4b0b2cdfc43.png "Angular Class")](https://angularclass.com) +##[AngularClass](https://angularclass.com) +> Learn AngularJS, Angular 2, and Modern Web Development from the best. +> Looking for corporate Angular training, want to host us, or Angular consulting? patrick@angularclass.com + +# License + [MIT](/LICENSE) diff --git a/config/helpers.js b/config/helpers.js new file mode 100644 index 00000000..26ee963f --- /dev/null +++ b/config/helpers.js @@ -0,0 +1,69 @@ +/** + * @author: @AngularClass + */ + +var path = require('path'); + +// Helper functions +var _root = path.resolve(__dirname, '..'); + +console.log('root directory:', root()); + +function hasProcessFlag(flag) { + return process.argv.join('').indexOf(flag) > -1; +} + +function root(args) { + args = Array.prototype.slice.call(arguments, 0); + return path.join.apply(path, [_root].concat(args)); +} + +function rootNode(args) { + args = Array.prototype.slice.call(arguments, 0); + return root.apply(path, ['node_modules'].concat(args)); +} + +function prependExt(extensions, args) { + args = args || []; + if (!Array.isArray(args)) { args = [args] } + return extensions.reduce(function(memo, val) { + return memo.concat(val, args.map(function(prefix) { + return prefix + val; + })); + }, ['']); +} + +function packageSort(packages) { + // packages = ['polyfills', 'vendor', 'main'] + var len = packages.length - 1; + var first = packages[0]; + var last = packages[len]; + return function sort(a, b) { + // polyfills always first + if (a.names[0] === first) { + return -1; + } + // main always last + if (a.names[0] === last) { + return 1; + } + // vendor before app + if (a.names[0] !== first && b.names[0] === last) { + return -1; + } else { + return 1; + } + } +} + +function reverse(arr) { + return arr.reverse(); +} + +exports.reverse = reverse; +exports.hasProcessFlag = hasProcessFlag; +exports.root = root; +exports.rootNode = rootNode; +exports.prependExt = prependExt; +exports.prepend = prependExt; +exports.packageSort = packageSort; diff --git a/config/karma.conf.js b/config/karma.conf.js new file mode 100644 index 00000000..a736cdec --- /dev/null +++ b/config/karma.conf.js @@ -0,0 +1,90 @@ +/** + * @author: @AngularClass + */ + +module.exports = function(config) { + var testWebpackConfig = require('./webpack.test.js'); + + config.set({ + + // base path that will be used to resolve all patterns (e.g. files, exclude) + basePath: '', + + /* + * Frameworks to use + * + * available frameworks: https://npmjs.org/browse/keyword/karma-adapter + */ + frameworks: ['jasmine'], + + // list of files to exclude + exclude: [ ], + + /* + * list of files / patterns to load in the browser + * + * we are building the test environment in ./spec-bundle.js + */ + files: [ { pattern: './config/spec-bundle.js', watched: false } ], + + /* + * preprocess matching files before serving them to the browser + * available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + */ + preprocessors: { './config/spec-bundle.js': ['coverage', 'webpack', 'sourcemap'] }, + + // Webpack Config at ./webpack.test.js + webpack: testWebpackConfig, + + coverageReporter: { + dir : 'coverage/', + reporters: [ + { type: 'text-summary' }, + { type: 'json' }, + { type: 'html' } + ] + }, + + // Webpack please don't spam the console when running in karma! + webpackServer: { noInfo: true }, + + /* + * test results reporter to use + * + * possible values: 'dots', 'progress' + * available reporters: https://npmjs.org/browse/keyword/karma-reporter + */ + reporters: [ 'mocha', 'coverage' ], + + // web server port + port: 9876, + + // enable / disable colors in the output (reporters and logs) + colors: true, + + /* + * level of logging + * possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + */ + logLevel: config.LOG_INFO, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: false, + + /* + * start these browsers + * available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + */ + browsers: [ + // 'Chrome', + 'PhantomJS' + ], + + /* + * Continuous Integration mode + * if true, Karma captures browsers, runs the tests and exits + */ + singleRun: true + }); + +}; diff --git a/config/protractor.conf.js b/config/protractor.conf.js new file mode 100644 index 00000000..f7fb6392 --- /dev/null +++ b/config/protractor.conf.js @@ -0,0 +1,51 @@ +/** + * @author: @AngularClass + */ + +require('ts-node/register'); +var helpers = require('./helpers'); + +exports.config = { + baseUrl: 'http://localhost:3000/', + + // use `npm run e2e` + specs: [ + helpers.root('src/**/**.e2e.ts'), + helpers.root('src/**/*.e2e.ts') + ], + exclude: [], + + framework: 'jasmine2', + + allScriptsTimeout: 110000, + + jasmineNodeOpts: { + showTiming: true, + showColors: true, + isVerbose: false, + includeStackTrace: false, + defaultTimeoutInterval: 400000 + }, + directConnect: true, + + capabilities: { + 'browserName': 'chrome', + 'chromeOptions': { + 'args': ['show-fps-counter=true'] + } + }, + + onPrepare: function() { + browser.ignoreSynchronization = true; + }, + + seleniumServerJar: 'node_modules/protractor/selenium/selenium-server-standalone-2.52.0.jar', + + /** + * Angular 2 configuration + * + * useAllAngular2AppRoots: tells Protractor to wait for any angular2 apps on the page instead of just the one matching + * `rootEl` + */ + useAllAngular2AppRoots: true +}; diff --git a/config/spec-bundle.js b/config/spec-bundle.js new file mode 100644 index 00000000..4ebf0ba9 --- /dev/null +++ b/config/spec-bundle.js @@ -0,0 +1,59 @@ +/** + * @author: @AngularClass + */ + +/* + * When testing with webpack and ES6, we have to do some extra + * things get testing to work right. Because we are gonna write test + * in ES6 to, we have to compile those as well. That's handled in + * karma.conf.js with the karma-webpack plugin. This is the entry + * file for webpack test. Just like webpack will create a bundle.js + * file for our client, when we run test, it well compile and bundle them + * all here! Crazy huh. So we need to do some setup + */ +Error.stackTraceLimit = Infinity; + +require('core-js'); + +// Typescript emit helpers polyfill +require('ts-helpers'); + +require('zone.js/dist/zone'); +require('zone.js/dist/long-stack-trace-zone'); +require('zone.js/dist/jasmine-patch'); + +// RxJS +require('rxjs/Rx'); + +var testing = require('angular2/testing'); +var browser = require('angular2/platform/testing/browser'); + +testing.setBaseTestProviders( + browser.TEST_BROWSER_PLATFORM_PROVIDERS, + browser.TEST_BROWSER_APPLICATION_PROVIDERS +); + +Object.assign(global, testing); + +/* + * Ok, this is kinda crazy. We can use the the context method on + * require that webpack created in order to tell webpack + * what files we actually want to require or import. + * Below, context will be an function/object with file names as keys. + * using that regex we are saying look in ./src/app and ./test then find + * any file that ends with spec.js and get its path. By passing in true + * we say do this recursively + */ +var testContext = require.context('../src', true, /\.spec\.ts/); + +/* + * get all the files, for each file, call the context function + * that will require the file and load it up here. Context will + * loop and require those spec files here + */ +function requireAll(requireContext) { + return requireContext.keys().map(requireContext); +} + +// requires and returns all modules that match +var modules = requireAll(testContext); diff --git a/config/webpack.common.js b/config/webpack.common.js new file mode 100644 index 00000000..893556f2 --- /dev/null +++ b/config/webpack.common.js @@ -0,0 +1,255 @@ +/** + * @author: @AngularClass + */ + +const webpack = require('webpack'); +const helpers = require('./helpers'); + +/* + * Webpack Plugins + */ +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin; + +/* + * Webpack Constants + */ +const METADATA = { + title: 'Angular2 Webpack Starter by @gdi2290 from @AngularClass', + baseUrl: '/' +}; + +/* + * Webpack configuration + * + * See: http://webpack.github.io/docs/configuration.html#cli + */ +module.exports = { + + /* + * Static metadata for index.html + * + * See: (custom attribute) + */ + metadata: METADATA, + + /* + * Cache generated modules and chunks to improve performance for multiple incremental builds. + * This is enabled by default in watch mode. + * You can pass false to disable it. + * + * See: http://webpack.github.io/docs/configuration.html#cache + * cache: false, + * + * The entry point for the bundle + * Our Angular.js app + * + * See: http://webpack.github.io/docs/configuration.html#entry + */ + entry: { + + 'polyfills': './src/polyfills.ts', + 'vendor': './src/vendor.ts', + 'main': './src/main.browser.ts' + + }, + + /* + * Options affecting the resolving of modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve + */ + resolve: { + + /* + * An array of extensions that should be used to resolve modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve-extensions + */ + extensions: ['', '.ts', '.js'], + + // Make sure root is src + root: helpers.root('src'), + + // remove other default values + modulesDirectories: ['node_modules'] + + }, + + /* + * Options affecting the normal modules. + * + * See: http://webpack.github.io/docs/configuration.html#module + */ + module: { + + /* + * An array of applied pre and post loaders. + * + * See: http://webpack.github.io/docs/configuration.html#module-preloaders-module-postloaders + */ + preLoaders: [ + + /* + * Tslint loader support for *.ts files + * + * See: https://github.com/wbuchwalter/tslint-loader + */ + // { test: /\.ts$/, loader: 'tslint-loader', exclude: [ helpers.root('node_modules') ] }, + + /* + * Source map loader support for *.js files + * Extracts SourceMaps for source files that as added as sourceMappingURL comment. + * + * See: https://github.com/webpack/source-map-loader + */ + { + test: /\.js$/, + loader: 'source-map-loader', + exclude: [ + // these packages have problems with their sourcemaps + helpers.root('node_modules/rxjs'), + helpers.root('node_modules/@angular2-material') + ] + } + + ], + + /* + * An array of automatically applied loaders. + * + * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. + * This means they are not resolved relative to the configuration file. + * + * See: http://webpack.github.io/docs/configuration.html#module-loaders + */ + loaders: [ + + /* + * Typescript loader support for .ts and Angular 2 async routes via .async.ts + * + * See: https://github.com/s-panferov/awesome-typescript-loader + */ + { + test: /\.ts$/, + loader: 'awesome-typescript-loader', + exclude: [/\.(spec|e2e)\.ts$/] + }, + + /* + * Json loader support for *.json files. + * + * See: https://github.com/webpack/json-loader + */ + { + test: /\.json$/, + loader: 'json-loader' + }, + + /* + * Raw loader support for *.css files + * Returns file content as string + * + * See: https://github.com/webpack/raw-loader + */ + { + test: /\.css$/, + loader: 'raw-loader' + }, + + /* Raw loader support for *.html + * Returns file content as string + * + * See: https://github.com/webpack/raw-loader + */ + { + test: /\.html$/, + loader: 'raw-loader', + exclude: [helpers.root('src/index.html')] + } + + ] + + }, + + /* + * Add additional plugins to the compiler. + * + * See: http://webpack.github.io/docs/configuration.html#plugins + */ + plugins: [ + + /* + * Plugin: ForkCheckerPlugin + * Description: Do type checking in a separate process, so webpack don't need to wait. + * + * See: https://github.com/s-panferov/awesome-typescript-loader#forkchecker-boolean-defaultfalse + */ + new ForkCheckerPlugin(), + + /* + * Plugin: OccurenceOrderPlugin + * Description: Varies the distribution of the ids to get the smallest id length + * for often used ids. + * + * See: https://webpack.github.io/docs/list-of-plugins.html#occurrenceorderplugin + * See: https://github.com/webpack/docs/wiki/optimization#minimize + */ + new webpack.optimize.OccurenceOrderPlugin(true), + + /* + * Plugin: CommonsChunkPlugin + * Description: Shares common code between the pages. + * It identifies common modules and put them into a commons chunk. + * + * See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin + * See: https://github.com/webpack/docs/wiki/optimization#multi-page-app + */ + new webpack.optimize.CommonsChunkPlugin({ + name: helpers.reverse(['polyfills', 'vendor']) + }), + + /* + * Plugin: CopyWebpackPlugin + * Description: Copy files and directories in webpack. + * + * Copies project static assets. + * + * See: https://www.npmjs.com/package/copy-webpack-plugin + */ + new CopyWebpackPlugin([{ + from: 'src/assets', + to: 'assets' + }]), + + /* + * Plugin: HtmlWebpackPlugin + * Description: Simplifies creation of HTML files to serve your webpack bundles. + * This is especially useful for webpack bundles that include a hash in the filename + * which changes every compilation. + * + * See: https://github.com/ampedandwired/html-webpack-plugin + */ + new HtmlWebpackPlugin({ + template: 'src/index.html', + chunksSortMode: helpers.packageSort(['polyfills', 'vendor', 'main']) + }) + + ], + + /* + * Include polyfills or mocks for various node stuff + * Description: Node configuration + * + * See: https://webpack.github.io/docs/configuration.html#node + */ + node: { + global: 'window', + crypto: 'empty', + module: false, + clearImmediate: false, + setImmediate: false + } + +}; diff --git a/config/webpack.dev.js b/config/webpack.dev.js new file mode 100644 index 00000000..27e93b36 --- /dev/null +++ b/config/webpack.dev.js @@ -0,0 +1,162 @@ +/** + * @author: @AngularClass + */ + +const helpers = require('./helpers'); +const webpackMerge = require('webpack-merge'); // used to merge webpack configs +const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev + +/** + * Webpack Plugins + */ +const DefinePlugin = require('webpack/lib/DefinePlugin'); + +/** + * Webpack Constants + */ +const ENV = process.env.ENV = process.env.NODE_ENV = 'development'; +const HMR = helpers.hasProcessFlag('hot'); +const METADATA = webpackMerge(commonConfig.metadata, { + host: 'localhost', + port: 3000, + ENV: ENV, + HMR: HMR +}); + +/** + * Webpack configuration + * + * See: http://webpack.github.io/docs/configuration.html#cli + */ +module.exports = webpackMerge(commonConfig, { + + /** + * Merged metadata from webpack.common.js for index.html + * + * See: (custom attribute) + */ + metadata: METADATA, + + /** + * Switch loaders to debug mode. + * + * See: http://webpack.github.io/docs/configuration.html#debug + */ + debug: true, + + /** + * Developer tool to enhance debugging + * + * See: http://webpack.github.io/docs/configuration.html#devtool + * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps + */ + devtool: 'cheap-module-eval-source-map', + + /** + * Options affecting the output of the compilation. + * + * See: http://webpack.github.io/docs/configuration.html#output + */ + output: { + + /** + * The output directory as absolute path (required). + * + * See: http://webpack.github.io/docs/configuration.html#output-path + */ + path: helpers.root('dist'), + + /** + * Specifies the name of each output file on disk. + * IMPORTANT: You must not specify an absolute path here! + * + * See: http://webpack.github.io/docs/configuration.html#output-filename + */ + filename: '[name].bundle.js', + + /** + * The filename of the SourceMaps for the JavaScript files. + * They are inside the output.path directory. + * + * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename + */ + sourceMapFilename: '[name].map', + + /** The filename of non-entry chunks as relative path + * inside the output.path directory. + * + * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename + */ + chunkFilename: '[id].chunk.js' + + }, + + plugins: [ + + /** + * Plugin: DefinePlugin + * Description: Define free variables. + * Useful for having development builds with debug logging or adding global constants. + * + * Environment helpers + * + * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin + */ + // NOTE: when adding more properties, make sure you include them in custom-typings.d.ts + new DefinePlugin({ + 'ENV': JSON.stringify(METADATA.ENV), + 'HMR': METADATA.HMR, + 'process.env': { + 'ENV': JSON.stringify(METADATA.ENV), + 'NODE_ENV': JSON.stringify(METADATA.ENV), + 'HMR': METADATA.HMR, + } + }) + ], + + /** + * Static analysis linter for TypeScript advanced options configuration + * Description: An extensible linter for the TypeScript language. + * + * See: https://github.com/wbuchwalter/tslint-loader + */ + tslint: { + emitErrors: false, + failOnHint: false, + resourcePath: 'src' + }, + + /** + * Webpack Development Server configuration + * Description: The webpack-dev-server is a little node.js Express server. + * The server emits information about the compilation state to the client, + * which reacts to those events. + * + * See: https://webpack.github.io/docs/webpack-dev-server.html + */ + devServer: { + port: METADATA.port, + host: METADATA.host, + historyApiFallback: true, + watchOptions: { + aggregateTimeout: 300, + poll: 1000 + } + }, + + /* + * Include polyfills or mocks for various node stuff + * Description: Node configuration + * + * See: https://webpack.github.io/docs/configuration.html#node + */ + node: { + global: 'window', + crypto: 'empty', + process: true, + module: false, + clearImmediate: false, + setImmediate: false + } + +}); diff --git a/config/webpack.prod.js b/config/webpack.prod.js new file mode 100644 index 00000000..8be41327 --- /dev/null +++ b/config/webpack.prod.js @@ -0,0 +1,230 @@ +/** + * @author: @AngularClass + */ + +const helpers = require('./helpers'); +const webpackMerge = require('webpack-merge'); // used to merge webpack configs +const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev + +/** + * Webpack Plugins + */ +const ProvidePlugin = require('webpack/lib/ProvidePlugin'); +const DefinePlugin = require('webpack/lib/DefinePlugin'); +const DedupePlugin = require('webpack/lib/optimize/DedupePlugin'); +const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin'); +const CompressionPlugin = require('compression-webpack-plugin'); +const WebpackMd5Hash = require('webpack-md5-hash'); + +/** + * Webpack Constants + */ +const ENV = process.env.NODE_ENV = process.env.ENV = 'production'; +const HOST = process.env.HOST || 'localhost'; +const PORT = process.env.PORT || 8080; +const METADATA = webpackMerge(commonConfig.metadata, { + host: HOST, + port: PORT, + ENV: ENV, + HMR: false +}); + +module.exports = webpackMerge(commonConfig, { + + /** + * Switch loaders to debug mode. + * + * See: http://webpack.github.io/docs/configuration.html#debug + */ + debug: false, + + /** + * Developer tool to enhance debugging + * + * See: http://webpack.github.io/docs/configuration.html#devtool + * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps + */ + devtool: 'source-map', + + /** + * Options affecting the output of the compilation. + * + * See: http://webpack.github.io/docs/configuration.html#output + */ + output: { + + /** + * The output directory as absolute path (required). + * + * See: http://webpack.github.io/docs/configuration.html#output-path + */ + path: helpers.root('dist'), + + /** + * Specifies the name of each output file on disk. + * IMPORTANT: You must not specify an absolute path here! + * + * See: http://webpack.github.io/docs/configuration.html#output-filename + */ + filename: '[name].[chunkhash].bundle.js', + + /** + * The filename of the SourceMaps for the JavaScript files. + * They are inside the output.path directory. + * + * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename + */ + sourceMapFilename: '[name].[chunkhash].bundle.map', + + /** + * The filename of non-entry chunks as relative path + * inside the output.path directory. + * + * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename + */ + chunkFilename: '[id].[chunkhash].chunk.js' + + }, + + /** + * Add additional plugins to the compiler. + * + * See: http://webpack.github.io/docs/configuration.html#plugins + */ + plugins: [ + + /** + * Plugin: WebpackMd5Hash + * Description: Plugin to replace a standard webpack chunkhash with md5. + * + * See: https://www.npmjs.com/package/webpack-md5-hash + */ + new WebpackMd5Hash(), + + /** + * Plugin: DedupePlugin + * Description: Prevents the inclusion of duplicate code into your bundle + * and instead applies a copy of the function at runtime. + * + * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin + * See: https://github.com/webpack/docs/wiki/optimization#deduplication + */ + new DedupePlugin(), + + /** + * Plugin: DefinePlugin + * Description: Define free variables. + * Useful for having development builds with debug logging or adding global constants. + * + * Environment helpers + * + * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin + */ + // NOTE: when adding more properties make sure you include them in custom-typings.d.ts + new DefinePlugin({ + 'ENV': JSON.stringify(METADATA.ENV), + 'HMR': METADATA.HMR, + 'process.env': { + 'ENV': JSON.stringify(METADATA.ENV), + 'NODE_ENV': JSON.stringify(METADATA.ENV), + 'HMR': METADATA.HMR, + } + }), + + /** + * Plugin: UglifyJsPlugin + * Description: Minimize all JavaScript output of chunks. + * Loaders are switched into minimizing mode. + * + * See: https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin + */ + // NOTE: To debug prod builds uncomment //debug lines and comment //prod lines + new UglifyJsPlugin({ + // beautify: true, //debug + // mangle: false, //debug + // dead_code: false, //debug + // unused: false, //debug + // deadCode: false, //debug + // compress: { + // screw_ie8: true, + // keep_fnames: true, + // drop_debugger: false, + // dead_code: false, + // unused: false + // }, // debug + // comments: true, //debug + + beautify: false, //prod + + mangle: { + screw_ie8 : true, + keep_fnames: true + }, //prod + + compress: { + screw_ie8: true + }, //prod + + comments: false //prod + }), + + /** + * Plugin: CompressionPlugin + * Description: Prepares compressed versions of assets to serve + * them with Content-Encoding + * + * See: https://github.com/webpack/compression-webpack-plugin + */ + new CompressionPlugin({ + regExp: /\.css$|\.html$|\.js$|\.map$/, + threshold: 2 * 1024 + }) + + ], + + /** + * Static analysis linter for TypeScript advanced options configuration + * Description: An extensible linter for the TypeScript language. + * + * See: https://github.com/wbuchwalter/tslint-loader + */ + tslint: { + emitErrors: true, + failOnHint: true, + resourcePath: 'src' + }, + + /** + * Html loader advanced options + * + * See: https://github.com/webpack/html-loader#advanced-options + */ + // TODO: Need to workaround Angular 2's html syntax => #id [bind] (event) *ngFor + htmlLoader: { + minimize: true, + removeAttributeQuotes: false, + caseSensitive: true, + customAttrSurround: [ + [/#/, /(?:)/], + [/\*/, /(?:)/], + [/\[?\(?/, /(?:)/] + ], + customAttrAssign: [/\)?\]?=/] + }, + + /* + * Include polyfills or mocks for various node stuff + * Description: Node configuration + * + * See: https://webpack.github.io/docs/configuration.html#node + */ + node: { + global: 'window', + crypto: 'empty', + process: false, + module: false, + clearImmediate: false, + setImmediate: false + } + +}); diff --git a/config/webpack.test.js b/config/webpack.test.js new file mode 100644 index 00000000..212cdd07 --- /dev/null +++ b/config/webpack.test.js @@ -0,0 +1,233 @@ +/** + * @author: @AngularClass + */ + +const helpers = require('./helpers'); + +/** + * Webpack Plugins + */ +const ProvidePlugin = require('webpack/lib/ProvidePlugin'); +const DefinePlugin = require('webpack/lib/DefinePlugin'); + +/** + * Webpack Constants + */ +const ENV = process.env.ENV = process.env.NODE_ENV = 'test'; + +/** + * Webpack configuration + * + * See: http://webpack.github.io/docs/configuration.html#cli + */ +module.exports = { + + /** + * Source map for Karma from the help of karma-sourcemap-loader & karma-webpack + * + * Do not change, leave as is or it wont work. + * See: https://github.com/webpack/karma-webpack#source-maps + */ + devtool: 'inline-source-map', + + /** + * Options affecting the resolving of modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve + */ + resolve: { + + /** + * An array of extensions that should be used to resolve modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve-extensions + */ + extensions: ['', '.ts', '.js'], + + /** + * Make sure root is src + */ + root: helpers.root('src'), + + }, + + /** + * Options affecting the normal modules. + * + * See: http://webpack.github.io/docs/configuration.html#module + */ + module: { + + /** + * An array of applied pre and post loaders. + * + * See: http://webpack.github.io/docs/configuration.html#module-preloaders-module-postloaders + */ + preLoaders: [ + + /** + * Tslint loader support for *.ts files + * + * See: https://github.com/wbuchwalter/tslint-loader + */ + { + test: /\.ts$/, + loader: 'tslint-loader', + exclude: [helpers.root('node_modules')] + }, + + /** + * Source map loader support for *.js files + * Extracts SourceMaps for source files that as added as sourceMappingURL comment. + * + * See: https://github.com/webpack/source-map-loader + */ + { + test: /\.js$/, + loader: 'source-map-loader', + exclude: [ + // these packages have problems with their sourcemaps + helpers.root('node_modules/rxjs'), + helpers.root('node_modules/@angular2-material') + ]} + + ], + + /** + * An array of automatically applied loaders. + * + * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. + * This means they are not resolved relative to the configuration file. + * + * See: http://webpack.github.io/docs/configuration.html#module-loaders + */ + loaders: [ + + /** + * Typescript loader support for .ts and Angular 2 async routes via .async.ts + * + * See: https://github.com/s-panferov/awesome-typescript-loader + */ + { + test: /\.ts$/, + loader: 'awesome-typescript-loader', + query: { + compilerOptions: { + + // Remove TypeScript helpers to be injected + // below by DefinePlugin + removeComments: true + + } + }, + exclude: [/\.e2e\.ts$/] + }, + + /** + * Json loader support for *.json files. + * + * See: https://github.com/webpack/json-loader + */ + { test: /\.json$/, loader: 'json-loader', exclude: [helpers.root('src/index.html')] }, + + /** + * Raw loader support for *.css files + * Returns file content as string + * + * See: https://github.com/webpack/raw-loader + */ + { test: /\.css$/, loader: 'raw-loader', exclude: [helpers.root('src/index.html')] }, + + /** + * Raw loader support for *.html + * Returns file content as string + * + * See: https://github.com/webpack/raw-loader + */ + { test: /\.html$/, loader: 'raw-loader', exclude: [helpers.root('src/index.html')] } + + ], + + /** + * An array of applied pre and post loaders. + * + * See: http://webpack.github.io/docs/configuration.html#module-preloaders-module-postloaders + */ + postLoaders: [ + + /** + * Instruments JS files with Istanbul for subsequent code coverage reporting. + * Instrument only testing sources. + * + * See: https://github.com/deepsweet/istanbul-instrumenter-loader + */ + { + test: /\.(js|ts)$/, loader: 'istanbul-instrumenter-loader', + include: helpers.root('src'), + exclude: [ + /\.(e2e|spec)\.ts$/, + /node_modules/ + ] + } + + ] + }, + + /** + * Add additional plugins to the compiler. + * + * See: http://webpack.github.io/docs/configuration.html#plugins + */ + plugins: [ + + /** + * Plugin: DefinePlugin + * Description: Define free variables. + * Useful for having development builds with debug logging or adding global constants. + * + * Environment helpers + * + * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin + */ + // NOTE: when adding more properties make sure you include them in custom-typings.d.ts + new DefinePlugin({ + 'ENV': JSON.stringify(ENV), + 'HMR': false, + 'process.env': { + 'ENV': JSON.stringify(ENV), + 'NODE_ENV': JSON.stringify(ENV), + 'HMR': false, + } + }), + + + ], + + /** + * Static analysis linter for TypeScript advanced options configuration + * Description: An extensible linter for the TypeScript language. + * + * See: https://github.com/wbuchwalter/tslint-loader + */ + tslint: { + emitErrors: false, + failOnHint: false, + resourcePath: 'src' + }, + + /** + * Include polyfills or mocks for various node stuff + * Description: Node configuration + * + * See: https://webpack.github.io/docs/configuration.html#node + */ + node: { + global: 'window', + process: false, + crypto: 'empty', + module: false, + clearImmediate: false, + setImmediate: false + } + +}; diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 00000000..27c49adc --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,6 @@ +/** + * @author: @AngularClass + */ + +// Look in ./config for karma.conf.js +module.exports = require('./config/karma.conf.js'); diff --git a/package.json b/package.json new file mode 100644 index 00000000..693d2921 --- /dev/null +++ b/package.json @@ -0,0 +1,144 @@ +{ + "name": "angular2-webpack-starter", + "version": "5.0.4", + "description": "An Angular 2 Webpack Starter kit featuring Angular 2 (Router, Http, Forms, Services, Tests, E2E, Coverage), Karma, Protractor, Jasmine, Istanbul, TypeScript, and Webpack by AngularClass", + "author": "Patrick Stapleton ", + "homepage": "https://github.com/angularclass/angular2-webpack-starter", + "license": "MIT", + "scripts": { + "rimraf": "rimraf", + "tslint": "tslint", + "typedoc": "typedoc", + "typings": "typings", + "webpack": "webpack", + "webpack-dev-server": "webpack-dev-server", + "webdriver-manager": "webdriver-manager", + "protractor": "protractor", + + "clean": "npm cache clean && npm run rimraf -- node_modules doc typings coverage dist", + "clean:dist": "npm run rimraf -- dist", + "preclean:install": "npm run clean", + "clean:install": "npm set progress=false && npm install", + "preclean:start": "npm run clean", + "clean:start": "npm start", + + "watch": "npm run watch:dev", + "watch:dev": "npm run build:dev -- --watch", + "watch:dev:hmr": "npm run watch:dev -- --hot", + "watch:test": "npm run test -- --auto-watch --no-single-run", + "watch:prod": "npm run build:prod -- --watch", + + "build": "npm run build:dev", + "prebuild:dev": "npm run clean:dist", + "build:dev": "webpack --config config/webpack.dev.js --progress --profile --colors --display-error-details --display-cached", + "prebuild:prod": "npm run clean:dist", + "build:prod": "webpack --config config/webpack.prod.js --progress --profile --colors --display-error-details --display-cached --bail", + + "server": "npm run server:dev", + "server:dev": "webpack-dev-server --config config/webpack.dev.js --inline --progress --profile --colors --watch --display-error-details --display-cached --content-base src/", + "server:dev:hmr": "npm run server:dev -- --hot", + "server:prod": "http-server dist --cors", + + "webdriver:update": "npm run webdriver-manager update", + "webdriver:start": "npm run webdriver-manager start", + + "lint": "npm run tslint 'src/**/*.ts'", + + "pree2e": "npm run webdriver:update -- --standalone", + "e2e": "npm run protractor", + "e2e:live": "npm run e2e -- --elementExplorer", + + "test": "node --max-old-space-size=4096 node_modules/karma/bin/karma start", + + "ci": "npm run e2e && npm run test", + + "docs": "npm run typedoc -- --options typedoc.json --exclude '**/*.spec.ts' ./src/", + + "start": "npm run server:dev", + "start:hmr": "npm run server:dev:hmr", + + "postinstall": "npm run typings -- install", + + "preversion": "npm test", + "version": "npm run build", + "postversion": "git push && git push --tags" + + }, + "dependencies": { + "@angular2-material/button": "2.0.0-alpha.2", + "@angular2-material/card": "2.0.0-alpha.2", + "@angular2-material/checkbox": "2.0.0-alpha.2", + "@angular2-material/core": "2.0.0-alpha.2", + "@angular2-material/input": "2.0.0-alpha.2", + "@angular2-material/list": "2.0.0-alpha.2", + "@angular2-material/progress-circle": "2.0.0-alpha.2", + "@angular2-material/radio": "2.0.0-alpha.2", + "@angular2-material/sidenav": "2.0.0-alpha.2", + "@angular2-material/toolbar": "2.0.0-alpha.2", + "angular2": "2.0.0-beta.15", + "core-js": "^2.2.2", + "normalize.css": "^4.1.1", + "rxjs": "5.0.0-beta.2", + "zone.js": "~0.6.11" + }, + "devDependencies": { + "angular2-hmr": "~0.5.5", + "awesome-typescript-loader": "~0.16.2", + "codelyzer": "0.0.12", + "compression-webpack-plugin": "^0.3.1", + "copy-webpack-plugin": "^1.1.1", + "css-loader": "^0.23.1", + "es6-promise": "^3.1.2", + "es6-promise-loader": "^1.0.1", + "es6-shim": "^0.35.0", + "es7-reflect-metadata": "^1.6.0", + "exports-loader": "^0.6.3", + "expose-loader": "^0.7.1", + "file-loader": "^0.8.5", + "html-webpack-plugin": "^2.15.0", + "http-server": "^0.9.0", + "imports-loader": "^0.6.5", + "istanbul-instrumenter-loader": "^0.2.0", + "json-loader": "^0.5.4", + "karma": "^0.13.22", + "karma-chrome-launcher": "^0.2.3", + "karma-coverage": "^0.5.5", + "karma-jasmine": "^0.3.8", + "karma-mocha-reporter": "^2.0.0", + "karma-phantomjs-launcher": "^1.0.0", + "karma-sourcemap-loader": "^0.3.7", + "karma-webpack": "1.7.0", + "parse5": "^2.1.5", + "phantomjs-polyfill": "0.0.2", + "phantomjs-prebuilt": "^2.1.7", + "protractor": "^3.2.2", + "raw-loader": "0.5.1", + "remap-istanbul": "^0.5.1", + "rimraf": "^2.5.2", + "source-map-loader": "^0.1.5", + "style-loader": "^0.13.1", + "ts-helpers": "1.1.0", + "ts-node": "^0.7.1", + "tslint": "^3.7.1", + "tslint-loader": "^2.1.3", + "typedoc": "^0.3.12", + "typescript": "~1.8.9", + "typings": "^0.7.12", + "url-loader": "^0.5.7", + "webpack": "^1.12.14", + "webpack-dev-server": "^1.14.1", + "webpack-md5-hash": "^0.0.5", + "webpack-merge": "^0.8.4" + }, + "repository": { + "type": "git", + "url": "https://github.com/angularclass/angular2-webpack-starter.git" + }, + "bugs": { + "url": "https://github.com/angularclass/angular2-webpack-starter/issues" + }, + "engines": { + "node": ">= 4.2.1", + "npm": ">= 3" + } +} diff --git a/protractor.conf.js b/protractor.conf.js new file mode 100644 index 00000000..b3f7738f --- /dev/null +++ b/protractor.conf.js @@ -0,0 +1,6 @@ +/** + * @author: @AngularClass + */ + +// look in ./config for protractor.conf.js +exports.config = require('./config/protractor.conf.js').config; diff --git a/src/app/about/about.component.ts b/src/app/about/about.component.ts new file mode 100644 index 00000000..0aec2739 --- /dev/null +++ b/src/app/about/about.component.ts @@ -0,0 +1,55 @@ +import {Component} from 'angular2/core'; + +/* + * We're loading this component asynchronously + * We are using some magic with es6-promise-loader that will wrap the module with a Promise + * see https://github.com/gdi2290/es6-promise-loader for more info + */ + +console.log('`About` component loaded asynchronously'); + +@Component({ + selector: 'about', + styles: [` + h1 { + font-family: Arial, Helvetica, sans-serif + } + `], + template: ` + +

+ patrick@AngularClass.com +

+
+ + ` +}) +export class About { + constructor() { + + } + + ngOnInit() { + console.log('hello `About` component'); + // static data that is bundled + // var mockData = require('assets/mock-data/mock-data.json'); + // console.log('mockData', mockData); + // if you're working with mock data you can also use http.get('assets/mock-data/mock-data.json') + // this.asyncDataWithWebpack(); + } + asyncDataWithWebpack() { + // you can also async load mock data with 'es6-promise-loader' + // you would do this if you don't want the mock-data bundled + // remember that 'es6-promise-loader' is a promise + // var asyncMockDataPromiseFactory = require('es6-promise!assets/mock-data/mock-data.json'); + // setTimeout(() => { + // + // let asyncDataPromise = asyncMockDataPromiseFactory(); + // asyncDataPromise.then(json => { + // console.log('async mockData', json); + // }); + // + // }); + } + +} diff --git a/src/app/about/about.spec.ts b/src/app/about/about.spec.ts new file mode 100644 index 00000000..8b97cb50 --- /dev/null +++ b/src/app/about/about.spec.ts @@ -0,0 +1,29 @@ +import { + it, + inject, + injectAsync, + describe, + beforeEachProviders, + TestComponentBuilder +} from 'angular2/testing'; + +import {Component, provide} from 'angular2/core'; + +// Load the implementations that should be tested +import {About} from './about.component'; + +describe('About', () => { + // provide our implementations or mocks to the dependency injector + beforeEachProviders(() => [ + About + ]); + + it('should log ngOnInit', inject([ About ], (about) => { + spyOn(console, 'log'); + expect(console.log).not.toHaveBeenCalled(); + + about.ngOnInit(); + expect(console.log).toHaveBeenCalled(); + })); + +}); diff --git a/src/app/about/index.ts b/src/app/about/index.ts new file mode 100644 index 00000000..b7cb92ae --- /dev/null +++ b/src/app/about/index.ts @@ -0,0 +1 @@ +export * from './about.component'; diff --git a/src/app/app.component.ts b/src/app/app.component.ts new file mode 100644 index 00000000..9da15f6d --- /dev/null +++ b/src/app/app.component.ts @@ -0,0 +1,99 @@ +/* + * Angular 2 decorators and services + */ +import {Component, ViewEncapsulation} from 'angular2/core'; +import {RouteConfig, Router} from 'angular2/router'; + +import {Home} from './home'; +import {AppState} from './app.service'; +import {RouterActive} from './router-active'; + +/* + * App Component + * Top Level Component + */ +@Component({ + selector: 'app', + pipes: [ ], + providers: [ ], + directives: [ RouterActive ], + encapsulation: ViewEncapsulation.None, + styles: [ + require('normalize.css'), + ` + md-toolbar ul { + display: inline; + list-style-type: none; + margin: 0; + padding: 0; + width: 60px; + } + md-toolbar li { + display: inline; + } + md-toolbar li.active { + background-color: lightgray; + } + `], + template: ` +
+ + {{ name }} + + +
+ +
+ +
+ +
this.appState.state = {{ appState.state | json }}
+ + + ` +}) +@RouteConfig([ + { path: '/', name: 'Index', component: Home, useAsDefault: true }, + { path: '/home', name: 'Home', component: Home }, + // Async load a component using Webpack's require with es6-promise-loader and webpack `require` + { path: '/about', name: 'About', loader: () => require('es6-promise!./about')('About') } +]) +export class App { + angularclassLogo = 'assets/img/angularclass-avatar.png'; + name = 'Angular 2 Webpack Starter'; + url = 'https://twitter.com/AngularClass'; + + constructor(public appState: AppState) {} + + ngOnInit() { + console.log('Initial App State', this.appState.state); + } + +} + +/* + * Please review the https://github.com/AngularClass/angular2-examples/ repo for + * more angular app examples that you may copy/paste + * (The examples may not be updated as quickly. Please open an issue on github for us to update it) + * For help or questions please contact us at @AngularClass on twitter + * or our chat on Slack at https://AngularClass.com/slack-join + */ diff --git a/src/app/app.e2e.ts b/src/app/app.e2e.ts new file mode 100644 index 00000000..ecc503e1 --- /dev/null +++ b/src/app/app.e2e.ts @@ -0,0 +1,32 @@ +describe('App', () => { + + beforeEach(() => { + browser.get('/'); + }); + + + it('should have a title', () => { + let subject = browser.getTitle(); + let result = 'Angular2 Webpack Starter by @gdi2290 from @AngularClass'; + expect(subject).toEqual(result); + }); + + it('should have
', () => { + let subject = element(by.css('app header')).isPresent(); + let result = true; + expect(subject).toEqual(result); + }); + + it('should have
', () => { + let subject = element(by.css('app main')).isPresent(); + let result = true; + expect(subject).toEqual(result); + }); + + it('should have