Skip to content

Commit 0f3f11b

Browse files
committed
feat(prod-build): add environment config (#411)
1 parent f34eedc commit 0f3f11b

File tree

7 files changed

+85
-41
lines changed

7 files changed

+85
-41
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,15 @@ ng build
159159

160160
The build artifacts will be stored in the `dist/` directory.
161161

162+
### Environments
163+
164+
At build time, the `src/client/app/environment.ts` will be replaced by either
165+
`config/environment.dev.ts` or `config/environment.prod.ts`, depending on the
166+
current cli environment.
167+
168+
Environment defaults to `dev`, but you can generate a production build via
169+
the `-prod` flag in either `ng build -prod` or `ng serve -prod`.
170+
162171
### Running unit tests
163172

164173
```bash
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const environment = {
2+
production: false
3+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const environment = {
2+
production: true
3+
};
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
import {bootstrap} from 'angular2/platform/browser';
2+
import {enableProdMode} from 'angular2/core';
3+
import {environment} from './app/environment';
24
import {<%= jsComponentName %>App} from './app/<%= htmlComponentName %>';
35

4-
bootstrap(<%= jsComponentName %>App, []);
6+
if (environment.production) {
7+
enableProdMode();
8+
}
9+
10+
bootstrap(<%= jsComponentName %>App);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// The file for the current environment will overwrite this one during build
2+
// Different environments can be found in config/environment.{dev|prod}.ts
3+
// The build system defaults to the dev environment
4+
5+
export const environment = {
6+
production: false
7+
};

lib/broccoli/angular2-app.js

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,12 @@ class Angular2App {
9494
this.initializeAddons();
9595
this.project.addons = this.project.addons.filter(function (addon) {
9696
addon.app = this;
97-
97+
9898
if (!addon.isEnabled || addon.isEnabled()) {
9999
if (addon.included) {
100100
addon.included(this);
101101
}
102-
102+
103103
return addon;
104104
}
105105
}, this);
@@ -139,7 +139,7 @@ class Angular2App {
139139
*/
140140
_contentFor(match, type) {
141141
var content = [];
142-
142+
143143
/*switch (type) {
144144
case 'head': this._contentForHead(content, config); break;
145145
case 'config-module': this._contentForConfigModule(content, config); break;
@@ -151,14 +151,14 @@ class Angular2App {
151151
if (addonContent) {
152152
return content.concat(addonContent);
153153
}
154-
154+
155155
return content;
156156
}, content);
157-
158-
157+
158+
159159
return content.join('\n');
160160
}
161-
161+
162162
/**
163163
* @private
164164
* @method _getReplacePatterns
@@ -183,19 +183,19 @@ class Angular2App {
183183
var files = [
184184
'index.html'
185185
];
186-
186+
187187
var index = new Funnel(this._sourceDir, {
188188
files: files,
189189
description: 'Funnel: index.html'
190190
});
191-
192-
191+
192+
193193
return configReplace(index, {
194194
files: [htmlName],
195195
patterns: this._getReplacePatterns()
196196
});
197197
}
198-
198+
199199
/**
200200
* Returns the source root dir tree.
201201
*
@@ -223,7 +223,7 @@ class Angular2App {
223223
destDir: 'typings'
224224
});
225225
}
226-
226+
227227
/**
228228
* Returns the TS tree.
229229
*
@@ -234,6 +234,7 @@ class Angular2App {
234234
_getTsTree() {
235235
var typingsTree = this._getTypingsTree();
236236
var sourceTree = this._getSourceTree();
237+
var configTree = this._getConfigTree();
237238

238239
var tsConfigPath = path.join(this._sourceDir, 'tsconfig.json');
239240
var tsconfig = JSON.parse(fs.readFileSync(tsConfigPath, 'utf-8'));
@@ -264,23 +265,23 @@ class Angular2App {
264265
// Because the tsconfig does not include the source directory, add this as the first path
265266
// element.
266267
tsconfig.files = tsconfig.files.map(name => path.join(this._sourceDir, name));
267-
268-
var srcAndTypingsTree = mergeTrees([sourceTree, typingsTree]);
269-
var tsTree = new compileWithTypescript(srcAndTypingsTree, tsconfig);
270-
268+
269+
var mergedTree = mergeTrees([sourceTree, typingsTree, configTree], { overwrite: true });
270+
var tsTree = new compileWithTypescript(mergedTree, tsconfig);
271+
271272
var tsTreeExcludes = ['*.d.ts', 'tsconfig.json'];
272273
var excludeSpecFiles = '**/*.spec.*';
273-
274+
274275
if (isProduction) {
275276
tsTreeExcludes.push(excludeSpecFiles);
276277
tsTree = uglify(tsTree);
277278
}
278-
279+
279280
tsTree = new Funnel(tsTree, {
280281
srcDir: this._sourceDir,
281282
exclude: tsTreeExcludes
282283
});
283-
284+
284285
return tsTree;
285286
}
286287

@@ -305,19 +306,19 @@ class Angular2App {
305306
'angular2/bundles/router.dev.js',
306307
'angular2/bundles/upgrade.dev.js'
307308
];
308-
309+
309310
if (this._options.vendorNpmFiles) {
310311
vendorNpmFiles = vendorNpmFiles.concat(this._options.vendorNpmFiles);
311312
}
312-
313+
313314
var vendorNpmTree = new Funnel('node_modules', {
314315
include: vendorNpmFiles,
315316
destDir: 'vendor'
316317
});
317-
318+
318319
return vendorNpmTree;
319320
}
320-
321+
321322
/**
322323
* Returns the `assets` tree.
323324
*
@@ -353,6 +354,23 @@ class Angular2App {
353354
allowEmpty: true
354355
});
355356
}
357+
358+
/**
359+
* Returns the config files tree.
360+
*
361+
* @private
362+
* @method _getConfigTree
363+
* @return {Tree} The config files tree.
364+
*/
365+
_getConfigTree() {
366+
var envConfigFile = isProduction ? 'environment.prod.ts' : 'environment.dev.ts';
367+
// console.log(envConfigFile);
368+
return new Funnel('config', {
369+
include: [envConfigFile],
370+
destDir: 'src/client/app',
371+
getDestinationPath: () => 'environment.ts'
372+
});
373+
}
356374
}
357375

358376
module.exports = Angular2App;

tests/e2e/e2e_workflow.spec.js

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,26 +57,24 @@ describe('Basic end-to-end Workflow', function () {
5757
expect(path.basename(process.cwd())).to.equal('test-project');
5858
});
5959

60-
it('Can run `ng build` in created project', function () {
60+
it('Supports production builds via `ng build --environment=production`', function() {
6161
this.timeout(420000);
6262

63-
return ng(['build', '--silent'])
64-
.then(function () {
65-
expect(existsSync(path.join(process.cwd(), 'dist'))).to.be.equal(true);
66-
})
67-
.then(function () {
68-
// Also does not create new things in GIT.
69-
expect(sh.exec('git status --porcelain').output).to.be.equal('');
70-
})
71-
.catch(() => {
72-
throw new Error('Build failed.');
73-
});
63+
// Can't user the `ng` helper because somewhere the environment gets
64+
// stuck to the first build done
65+
sh.exec('./node_modules/.bin/ng build --environment=production --silent');
66+
expect(existsSync(path.join(process.cwd(), 'dist'))).to.be.equal(true);
67+
var envPath = path.join(process.cwd(), 'dist', 'app', 'environment.js');
68+
var envContent = fs.readFileSync(envPath, { encoding: 'utf8' });
69+
expect(envContent).to.include('production:true');
70+
// Also does not create new things in GIT.
71+
expect(sh.exec('git status --porcelain').output).to.be.equal('');
7472
});
7573

76-
it('Supports production builds via `ng build --envinroment=production`', function() {
74+
it('Can run `ng build` in created project', function () {
7775
this.timeout(420000);
7876

79-
return ng(['build', '--environment=production', '--silent'])
77+
return ng(['build', '--silent'])
8078
.then(function () {
8179
expect(existsSync(path.join(process.cwd(), 'dist'))).to.be.equal(true);
8280
})
@@ -214,7 +212,7 @@ describe('Basic end-to-end Workflow', function () {
214212
expect(existsSync(cssFile)).to.be.equal(false);
215213
let scssExample = '.outer {\n .inner { background: #fff; }\n }';
216214
fs.writeFileSync(scssFile, scssExample, 'utf8');
217-
215+
218216
sh.exec('ng build --silent');
219217
let destCss = path.join(process.cwd(), 'dist', 'app', 'test-component', 'test-component.css');
220218
expect(existsSync(destCss)).to.be.equal(true);
@@ -249,7 +247,7 @@ describe('Basic end-to-end Workflow', function () {
249247
expect(existsSync(cssFile)).to.be.equal(false);
250248
let lessExample = '.outer {\n .inner { background: #fff; }\n }';
251249
fs.writeFileSync(lessFile, lessExample, 'utf8');
252-
250+
253251
sh.exec('ng build --silent');
254252
let destCss = path.join(process.cwd(), 'dist', 'app', 'test-component', 'test-component.css');
255253
expect(existsSync(destCss)).to.be.equal(true);
@@ -283,7 +281,7 @@ describe('Basic end-to-end Workflow', function () {
283281
expect(existsSync(cssFile)).to.be.equal(false);
284282
let stylusExample = '.outer {\n .inner { background: #fff; }\n }';
285283
fs.writeFileSync(stylusFile, stylusExample, 'utf8');
286-
284+
287285
sh.exec('ng build --silent');
288286
let destCss = path.join(process.cwd(), 'dist', 'app', 'test-component', 'test-component.css');
289287
expect(existsSync(destCss)).to.be.equal(true);

0 commit comments

Comments
 (0)