diff --git a/.travis.yml b/.travis.yml index c4edbe49..157b81b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,6 @@ install: - npm config set spin false - npm install -g npm@3 - npm install -g webpack - - npm install -g typings - npm install -g typescript - npm install -g bower diff --git a/config/head-config.common.js b/config/head-config.common.js new file mode 100644 index 00000000..c686518d --- /dev/null +++ b/config/head-config.common.js @@ -0,0 +1,43 @@ +/** + * Configuration for head elements added during the creation of index.html. + * + * All href attributes are added the publicPath (if exists) by default. + * You can explicitly hint to prefix a publicPath by setting a boolean value to a key that has + * the same name as the attribute you want to operate on, but prefix with = + * + * Example: + * { name: "msapplication-TileImage", content: "/assets/icon/ms-icon-144x144.png", "=content": true }, + * Will prefix the publicPath to content. + * + * { rel: "apple-touch-icon", sizes: "57x57", href: "/assets/icon/apple-icon-57x57.png", "=href": false }, + * Will not prefix the publicPath on href (href attributes are added by default + * + */ +module.exports = { + link: [ + /** tags for "apple-touch-icon" (AKA Web Clips). **/ + { rel: "apple-touch-icon", sizes: "57x57", href: "/assets/icon/apple-icon-57x57.png" }, + { rel: "apple-touch-icon", sizes: "60x60", href: "/assets/icon/apple-icon-60x60.png" }, + { rel: "apple-touch-icon", sizes: "72x72", href: "/assets/icon/apple-icon-72x72.png" }, + { rel: "apple-touch-icon", sizes: "76x76", href: "/assets/icon/apple-icon-76x76.png" }, + { rel: "apple-touch-icon", sizes: "114x114", href: "/assets/icon/apple-icon-114x114.png" }, + { rel: "apple-touch-icon", sizes: "120x120", href: "/assets/icon/apple-icon-120x120.png" }, + { rel: "apple-touch-icon", sizes: "144x144", href: "/assets/icon/apple-icon-144x144.png" }, + { rel: "apple-touch-icon", sizes: "152x152", href: "/assets/icon/apple-icon-152x152.png" }, + { rel: "apple-touch-icon", sizes: "180x180", href: "/assets/icon/apple-icon-180x180.png" }, + + /** tags for android web app icons **/ + { rel: "icon", type: "image/png", sizes: "192x192", href: "/assets/icon/android-icon-192x192.png" }, + + /** tags for favicons **/ + { rel: "icon", type: "image/png", sizes: "32x32", href: "/assets/icon/favicon-32x32.png" }, + { rel: "icon", type: "image/png", sizes: "96x96", href: "/assets/icon/favicon-96x96.png" }, + { rel: "icon", type: "image/png", sizes: "16x16", href: "/assets/icon/favicon-16x16.png" } + + ], + meta: [ + { name: "msapplication-TileColor", content: "#ffffff" }, + { name: "msapplication-TileImage", content: "/assets/icon/ms-icon-144x144.png", "=content": true }, + { name: "theme-color", content: "#4691d1" } + ] +}; diff --git a/config/helpers.js b/config/helpers.js index 26ee963f..25920a99 100644 --- a/config/helpers.js +++ b/config/helpers.js @@ -1,69 +1,32 @@ /** * @author: @AngularClass */ - var path = require('path'); // Helper functions -var _root = path.resolve(__dirname, '..'); - -console.log('root directory:', root()); +var ROOT = path.resolve(__dirname, '..'); function hasProcessFlag(flag) { return process.argv.join('').indexOf(flag) > -1; } +function isWebpackDevServer() { + return process.argv[1] && !! (/webpack-dev-server$/.exec(process.argv[1])); +} + function root(args) { args = Array.prototype.slice.call(arguments, 0); - return path.join.apply(path, [_root].concat(args)); + 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 checkNodeImport(context, request, cb) { + if (!path.isAbsolute(request) && request.charAt(0) !== '.') { + cb(null, 'commonjs ' + request); return; } + cb(); } -function reverse(arr) { - return arr.reverse(); -} - -exports.reverse = reverse; exports.hasProcessFlag = hasProcessFlag; +exports.isWebpackDevServer = isWebpackDevServer; exports.root = root; -exports.rootNode = rootNode; -exports.prependExt = prependExt; -exports.prepend = prependExt; -exports.packageSort = packageSort; +exports.checkNodeImport = checkNodeImport; diff --git a/config/html-elements-plugin/index.js b/config/html-elements-plugin/index.js new file mode 100644 index 00000000..dafc2635 --- /dev/null +++ b/config/html-elements-plugin/index.js @@ -0,0 +1,103 @@ +function HtmlElementsPlugin(locations) { + this.locations = locations; +} + +HtmlElementsPlugin.prototype.apply = function(compiler) { + var self = this; + compiler.plugin('compilation', function(compilation) { + compilation.options.htmlElements = compilation.options.htmlElements || {}; + + compilation.plugin('html-webpack-plugin-before-html-generation', function(htmlPluginData, callback) { + const locations = self.locations; + + if (locations) { + const publicPath = htmlPluginData.assets.publicPath; + + Object.getOwnPropertyNames(locations).forEach(function(loc) { + compilation.options.htmlElements[loc] = getHtmlElementString(locations[loc], publicPath); + }); + } + + + callback(null, htmlPluginData); + }); + }); + +}; + +const RE_ENDS_WITH_BS = /\/$/; + +/** + * Create an HTML tag with attributes from a map. + * + * Example: + * createTag('link', { rel: "manifest", href: "/assets/manifest.json" }) + * // + * @param tagName The name of the tag + * @param attrMap A Map of attribute names (keys) and their values. + * @param publicPath a path to add to eh start of static asset url + * @returns {string} + */ +function createTag(tagName, attrMap, publicPath) { + publicPath = publicPath || ''; + + // add trailing slash if we have a publicPath and it doesn't have one. + if (publicPath && !RE_ENDS_WITH_BS.test(publicPath)) publicPath += '/'; + + const attributes = Object.getOwnPropertyNames(attrMap) + .filter(function(name) { return name[0] !== '='; } ) + .map(function(name) { + var value = attrMap[name]; + + if (publicPath) { + // check if we have explicit instruction, use it if so (e.g: =herf: false) + // if no instruction, use public path if it's href attribute. + const usePublicPath = attrMap.hasOwnProperty('=' + name) ? !!attrMap['=' + name] : name === 'href'; + + if (usePublicPath) { + // remove a starting trailing slash if the value has one so we wont have // + value = publicPath + (value[0] === '/' ? value.substr(1) : value); + } + } + + return name + '="' + value + '"'; + }); + + return '<' + tagName + ' ' + attributes.join(' ') + '>'; +} + +/** + * Returns a string representing all html elements defined in a data source. + * + * Example: + * + * const ds = { + * link: [ + * { rel: "apple-touch-icon", sizes: "57x57", href: "/assets/icon/apple-icon-57x57.png" } + * ], + * meta: [ + * { name: "msapplication-TileColor", content: "#00bcd4" } + * ] + * } + * + * getHeadTags(ds); + * // "" + * "" + * + * @returns {string} + */ +function getHtmlElementString(dataSource, publicPath) { + return Object.getOwnPropertyNames(dataSource) + .map(function(name) { + if (Array.isArray(dataSource[name])) { + return dataSource[name].map(function(attrs) { return createTag(name, attrs, publicPath); } ); + } else { + return [ createTag(name, dataSource[name], publicPath) ]; + } + }) + .reduce(function(arr, curr) { + return arr.concat(curr); + }, []) + .join('\n\t'); +} +module.exports = HtmlElementsPlugin; diff --git a/config/modules/angular2-hmr-prod.js b/config/modules/angular2-hmr-prod.js new file mode 100644 index 00000000..1ef1ec84 --- /dev/null +++ b/config/modules/angular2-hmr-prod.js @@ -0,0 +1,2 @@ +exports.HmrState = function() { +}; diff --git a/config/webpack.common.js b/config/webpack.common.js index 979d8d2b..0393e28e 100644 --- a/config/webpack.common.js +++ b/config/webpack.common.js @@ -1,20 +1,37 @@ const webpack = require('webpack'); const helpers = require('./helpers'); +/* + * Webpack Plugins + */ +// problem with copy-webpack-plugin const CopyWebpackPlugin = require('copy-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin; -var ExtractTextPlugin = require('extract-text-webpack-plugin'); +const HtmlElementsPlugin = require('./html-elements-plugin'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +/* + * Webpack Constants + */ const METADATA = { title: 'ng2-admin - Angular 2 Admin Template', description: 'Free Angular 2 and Bootstrap 4 Admin Template', baseUrl: '/' }; - +/* + * Webpack configuration + * + * See: http://webpack.github.io/docs/configuration.html#cli + */ module.exports = { + /* + * Static metadata for index.html + * + * See: (custom attribute) + */ metadata: METADATA, /* @@ -23,8 +40,10 @@ module.exports = { * You can pass false to disable it. * * See: http://webpack.github.io/docs/configuration.html#cache - * cache: false, - * + */ + //cache: false, + + /* * The entry point for the bundle * Our Angular.js app * @@ -32,9 +51,9 @@ module.exports = { */ entry: { - 'polyfills': './src/polyfills.ts', - 'vendor': './src/vendor.ts', - 'main': './src/main.browser.ts' + 'polyfills': './src/polyfills.browser.ts', + 'vendor': './src/vendor.browser.ts', + 'main': './src/main.browser.ts' }, @@ -50,16 +69,21 @@ module.exports = { * * See: http://webpack.github.io/docs/configuration.html#resolve-extensions */ - extensions: ['', '.ts', '.js', '.css', '.scss'], + extensions: ['', '.ts', '.js', '.css', '.scss', '.json'], // Make sure root is src root: helpers.root('src'), // remove other default values - modulesDirectories: ['node_modules', 'bower_components'] + modulesDirectories: ['node_modules'], }, + /* + * Options affecting the normal modules. + * + * See: http://webpack.github.io/docs/configuration.html#module + */ module: { /* @@ -74,7 +98,7 @@ module.exports = { * * See: https://github.com/wbuchwalter/tslint-loader */ - // { test: /\.ts$/, loader: 'tslint-loader', exclude: [ helpers.root('node_modules') ] }, + // { test: /\.ts$/, loader: 'tslint-loader', exclude: [ helpers.root('node_modules') ] }, /* * Source map loader support for *.js files @@ -88,6 +112,8 @@ module.exports = { exclude: [ // these packages have problems with their sourcemaps helpers.root('node_modules/rxjs'), + helpers.root('node_modules/@angular'), + helpers.root('node_modules/@ngrx'), helpers.root('node_modules/ng2-bootstrap'), helpers.root('node_modules/ng2-branchy') ] @@ -95,6 +121,14 @@ module.exports = { ], + /* + * 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: [ /* @@ -119,14 +153,14 @@ module.exports = { }, /* - * Raw loader support for *.css files + * to string and css loader support for *.css files * Returns file content as string * - * See: https://github.com/webpack/raw-loader */ { test: /\.css$/, - loader: 'raw-loader' + // loaders: ['to-string-loader', 'css-loader'] + loaders: ['raw-loader'] }, { @@ -208,7 +242,7 @@ module.exports = { * See: https://github.com/webpack/docs/wiki/optimization#multi-page-app */ new webpack.optimize.CommonsChunkPlugin({ - name: helpers.reverse(['polyfills', 'vendor']) + name: ['polyfills', 'vendor'].reverse() }), /* @@ -234,16 +268,39 @@ module.exports = { */ new HtmlWebpackPlugin({ template: 'src/index.html', - chunksSortMode: helpers.packageSort(['polyfills', 'vendor', 'main']) + chunksSortMode: 'dependency' }), - // TODO: make sure this is a correct configuration new webpack.ProvidePlugin({ jQuery: 'jquery', - $: 'jquery', - jquery: 'jquery', 'Tether': 'tether', 'window.Tether': 'tether' + }), + + /* + * Plugin: HtmlHeadConfigPlugin + * Description: Generate html tags based on javascript maps. + * + * If a publicPath is set in the webpack output configuration, it will be automatically added to + * href attributes, you can disable that by adding a "=href": false property. + * You can also enable it to other attribute by settings "=attName": true. + * + * The configuration supplied is map between a location (key) and an element definition object (value) + * The location (key) is then exported to the template under then htmlElements property in webpack configuration. + * + * Example: + * Adding this plugin configuration + * new HtmlElementsPlugin({ + * headTags: { ... } + * }) + * + * Means we can use it in the template like this: + * <%= webpackConfig.htmlElements.headTags %> + * + * Dependencies: HtmlWebpackPlugin + */ + new HtmlElementsPlugin({ + headTags: require('./head-config.common') }) ], diff --git a/config/webpack.dev.js b/config/webpack.dev.js index 1c553394..0fc7da42 100644 --- a/config/webpack.dev.js +++ b/config/webpack.dev.js @@ -50,7 +50,7 @@ module.exports = webpackMerge(commonConfig, { * 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', + devtool: 'cheap-module-source-map', /** * Options affecting the output of the compilation. @@ -80,15 +80,17 @@ module.exports = webpackMerge(commonConfig, { * * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename */ - sourceMapFilename: '[file].map', + 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' + chunkFilename: '[id].chunk.js', + library: 'ac_[name]', + libraryTarget: 'var', }, plugins: [ @@ -111,7 +113,7 @@ module.exports = webpackMerge(commonConfig, { 'NODE_ENV': JSON.stringify(METADATA.ENV), 'HMR': METADATA.HMR, } - }) + }), ], /** diff --git a/config/webpack.prod.js b/config/webpack.prod.js index 9a113851..e2db260f 100644 --- a/config/webpack.prod.js +++ b/config/webpack.prod.js @@ -1,3 +1,7 @@ +/** + * @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 @@ -7,11 +11,12 @@ const commonConfig = require('./webpack.common.js'); // the settings that are co */ const ProvidePlugin = require('webpack/lib/ProvidePlugin'); const DefinePlugin = require('webpack/lib/DefinePlugin'); +const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin'); +const IgnorePlugin = require('webpack/lib/IgnorePlugin'); 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'); - +const CompressionPlugin = require('compression-webpack-plugin'); /** * Webpack Constants */ @@ -22,13 +27,11 @@ const METADATA = webpackMerge(commonConfig.metadata, { host: HOST, port: PORT, ENV: ENV, - HMR: false, - baseUrl: '' + HMR: false }); module.exports = webpackMerge(commonConfig, { - metadata: METADATA, /** * Switch loaders to debug mode. * @@ -72,7 +75,7 @@ module.exports = webpackMerge(commonConfig, { * * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename */ - sourceMapFilename: '[file].map', + sourceMapFilename: '[name].[chunkhash].bundle.map', /** * The filename of non-entry chunks as relative path @@ -152,17 +155,34 @@ module.exports = webpackMerge(commonConfig, { // }, // debug // comments: true, //debug + beautify: false, //prod - - mangle: false, //prod - - compress: { - screw_ie8: true - }, //prod - + mangle: { screw_ie8 : true }, //prod + compress: { screw_ie8: true }, //prod comments: false //prod }), + /** + * Plugin: NormalModuleReplacementPlugin + * Description: Replace resources that matches resourceRegExp with newResource + * + * See: http://webpack.github.io/docs/list-of-plugins.html#normalmodulereplacementplugin + */ + + new NormalModuleReplacementPlugin( + /angular2-hmr/, + helpers.root('config/modules/angular2-hmr-prod.js') + ), + + /** + * Plugin: IgnorePlugin + * Description: Don’t generate modules for requests matching the provided RegExp. + * + * See: http://webpack.github.io/docs/list-of-plugins.html#ignoreplugin + */ + + // new IgnorePlugin(/angular2-hmr/), + /** * Plugin: CompressionPlugin * Description: Prepares compressed versions of assets to serve diff --git a/package.json b/package.json index 77202dc2..c2754064 100644 --- a/package.json +++ b/package.json @@ -9,17 +9,17 @@ "@angular/common": "2.0.0-rc.4", "@angular/compiler": "2.0.0-rc.4", "@angular/core": "2.0.0-rc.4", + "@angular/forms": "^0.2.0", "@angular/http": "2.0.0-rc.4", "@angular/platform-browser": "2.0.0-rc.4", "@angular/platform-browser-dynamic": "2.0.0-rc.4", "@angular/platform-server": "2.0.0-rc.4", "@angular/router": "3.0.0-beta.2", - "@angular/forms":"0.2.0", "amcharts3": "github:amcharts/amcharts3", "ammap3": "github:amcharts/ammap3", "animate.css": "^3.5.1", - "bootstrap": "^4.0.0-alpha.2", - "bootstrap-loader": "^1.0.8", + "bootstrap": "4.0.0-alpha.2", + "bootstrap-loader": "^1.0.10", "chart.js": "^1.1.1", "chartist": "^0.9.7", "ckeditor": "^4.5.9", @@ -30,14 +30,16 @@ "font-awesome-sass-loader": "^1.0.1", "fullcalendar": "^2.7.2", "google-maps": "^3.2.1", + "http-server": "^0.9.0", + "ie-shim": "^0.1.0", "jquery": "^2.2.3", "jquery-slimscroll": "^1.3.6", "leaflet": "^0.7.7", "leaflet-map": "^0.2.1", "lodash": "^4.12.0", "ng2-bootstrap": "^1.0.20", - "ng2-ckeditor": "^1.0.4", "ng2-branchy": "^0.0.2-5", + "ng2-ckeditor": "^1.0.4", "ng2-uploader": "0.5.2", "normalize.css": "^4.1.1", "rxjs": "5.0.0-beta.6", @@ -45,54 +47,61 @@ "zone.js": "~0.6.12" }, "devDependencies": { - "angular2-hmr": "~0.7.0", + "@types/core-js": "^0.9.28", + "@types/hammerjs": "^2.0.28", + "@types/node": "^4.0.29", + "@types/source-map": "^0.1.26", + "@types/uglify-js": "^2.0.27", + "@types/webpack": "^1.12.29", + "@types/lodash": "0.0.28", + "angular2-hmr": "~0.8.0", + "gh-pages": "^0.11.0", + "parse5": "^1.5.1", + "rimraf": "^2.5.2", + "codelyzer": "~0.0.21", + "tslint": "^3.7.1", + "ts-helpers": "1.1.1", + "ts-node": "^0.9.1", + "typedoc": "^0.4.4", + "typescript": "^2.0.0-beta", "awesome-typescript-loader": "1.1.1", - "codelyzer": "~0.0.19", - "compression-webpack-plugin": "^0.3.1", - "copy-webpack-plugin": "^3.0.1", - "css-loader": "^0.23.1", - "es6-promise": "^3.1.2", + "angular2-template-loader": "^0.4.0", + "tslint-loader": "^2.1.3", + "url-loader": "^0.5.7", + "style-loader": "^0.13.1", + "raw-loader": "0.5.1", + "source-map-loader": "^0.1.5", + "imports-loader": "^0.6.5", + "istanbul-instrumenter-loader": "^0.2.0", + "json-loader": "^0.5.4", "es6-promise-loader": "^1.0.1", - "es6-shim": "^0.35.0", - "es7-reflect-metadata": "^1.6.0", + "css-loader": "^0.23.1", "exports-loader": "^0.6.3", "expose-loader": "^0.7.1", - "file-loader": "^0.8.5", - "gh-pages": "^0.11.0", - "html-webpack-plugin": "^2.15.0", - "http-server": "^0.9.0", - "imports-loader": "^0.6.5", - "json-loader": "^0.5.4", - "node-sass": "^3.5.3", - "parse5": "^2.1.5", - "raw-loader": "0.5.1", - "resolve-url-loader": "^1.4.3", - "rimraf": "^2.5.2", + "file-loader": "^0.9.0", + "to-string-loader": "^1.1.4", "sass-loader": "^3.2.0", - "source-map-loader": "^0.1.5", - "style-loader": "^0.13.1", - "ts-helpers": "1.1.1", - "ts-node": "^0.9.0", - "tslint": "^3.7.1", - "tslint-loader": "^2.1.3", - "typedoc": "^0.4.4", - "typescript": "~1.8.9", - "typings": "^1.0.5", - "url-loader": "^0.5.7", + "resolve-url-loader": "^1.4.3", + "node-sass": "^3.5.3", + "html-webpack-plugin": "^2.21.0", + "copy-webpack-plugin": "^3.0.1", "webpack": "^1.13.1", "webpack-dev-server": "^1.14.1", "webpack-md5-hash": "^0.0.5", - "webpack-merge": "^0.14.0" + "webpack-merge": "^0.14.0", + "compression-webpack-plugin": "^0.3.1", + "es6-promise": "^3.1.2", + "es6-shim": "^0.35.0", + "es7-reflect-metadata": "^1.6.0" }, "scripts": { "rimraf": "rimraf", "tslint": "tslint", "typedoc": "typedoc", - "typings": "typings", "webpack": "webpack", "webpack-dev-server": "webpack-dev-server", "webdriver-manager": "webdriver-manager", - "clean": "npm cache clean && npm run rimraf -- node_modules doc typings coverage dist", + "clean": "npm cache clean && npm run rimraf -- node_modules doc coverage dist", "clean:dist": "npm run rimraf -- dist", "preclean:install": "npm run clean", "clean:install": "npm set progress=false && npm install", @@ -108,8 +117,8 @@ "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:dev": "webpack-dev-server --config config/webpack.dev.js --progress --profile --colors --watch --display-error-details --display-cached --content-base src/", + "server:dev:hmr": "npm run server:dev -- --inline --hot", "server:prod": "http-server dist --cors", "webdriver:update": "npm run webdriver-manager update", "webdriver:start": "npm run webdriver-manager start", @@ -120,7 +129,7 @@ "gh-pages": "wintersmith build -C docs && gh-pages -d docs/build", "start": "npm run server:dev", "start:hmr": "npm run server:dev:hmr", - "postinstall": "npm run typings -- install && bower install", + "postinstall": "bower install", "version": "npm run build", "postversion": "git push && git push --tags" }, diff --git a/src/custom-typings.d.ts b/src/custom-typings.d.ts index ac2c0c9c..0ddf536e 100644 --- a/src/custom-typings.d.ts +++ b/src/custom-typings.d.ts @@ -1,31 +1,34 @@ /* * 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 + * if they don't provide one within the module. You can try to install it with @types + npm install @types/node + npm install @types/lodash + * If you can't find the type definition in the registry we can make an ambient/global definition in * this file for now. For example - -declare module "my-module" { - export function doesSomething(value: string): string; -} - + declare module "my-module" { + export function doesSomething(value: string): string; + } + * If you are using a CommonJS module that is using module.exports then you will have to write your + * types using export = yourObjectOrFunction with a namespace above it + * notice how we have to create a namespace that is equal to the function we're assigning the export to + declare module "jwt-decode" { + function jwtDecode(token: string): any; + namespace jwtDecode {} + export = jwtDecode; + } * * If you're prototying and you will fix the types later you can also declare it as type any * - -declare var assert: any; - + declare var assert: any; + declare var _: any; + declare var $: any; * * If you're importing a module that uses Node.js modules which are CommonJS you need to import as + * in the files such as main.browser.ts or any file within app/ * - -import * as _ from 'lodash' - - * You can include your type definitions in this file until you create one for the typings registry - * see https://github.com/typings/registry + import * as _ from 'lodash' + * You can include your type definitions in this file until you create one for the @types * */ @@ -36,14 +39,38 @@ declare var AmCharts:any; declare var Chart:any; declare var Chartist:any; +// support NodeJS modules without type definitions +declare module "*"; + // Extra variables that live on Global that will be replaced by webpack DefinePlugin declare var ENV: string; declare var HMR: boolean; + interface GlobalEnvironment { ENV; HMR; } +interface Es6PromiseLoader { + (id: string): (exportName?: string) => Promise; +} + +type FactoryEs6PromiseLoader = () => Es6PromiseLoader; +type FactoryPromise = () => Promise; + +type AsyncRoutes = { + [component: string]: Es6PromiseLoader | + Function | + FactoryEs6PromiseLoader | + FactoryPromise +}; + + +type IdleCallbacks = Es6PromiseLoader | + Function | + FactoryEs6PromiseLoader | + FactoryPromise ; + interface WebpackModule { hot: { data?: any, @@ -60,66 +87,26 @@ interface WebpackModule { }; } + interface WebpackRequire { - context(file: string, flag?: boolean, exp?: RegExp): any; + (id: string): any; + (paths: string[], callback: (...modules: any[]) => void): void; + ensure(ids: string[], callback: (req: WebpackRequire) => void, chunkName?: string): void; + context(directory: string, useSubDirectories?: boolean, regExp?: RegExp): WebpackContext; } +interface WebpackContext extends WebpackRequire { + keys(): string[]; +} interface ErrorStackTraceLimit { stackTraceLimit: number; } - // Extend typings interface NodeRequire extends WebpackRequire {} interface ErrorConstructor extends ErrorStackTraceLimit {} +interface NodeRequireFunction extends Es6PromiseLoader {} interface NodeModule extends WebpackModule {} interface Global extends GlobalEnvironment {} - - -declare namespace Reflect { - function decorate(decorators: ClassDecorator[], target: Function): Function; - function decorate( - decorators: (PropertyDecorator | MethodDecorator)[], - target: Object, - targetKey: string | symbol, - descriptor?: PropertyDescriptor): PropertyDescriptor; - - function metadata(metadataKey: any, metadataValue: any): { - (target: Function): void; - (target: Object, propertyKey: string | symbol): void; - }; - function defineMetadata(metadataKey: any, metadataValue: any, target: Object): void; - function defineMetadata( - metadataKey: any, - metadataValue: any, - target: Object, - targetKey: string | symbol): void; - function hasMetadata(metadataKey: any, target: Object): boolean; - function hasMetadata(metadataKey: any, target: Object, targetKey: string | symbol): boolean; - function hasOwnMetadata(metadataKey: any, target: Object): boolean; - function hasOwnMetadata(metadataKey: any, target: Object, targetKey: string | symbol): boolean; - function getMetadata(metadataKey: any, target: Object): any; - function getMetadata(metadataKey: any, target: Object, targetKey: string | symbol): any; - function getOwnMetadata(metadataKey: any, target: Object): any; - function getOwnMetadata(metadataKey: any, target: Object, targetKey: string | symbol): any; - function getMetadataKeys(target: Object): any[]; - function getMetadataKeys(target: Object, targetKey: string | symbol): any[]; - function getOwnMetadataKeys(target: Object): any[]; - function getOwnMetadataKeys(target: Object, targetKey: string | symbol): any[]; - function deleteMetadata(metadataKey: any, target: Object): boolean; - function deleteMetadata(metadataKey: any, target: Object, targetKey: string | symbol): boolean; -} - - -// We need this here since there is a problem with Zone.js typings -interface Thenable { - then( - onFulfilled?: (value: T) => U | Thenable, - onRejected?: (error: any) => U | Thenable): Thenable; - then( - onFulfilled?: (value: T) => U | Thenable, - onRejected?: (error: any) => void): Thenable; - catch(onRejected?: (error: any) => U | Thenable): Thenable; -} diff --git a/src/index.html b/src/index.html index 4bbbbb89..309de6c7 100644 --- a/src/index.html +++ b/src/index.html @@ -1,31 +1,18 @@ + + + <%= webpackConfig.metadata.title %> - - - - - - - - - - - - - - - - - - - - + <% if (webpackConfig.htmlElements.headTags) { %> + + <%= webpackConfig.htmlElements.headTags %> + <% } %> @@ -40,9 +27,9 @@
-<% if (webpackConfig.metadata.ENV === 'development') { %> - - +<% if (webpackConfig.metadata.isDevServer && webpackConfig.metadata.HMR !== true) { %> + + <% } %> { return bootstrap(App, [ - ...PROVIDERS, + // To add more vendor providers please look in the platform/ folder + ...PLATFORM_PROVIDERS, ...ENV_PROVIDERS, - ...DIRECTIVES, - ...PIPES, - ...APP_PROVIDERS + ...APP_PROVIDERS, ]) - .catch(err => console.error(err)); + .then(decorateComponentRef) + .catch(err => console.error(err)); } @@ -51,6 +51,6 @@ if ('development' === ENV && HMR === true) { let ngHmr = require('angular2-hmr'); ngHmr.hotModuleReplacement(main, module); } else { - // bootstrap when documetn is ready + // bootstrap when document is ready document.addEventListener('DOMContentLoaded', () => main()); } diff --git a/src/platform/browser/directives.ts b/src/platform/browser-directives.ts similarity index 65% rename from src/platform/browser/directives.ts rename to src/platform/browser-directives.ts index 0b63ed5f..63f1a90b 100644 --- a/src/platform/browser/directives.ts +++ b/src/platform/browser-directives.ts @@ -1,11 +1,10 @@ /* * These are globally available directives in any template */ - -import {PLATFORM_DIRECTIVES} from '@angular/core'; - +// Angular 2 +import { PLATFORM_DIRECTIVES } from '@angular/core'; // Angular 2 Router -import {ROUTER_DIRECTIVES} from '@angular/router'; +import { ROUTER_DIRECTIVES } from '@angular/router'; // Angular 2 forms import { REACTIVE_FORM_DIRECTIVES } from '@angular/forms'; @@ -16,5 +15,5 @@ export const APPLICATION_DIRECTIVES = [ ]; export const DIRECTIVES = [ - {provide: PLATFORM_DIRECTIVES, multi: true, useValue: APPLICATION_DIRECTIVES } + { provide: PLATFORM_DIRECTIVES, multi: true, useValue: APPLICATION_DIRECTIVES } ]; diff --git a/src/platform/browser/pipes.ts b/src/platform/browser-pipes.ts similarity index 62% rename from src/platform/browser/pipes.ts rename to src/platform/browser-pipes.ts index bb9c3806..a08bfe02 100644 --- a/src/platform/browser/pipes.ts +++ b/src/platform/browser-pipes.ts @@ -2,7 +2,7 @@ * These are globally available pipes in any template */ -import {PLATFORM_PIPES} from '@angular/core'; +import { PLATFORM_PIPES } from '@angular/core'; // application_pipes: pipes that are global through out the application export const APPLICATION_PIPES = [ @@ -10,5 +10,5 @@ export const APPLICATION_PIPES = [ ]; export const PIPES = [ - {provide: PLATFORM_PIPES, multi: true, useValue: APPLICATION_PIPES } + { provide: PLATFORM_PIPES, multi: true, useValue: APPLICATION_PIPES } ]; diff --git a/src/platform/browser/providers.ts b/src/platform/browser-providers.ts similarity index 52% rename from src/platform/browser/providers.ts rename to src/platform/browser-providers.ts index 6f9dfa8f..c1eaae5f 100644 --- a/src/platform/browser/providers.ts +++ b/src/platform/browser-providers.ts @@ -3,15 +3,16 @@ */ // Angular 2 -import {FORM_PROVIDERS, LocationStrategy, HashLocationStrategy} from '@angular/common'; - +import { HashLocationStrategy, LocationStrategy } from '@angular/common'; // Angular 2 Http -import {HTTP_PROVIDERS} from '@angular/http'; -import {APP_ROUTER_PROVIDERS} from '../../app/app.routes'; - - +import { HTTP_PROVIDERS } from '@angular/http'; +// Angular 2 Router +import { provideRouter } from '@angular/router'; // Angular 2 forms -import {disableDeprecatedForms, provideForms} from '@angular/forms'; +import { disableDeprecatedForms, provideForms } from '@angular/forms'; + + +import { routes } from '../app/app.routes'; /* * Application Providers/Directives/Pipes @@ -21,10 +22,12 @@ export const APPLICATION_PROVIDERS = [ // new Angular 2 forms disableDeprecatedForms(), provideForms(), + + provideRouter(routes), + ...HTTP_PROVIDERS, - ...APP_ROUTER_PROVIDERS, - {provide: LocationStrategy, useClass: HashLocationStrategy}, - {provide: LocationStrategy, useClass: HashLocationStrategy} + + { provide: LocationStrategy, useClass: HashLocationStrategy } ]; export const PROVIDERS = [ diff --git a/src/platform/browser.ts b/src/platform/browser.ts new file mode 100644 index 00000000..8376c65c --- /dev/null +++ b/src/platform/browser.ts @@ -0,0 +1,14 @@ +export * from './browser-directives'; +export * from './browser-pipes'; +export * from './browser-providers'; + +import { DIRECTIVES } from './browser-directives'; +import { PIPES } from './browser-pipes'; +import { PROVIDERS } from './browser-providers'; + + +export const PLATFORM_PROVIDERS = [ + ...PROVIDERS, + ...DIRECTIVES, + ...PIPES +]; diff --git a/src/platform/browser/index.ts b/src/platform/browser/index.ts deleted file mode 100644 index 487aec6e..00000000 --- a/src/platform/browser/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './directives'; -export * from './pipes'; -export * from './providers'; diff --git a/src/platform/environment.ts b/src/platform/environment.ts index a1b1b4ee..9b1cea23 100644 --- a/src/platform/environment.ts +++ b/src/platform/environment.ts @@ -1,3 +1,4 @@ + // Angular 2 // rc2 workaround import { enableDebugTools, disableDebugTools } from '@angular/platform-browser'; @@ -23,7 +24,13 @@ if ('production' === ENV) { } else { - _decorateComponentRef = (cmpRef) => enableDebugTools(cmpRef); + _decorateComponentRef = (cmpRef) => { + let _ng = (window).ng; + enableDebugTools(cmpRef); + (window).ng.probe = _ng.probe; + (window).ng.coreTokens = _ng.coreTokens; + return cmpRef; + }; // Development PROVIDERS = [ diff --git a/src/polyfills.browser.ts b/src/polyfills.browser.ts new file mode 100644 index 00000000..a4037ba9 --- /dev/null +++ b/src/polyfills.browser.ts @@ -0,0 +1,45 @@ +// Polyfills + +// import 'ie-shim'; // Internet Explorer 9 support + + +// import 'core-js/es6'; +// Added parts of es6 which are necessary for your project or your browser support requirements. +import 'core-js/es6/symbol'; +import 'core-js/es6/object'; +import 'core-js/es6/function'; +import 'core-js/es6/parse-int'; +import 'core-js/es6/parse-float'; +import 'core-js/es6/number'; +import 'core-js/es6/math'; +import 'core-js/es6/string'; +import 'core-js/es6/date'; +import 'core-js/es6/array'; +import 'core-js/es6/regexp'; +import 'core-js/es6/map'; +import 'core-js/es6/set'; +import 'core-js/es6/weak-map'; +import 'core-js/es6/weak-set'; +import 'core-js/es6/typed'; +import 'core-js/es6/reflect'; +// see issue https://github.com/AngularClass/angular2-webpack-starter/issues/709 +// import 'core-js/es6/promise'; + +import 'core-js/es7/reflect'; +import 'zone.js/dist/zone'; + +// Typescript emit helpers polyfill +import 'ts-helpers'; + +if ('production' === ENV) { + // Production + + +} else { + // Development + + Error.stackTraceLimit = Infinity; + + require('zone.js/dist/long-stack-trace-zone'); + +} diff --git a/src/polyfills.ts b/src/polyfills.ts deleted file mode 100644 index 3395eed7..00000000 --- a/src/polyfills.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Polyfills -// (these modules are what are in 'angular2/bundles/angular2-polyfills' so don't use that here) - -// import 'ie-shim'; // Internet Explorer -// import 'es6-shim'; -// import 'es6-promise'; -// import 'es7-reflect-metadata'; - -// Prefer CoreJS over the polyfills above -import 'core-js/es6'; -import 'core-js/es7/reflect'; -require('zone.js/dist/zone'); - -// Typescript emit helpers polyfill -import 'ts-helpers'; - -if ('production' === ENV) { - // Production - - -} else { - // Development - - Error.stackTraceLimit = Infinity; - - require('zone.js/dist/long-stack-trace-zone'); - -} diff --git a/src/vendor.ts b/src/vendor.browser.ts similarity index 93% rename from src/vendor.ts rename to src/vendor.browser.ts index 3ace4485..e89dc2a1 100644 --- a/src/vendor.ts +++ b/src/vendor.browser.ts @@ -8,6 +8,7 @@ import '@angular/platform-browser'; import '@angular/platform-browser-dynamic'; import '@angular/core'; import '@angular/common'; +import '@angular/forms'; import '@angular/http'; import '@angular/router'; @@ -26,5 +27,6 @@ if ('production' === ENV) { } else { // Development + require('angular2-hmr'); } diff --git a/tsconfig.json b/tsconfig.json index c8ea38d1..86493b48 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,16 +2,31 @@ "compilerOptions": { "target": "es5", "module": "commonjs", + "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "sourceMap": true, - "noEmitHelpers": true + "noEmitHelpers": true, + "lib": ["es6", "dom"], + "strictNullChecks": false, + "baseUrl": "./src", + "paths": [ + ], + "types": [ + "core-js", + "hammerjs", + "node", + "source-map", + "uglify-js", + "webpack" + ] }, "exclude": [ "node_modules" ], "awesomeTypescriptLoaderOptions": { - "forkChecker": true + "forkChecker": true, + "useWebpackText": true }, "compileOnSave": false, "buildOnSave": false, diff --git a/tslint.json b/tslint.json index dd143204..709609e4 100644 --- a/tslint.json +++ b/tslint.json @@ -55,9 +55,9 @@ "no-duplicate-variable": true, "no-empty": false, "no-eval": true, - "no-null-keyword": true, + "no-null-keyword": false, "no-shadowed-variable": true, - "no-string-literal": true, + "no-string-literal": false, "no-switch-case-fall-through": true, "no-unreachable": true, "no-unused-expression": true, @@ -90,7 +90,7 @@ "trailing-comma": [ true, { - "multiline": "never", + "multiline": false, "singleline": "never" } ], diff --git a/typings.json b/typings.json deleted file mode 100644 index 7c44bf64..00000000 --- a/typings.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "globalDependencies": { - "angular-protractor": "registry:dt/angular-protractor#1.5.0+20160425143459", - "core-js": "registry:dt/core-js#0.0.0+20160602141332", - "hammerjs": "registry:dt/hammerjs#2.0.4+20160417130828", - "jasmine": "registry:dt/jasmine#2.2.0+20160621224255", - "node": "registry:dt/node#6.0.0+20160621231320", - "selenium-webdriver": "registry:dt/selenium-webdriver#2.44.0+20160317120654", - "source-map": "registry:dt/source-map#0.0.0+20160317120654", - "uglify-js": "registry:dt/uglify-js#2.6.1+20160316155526", - "webpack": "registry:dt/webpack#1.12.9+20160523035535" - }, - "dependencies": { - "lodash": "registry:npm/lodash#4.0.0+20160416211519" - } -}