From 049094f179318532fc1db5792a27dc71e8a16201 Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Fri, 6 Jan 2017 21:38:04 +0200 Subject: [PATCH] Development tools refactor - common webpack config - use latest karma-coverage + remap-istanbul - use webpack-ngc instead of ngc buildstep - update dev dependencies - use V8LazyParseWebpackPlugin --- .gitignore | 1 + .npmignore | 2 +- bower.json | 1 + build/resource-override.js | 0 build/webpack.common.js | 133 +++++++++++++++++++++++++++++++++++++ build/webpack.dev.js | 128 +++++++---------------------------- build/webpack.prod.js | 93 +++++++------------------- build/webpack.test.js | 79 +++++----------------- karma.conf.js | 16 ++--- lib/bootstrap.ts | 2 +- package.json | 29 +++++--- tests/spec-bundle.js | 9 --- tsconfig.json | 2 - tsconfig.webpack.json | 41 ++++++++++++ 14 files changed, 267 insertions(+), 269 deletions(-) create mode 100644 build/resource-override.js create mode 100644 build/webpack.common.js create mode 100644 tsconfig.webpack.json diff --git a/.gitignore b/.gitignore index 045d5fea..e4d93b73 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ lib/**/*.shim.ngstyle.ts /dist /demo/build .tmp +compiled /coverage .ghpages-tmp stats.json diff --git a/.npmignore b/.npmignore index f66b4783..7d2abb70 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,6 @@ .DS_Store **/.* -.tmp +compiled node_modules jspm_packages diff --git a/bower.json b/bower.json index e21e0317..d3d14e62 100644 --- a/bower.json +++ b/bower.json @@ -26,6 +26,7 @@ "**/.*", "node_modules", "tests", + "compiled", "lib", "demo", "build", diff --git a/build/resource-override.js b/build/resource-override.js new file mode 100644 index 00000000..e69de29b diff --git a/build/webpack.common.js b/build/webpack.common.js new file mode 100644 index 00000000..c24c5e03 --- /dev/null +++ b/build/webpack.common.js @@ -0,0 +1,133 @@ +const webpack = require('webpack'); + +const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin; +const StringReplacePlugin = require("string-replace-webpack-plugin"); +const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin'); +const ngcWebpack = require('ngc-webpack'); + +const VERSION = JSON.stringify(require('../package.json').version); + +const root = require('./helpers').root; + +module.exports = function (options) { + const conf = { + performance: { hints: false }, + + output: { + path: root('dist'), + filename: '[name].js', + sourceMapFilename: '[name].[id].map', + chunkFilename: '[id].chunk.js' + }, + + resolve: { + extensions: ['.ts', '.js', '.json', '.css'], + alias: { + http: 'stream-http', + https: 'stream-http' + } + }, + + externals: { + 'jquery': 'jquery', + 'esprima': 'esprima' // optional dep of ys-yaml not needed for redoc + }, + + module: { + exprContextCritical: false, + rules: [ + { + enforce: 'pre', + test: /\.ts$/, + exclude: [ + /node_modules/ + ], + loader: StringReplacePlugin.replace({ + replacements: [ + { + pattern: /styleUrls:\s*\[\s*'([\w\.\/-]*)\.css'\s*\][\s,]*$/gm, + replacement: function (match, p1, offset, string) { + return `styleUrls: ['${p1}.scss'],`; + } + }, + { + pattern: /(\.\/components\/Redoc\/redoc-initial-styles\.css)/gm, + replacement: function (match, p1, offset, string) { + return p1.replace('.css', '.scss'); + } + } + ] + }) + }, + { + enforce: 'pre', + test: /\.js$/, + loader: 'source-map-loader', + exclude: [ + /node_modules/ + ] + }, + { + test: /\.json$/, + use: 'json-loader' + }, + { + test: /lib[\\\/].*\.css$/, + loaders: ['raw-loader'], + exclude: [/redoc-initial-styles\.css$/] + }, { + test: /\.css$/, + loaders: ['style-loader', 'css-loader?-import'], + exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.css$/] + }, + { + test: /lib[\\\/].*\.scss$/, + loaders: ['raw-loader', "sass-loader"], + exclude: [/redoc-initial-styles\.scss$/] + }, + { + test: /\.scss$/, + loaders: ['style-loader', 'css-loader?-import', "sass-loader"], + exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.scss$/] + }, + { + test: /\.html$/, + loader: 'raw-loader' + } + ], + + }, + + plugins: [ + new CheckerPlugin(), + new webpack.DefinePlugin({ + 'IS_PRODUCTION': options.IS_PRODUCTION, + 'LIB_VERSION': VERSION, + 'AOT': options.AOT + }), + + new StringReplacePlugin() + ], + node: { + global: true, + crypto: 'empty', + fs: 'empty', + process: true, + module: false, + clearImmediate: false, + setImmediate: false + } + }; + + if (options.AOT) { + conf.plugins.push( + new ngcWebpack.NgcWebpackPlugin({ + disable: !options.AOT, + tsConfig: root('tsconfig.webpack.json'), + resourceOverride: root('build/resource-override.js') + }) + ); + } + + return conf; +} diff --git a/build/webpack.dev.js b/build/webpack.dev.js index ca8cf7c7..fe46d15e 100644 --- a/build/webpack.dev.js +++ b/build/webpack.dev.js @@ -1,41 +1,24 @@ const webpack = require('webpack'); -const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin; +const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin; const StringReplacePlugin = require("string-replace-webpack-plugin"); const root = require('./helpers').root; const VERSION = JSON.stringify(require('../package.json').version); const IS_PRODUCTION = process.env.NODE_ENV === "production"; -// TODO Refactor common parts of config -module.exports = { +const webpackMerge = require('webpack-merge'); // used to merge webpack configs +const commonConfig = require('./webpack.common.js'); + +module.exports = webpackMerge(commonConfig({ + IS_PRODUCTION: process.env.NODE_ENV === "production", + AOT: false +}), { devtool: '#inline-source-map', - performance: { hints: false }, - resolve: { - extensions: ['.ts', '.js', '.json', '.css'], - alias: { - http: 'stream-http', - https: 'stream-http' - } - }, - externals: { - 'jquery': 'jquery', - 'esprima': 'esprima' // optional dep of ys-yaml not needed for redoc - }, - node: { - fs: "empty", - crypto: "empty", - global: true, - process: true, - module: false, - clearImmediate: false, - setImmediate: false - }, entry: { - 'redoc': './lib/index.ts', + 'polyfills': './lib/polyfills.ts', 'vendor': './lib/vendor.ts', - 'polyfills': './lib/polyfills.ts' + 'redoc': './lib/index.ts', }, - devServer: { contentBase: root('demo'), watchContentBase: true, @@ -47,87 +30,22 @@ module.exports = { hot: false, stats: 'errors-only' }, - - output: { - path: root('dist'), - filename: '[name].js', - sourceMapFilename: '[name].[id].map', - chunkFilename: '[id].chunk.js', - // devtoolModuleFilenameTemplate: "[resource-path]", - // devtoolFallbackModuleFilenameTemplate: "[resource-path]?[hash]", - }, - module: { - exprContextCritical: false, - rules: [{ - enforce: 'pre', - test: /\.js$/, - loader: 'source-map-loader', - exclude: [ - /node_modules/ - ] - }, { - enforce: 'pre', - test: /\.ts$/, - exclude: [ - /node_modules/ - ], - loader: StringReplacePlugin.replace({ - replacements: [ - { - pattern: /styleUrls:\s*\[\s*'([\w\.\/-]*)\.css'\s*\][\s,]*$/gm, - replacement: function (match, p1, offset, string) { - return `styleUrls: ['${p1}.scss'],`; - } - }, - { - pattern: /(\.\/components\/Redoc\/redoc-initial-styles\.css)/gm, - replacement: function (match, p1, offset, string) { - return p1.replace('.css', '.scss'); - } - } - ] - }) - }, { - test: /\.ts$/, - loaders: [ - 'awesome-typescript-loader', - 'angular2-template-loader' - ], - exclude: [/\.(spec|e2e)\.ts$/] - }, { - test: /lib[\\\/].*\.scss$/, - loaders: ['raw-loader', "sass-loader"], - exclude: [/redoc-initial-styles\.scss$/] - }, { - test: /\.scss$/, - loaders: ['style-loader', 'css-loader?-import', "sass-loader"], - exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.scss$/] - }, { - test: /\.css$/, - loaders: ['style-loader', 'css-loader?-import'], - }, { - test: /\.html$/, - loader: 'raw-loader' - }] + rules: [ + { + test: /\.ts$/, + use: [ + 'awesome-typescript-loader?{configFileName: "tsconfig.webpack.json"}', + 'angular2-template-loader', + ], + exclude: [/\.(spec|e2e)\.ts$/] + }, + ] }, - plugins: [ - new webpack.HotModuleReplacementPlugin(), - new webpack.optimize.CommonsChunkPlugin({ name: ['vendor', 'polyfills'], minChunks: Infinity - }), - - new webpack.DefinePlugin({ - 'IS_PRODUCTION': IS_PRODUCTION, - 'LIB_VERSION': VERSION, - 'AOT': IS_PRODUCTION - }), - - new ForkCheckerPlugin(), - - new StringReplacePlugin() - ], -} + }) + ] +}) diff --git a/build/webpack.prod.js b/build/webpack.prod.js index baeee310..f9908b07 100644 --- a/build/webpack.prod.js +++ b/build/webpack.prod.js @@ -1,4 +1,5 @@ const webpack = require('webpack'); +const V8LazyParseWebpackPlugin = require('v8-lazy-parse-webpack-plugin'); const VERSION = JSON.stringify(require('../package.json').version); @@ -11,31 +12,15 @@ const BANNER = const IS_MODULE = process.env.IS_MODULE != null; -const config = { - context: root(), - devtool: 'source-map', - performance: { hints: false }, +const webpackMerge = require('webpack-merge'); // used to merge webpack configs +const commonConfig = require('./webpack.common.js'); + +const config = webpackMerge(commonConfig({ + IS_PRODUCTION: true, + AOT: true +}), { + devtool: 'source-map', - resolve: { - extensions: ['.ts', '.js', '.json', '.css'], - alias: { - http: 'stream-http', - https: 'stream-http' - } - }, - externals: { - 'jquery': 'jquery', - 'esprima': 'esprima' // optional dep of ys-yaml not needed for redoc - }, - node: { - fs: "empty", - crypto: "empty", - global: true, - process: true, - module: false, - clearImmediate: false, - setImmediate: false - }, entry: { 'redoc': IS_MODULE ? ['./lib/vendor.ts', './lib/redoc.module.ts'] : ['./lib/polyfills.ts', './lib/vendor.ts', './lib/index.ts'] }, @@ -48,34 +33,18 @@ const config = { libraryTarget: 'umd', umdNamedDefine: true }, - module: { - exprContextCritical: false, - rules: [{ - enforce: 'pre', - test: /\.js$/, - loader: 'source-map-loader', - exclude: [ - /node_modules/ - ] - }, { - test: /node_modules\/.*\.ngfactory\.ts$/, - loader: 'awesome-typescript-loader' - }, { - test: /\.ts$/, - loader: 'awesome-typescript-loader', - exclude: /(node_modules)/, - }, { - test: /lib[\\\/].*\.css$/, - loaders: ['raw-loader'], - exclude: [/redoc-initial-styles\.css$/] - }, { - test: /\.css$/, - loaders: ['style-loader', 'css-loader?-import'], - exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.css$/] - }] + rules: [ + { + test: /\.ts$/, + use: [ + 'awesome-typescript-loader?{configFileName: "tsconfig.webpack.json"}', + 'angular2-template-loader', + ], + exclude: [/\.(spec|e2e)\.ts$/] + } + ] }, - plugins: [ new webpack.LoaderOptionsPlugin({ minimize: true, @@ -84,7 +53,8 @@ const config = { new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false, - screw_ie8: true + screw_ie8: true, + negate_iife: false // for lazy v8 }, mangle: { screw_ie8 : true }, output: { @@ -93,13 +63,9 @@ const config = { sourceMap: true }), new webpack.BannerPlugin(BANNER), - new webpack.DefinePlugin({ - 'IS_PRODUCTION': true, - 'LIB_VERSION': VERSION, - 'AOT': true - }) - ], -} + new V8LazyParseWebpackPlugin() + ] +}) if (IS_MODULE) { config.externals = { @@ -114,17 +80,6 @@ if (IS_MODULE) { 'rxjs': 'rxjs', 'zone.js/dist/zone': 'zone.js/dist/zone' }; - - config.module.rules.push({ - test: /\.ts$/, - loader: 'angular2-template-loader', - exclude: [/\.(spec|e2e)\.ts$/] - }); - - config.module.rules.push({ - test: /\.html$/, - loader: 'raw-loader' - }); } module.exports = config; diff --git a/build/webpack.test.js b/build/webpack.test.js index 3b76fa98..e1296d74 100644 --- a/build/webpack.test.js +++ b/build/webpack.test.js @@ -1,73 +1,31 @@ const webpack = require('webpack'); const root = require('./helpers').root; -const VERSION = JSON.stringify(require('../package.json').version); +const webpackMerge = require('webpack-merge'); // used to merge webpack configs +const commonConfig = require('./webpack.common.js'); -module.exports = { - +module.exports = webpackMerge(commonConfig({ + IS_PRODUCTION: true, + AOT: false +}), { devtool: 'inline-source-map', - performance: { hints: false }, - resolve: { - extensions: ['.ts', '.js', '.json', '.css'], - alias: { - http: 'stream-http', - https: 'stream-http' - } - }, - externals: { - 'jquery': 'jquery', - 'esprima': 'esprima' // optional dep of ys-yaml not needed for redoc - }, - node: { - fs: "empty", - crypto: "empty", - global: true, - process: true, - module: false, - clearImmediate: false, - setImmediate: false - }, - - output: { - path: root('dist'), - filename: '[name].js', - sourceMapFilename: '[name].map', - chunkFilename: '[id].chunk.js' - }, module: { exprContextCritical: false, - rules: [{ - enforce: 'pre', - test: /\.js$/, - loader: 'source-map-loader', - exclude: [ - /node_modules/ - ] - },{ + rules: [ + { test: /\.ts$/, - loaders: [ - 'awesome-typescript-loader' - ] - }, { + use: 'awesome-typescript-loader' + }, + { test: /\.ts$/, - loaders: [ - 'angular2-template-loader' + use: [ + 'angular2-template-loader', ], exclude: [/\.(spec|e2e)\.ts$/] - }, { - test: /lib[\\\/].*\.css$/, - loaders: ['raw-loader'], - exclude: [/redoc-initial-styles\.css$/] - }, { - test: /\.css$/, - loaders: ['style-loader', 'css-loader?-import'], - exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.css$/] - }, { - test: /\.html$/, - loader: 'raw-loader' - }, { + }, + { /** * Instruments JS files with Istanbul for subsequent code coverage reporting. * Instrument only testing sources. @@ -85,11 +43,6 @@ module.exports = { }, plugins: [ - new webpack.DefinePlugin({ - 'IS_PRODUCTION': false, - 'LIB_VERSION': VERSION, - 'AOT': 'false' - }), new webpack.LoaderOptionsPlugin({ test: /\.ts$/, sourceMap: false, @@ -106,4 +59,4 @@ module.exports = { /(?:[^\\\/]*(?:[\\\/]|$))*[^\\\/]*\.css$/ // ignore css files ]) ], -} +}) diff --git a/karma.conf.js b/karma.conf.js index a9a14697..0732fa82 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -9,13 +9,13 @@ module.exports = function (config) { }, coverageReporter: { - dir: 'coverage/', - reporters: [ - {type: 'html'}, - {type: 'lcov'}, - {type: 'json'}, - {type: 'text-summary'} - ] + type: 'in-memory' + }, + + remapCoverageReporter: { + 'text-summary': null, + 'text-lcov': './coverage/lcov.info', + 'html': './coverage/html' }, webpack: testWebpackConfig, webpackMiddleware: { @@ -42,7 +42,7 @@ module.exports = function (config) { }, colors: true, singleRun: true, - reporters: travis ? ['mocha', 'coverage', 'coveralls'] : ['mocha', 'coverage'], + reporters: travis ? ['mocha', 'coverage', 'remap-coverage', 'coveralls'] : ['mocha', 'coverage', 'remap-coverage'], browsers: ['PhantomJS'], diff --git a/lib/bootstrap.ts b/lib/bootstrap.ts index c55ccecb..86eddbd3 100644 --- a/lib/bootstrap.ts +++ b/lib/bootstrap.ts @@ -1,5 +1,5 @@ import { platformBrowser } from '@angular/platform-browser'; -import { AppModuleNgFactory } from './app.module.ngfactory'; +import { AppModuleNgFactory } from '../compiled/lib/app.module.ngfactory'; export function bootstrapRedoc() { return platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); diff --git a/package.json b/package.json index 8359238a..60b3733a 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,11 @@ "e2e": "npm run build:prod && npm run e2e-copy && npm run webdriver && protractor", "deploy": "node ./build/prepare_deploy.js && deploy-to-gh-pages --update demo", "ngc": "ngc -p .", - "webpack:prod": "webpack --config build/webpack.prod.js --profile --bail", + "clean:aot": "npm run rimraf -- .tmp lib/**/*.css", + "rimraf": "rimraf", + "webpack:prod": "npm run clean:aot && npm run build:sass && webpack --config build/webpack.prod.js --profile --bail", "build:sass": "node-sass -q -o lib lib", - "build:prod": "npm run build:sass && npm run ngc && npm run webpack:prod", + "build:prod": "npm run webpack:prod", "build:prod-module": "npm run build:sass && npm run ngc && npm run webpack:prod && IS_MODULE=true npm run webpack:prod", "build-dist": "npm run build:prod", "stats": "webpack --config build/webpack.prod.js --json > stats.json", @@ -57,7 +59,7 @@ "@types/requirejs": "^2.1.26", "@types/should": "^8.1.28", "angular2-template-loader": "^0.6.0", - "awesome-typescript-loader": "^2.2.4", + "awesome-typescript-loader": "~3.0.0-beta.17", "branch-release": "^1.0.3", "chalk": "^1.1.3", "codelyzer": "^2.0.0-beta.4", @@ -66,27 +68,30 @@ "css-loader": "^0.26.0", "deploy-to-gh-pages": "^1.1.2", "http-server": "^0.9.0", - "istanbul-instrumenter-loader": "^0.2.0", + "istanbul-instrumenter-loader": "^1.2.0", "jasmine-core": "^2.4.1", "jasmine-spec-reporter": "^2.4.0", "karma": "^1.2.0", "karma-chrome-launcher": "^2.0.0", - "karma-coverage": "github:douglasduteil/karma-coverage#next", + "karma-coverage": "^1.1.1", "karma-coveralls": "^1.1.2", "karma-jasmine": "^1.0.2", "karma-mocha-reporter": "^2.0.0", "karma-phantomjs-launcher": "^1.0.0", "karma-phantomjs-shim": "^1.1.2", + "karma-remap-coverage": "^0.1.4", "karma-should": "^1.0.0", "karma-sinon": "^1.0.4", "karma-sourcemap-loader": "^0.3.7", - "karma-webpack": "^1.8.0", + "karma-webpack": "^1.8.1 ", + "ngc-webpack": "^1.1.0", "node-sass": "^4.1.1", "phantomjs-prebuilt": "^2.1.7", "protractor": "^4.0.10", "raw-loader": "^0.5.1", + "rimraf": "^2.5.4", "rxjs": "^5.0.1", - "sass-loader": "^4.0.2", + "sass-loader": "^4.1.1", "shelljs": "^0.7.0", "should": "^11.1.0", "sinon": "^1.17.2", @@ -94,10 +99,12 @@ "string-replace-webpack-plugin": "0.0.4", "style-loader": "^0.13.1", "ts-helpers": "^1.1.1", - "tslint": "^4.0.2", - "typescript": "2.0.9", - "webpack": "^2.1.0-beta.28", - "webpack-dev-server": "^2.1.0-beta.12", + "tslint": "^4.2.0", + "typescript": "2.0.10", + "v8-lazy-parse-webpack-plugin": "^0.3.0", + "webpack": "2.2.0-rc.3", + "webpack-dev-server": "^2.2.0-rc.0", + "webpack-merge": "^2.3.1", "zone.js": "^0.7.2" }, "dependencies": { diff --git a/tests/spec-bundle.js b/tests/spec-bundle.js index 4b5637d4..8a2964ba 100644 --- a/tests/spec-bundle.js +++ b/tests/spec-bundle.js @@ -61,15 +61,6 @@ beforeEach(function() { }); }); -// afterEach(function() { -// TestBed.resetTestingModule(); -// }); - -// afterEach(function() { -// TestBed.resetTestEnvironment(); -// }) - - var testContext = require.context('..', true, /\.spec\.ts/); /* diff --git a/tsconfig.json b/tsconfig.json index 950a07a1..0beacebc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,6 @@ "target": "es5", "noImplicitAny": false, "sourceMap": true, - "outDir": ".tmp", "pretty": true, "moduleResolution": "node", "types": [ @@ -20,7 +19,6 @@ "compileOnSave": false, "exclude": [ "node_modules", - ".tmp", "dist" ], "awesomeTypescriptLoaderOptions": { diff --git a/tsconfig.webpack.json b/tsconfig.webpack.json new file mode 100644 index 00000000..514aa3e4 --- /dev/null +++ b/tsconfig.webpack.json @@ -0,0 +1,41 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "es2015", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "sourceMap": true, + "noEmit": true, + "noEmitHelpers": true, + "strictNullChecks": false, + "baseUrl": "./src", + "paths": { + }, + "lib": [ + "es2015", + "dom" + ], + "types": [ + "node" + ] + }, + "exclude": [ + "node_modules", + "dist", + "**/*.spec.ts", + "**/*.e2e.ts" + ], + "awesomeTypescriptLoaderOptions": { + "forkChecker": true, + "useWebpackText": true + }, + "angularCompilerOptions": { + "genDir": "./compiled", + "skipMetadataEmit": true + }, + "compileOnSave": false, + "buildOnSave": false, + "atom": { "rewriteTsconfig": false } +}