Skip to content

Commit 1f117a1

Browse files
committed
feat(@angular/cli): support ES2015 target
1 parent 642f6ba commit 1f117a1

File tree

7 files changed

+146
-54
lines changed

7 files changed

+146
-54
lines changed

package-lock.json

Lines changed: 63 additions & 42 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
"stylus": "^0.54.5",
9393
"stylus-loader": "^3.0.1",
9494
"typescript": "~2.4.2",
95+
"uglifyjs-webpack-plugin": "1.0.0-beta.1",
9596
"url-loader": "^0.5.7",
9697
"webpack": "~3.5.5",
9798
"webpack-concat-plugin": "1.4.0",

packages/@angular/cli/models/webpack-configs/common.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ export function getCommonConfig(wco: WebpackConfigOptions) {
153153
resolve: {
154154
extensions: ['.ts', '.js'],
155155
modules: ['node_modules', nodeModules],
156+
mainFields: [
157+
...(buildOptions.compilationTarget === 'ES2015' ? ['es2015'] : []),
158+
'browser', 'module', 'main'
159+
],
156160
symlinks: !buildOptions.preserveSymlinks
157161
},
158162
resolveLoader: {

packages/@angular/cli/models/webpack-configs/production.ts

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,22 @@ import * as path from 'path';
22
import * as webpack from 'webpack';
33
import * as fs from 'fs';
44
import * as semver from 'semver';
5+
import * as ts from 'typescript';
56
import { stripIndent } from 'common-tags';
67
import { LicenseWebpackPlugin } from 'license-webpack-plugin';
78
import { PurifyPlugin } from '@angular-devkit/build-optimizer';
89
import { StaticAssetPlugin } from '../../plugins/static-asset';
910
import { GlobCopyWebpackPlugin } from '../../plugins/glob-copy-webpack-plugin';
1011
import { WebpackConfigOptions } from '../webpack-config';
1112

13+
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
14+
1215

1316
export const getProdConfig = function (wco: WebpackConfigOptions) {
1417
const { projectRoot, buildOptions, appConfig } = wco;
1518

1619
let extraPlugins: any[] = [];
17-
let entryPoints: {[key: string]: string[]} = {};
20+
let entryPoints: { [key: string]: string[] } = {};
1821

1922
if (appConfig.serviceWorker) {
2023
const nodeModules = path.resolve(projectRoot, 'node_modules');
@@ -66,7 +69,7 @@ export const getProdConfig = function (wco: WebpackConfigOptions) {
6669
extraPlugins.push(new GlobCopyWebpackPlugin({
6770
patterns: [
6871
'ngsw-manifest.json',
69-
{glob: 'ngsw-manifest.json', input: path.resolve(projectRoot, appConfig.root), output: ''}
72+
{ glob: 'ngsw-manifest.json', input: path.resolve(projectRoot, appConfig.root), output: '' }
7073
],
7174
globOptions: {
7275
cwd: projectRoot,
@@ -99,7 +102,7 @@ export const getProdConfig = function (wco: WebpackConfigOptions) {
99102
}));
100103
}
101104

102-
const uglifyCompressOptions: any = { screw_ie8: true, warnings: buildOptions.verbose };
105+
const uglifyCompressOptions: any = {};
103106

104107
if (buildOptions.buildOptimizer) {
105108
// This plugin must be before webpack.optimize.UglifyJsPlugin.
@@ -110,21 +113,50 @@ export const getProdConfig = function (wco: WebpackConfigOptions) {
110113
uglifyCompressOptions.passes = 3;
111114
}
112115

116+
// Read the tsconfig to determine if we should apply ES6 uglify.
117+
const tsconfigPath = path.resolve(projectRoot, appConfig.root, appConfig.tsconfig);
118+
const configResult = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
119+
const tsConfig = ts.parseJsonConfigFileContent(configResult.config, ts.sys,
120+
path.dirname(tsconfigPath), undefined, tsconfigPath);
121+
122+
if (tsConfig.options.target !== ts.ScriptTarget.ES3
123+
&& tsConfig.options.target !== ts.ScriptTarget.ES5) {
124+
extraPlugins.push(new UglifyJSPlugin({
125+
sourceMap: buildOptions.sourcemaps,
126+
uglifyOptions: {
127+
ecma: 6,
128+
warnings: buildOptions.verbose,
129+
ie8: false,
130+
mangle: true,
131+
compress: uglifyCompressOptions,
132+
output: {
133+
ascii_only: true,
134+
comments: false
135+
},
136+
}
137+
}));
138+
} else {
139+
uglifyCompressOptions.screw_ie8 = true;
140+
uglifyCompressOptions.warnings = buildOptions.verbose;
141+
extraPlugins.push(new webpack.optimize.UglifyJsPlugin(<any>{
142+
mangle: { screw_ie8: true },
143+
compress: uglifyCompressOptions,
144+
output: { ascii_only: true },
145+
sourceMap: buildOptions.sourcemaps,
146+
comments: false
147+
}));
148+
149+
}
150+
113151
return {
114152
entry: entryPoints,
115-
plugins: extraPlugins.concat([
153+
plugins: [
116154
new webpack.EnvironmentPlugin({
117155
'NODE_ENV': 'production'
118156
}),
119157
new webpack.HashedModuleIdsPlugin(),
120158
new webpack.optimize.ModuleConcatenationPlugin(),
121-
new webpack.optimize.UglifyJsPlugin(<any>{
122-
mangle: { screw_ie8: true },
123-
compress: uglifyCompressOptions,
124-
output: { ascii_only: true },
125-
sourceMap: buildOptions.sourcemaps,
126-
comments: false
127-
})
128-
])
159+
...extraPlugins
160+
]
129161
};
130162
};

packages/@angular/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
"stylus": "^0.54.5",
7777
"stylus-loader": "^3.0.1",
7878
"typescript": ">=2.0.0 <2.6.0",
79+
"uglifyjs-webpack-plugin": "1.0.0-beta.1",
7980
"url-loader": "^0.5.7",
8081
"webpack": "~3.5.5",
8182
"webpack-concat-plugin": "1.4.0",

packages/@angular/cli/tasks/eject.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
2424
const SilentError = require('silent-error');
2525
const CircularDependencyPlugin = require('circular-dependency-plugin');
2626
const ConcatPlugin = require('webpack-concat-plugin');
27+
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
2728
const Task = require('../ember-cli/lib/models/task');
2829

2930
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
@@ -158,6 +159,10 @@ class JsonWebpackSerializer {
158159
return plugin.settings;
159160
}
160161

162+
private _uglifyjsPlugin(plugin: any) {
163+
return plugin.options;
164+
}
165+
161166
private _pluginsReplacer(plugins: any[]) {
162167
return plugins.map(plugin => {
163168
let args = plugin.options || undefined;
@@ -229,6 +234,10 @@ class JsonWebpackSerializer {
229234
args = this._concatPlugin(plugin);
230235
this.variableImports['webpack-concat-plugin'] = 'ConcatPlugin';
231236
break;
237+
case UglifyJSPlugin:
238+
args = this._uglifyjsPlugin(plugin);
239+
this.variableImports['uglifyjs-webpack-plugin'] = 'UglifyJsPlugin';
240+
break;
232241
default:
233242
if (plugin.constructor.name == 'AngularServiceWorkerPlugin') {
234243
this._addImport('@angular/service-worker/build/webpack', plugin.constructor.name);
@@ -546,6 +555,7 @@ export default Task.extend({
546555
'circular-dependency-plugin',
547556
'webpack-concat-plugin',
548557
'copy-webpack-plugin',
558+
'uglifyjs-webpack-plugin',
549559
].forEach((packageName: string) => {
550560
packageJson['devDependencies'][packageName] = ourPackageJson['dependencies'][packageName];
551561
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { appendToFile, expectFileToMatch } from '../../utils/fs';
2+
import { ng } from '../../utils/process';
3+
import { expectToFail } from '../../utils/utils';
4+
import { updateJsonFile } from '../../utils/project';
5+
6+
7+
export default function () {
8+
return Promise.resolve()
9+
// Force import a known ES6 module and build with prod.
10+
// ES6 modules will cause UglifyJS to fail on a ES5 compilation target (default).
11+
.then(() => appendToFile('src/main.ts', `
12+
import * as es6module from '@angular/core/@angular/core';
13+
console.log(es6module);
14+
`))
15+
.then(() => expectToFail(() => ng('build', '--prod')))
16+
.then(() => updateJsonFile('tsconfig.json', configJson => {
17+
const compilerOptions = configJson['compilerOptions'];
18+
compilerOptions['target'] = 'es2015';
19+
}))
20+
.then(() => ng('build', '--prod', '--output-hashing=none'))
21+
// Check class constructors are present in the vendor output.
22+
.then(() => expectFileToMatch('dist/vendor.bundle.js', /class \w{constructor\(\){/));
23+
}

0 commit comments

Comments
 (0)