diff --git a/.editorconfig b/.editorconfig index 802ae913..a443ba78 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,20 +5,8 @@ root = true # Unix-style newlines with a newline ending every file [*] -end_of_line = lf -insert_final_newline = true - -# Matches multiple files with brace expansion notation -# Set default charset -[*.{js,css,scss,html}] charset = utf-8 - -# 4 space indentation -[*.{js,css,scss,html}] -indent_style = space -indent_size = 2 - -# Matches the exact files either package.json or .travis.yml -[{package.json,.travis.yml,bower.json}] indent_style = space indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..ba275de1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,33 @@ +# Changelog + +# 04 October 2016 + +- Migrate to webpack 2 + +# 18 September 2016 + +- Using `awesome-typescript-loader` instead of `ts-loader`. + +# 5 September 2016 + +- Migration to TS2 and @types + +## 1 September 2016 + +- Using RC6. + +## 28 August 2016 + +- Adding webpack-dashboard. + +## 23 August 2016 + +- Adding HMR support. + +## 3 July 2016 + +- Use html5mode instead of hash navigation. + +## 24 June 2016 + +- Be able to import Component's templates and styles without using require. diff --git a/README.md b/README.md index ccaa5b95..5f91819a 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,27 @@ -# angular2-webpack +# angular-webpack -[![Dependency Status](https://david-dm.org/preboot/angular2-webpack/status.svg)](https://david-dm.org/preboot/angular2-webpack#info=dependencies) [![devDependency Status](https://david-dm.org/preboot/angular2-webpack/dev-status.svg)](https://david-dm.org/preboot/angular2-webpack#info=devDependencies) +[![Dependency Status](https://david-dm.org/preboot/angular-webpack/status.svg)](https://david-dm.org/preboot/angular-webpack#info=dependencies) [![devDependency Status](https://david-dm.org/preboot/angular-webpack/dev-status.svg)](https://david-dm.org/preboot/angular-webpack#info=devDependencies) +[![Join the chat at https://gitter.im/preboot/angular-webpack](https://badges.gitter.im/preboot/angular-webpack.svg)](https://gitter.im/preboot/angular-webpack?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -A complete, yet simple, starter for Angular 2 using Webpack. +A complete, yet simple, starter for Angular v2+ using Webpack. -This seed repo serves as an Angular 2 starter for anyone looking to get up and running with Angular 2 and TypeScript fast. Using [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](https://angular.io/). +This seed repo serves as an Angular starter for anyone looking to get up and running with Angular and TypeScript fast. Using [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](https://angular.io/). * Ready to go build system using [Webpack](https://webpack.github.io/docs/) for working with [TypeScript](http://www.typescriptlang.org/). -* Easily add new components using [Angular 2 cli](https://github.com/angular/angular-cli). -* Testing Angular 2 code with [Jasmine](http://jasmine.github.io/) and [Karma](http://karma-runner.github.io/). +* Testing Angular code with [Jasmine](http://jasmine.github.io/) and [Karma](http://karma-runner.github.io/). * Coverage with [Istanbul](https://github.com/gotwarlost/istanbul) -* End-to-end Angular 2 code using [Protractor](https://angular.github.io/protractor/). +* End-to-end Angular code using [Protractor](https://angular.github.io/protractor/). * Stylesheets with [SASS](http://sass-lang.com/) (not required, it supports regular css too). -* Error reported with [TSLint](http://palantir.github.io/tslint/). -* Documentation with [TypeDoc](http://typedoc.io/). +* Error reported with [TSLint](http://palantir.github.io/tslint/) and [Codelyzer](https://github.com/mgechev/codelyzer). +* Documentation with [TypeDoc](http://typedoc.org/). >Warning: Make sure you're using the latest version of Node.js and NPM -[Is Angular 2 Ready Yet?](http://splintercode.github.io/is-angular-2-ready/) - ### Quick start -> Clone/Download the repo then edit `app.ts` inside [`/src/app/app.ts`](/src/app/app.ts) - ```bash # clone our repo -$ git clone https://github.com/preboot/angular2-webpack.git my-app +$ git clone https://github.com/preboot/angular-webpack.git my-app # change directory to your app $ cd my-app @@ -43,10 +39,9 @@ go to [http://localhost:8080](http://localhost:8080) in your browser. * [Getting Started](#getting-started) * [Dependencies](#dependencies) * [Installing](#installing) - * [Running the app](#running-the-app) * [Developing](#developing) - * [Add new components with Angular 2 cli](#add-new-components-services-pipes-with-angular-2-cli) * [Testing](#testing) + * [Production](#production) * [Documentation](#documentation) * [Frequently asked questions](#faq) * [TypeScript](#typescript) @@ -58,7 +53,7 @@ go to [http://localhost:8080](http://localhost:8080) in your browser. What you need to run this app: * `node` and `npm` (Use [NVM](https://github.com/creationix/nvm)) -* Ensure you're running Node (`v4.1.x`+) and NPM (`2.14.x`+) +* Ensure you're running Node (`v6.x.x`+) and NPM (`3.x.x`+) ## Installing @@ -66,31 +61,19 @@ What you need to run this app: * `clone` your fork * `npm install` to install all dependencies -## Running the app - -After you have installed all dependencies you can now run the app with: - -```bash -npm start -``` - -It will 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://localhost:8080`. - ## Developing -### Add new components, services, pipes with Angular 2 cli +After you have installed all dependencies you can now start developing with: -* `npm install -g angular-cli` to install Angular 2 cli -* Add a new component with: `ng generate component my-new-component` -* Add a new service with: `ng generate service my-new-service` -* Add a new pipe with: `ng generate pipe my-new-pipe` +* `npm start` -Read more at [angular-cli github](https://github.com/angular/angular-cli). +It will start a local server using `webpack-dev-server` which will watch, build (in-memory), and reload for you. The application can be checked at `http://localhost:8080`. -### Build files +As an alternative, you can work using Hot Module Replacement (HMR): -* single run: `npm run build` -* build files and watch: `npm run watch` +* `npm run start:hmr` + +And you are all set! You can now modify your components on the fly without having to reload the entire page. ## Testing @@ -110,32 +93,39 @@ Read more at [angular-cli github](https://github.com/angular/angular-cli). * when debugging or first writing test suites, you may find it helpful to try out Protractor commands without starting up the entire test suite. You can do this with the element explorer. * you can learn more about [Protractor Interactive Mode here](https://github.com/angular/protractor/blob/master/docs/debugging.md#testing-out-protractor-interactively) +## Production + +To build your application, run: + +* `npm run build` + +You can now go to `/dist` and deploy that to your server! + ## Documentation -You can generate api docs (using [TypeDoc](http://typedoc.io/)) for your code with the following: -```bash -npm run docs -``` +You can generate api docs (using [TypeDoc](http://typedoc.org/)) for your code with the following: + +* `npm run docs` # FAQ #### Do I need to add script / link tags into index.html ? -No, Webpack will add all the needed Javascript bundles as script tags and all the CSS files as link tags. The advantage is that you don't need to modify the index.html everytime you build your solution to update the hashes. +No, Webpack will add all the needed Javascript bundles as script tags and all the CSS files as link tags. The advantage is that you don't need to modify the index.html every time you build your solution to update the hashes. -#### How to include external angular 2 libraries ? +#### How to include external angular libraries ? -It's simple, just install the lib via npm and import it in your code when you need it. Don't forget that you need to configure some external libs in the [bootstrap](https://github.com/preboot/angular2-webpack/blob/master/src/bootstrap.ts) of your application. +It's simple, just install the lib via npm and import it in your code when you need it. Don't forget that you need to configure some external libs in the [bootstrap](https://github.com/preboot/angular-webpack/blob/master/src/main.ts) of your application. -### How to include external css files such as bootstrap.css ? +#### How to include external css files such as bootstrap.css ? -Just install the lib and import the css files in [vendor.ts](https://github.com/preboot/angular2-webpack/blob/master/src/vendor.ts). For example this is how to do it with bootstrap: +Just install the lib and import the css files in [vendor.ts](https://github.com/preboot/angular-webpack/blob/master/src/vendor.ts). For example this is how to do it with bootstrap: ```sh -npm install bootstrap@4.0.0 --save +npm install bootstrap@next --save ``` -And in [vendor.ts](https://github.com/preboot/angular2-webpack/blob/master/src/vendor.ts) add the following: +And in [vendor.ts](https://github.com/preboot/angular-webpack/blob/master/src/vendor.ts) add the following: ```ts import 'bootstrap/dist/css/bootstrap.css'; diff --git a/karma-shim.js b/karma-shim.js index 62df8d43..def06d7c 100644 --- a/karma-shim.js +++ b/karma-shim.js @@ -1,15 +1,25 @@ Error.stackTraceLimit = Infinity; -require('es6-shim'); -require('angular2/bundles/angular2-polyfills.js'); -require('angular2/testing'); + +require('core-js/client/shim'); +require('reflect-metadata'); + +require('ts-helpers'); + +require('zone.js/dist/zone'); +require('zone.js/dist/long-stack-trace-zone'); +require('zone.js/dist/proxy'); +require('zone.js/dist/sync-test'); +require('zone.js/dist/jasmine-patch'); +require('zone.js/dist/async-test'); +require('zone.js/dist/fake-async-test'); /* 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. + Below, context will be a function/object with file names as keys. using that regex we are saying look in client/app and find - any file that ends with spec.js and get its path. By passing in true + any file that ends with '.spec.ts' and get its path. By passing in true we say do this recursively */ var appContext = require.context('./src', true, /\.spec\.ts/); @@ -19,11 +29,10 @@ var appContext = require.context('./src', true, /\.spec\.ts/); // loop and require those spec files here appContext.keys().forEach(appContext); - // Select BrowserDomAdapter. // see https://github.com/AngularClass/angular2-webpack-starter/issues/124 // Somewhere in the test setup -var testing = require('angular2/testing'); -var browser = require('angular2/platform/testing/browser'); +var testing = require('@angular/core/testing'); +var browser = require('@angular/platform-browser-dynamic/testing'); -testing.setBaseTestProviders(browser.TEST_BROWSER_PLATFORM_PROVIDERS, browser.TEST_BROWSER_APPLICATION_PROVIDERS); +testing.TestBed.initTestEnvironment(browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting()); diff --git a/karma.conf.js b/karma.conf.js index 6a9b4068..91b79ad0 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,6 +1,10 @@ var path = require('path'); + var webpackConfig = require('./webpack.config'); +var ENV = process.env.npm_lifecycle_event; +var isTestWatch = ENV === 'test-watch'; + module.exports = function (config) { var _config = { @@ -13,8 +17,7 @@ module.exports = function (config) { // list of files / patterns to load in the browser files: [ - {pattern: './karma-shim.js', watched: false}, - {pattern: './src/app/**/*.spec.ts', watched: true, included: false} + { pattern: './karma-shim.js', watched: false } ], // list of files to exclude @@ -34,22 +37,14 @@ module.exports = function (config) { stats: 'errors-only' }, - coverageReporter: { - dir: 'coverage/', - reporters: [ - {type: 'text-summary'}, - {type: 'html'} - ] - }, - webpackServer: { noInfo: true // please don't spam the console when running in karma! }, // test results reporter to use - // possible values: 'dots', 'progress' + // possible values: 'dots', 'progress', 'mocha' // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['progress', 'coverage'], + reporters: ["mocha"], // web server port port: 9876, @@ -66,13 +61,27 @@ module.exports = function (config) { // start these browsers // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: ['PhantomJS'], // you can also use Chrome + browsers: ['Chrome'], // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits singleRun: true }; + if (!isTestWatch) { + _config.reporters.push("coverage"); + + _config.coverageReporter = { + dir: 'coverage/', + reporters: [{ + type: 'json', + dir: 'coverage', + subdir: 'json', + file: 'coverage-final.json' + }] + }; + } + config.set(_config); }; diff --git a/package.json b/package.json index a7966fe8..27ea2952 100644 --- a/package.json +++ b/package.json @@ -5,67 +5,85 @@ "scripts": { "clean": "rimraf node_modules doc dist && npm cache clean", "clean-install": "npm run clean && npm install", - "clean-start": "npm run clean && npm start", + "clean-start": "npm run clean-install && npm start", "watch": "webpack --watch --progress --profile", - "build": "rimraf dist && webpack --progress --profile", + "build": "rimraf dist && webpack --progress --profile --bail", "server": "webpack-dev-server --inline --progress --port 8080", "webdriver-update": "webdriver-manager update", "webdriver-start": "webdriver-manager start", - "lint": "tsconfig-lint", + "lint": "tslint --force \"src/**/*.ts\"", "e2e": "protractor", "e2e-live": "protractor --elementExplorer", + "pretest": "npm run lint", "test": "karma start", + "posttest": "remap-istanbul -i coverage/json/coverage-final.json -o coverage/html -t html", "test-watch": "karma start --no-single-run --auto-watch", "ci": "npm run e2e && npm run test", - "docs": "typedoc --options typedoc.json src/app/app.ts", + "docs": "typedoc --options typedoc.json src/app/app.component.ts", "start": "npm run server", - "postinstall": "npm run webdriver-update && typings install" + "start:hmr": "npm run server -- --hot", + "postinstall": "npm run webdriver-update" }, "dependencies": { - "angular2": "2.0.0-beta.12", - "es6-shim": "^0.35.0", - "reflect-metadata": "0.1.2", - "rxjs": "5.0.0-beta.2", - "zone.js": "0.6.6" + "@angular/common": "~4.2.6", + "@angular/compiler": "~4.2.6", + "@angular/core": "~4.2.6", + "@angular/forms": "~4.2.6", + "@angular/http": "~4.2.6", + "@angular/platform-browser": "~4.2.6", + "@angular/platform-browser-dynamic": "~4.2.6", + "@angular/router": "~4.2.6", + "core-js": "^2.4.1", + "reflect-metadata": "^0.1.3", + "tslib": "^1.7.1", + "rxjs": "^5.0.1", + "zone.js": "^0.8.10" }, "devDependencies": { - "angular-cli": "0.0.*", + "@angularclass/hmr": "^1.0.1", + "@angularclass/hmr-loader": "^3.0.2", + "@types/jasmine": "^2.5.41", + "@types/node": "^6.0.38", + "@types/selenium-webdriver": "2.53.39", + "angular2-template-loader": "^0.6.0", "autoprefixer": "^6.3.2", - "copy-webpack-plugin": "^1.1.1", - "css-loader": "^0.23.0", - "extract-text-webpack-plugin": "^1.0.1", - "file-loader": "^0.8.4", + "awesome-typescript-loader": "^3.1.2", + "codelyzer": "2.0.0", + "copy-webpack-plugin": "^4.0.0", + "css-loader": "^0.28.4", + "extract-text-webpack-plugin": "^2.0.0-beta.4", + "file-loader": "^0.10.0", "html-loader": "^0.4.0", "html-webpack-plugin": "^2.8.1", - "istanbul-instrumenter-loader": "^0.1.3", + "istanbul-instrumenter-loader": "^0.2.0", "jasmine-core": "^2.3.4", - "jasmine-spec-reporter": "^2.4.0", + "jasmine-spec-reporter": "^3.2.0", "json-loader": "^0.5.3", - "karma": "0.13.19", - "karma-chrome-launcher": "^0.2.1", - "karma-coverage": "^0.5.2", - "karma-jasmine": "^0.3.7", - "karma-phantomjs-launcher": "^1.0.0", + "karma": "1.4.1", + "karma-chrome-launcher": "^2.0.0", + "karma-coverage": "^1.0.0", + "karma-jasmine": "^1.0.2", + "karma-mocha-reporter": "^2.0.3", + "karma-remap-istanbul": "0.2.1", "karma-sourcemap-loader": "^0.3.7", - "karma-webpack": "1.7.0", - "node-sass": "^3.4.2", - "null-loader": "git+https://github.com/webpack/null-loader.git", - "phantomjs-prebuilt": "^2.1.4", - "postcss-loader": "^0.8.0", - "protractor": "^3.1.1", + "karma-webpack": "2.0.2", + "node-sass": "^4.5.0", + "null-loader": "0.1.1", + "postcss-loader": "^1.1.0", + "protractor": "^4.0.10", "raw-loader": "0.5.1", + "remap-istanbul": "^0.6.4", "rimraf": "^2.5.1", - "sass-loader": "^3.1.2", + "sass-loader": "^6.0.1", + "shelljs": "^0.7.0", "style-loader": "^0.13.0", - "ts-loader": "^0.8.1", - "tsconfig-lint": "^0.5.0", - "tslint": "^3.4.0", - "tslint-loader": "^2.1.0", - "typedoc": "^0.3.12", - "typescript": "^1.8.0", - "typings": "^0.6.8", + "ts-helpers": "^1.1.1", + "tslint": "^4.3.1", + "tslint-loader": "^3.3.0", + "typedoc": "^0.5.1", + "typescript": "^2.3.1", "url-loader": "^0.5.6", - "webpack": "^1.12.13", - "webpack-dev-server": "^1.14.1" + "webpack": "2.2.1", + "webpack-dev-server": "2.3.0" } } diff --git a/protractor.conf.js b/protractor.conf.js index 9a129fa5..f2253b39 100644 --- a/protractor.conf.js +++ b/protractor.conf.js @@ -2,7 +2,7 @@ exports.config = { baseUrl: 'http://localhost:8080/', specs: [ - 'src/**/*.e2e.js' + 'src/**/*.e2e-spec.js' ], exclude: [], @@ -24,7 +24,7 @@ exports.config = { }, onPrepare: function () { - var SpecReporter = require('jasmine-spec-reporter'); + var SpecReporter = require('jasmine-spec-reporter').SpecReporter; // add jasmine spec reporter jasmine.getEnv().addReporter(new SpecReporter({displayStacktrace: true})); diff --git a/src/app/components/about/about.html b/src/app/about/about.component.html similarity index 100% rename from src/app/components/about/about.html rename to src/app/about/about.component.html diff --git a/src/app/components/about/about.scss b/src/app/about/about.component.scss similarity index 100% rename from src/app/components/about/about.scss rename to src/app/about/about.component.scss diff --git a/src/app/about/about.component.spec.ts b/src/app/about/about.component.spec.ts new file mode 100644 index 00000000..7cbe8d3a --- /dev/null +++ b/src/app/about/about.component.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AboutComponent } from './about.component'; + +describe('About Component', () => { + beforeEach(() => { + TestBed.configureTestingModule({declarations: [AboutComponent]}); + }); + + it('should ...', () => { + const fixture = TestBed.createComponent(AboutComponent); + fixture.detectChanges(); + expect(fixture.nativeElement.children[0].textContent).toContain('About Works!'); + }); + +}); diff --git a/src/app/about/about.component.ts b/src/app/about/about.component.ts new file mode 100644 index 00000000..a2e4ad51 --- /dev/null +++ b/src/app/about/about.component.ts @@ -0,0 +1,18 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'my-about', + templateUrl: './about.component.html', + styleUrls: ['./about.component.scss'] +}) +export class AboutComponent implements OnInit { + + constructor() { + // Do stuff + } + + ngOnInit() { + console.log('Hello About'); + } + +} diff --git a/src/app/app.e2e.js b/src/app/app.component.e2e-spec.js similarity index 56% rename from src/app/app.e2e.js rename to src/app/app.component.e2e-spec.js index 782244cf..9ec9d23d 100644 --- a/src/app/app.e2e.js +++ b/src/app/app.component.e2e-spec.js @@ -9,19 +9,19 @@ describe('App', function () { }); it('should have
', function () { - expect(element(by.css('app header')).isPresent()).toEqual(true); + expect(element(by.css('my-app header')).isPresent()).toEqual(true); }); it('should have
', function () { - expect(element(by.css('app main')).isPresent()).toEqual(true); + expect(element(by.css('my-app main')).isPresent()).toEqual(true); }); it('should have a main title', function () { - expect(element(by.css('main .title')).getText()).toEqual('Hello from Angular 2 !'); + expect(element(by.css('main h1')).getText()).toEqual('Hello from Angular 2!'); }); it('should have