Skip to content

Commit b74d609

Browse files
committed
feat(build): update angular-cli.json
1 parent 504a497 commit b74d609

27 files changed

+315
-161
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

+4-4
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ module.exports = {
2525

2626
var defaultPrefix = '';
2727
if (this.project.ngConfig &&
28-
this.project.ngConfig.defaults &&
29-
this.project.ngConfig.defaults.prefix) {
30-
defaultPrefix = this.project.ngConfig.defaults.prefix + '-';
28+
this.project.ngConfig.apps[0] &&
29+
this.project.ngConfig.apps[0].prefix) {
30+
defaultPrefix = this.project.ngConfig.apps[0].prefix + '-';
3131
}
3232
var prefix = this.options.prefix ? defaultPrefix : '';
3333
this.selector = stringUtils.dasherize(prefix + parsedPath.name);
@@ -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();

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// Prefer CoreJS over the polyfills above
1+
// This file includes polyfills needed by Angular 2 and is loaded before
2+
// the app. You can add your own extra polyfills to this file.
23
import 'core-js/es6/symbol';
34
import 'core-js/es6/object';
45
import 'core-js/es6/function';
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

+19-5
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,25 @@
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+
"prefix": "<%= prefix %>",
16+
"mobile": <%= isMobile %>,
17+
"additionalEntries": [
18+
{ "input": "polyfills.ts", "output": "polyfills.js" },
19+
"scripts.ts",
20+
"styles.<%= styleExt %>"
21+
],
22+
"environments": {
23+
"source": "environments/environment.ts",
24+
"prod": "environments/environment.prod.ts",
25+
"dev": "environments/environment.dev.ts"
26+
}
1127
}
1228
],
1329
"addons": [],
@@ -23,8 +39,6 @@
2339
}
2440
},
2541
"defaults": {
26-
"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/commands/github-pages-deploy.ts

+27-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as chalk from 'chalk';
66
import * as fs from 'fs';
77
import * as fse from 'fs-extra';
88
import * as path from 'path';
9-
import * as BuildTask from 'ember-cli/lib/tasks/build';
9+
import * as WebpackBuild from '../tasks/build-webpack';
1010
import * as CreateGithubRepo from '../tasks/create-github-repo';
1111

1212
const fsReadFile = Promise.denodeify(fs.readFile);
@@ -26,11 +26,16 @@ module.exports = Command.extend({
2626
type: String,
2727
default: 'new gh-pages version',
2828
description: 'The commit message to include with the build, must be wrapped in quotes.'
29-
}, {
29+
}, {
30+
name: 'target',
31+
type: String,
32+
default: 'development',
33+
aliases: ['t', { 'dev': 'development' }, { 'prod': 'production' }]
34+
}, {
3035
name: 'environment',
3136
type: String,
32-
default: 'production',
33-
description: 'The Angular environment to create a build for'
37+
default: '',
38+
aliases: ['e']
3439
}, {
3540
name: 'user-page',
3641
type: Boolean,
@@ -59,24 +64,37 @@ module.exports = Command.extend({
5964
var execOptions = {
6065
cwd: root
6166
};
67+
68+
if (options.environment === ''){
69+
if (options.target === 'development') {
70+
options.environment = 'dev';
71+
}
72+
if (options.target === 'production') {
73+
options.environment = 'prod';
74+
}
75+
}
76+
6277
var projectName = this.project.pkg.name;
6378

79+
const outDir = CliConfig.fromProject().apps[0].outDir;
80+
6481
let ghPagesBranch = 'gh-pages';
6582
let destinationBranch = options.userPage ? 'master' : ghPagesBranch;
6683
let initialBranch;
6784

6885
// declared here so that tests can stub exec
6986
const execPromise = Promise.denodeify(exec);
7087

71-
var buildTask = new BuildTask({
88+
var WebpackBuild = new WebpackBuild({
7289
ui: this.ui,
7390
analytics: this.analytics,
7491
project: this.project
7592
});
7693

7794
var buildOptions = {
95+
target: options.environment,
7896
environment: options.environment,
79-
outputPath: 'dist/'
97+
outputPath: outDir
8098
};
8199

82100
var createGithubRepoTask = new CreateGithubRepo({
@@ -116,7 +134,7 @@ module.exports = Command.extend({
116134

117135
function build() {
118136
if (options.skipBuild) return Promise.resolve();
119-
return buildTask.run(buildOptions);
137+
return WebpackBuild.run(buildOptions);
120138
}
121139

122140
function saveStartingBranchName() {
@@ -155,13 +173,13 @@ module.exports = Command.extend({
155173
}
156174

157175
function copyFiles() {
158-
return fsReadDir('dist')
176+
return fsReadDir(outDir)
159177
.then((files) => Promise.all(files.map((file) => {
160178
if (file === '.gitignore'){
161179
// don't overwrite the .gitignore file
162180
return Promise.resolve();
163181
}
164-
return fsCopy(path.join('dist', file), path.join('.', file))
182+
return fsCopy(path.join(outDir, file), path.join('.', file))
165183
})));
166184
}
167185

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

+61-19
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: {
@@ -30,7 +47,7 @@ export function getWebpackCommonConfig(projectRoot: string, sourceDir: string) {
3047
loader: 'awesome-typescript-loader',
3148
query: {
3249
useForkChecker: true,
33-
tsconfig: path.resolve(projectRoot, `./${sourceDir}/tsconfig.json`)
50+
tsconfig: path.resolve(appRoot, appConfig.tsconfig)
3451
}
3552
},
3653
{
@@ -39,23 +56,47 @@ export function getWebpackCommonConfig(projectRoot: string, sourceDir: string) {
3956
],
4057
exclude: [/\.(spec|e2e)\.ts$/]
4158
},
42-
{ test: /\.json$/, loader: 'json-loader'},
43-
{ test: /\.css$/, loaders: ['raw-loader', 'postcss-loader'] },
44-
{ test: /\.styl$/, loaders: ['raw-loader', 'postcss-loader', 'stylus-loader'] },
45-
{ test: /\.less$/, loaders: ['raw-loader', 'postcss-loader', 'less-loader'] },
46-
{ test: /\.scss$|\.sass$/, loaders: ['raw-loader', 'postcss-loader', 'sass-loader'] },
47-
{ test: /\.(jpg|png)$/, loader: 'url-loader?limit=128000'},
48-
{ test: /\.html$/, loader: 'raw-loader' }
59+
60+
// in main, load css as raw text
61+
       { exclude: additionalFiles, test: /\.css$/, loaders: ['raw-loader', 'postcss-loader'] },
62+
       { exclude: additionalFiles, test: /\.styl$/, loaders: ['raw-loader', 'postcss-loader', 'stylus-loader'] },
63+
       { exclude: additionalFiles, test: /\.less$/, loaders: ['raw-loader', 'postcss-loader', 'less-loader'] },
64+
       { exclude: additionalFiles, test: /\.scss$|\.sass$/, loaders: ['raw-loader', 'postcss-loader', 'sass-loader'] },
65+
66+
// outside of main, load it via style-loader
67+
       { include: additionalFiles, test: /\.css$/, loaders: ['style-loader', 'css-loader', 'postcss-loader'] },
68+
       { include: additionalFiles, test: /\.styl$/, loaders: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] },
69+
       { include: additionalFiles, test: /\.less$/, loaders: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'] },
70+
       { include: additionalFiles, test: /\.scss$|\.sass$/, loaders: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] },
71+
72+
       { test: /\.json$/, loader: 'json-loader' },
73+
       { test: /\.(jpg|png)$/, loader: 'url-loader?limit=10000' },
74+
       { test: /\.html$/, loader: 'raw-loader' },
75+
76+
       { test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff' },
77+
       { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream' },
78+
       { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file' },
79+
       { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml' }
4980
]
5081
},
5182
plugins: [
5283
new ForkCheckerPlugin(),
5384
new HtmlWebpackPlugin({
54-
template: path.resolve(projectRoot, `./${sourceDir}/index.html`),
85+
template: path.resolve(appRoot, appConfig.index),
5586
chunksSortMode: 'dependency'
5687
}),
88+
new webpack.NormalModuleReplacementPlugin(
89+
// escape the path to make a regex
90+
// TODO: this isn't working!
91+
new RegExp(path.resolve(appRoot, appConfig.environments.source)
92+
.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")),
93+
path.resolve(appRoot, appConfig.environments[environment])
94+
),
5795
new webpack.optimize.CommonsChunkPlugin({
58-
name: ['polyfills']
96+
name: separateBundles
97+
.concat('main')
98+
.map(bundle => bundle.output)
99+
.reverse()
59100
}),
60101
new webpack.optimize.CommonsChunkPlugin({
61102
minChunks: Infinity,
@@ -64,9 +105,9 @@ export function getWebpackCommonConfig(projectRoot: string, sourceDir: string) {
64105
sourceMapFilename: 'inline.map'
65106
}),
66107
new CopyWebpackPlugin([{
67-
context: path.resolve(projectRoot, './public'),
108+
context: path.resolve(appRoot, appConfig.assets),
68109
from: '**/*',
69-
to: path.resolve(projectRoot, './dist')
110+
to: path.resolve(projectRoot, appConfig.outDir, appConfig.assets)
70111
}])
71112
],
72113
node: {
@@ -79,3 +120,4 @@ export function getWebpackCommonConfig(projectRoot: string, sourceDir: string) {
79120
}
80121
}
81122
};
123+

0 commit comments

Comments
 (0)