diff --git a/.gitignore b/.gitignore
index 5525b5026f..b0db1067d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,6 +54,7 @@ npm-debug.log
/dist/**
/.awcache
.webpack.json
+*.temp.json
/compiled/
dll/
diff --git a/README.md b/README.md
index d47090575b..fbb49083e4 100644
--- a/README.md
+++ b/README.md
@@ -84,6 +84,7 @@ go to [http://0.0.0.0:3000](http://0.0.0.0:3000) or [http://localhost:3000](http
* [Configuration](#configuration)
* [AoT Don'ts](#aot-donts)
* [External Stylesheets](#external-stylesheets)
+* [Lazy Loading](#lazy-loading)
* [Contributing](#contributing)
* [TypeScript](#typescript)
* [@Types](#types)
@@ -240,11 +241,23 @@ The following are some things that will make AoT compile fail.
Any stylesheets (Sass or CSS) placed in the `src/styles` directory and imported into your project will automatically be compiled into an external `.css` and embedded in your production builds.
For example to use Bootstrap as an external stylesheet:
+
1) Create a `styles.scss` file (name doesn't matter) in the `src/styles` directory.
2) `npm install` the version of Boostrap you want.
3) In `styles.scss` add `@import 'bootstrap/scss/bootstrap.scss';`
4) In `src/app/app.module.ts` add underneath the other import statements: `import '../styles/styles.scss';`
+# Lazy Loading
+When you lazy load a module in your router config, it will go into a separate chunk and the browser won't download the code until the user attempts to navigate to the route.
+
+You can make a module lazy load by using the `loadChildren` syntax in your route definitions:
+
+```js
+{ path: 'detail', loadChildren: './+detail#DetailModule'}
+```
+
+To make sure TypeScript compiles your lazy-loaded modules, declare them in `./src/app/lazy-loaded.ts` with an import statement. Declaring the modules allows TypeScript to only compile the necessary files. Previously TS would compile every single `.ts` file in your project tree on every single build which was inefficient and lead to issues.
+
# Contributing
You can include more examples as components but they must introduce a new concept such as `Home` component (separate folders), and Todo (services). I'll accept pretty much everything so feel free to open a Pull-Request
diff --git a/config/specify-ts-files-plugin/index.js b/config/specify-ts-files-plugin/index.js
new file mode 100644
index 0000000000..28ef9c544c
--- /dev/null
+++ b/config/specify-ts-files-plugin/index.js
@@ -0,0 +1,35 @@
+/*
+ * Plugin: SpecifyTsFilesPlugin
+ *
+ * By default TypeScipt will compile every single .ts file in your project tree.
+ * This is inefficient and leads to problems. This plugin specifies your Webpack
+ * entries and any other files you pass in as "files" and writes them to a temporary
+ * tsconfig.json to use for your build. Only the entry files you pass in and their
+ * dependencies will get compiled. This makes builds faster and avoids issues.
+ */
+'use strict';
+const fs = require('fs');
+const path = require('path');
+
+function SpecifyTsFilesPlugin(options) {
+ this.root = options.root || process.cwd();
+ this.entry = options.entry;
+ this.otherFilesToCompile = options.otherFilesToCompile || [];
+ this.tsConfigBase = options.tsConfigBase || 'tsconfig.json';
+ this.customTsConfigFileName = options.customTsConfigFileName || 'tsconfig.temp.json';
+}
+
+SpecifyTsFilesPlugin.prototype.apply = function(compiler) {
+ if(!this.entry || typeof this.entry !== 'object') {
+ throw new Error('SpecifyTsFilesPlugin Error: entry was not specified');
+ }
+ const allFilesToCompile = Object.keys(this.entry)
+ .map(key => this.entry[key])
+ .concat(this.otherFilesToCompile);
+ const baseConfigData = require(path.join(this.root, this.tsConfigBase));
+ const tsConfigContent = Object.assign({}, baseConfigData, {files: allFilesToCompile});
+ const customConfigFilePath = path.join(this.root, this.customTsConfigFileName);
+ fs.writeFileSync(customConfigFilePath, JSON.stringify(tsConfigContent));
+};
+
+module.exports = SpecifyTsFilesPlugin;
diff --git a/config/webpack.common.js b/config/webpack.common.js
index ea8b2f1103..4a1bdef414 100644
--- a/config/webpack.common.js
+++ b/config/webpack.common.js
@@ -22,6 +22,7 @@ const InlineManifestWebpackPlugin = require('inline-manifest-webpack-plugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const ngcWebpack = require('ngc-webpack');
+const SpecifyTsFilesPlugin = require('./specify-ts-files-plugin');
/**
* Webpack Constants
@@ -42,6 +43,25 @@ const METADATA = {
*/
module.exports = function (options) {
isProd = options.env === 'production';
+
+ const entry = {
+ 'polyfills': './src/polyfills.browser.ts',
+ 'main': AOT ? './src/main.browser.aot.ts' :
+ './src/main.browser.ts'
+ };
+
+ const otherFilesToCompile = [
+ './src/app/app.module.ts',
+ './src/app/lazy-loaded.ts'
+ ];
+
+ const tsConfigBase = 'tsconfig.webpack.json';
+ const customTsConfigFileName = 'tsconfig.build.temp.json';
+
+ const atlConfig = {
+ configFileName: customTsConfigFileName
+ };
+
return {
/**
@@ -59,13 +79,7 @@ module.exports = function (options) {
*
* See: http://webpack.github.io/docs/configuration.html#entry
*/
- entry: {
-
- 'polyfills': './src/polyfills.browser.ts',
- 'main': AOT ? './src/main.browser.aot.ts' :
- './src/main.browser.ts'
-
- },
+ entry: entry,
/**
* Options affecting the resolving of modules.
@@ -381,10 +395,23 @@ module.exports = function (options) {
new ngcWebpack.NgcWebpackPlugin({
disabled: !AOT,
- tsConfig: helpers.root('tsconfig.webpack.json'),
+ tsConfig: helpers.root(customTsConfigFileName),
resourceOverride: helpers.root('config/resource-override.js')
}),
+ /**
+ * Plugin: SpecifyTsFilesPlugin
+ * Description: Generates a temporary tsconfig.json which specifies all the entry files to compile.
+ * This prevents TypeScript from having to compile every single .ts file in the project tree.
+ */
+ new SpecifyTsFilesPlugin({
+ root: helpers.root('.'),
+ entry: entry,
+ otherFilesToCompile: otherFilesToCompile,
+ tsConfigBase: tsConfigBase,
+ customTsConfigFileName: customTsConfigFileName
+ }),
+
/**
* Plugin: InlineManifestWebpackPlugin
* Inline Webpack's manifest.js in index.html
diff --git a/package.json b/package.json
index ded9450001..562ab81bba 100644
--- a/package.json
+++ b/package.json
@@ -28,7 +28,7 @@
"clean:aot": "npm run rimraf -- compiled",
"clean:dist": "npm run rimraf -- dist",
"clean:install": "npm set progress=false && npm install",
- "clean": "npm cache clean && npm run rimraf -- node_modules doc coverage dist compiled dll",
+ "clean": "npm cache clean && npm run rimraf -- node_modules doc coverage dist compiled dll *.temp.json",
"docker": "docker",
"docs": "npm run typedoc -- --options typedoc.json --exclude '**/*.spec.ts' ./src/",
"e2e:live": "npm-run-all -p -r server:prod:ci protractor:live",
diff --git a/src/app/lazy-loaded.ts b/src/app/lazy-loaded.ts
new file mode 100644
index 0000000000..807c88297b
--- /dev/null
+++ b/src/app/lazy-loaded.ts
@@ -0,0 +1,7 @@
+/*
+ * Declare your lazy loaded modules here to ensure they are processed by the TypeScript compiler
+ */
+import './+barrel';
+import './+barrel/+child-barrel';
+import './+detail';
+import './+detail/+child-detail';
diff --git a/src/main.browser.aot.ts b/src/main.browser.aot.ts
index 7bba1168c0..52e0d6fb69 100644
--- a/src/main.browser.aot.ts
+++ b/src/main.browser.aot.ts
@@ -1,6 +1,7 @@
/**
* Angular bootstrapping
*/
+///
import { platformBrowser } from '@angular/platform-browser';
import { decorateModuleRef } from './app/environment';
/**
diff --git a/src/main.browser.ts b/src/main.browser.ts
index 55f9ecc936..5cb9f788c3 100644
--- a/src/main.browser.ts
+++ b/src/main.browser.ts
@@ -1,6 +1,7 @@
/**
* Angular bootstrapping
*/
+///
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { decorateModuleRef } from './app/environment';
import { bootloader } from '@angularclass/hmr';
diff --git a/tsconfig.webpack.json b/tsconfig.webpack.json
index 082fd7c3bf..dbe8eb95ea 100644
--- a/tsconfig.webpack.json
+++ b/tsconfig.webpack.json
@@ -23,12 +23,6 @@
"node"
]
},
- "exclude": [
- "node_modules",
- "dist",
- "src/**/*.spec.ts",
- "src/**/*.e2e.ts"
- ],
"awesomeTypescriptLoaderOptions": {
"forkChecker": true,
"useWebpackText": true
diff --git a/tslint.json b/tslint.json
index e1f9814cdd..a4c5ff1685 100644
--- a/tslint.json
+++ b/tslint.json
@@ -21,6 +21,7 @@
"no-forward-ref": true,
"no-input-rename": true,
"no-output-rename": true,
+ "no-reference": false,
"pipe-naming": [true, "camelCase", "my"],
"templates-use-public": true,
"use-host-property-decorator": true,