From eab12f9ef44210e49e5df7f049df66a4b8f3ed08 Mon Sep 17 00:00:00 2001 From: Valentin Nazarov Date: Fri, 17 Jun 2016 08:26:15 +0300 Subject: [PATCH] Initial commit --- .gitignore | 48 ++++++++++++++++ .sass-lint.yml | 12 ++++ README.md | 5 ++ karma.conf.js | 95 ++++++++++++++++++++++++++++++++ package.json | 82 +++++++++++++++++++++++++++ src/app/app.component.ts | 19 +++++++ src/app/app.html | 1 + src/app/app.scss | 16 ++++++ src/app/app.service.ts | 7 +++ src/index.ejs | 16 ++++++ src/main.ts | 13 +++++ src/polyfills.ts | 29 ++++++++++ src/vendor.ts | 10 ++++ tests/app/app.component.spec.ts | 20 +++++++ tests/main.ts | 37 +++++++++++++ tsconfig.json | 27 +++++++++ tsconfig.test.json | 28 ++++++++++ tslint.json | 26 +++++++++ typedoc.json | 15 +++++ typings.json | 8 +++ webpack.config.common.js | 98 +++++++++++++++++++++++++++++++++ webpack.config.dev.js | 47 ++++++++++++++++ webpack.config.js | 22 ++++++++ webpack.config.prod.js | 39 +++++++++++++ webpack.config.test.js | 72 ++++++++++++++++++++++++ 25 files changed, 792 insertions(+) create mode 100644 .gitignore create mode 100644 .sass-lint.yml create mode 100644 README.md create mode 100644 karma.conf.js create mode 100644 package.json create mode 100644 src/app/app.component.ts create mode 100644 src/app/app.html create mode 100644 src/app/app.scss create mode 100644 src/app/app.service.ts create mode 100644 src/index.ejs create mode 100644 src/main.ts create mode 100644 src/polyfills.ts create mode 100644 src/vendor.ts create mode 100644 tests/app/app.component.spec.ts create mode 100644 tests/main.ts create mode 100644 tsconfig.json create mode 100644 tsconfig.test.json create mode 100644 tslint.json create mode 100644 typedoc.json create mode 100644 typings.json create mode 100644 webpack.config.common.js create mode 100644 webpack.config.dev.js create mode 100644 webpack.config.js create mode 100644 webpack.config.prod.js create mode 100644 webpack.config.test.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5c9661b --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +# Created by .ignore support plugin (hsz.mobi) +### Node template +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +# Build result +dist + +# Documentation +docs + +# TypeScript definitions +typings diff --git a/.sass-lint.yml b/.sass-lint.yml new file mode 100644 index 0000000..c17c835 --- /dev/null +++ b/.sass-lint.yml @@ -0,0 +1,12 @@ +# Linter Options +options: + # Don't merge default rules + merge-default-rules: false +# File Options +files: + include: 'src/**/*.s+(a|c)ss' +# Rule Configuration +rules: + extends-before-mixins: 2 + extends-before-declarations: 2 + placeholder-in-extend: 2 diff --git a/README.md b/README.md new file mode 100644 index 0000000..bac0e42 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Angular 2 + Webpack boilerplate + +Work in progress. + +For now: run `npm install` and `npm start`, go to `http://localhost:9045/`. diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..bb3b3b8 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,95 @@ +/** + * Please see Karma config file reference for better understanding: + * http://karma-runner.github.io/latest/config/configuration-file.html + */ +module.exports = function(config) { + config.set({ + /** + * This path will be used for resolving. + */ + basePath: '', + + /** + * List of test frameworks we will use. Most of them are provided by separate packages (adapters). + * You can find them on npmjs.org: https://npmjs.org/browse/keyword/karma-adapter + */ + frameworks: ['jasmine', 'source-map-support'], + + /** + * Entry point / test environment builder is also written in TypeScript. + */ + files: ['./tests/main.ts'], + + /** + * Transform files before loading them. + */ + preprocessors: { + './src/**/*.ts': [ + 'webpack', + 'sourcemap', + 'coverage' + ], + './tests/**/*.ts': [ + 'webpack' + ] + }, + + webpack: require('./webpack.config.test'), + + /** + * Make dev server silent. + */ + webpackServer: { noInfo: true }, + + /** + * A lot of plugins are available for test results reporting. + * You can find them here: https://npmjs.org/browse/keyword/karma-reporter + */ + reporters: ['coverage', 'karma-remap-istanbul'], + + /** + * Simple summary (printed to the console) and JSON file which we will remap back to TypeScript. + */ + coverageReporter: { + dir: 'coverage', + reporters: [ + { type: 'text-summary' }, + { + type: 'json', + subdir: '.', + file: 'coverage-final.json' + } + ] + }, + + /** + * Map code coverage result back to TypeScript using `karma-remap-istanbul`. + */ + remapIstanbulReporter: { + src: 'coverage/coverage-final.json', + reports: { + lcovonly: 'coverage/lcov.info', + html: 'coverage/report' + }, + timeoutNotCreated: 5000, + timeoutNoMoreFiles: 1000 + }, + + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + + /** + * Only Phantom is used in this example. + * You can find more browser launchers here: https://npmjs.org/browse/keyword/karma-launcher + */ + browsers: ['PhantomJS'], + + /** + * This is CI mode: run once and exit. + * TODO: Non-CI mode + */ + autoWatch: true, + singleRun: true + }) +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..a3dfad5 --- /dev/null +++ b/package.json @@ -0,0 +1,82 @@ +{ + "name": "angular2-webpack-boilerplate", + "version": "1.0.0", + "description": "A boilerplate for Angular 2 and Webpack", + "keywords": [ + "angular2", + "webpack", + "typescript" + ], + "author": "Valentin Nazarov ", + "license": "MIT", + "directories": { + "test": "tests" + }, + "scripts": { + "clean": "rimraf ./node_modules ./docs ./typings ./coverage ./dist", + "clean:dist": "rimraf ./dist", + "lint": "npm run lint:ts && npm run lint:sass", + "lint:ts": "tslint src/**/*.ts tests/**/*.ts", + "lint:sass": "sass-lint", + "pretest": "npm run lint", + "test": "karma start", + "build": "webpack", + "postinstall": "typings install", + "docs": "npm run docs:typedoc && npm run docs:kss", + "docs:typedoc": "typedoc --options ./typedoc.json ./src/app", + "docs:kss": "kss --source ./src --destination ./docs/styleguide", + "start": "webpack-dev-server --inline --progress --profile --colors --watch --display-error-details --display-cached --content-base ./dist" + }, + "devDependencies": { + "@angular/common": "2.0.0-rc.2", + "@angular/compiler": "2.0.0-rc.2", + "@angular/core": "2.0.0-rc.2", + "@angular/http": "2.0.0-rc.2", + "@angular/platform-browser": "2.0.0-rc.2", + "@angular/platform-browser-dynamic": "2.0.0-rc.2", + "@angular/platform-server": "2.0.0-rc.2", + "@angular/router": "2.0.0-rc.2", + "awesome-typescript-loader": "^1.1.1", + "codelyzer": "0.0.23", + "core-js": "^2.4.0", + "css-loader": "^0.23.1", + "es6-shim": "^0.35.1", + "file-loader": "^0.8.5", + "html-loader": "^0.4.3", + "html-webpack-plugin": "^2.21.0", + "istanbul-instrumenter-loader": "^0.2.0", + "jasmine-core": "^2.4.1", + "json-loader": "^0.5.4", + "karma": "^0.13.22", + "karma-coverage": "^1.0.0", + "karma-jasmine": "^1.0.2", + "karma-phantomjs-launcher": "^1.0.0", + "karma-remap-istanbul": "^0.1.0", + "karma-source-map-support": "^1.1.0", + "karma-sourcemap-loader": "^0.3.7", + "karma-webpack": "^1.7.0", + "kss": "^3.0.0-beta.14", + "node-sass": "^3.7.0", + "phantomjs-prebuilt": "^2.1.7", + "raw-loader": "^0.5.1", + "reflect-metadata": "^0.1.3", + "remap-istanbul": "^0.6.4", + "rimraf": "^2.5.2", + "rxjs": "5.0.0-beta.6", + "sass-lint": "^1.7.0", + "sass-loader": "^3.2.0", + "source-map-loader": "^0.1.5", + "style-loader": "^0.13.1", + "to-string-loader": "^1.1.4", + "ts-helpers": "^1.1.1", + "tslint": "^3.11.0", + "tslint-loader": "^2.1.4", + "typedoc": "^0.4.3", + "typescript": "^1.8.10", + "typings": "^1.3.0", + "webpack": "^1.13.1", + "webpack-dev-server": "^1.14.1", + "webpack-md5-hash": "0.0.5", + "zone.js": "~0.6.12" + } +} diff --git a/src/app/app.component.ts b/src/app/app.component.ts new file mode 100644 index 0000000..3a11545 --- /dev/null +++ b/src/app/app.component.ts @@ -0,0 +1,19 @@ +import { Component, ViewEncapsulation } from '@angular/core'; +import { AppService } from './app.service'; + +@Component({ + selector: 'da-app', + template: require('./app.html'), + styles: [ + require('./app.scss') + ], + encapsulation: ViewEncapsulation.Native, + providers: [ + AppService + ] +}) +export class AppComponent { + constructor(public appService: AppService) { + + } +} diff --git a/src/app/app.html b/src/app/app.html new file mode 100644 index 0000000..4658077 --- /dev/null +++ b/src/app/app.html @@ -0,0 +1 @@ +

{{ appService.getTitle() }}

diff --git a/src/app/app.scss b/src/app/app.scss new file mode 100644 index 0000000..c0d5796 --- /dev/null +++ b/src/app/app.scss @@ -0,0 +1,16 @@ +$heading-color: #333; +$heading-highlight-color: #fa2800; + +// App title +// +// :hover - Highlights when hovering +// +// Styleguide base +.app__title { + font-size: 4rem; + color: $heading-color; + + &:hover { + color: $heading-highlight-color; + } +} diff --git a/src/app/app.service.ts b/src/app/app.service.ts new file mode 100644 index 0000000..f4c9acb --- /dev/null +++ b/src/app/app.service.ts @@ -0,0 +1,7 @@ +export class AppService { + title: string = "Hello, world!"; + + public getTitle(): string { + return this.title; + } +} diff --git a/src/index.ejs b/src/index.ejs new file mode 100644 index 0000000..22ab039 --- /dev/null +++ b/src/index.ejs @@ -0,0 +1,16 @@ + + + + <%= webpackConfig.metadata.title %> + + + + + + + + +Loading… +<% for (var chunk in htmlWebpackPlugin.files.chunks) { %><% } %> + + \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..37efc72 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,13 @@ +import { bootstrap } from '@angular/platform-browser-dynamic'; +import { enableProdMode } from '@angular/core'; + +import { AppComponent } from './app/app.component'; + +if (process.env.ENV === 'prod') { + enableProdMode(); +} + +/** + * TODO: Example service (HTTP interaction), routing, nested directives, pipe + related tests + */ +bootstrap(AppComponent); diff --git a/src/polyfills.ts b/src/polyfills.ts new file mode 100644 index 0000000..75b921d --- /dev/null +++ b/src/polyfills.ts @@ -0,0 +1,29 @@ +/** + * Use CoreJS polyfills. + */ +import 'core-js/es6'; +import 'core-js/es7/reflect'; + +/** + * Quote from docs: "A Zone is an execution context that persists across async tasks. You can think of it as + * thread-local storage for JavaScript VMs." Angular 2 uses this library. + * See details here: https://github.com/angular/zone.js/ + */ +// TODO: Move to `vendor.ts`? +import 'zone.js/dist/zone'; + +/** + * This package helps to avoid generation of helper code in each file (e.g. for decorators). + * See details here: https://github.com/ngParty/ts-helpers + */ +import 'ts-helpers'; + +if (process.env.ENV === 'production') { + // TODO: Either do something here or negate condition and remove `else` +} else { + /** + * You can use `import` only in a namespace or module in TypeScript, so use `require` here. + */ + Error['stackTraceLimit'] = Infinity; + require('zone.js/dist/long-stack-trace-zone'); +} diff --git a/src/vendor.ts b/src/vendor.ts new file mode 100644 index 0000000..a8a9dfa --- /dev/null +++ b/src/vendor.ts @@ -0,0 +1,10 @@ +/** + * Angular 2 and RxJS. + */ +import '@angular/platform-browser'; +import '@angular/platform-browser-dynamic'; +import '@angular/core'; +import '@angular/common'; +import '@angular/http'; +import '@angular/router'; +import 'rxjs'; diff --git a/tests/app/app.component.spec.ts b/tests/app/app.component.spec.ts new file mode 100644 index 0000000..460fd3b --- /dev/null +++ b/tests/app/app.component.spec.ts @@ -0,0 +1,20 @@ +import { + beforeEachProviders, + it, + inject, + expect +} from '@angular/core/testing'; + +import { AppService } from '../../src/app/app.service'; + +describe('App Service', () => { + beforeEachProviders(() => { + return [ + AppService + ]; + }); + + it('should return title', inject([AppService], (appService) => { + expect(appService.getTitle()).toBe('Hello, world!'); + })); +}); diff --git a/tests/main.ts b/tests/main.ts new file mode 100644 index 0000000..1124111 --- /dev/null +++ b/tests/main.ts @@ -0,0 +1,37 @@ +/** + * TODO: Comments + */ +import 'core-js/es6'; +import 'core-js/es7/reflect'; +import 'reflect-metadata'; +import 'zone.js/dist/zone'; +import 'zone.js/dist/sync-test'; +import 'zone.js/dist/async-test'; +import 'zone.js/dist/fake-async-test'; +import 'zone.js/dist/jasmine-patch'; + +import 'ts-helpers'; + +import 'zone.js/dist/sync-test'; +import 'zone.js/dist/async-test'; +import 'zone.js/dist/fake-async-test'; + +import { setBaseTestProviders } from '@angular/core/testing'; + +import { + TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, + TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS +} from '@angular/platform-browser-dynamic/testing'; + +setBaseTestProviders( + TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, + TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS +); + +let testContext = (<{ context?: Function }>require).context( + './', + true, + /\.spec\.ts/ +); + +testContext.keys().forEach(testContext); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..cd93acf --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node", + "target": "es5", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "noImplicitAny": false, + "removeComments": false, + "noEmitHelpers": true, + "sourceMap": true + }, + "exclude": [ + "node_modules" + ], + "filesGlob": [ + "./src/app/**/*.ts", + "./typings/index.d.ts", + "!./node_modules/**" + ], + "awesomeTypescriptLoaderOptions": { + "resolveGlobs": true, + "forkChecker": true + }, + "compileOnSave": false, + "buildOnSave": false +} \ No newline at end of file diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 0000000..f7e54bc --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node", + "target": "es5", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "noImplicitAny": false, + "removeComments": false, + "noEmitHelpers": true, + "sourceMap": false, + "inlineSourceMap": true + }, + "exclude": [ + "node_modules" + ], + "filesGlob": [ + "./src/app/**/*.ts", + "./typings/index.d.ts", + "!./node_modules/**" + ], + "awesomeTypescriptLoaderOptions": { + "resolveGlobs": true, + "forkChecker": true + }, + "compileOnSave": false, + "buildOnSave": false +} \ No newline at end of file diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000..e24415d --- /dev/null +++ b/tslint.json @@ -0,0 +1,26 @@ +{ + "rulesDirectory": [ + "node_modules/codelyzer" + ], + "rules": { + "directive-selector-name": [true, "camelCase"], + "component-selector-name": [true, "kebab-case"], + "directive-selector-type": [true, "attribute"], + "component-selector-type": [true, "element"], + "directive-selector-prefix": [true, "da"], + "component-selector-prefix": [true, "da"], + "use-input-property-decorator": true, + "use-output-property-decorator": true, + "use-host-property-decorator": true, + "no-attribute-parameter-decorator": true, + "no-input-rename": true, + "no-output-rename": true, + "no-forward-ref" :true, + "use-life-cycle-interface": true, + "use-pipe-transform-interface": true, + "pipe-naming": [true, "camelCase", "da"], + "component-class-suffix": true, + "directive-class-suffix": true, + "import-destructuring-spacing": true + } +} \ No newline at end of file diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 0000000..76be11a --- /dev/null +++ b/typedoc.json @@ -0,0 +1,15 @@ +{ + "mode": "modules", + "out": "docs/app", + "theme": "default", + "ignoreCompilerErrors": "true", + "experimentalDecorators": "true", + "emitDecoratorMetadata": "true", + "target": "ES5", + "moduleResolution": "node", + "preserveConstEnums": "true", + "stripInternal": "true", + "suppressExcessPropertyErrors": "true", + "suppressImplicitAnyIndexErrors": "true", + "module": "commonjs" +} \ No newline at end of file diff --git a/typings.json b/typings.json new file mode 100644 index 0000000..bb2a18b --- /dev/null +++ b/typings.json @@ -0,0 +1,8 @@ +{ + "name": "angular2-webpack-boilerplate", + "globalDependencies": { + "core-js": "registry:dt/core-js#0.0.0+20160602141332", + "jasmine": "registry:dt/jasmine#2.2.0+20160505161446", + "node": "registry:dt/node#6.0.0+20160613154055" + } +} \ No newline at end of file diff --git a/webpack.config.common.js b/webpack.config.common.js new file mode 100644 index 0000000..3f72ee1 --- /dev/null +++ b/webpack.config.common.js @@ -0,0 +1,98 @@ +'use strict'; + +/** + * Please see webpack config reference for better understanding: + * https://webpack.github.io/docs/configuration.html + */ +const webpack = require('webpack'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin; + +module.exports = { + /** + * These parameters will be used for rendering `index.html`. + */ + metadata: { + title: 'Demo Application', + baseUrl: '/' + }, + + entry: { + 'polyfills': './src/polyfills.ts', + 'vendor': './src/vendor.ts', + 'app': './src/main.ts' + }, + + resolve: { + extensions: ['', '.ts', '.js', '.scss', '.html'] + }, + + module: { + loaders: [ + /** + * Loader for TypeScript. + * No need to exclude tests by `(spec|e2e)` mask here, as they are in separate directory. + * + * See project repository for details / configuration reference: + * https://github.com/s-panferov/awesome-typescript-loader + */ + {test: /\.ts$/, loader: 'awesome-typescript-loader'}, + + /** + * Loaders for HTML templates, JSON files, SASS/SCSS stylesheets. See details at projects' repositories: + * + * https://github.com/webpack/json-loader + * https://github.com/webpack/html-loader + * https://github.com/gajus/to-string-loader + */ + {test: /\.json$/, loader: 'json-loader'}, + {test: /\.html$/, loader: 'html-loader'}, + {test: /\.scss$/, loader: 'to-string-loader!css-loader!sass-loader'} + ] + }, + + plugins: [ + /** + * This plugin is a part of `awesome-typescript-loader`, it allows to run type checking in a separate process, + * so webpack won't wait for it. + */ + new ForkCheckerPlugin(), + + /** + * Quote from webpack docs: "Assign the module and chunk ids by occurrence count. Ids that are used often get + * lower (shorter) ids. This make ids predictable, reduces total file size and is recommended." + * + * See https://webpack.github.io/docs/list-of-plugins.html#occurrenceorderplugin + */ + new webpack.optimize.OccurenceOrderPlugin(true), + + /** + * This plugin simplifies generation of `index.html` file. Especially useful for production environment, + * where your files have hashes in their names. + * + * We have auto-injection disabled here, otherwise scripts will be automatically inserted at the end + * of `body` element. + * + * See https://www.npmjs.com/package/html-webpack-plugin for details. + * + * TODO: Google Analytics and other stuff like that + */ + new HtmlWebpackPlugin({ + title: 'Demo Application', + template: 'src/index.ejs', + chunksSortMode: 'dependency', + inject: false + }), + + /** + * This plugin helps to share common code between pages. + * + * For more info see: + * https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin + * https://github.com/webpack/docs/wiki/optimization#multi-page-app + */ + new webpack.optimize.CommonsChunkPlugin({ + name: ['vendor', 'polyfills'] + }) + ] +}; diff --git a/webpack.config.dev.js b/webpack.config.dev.js new file mode 100644 index 0000000..38aad39 --- /dev/null +++ b/webpack.config.dev.js @@ -0,0 +1,47 @@ +'use strict'; + +/** + * TODO: Comments + */ +const webpack = require('webpack'); +const ENV = process.env.ENV = process.env.NODE_ENV = 'dev'; +let config = require('./webpack.config.common'); + +config.devtool = 'inline-source-map'; + +config.output = { + path: './dist', + publicPath: 'http://localhost:9045/', + filename: '[name].js', + chunkFilename: '[id].chunk.js', + sourceMapFilename: '[name].map' +}; + +config.debug = true; + +config.devServer = { + historyApiFallback: true, + stats: 'minimal', + outputPath: 'dist', + host: 'localhost', + port: 9045, + watchOptions: { + aggregateTimeout: 300, + poll: 1000 + } +}; + +/** + * Quote from webpack docs: "Define free variables. Useful for having development builds with debug logging + * or adding global constants." + * + * Note, that values are _evaluated_, not just assigned (this is why we use `JSON.stringify` here). + */ +config.plugins.push(new webpack.DefinePlugin({ + 'ENV': JSON.stringify(ENV), + 'process.env': { + 'ENV': JSON.stringify(ENV) + } +})); + +module.exports = config; diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..8bde0a5 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,22 @@ +'use strict'; + +/** + * TODO: Comments? + * TODO: HMR + */ + +switch (process.env.NODE_ENV) { + case 'prod': + case 'production': + module.exports = require('./webpack.config.prod'); + break; + case 'test': + case 'testing': + module.exports = require('./webpack.config.test'); + break; + case 'dev': + case 'development': + default: + module.exports = require('./webpack.config.dev'); + break; +} diff --git a/webpack.config.prod.js b/webpack.config.prod.js new file mode 100644 index 0000000..b675828 --- /dev/null +++ b/webpack.config.prod.js @@ -0,0 +1,39 @@ +'use strict'; + +/** + * TODO: Comments + */ +const webpack = require('webpack'); +const ENV = process.env.ENV = process.env.NODE_ENV = 'prod'; +let config = require('./webpack.config.common'); + +config.devtool = 'source-map'; + +config.output = { + path: './dist', + publicPath: '/', + filename: '[name].[hash].js', + chunkFilename: '[id].[hash].chunk.js', + sourceMapFilename: '[name].map' +}; + +/** + * TODO: Something better? + */ +config.htmlLoader = { minimize: false }; + +config.plugins.push( + new webpack.NoErrorsPlugin(), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.UglifyJsPlugin() +); + +/** + * Same purpose as in dev config. + */ +config.plugins.push(new webpack.DefinePlugin({ + 'ENV': JSON.stringify(ENV), + 'process.env': { + 'ENV': JSON.stringify(ENV) + } +})); diff --git a/webpack.config.test.js b/webpack.config.test.js new file mode 100644 index 0000000..eeb9138 --- /dev/null +++ b/webpack.config.test.js @@ -0,0 +1,72 @@ +/** + * Config for test environment is pretty different from dev and prod, so we don't use common config as base. + */ +module.exports = { + /** + * Inline source maps, generated by TypeScript compiler, will be used. + */ + devtool: 'inline-source-map', + + /** + * Entry point / test environment builder is also written in TypeScript. + */ + entry: './tests/main.ts', + + verbose: true, + + resolve: { + extensions: ['', '.ts', '.js'] + }, + + module: { + preLoaders: [ + /** + * Lint TypeScript before loading it. + * See https://github.com/wbuchwalter/tslint-loader for details. + */ + { + test: /\.ts$/, + loader: 'tslint-loader', + exclude: ['node_modules'] + } + ], + loaders: [ + /** + * Unlike ts-loader, awesome-typescript-loader doesn't allow to override TS compiler options + * in query params. We use separate `tsconfig.test.json` file, which only differs in one thing: + * inline source maps. They are used for code coverage report. + * + * See project repository for details / configuration reference: + * https://github.com/s-panferov/awesome-typescript-loader + */ + { + test: /\.ts$/, + loader: 'awesome-typescript-loader', + query: { + tsconfig: 'tsconfig.test.json' + } + }, + /** + * These loaders are used in other environments as well. + */ + { test: /\.json$/, loader: 'json-loader' }, + { test: /\.html$/, loader: 'html-loader' }, + { test: /\.scss$/, loader: 'to-string-loader!css-loader!sass-loader' } + ], + postLoaders: [ + /** + * Instruments TS source files for subsequent code coverage. + * See https://github.com/deepsweet/istanbul-instrumenter-loader + */ + { + test: /\.ts$/, + loader: 'istanbul-instrumenter-loader', + exclude: [ + /node_modules/, + /tests/, + /\.(e2e|spec)\.ts$/ + ] + } + ] + } +};