Skip to content

feat: webpack plugin to support AoT natively #2333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/bootstrap-local.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const ts = require('typescript');


global.angularCliIsLocal = true;
global.angularCliPackages = require('./packages');

const compilerOptions = JSON.parse(fs.readFileSync(path.join(__dirname, '../tsconfig.json')));

Expand Down
5 changes: 4 additions & 1 deletion lib/packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ const packages = fs.readdirSync(packageRoot)
.map(pkgName => ({ name: pkgName, root: path.join(packageRoot, pkgName) }))
.filter(pkg => fs.statSync(pkg.root).isDirectory())
.reduce((packages, pkg) => {
let name = pkg == 'angular-cli' ? 'angular-cli' : `@angular-cli/${pkg.name}`;
let pkgJson = JSON.parse(fs.readFileSync(path.join(pkg.root, 'package.json'), 'utf8'));
let name = pkgJson['name'];
packages[name] = {
dist: path.join(__dirname, '../dist', pkg.name),
packageJson: path.join(pkg.root, 'package.json'),
root: pkg.root,
main: path.resolve(pkg.root, 'src/index.ts')
};
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"fs.realpath": "^1.0.0",
"glob": "^7.0.3",
"handlebars": "^4.0.5",
"html-loader": "^0.4.4",
"html-webpack-plugin": "^2.19.0",
"istanbul-instrumenter-loader": "^0.2.0",
"json-loader": "^0.5.4",
Expand Down
13 changes: 7 additions & 6 deletions packages/angular-cli/blueprints/component/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
var path = require('path');
var chalk = require('chalk');
var Blueprint = require('ember-cli/lib/models/blueprint');
var dynamicPathParser = require('../../utilities/dynamic-path-parser');
const path = require('path');
const chalk = require('chalk');
const Blueprint = require('ember-cli/lib/models/blueprint');
const dynamicPathParser = require('../../utilities/dynamic-path-parser');
const findParentModule = require('../../utilities/find-parent-module').default;
var getFiles = Blueprint.prototype.files;
const getFiles = Blueprint.prototype.files;
const stringUtils = require('ember-cli-string-utils');
const astUtils = require('../../utilities/ast-utils');
const NodeHost = require('@angular-cli/ast-tools').NodeHost;

module.exports = {
description: '',
Expand Down Expand Up @@ -117,7 +118,7 @@ module.exports = {
if (!options['skip-import']) {
returns.push(
astUtils.addDeclarationToModule(this.pathToModule, className, importPath)
.then(change => change.apply()));
.then(change => change.apply(NodeHost)));
}

return Promise.all(returns);
Expand Down
3 changes: 2 additions & 1 deletion packages/angular-cli/blueprints/directive/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var dynamicPathParser = require('../../utilities/dynamic-path-parser');
const stringUtils = require('ember-cli-string-utils');
const astUtils = require('../../utilities/ast-utils');
const findParentModule = require('../../utilities/find-parent-module').default;
const NodeHost = require('@angular-cli/ast-tools').NodeHost;

module.exports = {
description: '',
Expand Down Expand Up @@ -73,7 +74,7 @@ module.exports = {
if (!options['skip-import']) {
returns.push(
astUtils.addDeclarationToModule(this.pathToModule, className, importPath)
.then(change => change.apply()));
.then(change => change.apply(NodeHost)));
}

return Promise.all(returns);
Expand Down
3 changes: 2 additions & 1 deletion packages/angular-cli/blueprints/pipe/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var dynamicPathParser = require('../../utilities/dynamic-path-parser');
const stringUtils = require('ember-cli-string-utils');
const astUtils = require('../../utilities/ast-utils');
const findParentModule = require('../../utilities/find-parent-module').default;
const NodeHost = require('@angular-cli/ast-tools').NodeHost;

module.exports = {
description: '',
Expand Down Expand Up @@ -61,7 +62,7 @@ module.exports = {
if (!options['skip-import']) {
returns.push(
astUtils.addDeclarationToModule(this.pathToModule, className, importPath)
.then(change => change.apply()));
.then(change => change.apply(NodeHost)));
}

return Promise.all(returns);
Expand Down
2 changes: 2 additions & 0 deletions packages/angular-cli/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface BuildOptions {
watcher?: string;
supressSizes: boolean;
baseHref?: string;
aot?: boolean;
}

const BuildCommand = Command.extend({
Expand All @@ -30,6 +31,7 @@ const BuildCommand = Command.extend({
{ name: 'watcher', type: String },
{ name: 'suppress-sizes', type: Boolean, default: false },
{ name: 'base-href', type: String, default: null, aliases: ['bh'] },
{ name: 'aot', type: Boolean, default: false }
],

run: function (commandOptions: BuildOptions) {
Expand Down
4 changes: 3 additions & 1 deletion packages/angular-cli/commands/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface ServeTaskOptions {
ssl?: boolean;
sslKey?: string;
sslCert?: string;
aot?: boolean;
}

const ServeCommand = Command.extend({
Expand Down Expand Up @@ -77,7 +78,8 @@ const ServeCommand = Command.extend({
{ name: 'environment', type: String, default: '', aliases: ['e'] },
{ name: 'ssl', type: Boolean, default: false },
{ name: 'ssl-key', type: String, default: 'ssl/server.key' },
{ name: 'ssl-cert', type: String, default: 'ssl/server.crt' }
{ name: 'ssl-cert', type: String, default: 'ssl/server.crt' },
{ name: 'aot', type: Boolean, default: false }
],

run: function(commandOptions: ServeTaskOptions) {
Expand Down
29 changes: 5 additions & 24 deletions packages/angular-cli/models/webpack-build-common.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import * as webpack from 'webpack';
import * as path from 'path';
import {BaseHrefWebpackPlugin} from '@angular-cli/base-href-webpack';

const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
import * as webpack from 'webpack';
const atl = require('awesome-typescript-loader');

import { BaseHrefWebpackPlugin } from '@angular-cli/base-href-webpack';
import { findLazyModules } from './find-lazy-modules';


export function getWebpackCommonConfig(
Expand All @@ -23,7 +21,6 @@ export function getWebpackCommonConfig(
const scripts = appConfig.scripts
? appConfig.scripts.map((script: string) => path.resolve(appRoot, script))
: [];
const lazyModules = findLazyModules(appRoot);

let entry: { [key: string]: string[] } = {
main: [appMain]
Expand Down Expand Up @@ -56,21 +53,7 @@ export function getWebpackCommonConfig(
}
],
loaders: [
{
test: /\.ts$/,
loaders: [
{
loader: 'awesome-typescript-loader',
query: {
useForkChecker: true,
tsconfig: path.resolve(appRoot, appConfig.tsconfig)
}
}, {
loader: 'angular2-template-loader'
}
],
exclude: [/\.(spec|e2e)\.ts$/]
},
// TypeScript loaders are separated into webpack-build-typescript.

// in main, load css as raw text
       {
Expand Down Expand Up @@ -115,16 +98,14 @@ export function getWebpackCommonConfig(

       { test: /\.json$/, loader: 'json-loader' },
       { test: /\.(jpg|png|gif)$/, loader: 'url-loader?limit=10000' },
       { test: /\.html$/, loader: 'raw-loader' },
       { test: /\.html$/, loader: 'html-loader' },

{ test: /\.(otf|woff|ttf|svg)$/, loader: 'url?limit=10000' },
{ test: /\.woff2$/, loader: 'url?limit=10000&mimetype=font/woff2' },
{ test: /\.eot$/, loader: 'file' }
]
},
plugins: [
new webpack.ContextReplacementPlugin(/.*/, appRoot, lazyModules),
new atl.ForkCheckerPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(appRoot, appConfig.index),
chunksSortMode: 'dependency'
Expand Down
63 changes: 63 additions & 0 deletions packages/angular-cli/models/webpack-build-typescript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as path from 'path';
import * as webpack from 'webpack';
import {findLazyModules} from './find-lazy-modules';
import {NgcWebpackPlugin} from '@ngtools/webpack';

const atl = require('awesome-typescript-loader');

const g: any = global;
const webpackLoader: string = g['angularCliIsLocal']
? g.angularCliPackages['@ngtools/webpack'].main
: '@ngtools/webpack';


export const getWebpackNonAotConfigPartial = function(projectRoot: string, appConfig: any) {
const appRoot = path.resolve(projectRoot, appConfig.root);
const lazyModules = findLazyModules(appRoot);

return {
module: {
loaders: [
{
test: /\.ts$/,
loaders: [{
loader: 'awesome-typescript-loader',
query: {
useForkChecker: true,
tsconfig: path.resolve(appRoot, appConfig.tsconfig)
}
}, {
loader: 'angular2-template-loader'
}],
exclude: [/\.(spec|e2e)\.ts$/]
}
],
},
plugins: [
new webpack.ContextReplacementPlugin(/.*/, appRoot, lazyModules),
new atl.ForkCheckerPlugin(),
]
};
};

export const getWebpackAotConfigPartial = function(projectRoot: string, appConfig: any) {
return {
module: {
loaders: [
{
test: /\.ts$/,
loader: webpackLoader,
exclude: [/\.(spec|e2e)\.ts$/]
}
]
},
plugins: [
new NgcWebpackPlugin({
project: path.resolve(projectRoot, appConfig.root, appConfig.tsconfig),
baseDir: path.resolve(projectRoot, ''),
entryModule: path.join(projectRoot, appConfig.root, 'app/app.module#AppModule'),
genDir: path.join(projectRoot, appConfig.outDir, 'ngfactory')
}),
]
};
};
38 changes: 23 additions & 15 deletions packages/angular-cli/models/webpack-config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import {
getWebpackAotConfigPartial,
getWebpackNonAotConfigPartial
} from './webpack-build-typescript';
const webpackMerge = require('webpack-merge');
import { CliConfig } from './config';
import {
Expand All @@ -12,50 +16,54 @@ export class NgCliWebpackConfig {
// TODO: When webpack2 types are finished lets replace all these any types
// so this is more maintainable in the future for devs
public config: any;
private devConfigPartial: any;
private prodConfigPartial: any;
private baseConfig: any;

constructor(
public ngCliProject: any,
public target: string,
public environment: string,
outputDir?: string,
baseHref?: string
baseHref?: string,
isAoT = false
) {
const config: CliConfig = CliConfig.fromProject();
const appConfig = config.config.apps[0];

appConfig.outDir = outputDir || appConfig.outDir;

this.baseConfig = getWebpackCommonConfig(
let baseConfig = getWebpackCommonConfig(
this.ngCliProject.root,
environment,
appConfig,
baseHref
);
this.devConfigPartial = getWebpackDevConfigPartial(this.ngCliProject.root, appConfig);
this.prodConfigPartial = getWebpackProdConfigPartial(this.ngCliProject.root, appConfig);
let targetConfigPartial = this.getTargetConfig(this.ngCliProject.root, appConfig);
const typescriptConfigPartial = isAoT
? getWebpackAotConfigPartial(this.ngCliProject.root, appConfig)
: getWebpackNonAotConfigPartial(this.ngCliProject.root, appConfig);

if (appConfig.mobile) {
let mobileConfigPartial = getWebpackMobileConfigPartial(this.ngCliProject.root, appConfig);
let mobileProdConfigPartial = getWebpackMobileProdConfigPartial(this.ngCliProject.root,
appConfig);
this.baseConfig = webpackMerge(this.baseConfig, mobileConfigPartial);
this.prodConfigPartial = webpackMerge(this.prodConfigPartial, mobileProdConfigPartial);
baseConfig = webpackMerge(baseConfig, mobileConfigPartial);
if (this.target == 'production') {
targetConfigPartial = webpackMerge(targetConfigPartial, mobileProdConfigPartial);
}
}

this.generateConfig();
this.config = webpackMerge(
baseConfig,
targetConfigPartial,
typescriptConfigPartial
);
}

generateConfig(): void {
getTargetConfig(projectRoot: string, appConfig: any): any {
switch (this.target) {
case 'development':
this.config = webpackMerge(this.baseConfig, this.devConfigPartial);
break;
return getWebpackDevConfigPartial(projectRoot, appConfig);
case 'production':
this.config = webpackMerge(this.baseConfig, this.prodConfigPartial);
break;
return getWebpackProdConfigPartial(projectRoot, appConfig);
default:
throw new Error("Invalid build target. Only 'development' and 'production' are available.");
}
Expand Down
2 changes: 2 additions & 0 deletions packages/angular-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@angular/platform-browser": "^2.0.0",
"@angular/platform-server": "^2.0.0",
"@angular/tsc-wrapped": "^0.3.0",
"@ngtools/webpack": "latest",
"angular2-template-loader": "^0.5.0",
"awesome-typescript-loader": "^2.2.3",
"chalk": "^1.1.3",
Expand All @@ -53,6 +54,7 @@
"fs.realpath": "^1.0.0",
"glob": "^7.0.3",
"handlebars": "^4.0.5",
"html-loader": "^0.4.4",
"html-webpack-plugin": "^2.19.0",
"istanbul-instrumenter-loader": "^0.2.0",
"json-loader": "^0.5.4",
Expand Down
3 changes: 2 additions & 1 deletion packages/angular-cli/tasks/build-webpack-watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export default Task.extend({
runTaskOptions.target,
runTaskOptions.environment,
runTaskOptions.outputPath,
runTaskOptions.baseHref
runTaskOptions.baseHref,
runTaskOptions.aot
).config;
const webpackCompiler: any = webpack(config);

Expand Down
4 changes: 2 additions & 2 deletions packages/angular-cli/tasks/build-webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ export default <any>Task.extend({

const outputDir = runTaskOptions.outputPath || CliConfig.fromProject().config.apps[0].outDir;
rimraf.sync(path.resolve(project.root, outputDir));

const config = new NgCliWebpackConfig(
project,
runTaskOptions.target,
runTaskOptions.environment,
outputDir,
runTaskOptions.baseHref
runTaskOptions.baseHref,
runTaskOptions.aot
).config;

// fail on build error
Expand Down
8 changes: 6 additions & 2 deletions packages/angular-cli/tasks/serve-webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ export default Task.extend({
let webpackCompiler: any;

let config = new NgCliWebpackConfig(
this.project, commandOptions.target,
commandOptions.environment
this.project,
commandOptions.target,
commandOptions.environment,
undefined,
undefined,
commandOptions.aot
).config;

// This allows for live reload of page when changes are made to repo.
Expand Down
Loading