Skip to content

Commit ee59a84

Browse files
committed
feat(build): update angular-cli.json
1 parent f40e6f1 commit ee59a84

25 files changed

+281
-143
lines changed

README.md

+43-7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ The generated project has dependencies that require **Node 4 or greater**.
3636
* [Creating a Build](#creating-a-build)
3737
* [Build Targets and Environment Files](#build-targets-and-environment-files)
3838
* [Bundling](#bundling)
39+
* [Adding extra files to the build](#adding-extra-files-to-the-build)
3940
* [Running Unit Tests](#running-unit-tests)
4041
* [Running End-to-End Tests](#running-end-to-end-tests)
4142
* [Deploying the App via GitHub Pages](#deploying-the-app-via-github-pages)
@@ -124,8 +125,8 @@ A build can specify both a build target (`development` or `production`) and an
124125
environment file to be used with that build. By default, the development build
125126
target is used.
126127

127-
At build time, `src/app/environments/environment.ts` will be replaced by
128-
`src/app/environments/environment.{NAME}.ts` where `NAME` is the argument
128+
At build time, `src/environments/environment.ts` will be replaced by
129+
`src/environments/environment.NAME.ts` where `NAME` is the argument
129130
provided to the `--environment` flag.
130131

131132
These options also apply to the serve command. If you do not pass a value for `environment`,
@@ -143,14 +144,49 @@ ng build --dev
143144
ng build
144145
```
145146

146-
You can also add your own env files other than `dev` and `prod` by creating a
147-
`src/app/environments/environment.{NAME}.ts` and use them by using the `--env=NAME`
148-
flag on the build/serve commands.
147+
You can also add your own env files other than `dev` and `prod` by doing the following:
148+
- create a `src/environments/environment.NAME.ts`
149+
- add `{ NAME: 'src/environments/environment.NAME.ts' }` to the the `apps[0].environments` object in `angular-cli.json`
150+
- use them by using the `--env=NAME` flag on the build/serve commands.
149151

150152
### Bundling
151153

152-
Builds created with the `-prod` flag via `ng build -prod` or `ng serve -prod` bundle
153-
all dependencies into a single file, and make use of tree-shaking techniques.
154+
All builds make use of bundling, and using the `-prod` flag in `ng build -prod`
155+
or `ng serve -prod` will also make use of uglifying and tree-shaking functionality.
156+
157+
### Adding extra files to the build
158+
159+
The `apps[0].additionalEntries` array in `angular-cli.json` allows a user to add more files to the build.
160+
161+
The `additionalEntries` array supports two kinds of entries, with different behaviours.
162+
- strings will be bundled together with the `main` bundle
163+
- objects with `input` and `output` properties will create a new bundle which is loaded before the `main` bundle.
164+
165+
By default it looks like this:
166+
167+
```
168+
apps: [
169+
{
170+
//...
171+
"additionalEntries": [
172+
{ "input": "polyfills.ts", "output": "polyfills.js" },
173+
"scripts.ts",
174+
"styles.css"
175+
],
176+
}
177+
]
178+
```
179+
180+
These entries correspond to the following files in `src/`:
181+
- `polifills.ts` has browser polyfills needed for Angular 2. It will be
182+
bundled separately as `polyfills.js` and loaded before everything else.
183+
- `styles.css` allows users to add global styles and supports
184+
[CSS imports](https://developer.mozilla.org/en/docs/Web/CSS/@import). If the
185+
project is created with the `--style=sass` option, this will be a `.sass` file
186+
instead, and the same applies to `scss/less/styl`. It will be part of the main
187+
bundle.
188+
- `scripts.ts` allows users to add global code outside of the Angular 2 app. It
189+
will also be part of the main bundle.
154190

155191
### Running unit tests
156192

addon/ng2/blueprints/component/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ module.exports = {
9797
dir = dirParts.join(path.sep);
9898
}
9999
}
100-
var srcDir = this.project.ngConfig.defaults.sourceDir;
100+
var srcDir = this.project.ngConfig.apps[0].root;
101101
this.appDir = dir.substr(dir.indexOf(srcDir) + srcDir.length);
102102
this.generatePath = dir;
103103
return dir;
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
export * from './environments/environment';
21
export * from './app.component';
32
export * from './app.module';

addon/ng2/blueprints/ng2/files/__path__/main.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
22
import { enableProdMode } from '@angular/core';
3-
import { AppModule, environment } from './app/';
3+
import { environment } from './environments/environment';
4+
import { AppModule } from './app/';
45

56
if (environment.production) {
67
enableProdMode();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// You can add additional imports to this file and
2+
// they will be loaded before your app
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/* You can add add global styles to this file, and also import other style files */

addon/ng2/blueprints/ng2/files/angular-cli.json

+18-4
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,24 @@
55
},
66
"apps": [
77
{
8-
"main": "<%= sourceDir %>/main.ts",
9-
"tsconfig": "<%= sourceDir %>/tsconfig.json",
10-
"mobile": <%= isMobile %>
8+
"root": "<%= sourceDir %>",
9+
"outDir": "dist",
10+
"assets": "assets",
11+
"index": "index.html",
12+
"main": "main.ts",
13+
"test": "test.ts",
14+
"tsconfig": "tsconfig.json",
15+
"mobile": <%= isMobile %>,
16+
"additionalEntries": [
17+
{ "input": "polyfills.ts", "output": "polyfills.js" },
18+
"scripts.ts",
19+
"styles.<%= styleExt %>"
20+
],
21+
"environments": {
22+
"source": "environments/environment.ts",
23+
"prod": "environments/environment.prod.ts",
24+
"dev": "environments/environment.dev.ts"
25+
}
1126
}
1227
],
1328
"addons": [],
@@ -24,7 +39,6 @@
2439
},
2540
"defaults": {
2641
"prefix": "<%= prefix %>",
27-
"sourceDir": "<%= sourceDir %>",
2842
"styleExt": "<%= styleExt %>",
2943
"prefixInterfaces": false,
3044
"lazyRoutePrefix": "+"

addon/ng2/blueprints/ng2/files/public/.npmignore

Whitespace-only changes.

addon/ng2/models/webpack-build-common.ts

+63-21
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,37 @@ import * as webpack from 'webpack';
55
import { ForkCheckerPlugin } from 'awesome-typescript-loader';
66
import { CliConfig } from './config';
77

8-
export function getWebpackCommonConfig(projectRoot: string, sourceDir: string) {
8+
export function getWebpackCommonConfig(projectRoot: string, environment: string, appConfig: any) {
9+
10+
const appRoot = path.resolve(projectRoot, appConfig.root);
11+
const appMain = path.resolve(appRoot, appConfig.main);
12+
13+
const bundledWithMain = appConfig.additionalEntries
14+
.filter(entry => typeof entry === "string")
15+
.map(filename => path.resolve(appRoot, filename));
16+
17+
const separateBundles = appConfig.additionalEntries.filter(entry => typeof entry === "object");
18+
const entries = Object.assign(
19+
{ main: [appMain, ...bundledWithMain] },
20+
separateBundles.reduce((obj, entry) =>
21+
Object.assign(obj, { [entry.output]: path.resolve(appRoot, entry.input) }),
22+
{})
23+
);
24+
25+
const additionalFiles = separateBundles
26+
.map(entry => path.resolve(appRoot, entry.input))
27+
.concat(bundledWithMain);
28+
929
return {
1030
devtool: 'source-map',
1131
resolve: {
1232
extensions: ['', '.ts', '.js'],
13-
root: path.resolve(projectRoot, `./${sourceDir}`)
33+
root: appRoot
1434
},
1535
context: path.resolve(__dirname, './'),
16-
entry: {
17-
main: [path.resolve(projectRoot, `./${sourceDir}/main.ts`)],
18-
polyfills: path.resolve(projectRoot, `./${sourceDir}/polyfills.ts`)
19-
},
36+
entry: entries,
2037
output: {
21-
path: path.resolve(projectRoot, './dist'),
38+
path: path.resolve(projectRoot, appConfig.outDir),
2239
filename: '[name].bundle.js'
2340
},
2441
module: {
@@ -27,8 +44,8 @@ export function getWebpackCommonConfig(projectRoot: string, sourceDir: string) {
2744
test: /\.js$/,
2845
loader: 'source-map-loader',
2946
exclude: [
30-
path.resolve(projectRoot, 'node_modules/rxjs'),
31-
path.resolve(projectRoot, 'node_modules/@angular'),
47+
path.resolve(appRoot, 'node_modules/rxjs'),
48+
path.resolve(appRoot, 'node_modules/@angular'),
3249
]
3350
}
3451
],
@@ -40,7 +57,7 @@ export function getWebpackCommonConfig(projectRoot: string, sourceDir: string) {
4057
loader: 'awesome-typescript-loader',
4158
query: {
4259
useForkChecker: true,
43-
tsconfig: path.resolve(projectRoot, `./${sourceDir}/tsconfig.json`)
60+
tsconfig: path.resolve(appRoot, appConfig.tsconfig)
4461
}
4562
},
4663
{
@@ -49,23 +66,47 @@ export function getWebpackCommonConfig(projectRoot: string, sourceDir: string) {
4966
],
5067
exclude: [/\.(spec|e2e)\.ts$/]
5168
},
52-
{ test: /\.json$/, loader: 'json-loader'},
53-
{ test: /\.css$/, loaders: ['raw-loader', 'postcss-loader'] },
54-
{ test: /\.styl$/, loaders: ['raw-loader', 'postcss-loader', 'stylus-loader'] },
55-
{ test: /\.less$/, loaders: ['raw-loader', 'postcss-loader', 'less-loader'] },
56-
{ test: /\.scss$|\.sass$/, loaders: ['raw-loader', 'postcss-loader', 'sass-loader'] },
57-
{ test: /\.(jpg|png)$/, loader: 'url-loader?limit=128000'},
58-
{ test: /\.html$/, loader: 'raw-loader' }
69+
70+
// in main, load css as raw text
71+
       { exclude: additionalFiles, test: /\.css$/, loaders: ['raw-loader', 'postcss-loader'] },
72+
       { exclude: additionalFiles, test: /\.styl$/, loaders: ['raw-loader', 'postcss-loader', 'stylus-loader'] },
73+
       { exclude: additionalFiles, test: /\.less$/, loaders: ['raw-loader', 'postcss-loader', 'less-loader'] },
74+
       { exclude: additionalFiles, test: /\.scss$|\.sass$/, loaders: ['raw-loader', 'postcss-loader', 'sass-loader'] },
75+
76+
// outside of main, load it via style-loader
77+
       { include: additionalFiles, test: /\.css$/, loaders: ['style-loader', 'css-loader', 'postcss-loader'] },
78+
       { include: additionalFiles, test: /\.styl$/, loaders: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] },
79+
       { include: additionalFiles, test: /\.less$/, loaders: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'] },
80+
       { include: additionalFiles, test: /\.scss$|\.sass$/, loaders: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] },
81+
82+
       { test: /\.json$/, loader: 'json-loader' },
83+
       { test: /\.(jpg|png)$/, loader: 'url-loader?limit=10000' },
84+
       { test: /\.html$/, loader: 'raw-loader' },
85+
86+
       { test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff' },
87+
       { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream' },
88+
       { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file' },
89+
       { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml' }
5990
]
6091
},
6192
plugins: [
6293
new ForkCheckerPlugin(),
6394
new HtmlWebpackPlugin({
64-
template: path.resolve(projectRoot, `./${sourceDir}/index.html`),
95+
template: path.resolve(appRoot, appConfig.index),
6596
chunksSortMode: 'dependency'
6697
}),
98+
new webpack.NormalModuleReplacementPlugin(
99+
// escape the path to make a regex
100+
// TODO: this isn't working!
101+
new RegExp(path.resolve(appRoot, appConfig.environments.source)
102+
.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")),
103+
path.resolve(appRoot, appConfig.environments[environment])
104+
),
67105
new webpack.optimize.CommonsChunkPlugin({
68-
name: ['polyfills']
106+
name: separateBundles
107+
.concat('main')
108+
.map(bundle => bundle.output)
109+
.reverse()
69110
}),
70111
new webpack.optimize.CommonsChunkPlugin({
71112
minChunks: Infinity,
@@ -74,9 +115,9 @@ export function getWebpackCommonConfig(projectRoot: string, sourceDir: string) {
74115
sourceMapFilename: 'inline.map'
75116
}),
76117
new CopyWebpackPlugin([{
77-
context: path.resolve(projectRoot, './public'),
118+
context: path.resolve(appRoot, appConfig.assets),
78119
from: '**/*',
79-
to: path.resolve(projectRoot, './dist')
120+
to: path.resolve(projectRoot, appConfig.outDir, appConfig.assets)
80121
}])
81122
],
82123
node: {
@@ -89,3 +130,4 @@ export function getWebpackCommonConfig(projectRoot: string, sourceDir: string) {
89130
}
90131
}
91132
};
133+

addon/ng2/models/webpack-build-development.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { CliConfig } from './config';
22
const path = require('path')
33

4-
export const getWebpackDevConfigPartial = function(projectRoot: string, sourceDir: string) {
4+
export const getWebpackDevConfigPartial = function(projectRoot: string, appConfig: any) {
55
return {
66
debug: true,
77
devtool: 'source-map',
@@ -14,7 +14,7 @@ export const getWebpackDevConfigPartial = function(projectRoot: string, sourceDi
1414
tslint: {
1515
emitErrors: false,
1616
failOnHint: false,
17-
resourcePath: path.resolve(projectRoot, `./${sourceDir}`)
17+
resourcePath: path.resolve(projectRoot, appConfig.root)
1818
},
1919
node: {
2020
fs: 'empty',

addon/ng2/models/webpack-build-mobile.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,25 @@ import * as CopyWebpackPlugin from 'copy-webpack-plugin';
55
import { PrerenderWebpackPlugin } from '../utilities/prerender-webpack-plugin.ts';
66
import { CliConfig } from './config';
77

8-
export const getWebpackMobileConfigPartial = function (projectRoot: string, sourceDir: string) {
8+
export const getWebpackMobileConfigPartial = function (projectRoot: string, appConfig: any) {
9+
// Hardcoded files and paths here should be part of appConfig when
10+
// reworking the mobile app functionality
911
return {
1012
plugins: [
1113
new CopyWebpackPlugin([
12-
{from: path.resolve(projectRoot, `./${sourceDir}/icons`), to: path.resolve(projectRoot, './dist/icons')},
13-
{from: path.resolve(projectRoot, `./${sourceDir}/manifest.webapp`), to: path.resolve(projectRoot, './dist')}
14+
{from: path.resolve(projectRoot, appConfig.root, 'icons'), to: path.resolve(projectRoot, appConfig.outDir, 'icons')},
15+
{from: path.resolve(projectRoot, appConfig.root, 'manifest.webapp'), to: path.resolve(projectRoot, appConfig.outDir)}
1416
]),
1517
new PrerenderWebpackPlugin({
1618
templatePath: 'index.html',
17-
configPath: path.resolve(projectRoot, `./${sourceDir}/main-app-shell.ts`),
18-
appPath: path.resolve(projectRoot, `./${sourceDir}`)
19+
configPath: path.resolve(projectRoot, appConfig.root, 'main-app-shell.ts'),
20+
appPath: path.resolve(projectRoot, appConfig.root)
1921
})
2022
]
2123
}
2224
};
2325

24-
export const getWebpackMobileProdConfigPartial = function (projectRoot: string, sourceDir: string) {
26+
export const getWebpackMobileProdConfigPartial = function (projectRoot: string, appConfig: any) {
2527
return {
2628
entry: {
2729
'sw-install': path.resolve(__dirname, '../utilities/sw-install.js')

addon/ng2/models/webpack-build-production.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as CompressionPlugin from 'compression-webpack-plugin';
55
import * as webpack from 'webpack';
66
import { CliConfig } from './config';
77

8-
export const getWebpackProdConfigPartial = function(projectRoot: string, sourceDir: string) {
8+
export const getWebpackProdConfigPartial = function(projectRoot: string, appConfig: any) {
99
return {
1010
debug: false,
1111
devtool: 'source-map',
@@ -36,7 +36,7 @@ export const getWebpackProdConfigPartial = function(projectRoot: string, sourceD
3636
tslint: {
3737
emitErrors: true,
3838
failOnHint: true,
39-
resourcePath: path.resolve(projectRoot, `./${sourceDir}`)
39+
resourcePath: path.resolve(projectRoot, appConfig.root)
4040
},
4141
htmlLoader: {
4242
minimize: true,

addon/ng2/models/webpack-build-test.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@
33
const path = require('path');
44
const webpack = require('webpack');
55

6-
const getWebpackTestConfig = function(projectRoot, sourceDir) {
6+
const getWebpackTestConfig = function(projectRoot, appConfig) {
7+
8+
const appRoot = path.resolve(projectRoot, appConfig.root);
9+
710
return {
811
devtool: 'inline-source-map',
912
context: path.resolve(__dirname, './'),
1013
resolve: {
1114
extensions: ['', '.ts', '.js'],
12-
root: path.resolve(projectRoot, `./${sourceDir}`)
15+
root: appRoot
1316
},
1417
entry: {
15-
test: path.resolve(projectRoot, `./${sourceDir}/test.ts`)
18+
test: path.resolve(appRoot, appConfig.test)
1619
},
1720
output: {
1821
path: './dist.test',
@@ -43,7 +46,7 @@ const getWebpackTestConfig = function(projectRoot, sourceDir) {
4346
{
4447
loader: 'awesome-typescript-loader',
4548
query: {
46-
tsconfig: path.resolve(projectRoot, `./${sourceDir}/tsconfig.json`),
49+
tsconfig: path.resolve(appRoot, appConfig.tsconfig),
4750
module: 'commonjs',
4851
target: 'es5',
4952
useForkChecker: true
@@ -61,7 +64,7 @@ const getWebpackTestConfig = function(projectRoot, sourceDir) {
6164
{ test: /\.less$/, loaders: ['raw-loader', 'postcss-loader', 'less-loader'] },
6265
{ test: /\.scss$|\.sass$/, loaders: ['raw-loader', 'postcss-loader', 'sass-loader'] },
6366
{ test: /\.(jpg|png)$/, loader: 'url-loader?limit=128000' },
64-
{ test: /\.html$/, loader: 'raw-loader', exclude: [path.resolve(projectRoot, `./${sourceDir}/index.html`)] }
67+
{ test: /\.html$/, loader: 'raw-loader', exclude: [path.resolve(appRoot, appConfig.index)] }
6568
],
6669
postLoaders: [
6770
{
@@ -83,7 +86,7 @@ const getWebpackTestConfig = function(projectRoot, sourceDir) {
8386
tslint: {
8487
emitErrors: false,
8588
failOnHint: false,
86-
resourcePath: `./${sourceDir}`
89+
resourcePath: `./${appConfig.root}`
8790
},
8891
node: {
8992
fs: 'empty',

0 commit comments

Comments
 (0)