diff --git a/packages/angular-cli/lib/config/schema.json b/packages/angular-cli/lib/config/schema.json index e5f28d42b270..3a2a1f02fcc9 100644 --- a/packages/angular-cli/lib/config/schema.json +++ b/packages/angular-cli/lib/config/schema.json @@ -59,7 +59,8 @@ "type": "string" }, "tsconfig": { - "type": "string" + "type": "string", + "default": "tsconfig.json" }, "prefix": { "type": "string" diff --git a/packages/angular-cli/models/json-schema/schema-tree.ts b/packages/angular-cli/models/json-schema/schema-tree.ts index 2dd120a22788..2b80057b6424 100644 --- a/packages/angular-cli/models/json-schema/schema-tree.ts +++ b/packages/angular-cli/models/json-schema/schema-tree.ts @@ -134,9 +134,11 @@ export abstract class NonLeafSchemaTreeNode extends SchemaTreeNode { if (!schema['oneOf']) { type = schema['type']; } else { + let testValue = value || schema['default']; + // Match existing value to one of the schema types for (let testSchema of schema['oneOf']) { - if ((testSchema['type'] === 'array' && Array.isArray(value)) - || typeof value === testSchema['type']) { + if ((testSchema['type'] === 'array' && Array.isArray(testValue)) + || typeof testValue === testSchema['type']) { type = testSchema['type']; schema = testSchema; break; diff --git a/packages/angular-cli/models/webpack-build-common.ts b/packages/angular-cli/models/webpack-build-common.ts index cd0465ea2335..6130f887fbc0 100644 --- a/packages/angular-cli/models/webpack-build-common.ts +++ b/packages/angular-cli/models/webpack-build-common.ts @@ -46,12 +46,8 @@ export function getWebpackCommonConfig( main: [appMain] }; - if (!(environment in appConfig.environments)) { - throw new SilentError(`Environment "${environment}" does not exist.`); - } - // process global scripts - if (appConfig.scripts.length > 0) { + if (appConfig.scripts && appConfig.scripts.length > 0) { const globalScripts = extraEntryParser(appConfig.scripts, appRoot, 'scripts'); // add entry points and lazy chunks @@ -67,7 +63,7 @@ export function getWebpackCommonConfig( } // process global styles - if (appConfig.styles.length === 0) { + if (!appConfig.styles || appConfig.styles.length === 0) { // create css loaders for component css extraRules.push(...makeCssLoaders()); } else { @@ -104,6 +100,33 @@ export function getWebpackCommonConfig( })); } + // process environment file replacement + if (appConfig.environments) { + if (!('source' in appConfig.environments)) { + throw new SilentError(`Environment configuration does not contain "source" entry.`); + } + if (!(environment in appConfig.environments)) { + throw new SilentError(`Environment "${environment}" does not exist.`); + } + + extraPlugins.push(new webpack.NormalModuleReplacementPlugin( + // This plugin is responsible for swapping the environment files. + // Since it takes a RegExp as first parameter, we need to escape the path. + // See https://webpack.github.io/docs/list-of-plugins.html#normalmodulereplacementplugin + new RegExp(path.resolve(appRoot, appConfig.environments['source']) + .replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&')), + path.resolve(appRoot, appConfig.environments[environment]) + )); + } + + // process asset entries + if (appConfig.assets) { + extraPlugins.push(new GlobCopyWebpackPlugin({ + patterns: appConfig.assets, + globOptions: { cwd: appRoot, dot: true, ignore: '**/.gitkeep' } + })); + } + if (progress) { extraPlugins.push(new ProgressPlugin({ profile: verbose, colors: true })); } return { @@ -145,22 +168,10 @@ export function getWebpackCommonConfig( new BaseHrefWebpackPlugin({ baseHref: baseHref }), - new webpack.NormalModuleReplacementPlugin( - // This plugin is responsible for swapping the environment files. - // Since it takes a RegExp as first parameter, we need to escape the path. - // See https://webpack.github.io/docs/list-of-plugins.html#normalmodulereplacementplugin - new RegExp(path.resolve(appRoot, appConfig.environments['source']) - .replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&')), - path.resolve(appRoot, appConfig.environments[environment]) - ), new webpack.optimize.CommonsChunkPlugin({ minChunks: Infinity, name: 'inline' }), - new GlobCopyWebpackPlugin({ - patterns: appConfig.assets, - globOptions: { cwd: appRoot, dot: true, ignore: '**/.gitkeep' } - }), new webpack.LoaderOptionsPlugin({ test: /\.(css|scss|sass|less|styl)$/, options: { diff --git a/packages/angular-cli/models/webpack-build-typescript.ts b/packages/angular-cli/models/webpack-build-typescript.ts index 67940af47ab8..0e7ba7807aa6 100644 --- a/packages/angular-cli/models/webpack-build-typescript.ts +++ b/packages/angular-cli/models/webpack-build-typescript.ts @@ -9,6 +9,8 @@ const webpackLoader: string = g['angularCliIsLocal'] export const getWebpackNonAotConfigPartial = function(projectRoot: string, appConfig: any) { + let exclude = [ '**/*.spec.ts' ]; + if (appConfig.test) { exclude.push(path.join(projectRoot, appConfig.root, appConfig.test)); }; return { module: { rules: [ @@ -23,10 +25,7 @@ export const getWebpackNonAotConfigPartial = function(projectRoot: string, appCo new AotPlugin({ tsConfigPath: path.resolve(projectRoot, appConfig.root, appConfig.tsconfig), mainPath: path.join(projectRoot, appConfig.root, appConfig.main), - exclude: [ - path.join(projectRoot, appConfig.root, appConfig.test), - '**/*.spec.ts' - ], + exclude: exclude, skipCodeGeneration: true }), ] @@ -35,6 +34,8 @@ export const getWebpackNonAotConfigPartial = function(projectRoot: string, appCo export const getWebpackAotConfigPartial = function(projectRoot: string, appConfig: any, i18nFile: string, i18nFormat: string, locale: string) { + let exclude = [ '**/*.spec.ts' ]; + if (appConfig.test) { exclude.push(path.join(projectRoot, appConfig.root, appConfig.test)); }; return { module: { rules: [ @@ -52,10 +53,7 @@ export const getWebpackAotConfigPartial = function(projectRoot: string, appConfi i18nFile: i18nFile, i18nFormat: i18nFormat, locale: locale, - exclude: [ - path.join(projectRoot, appConfig.root, appConfig.test), - '**/*.spec.ts' - ] + exclude: exclude }) ] }; diff --git a/packages/angular-cli/tasks/serve-webpack.ts b/packages/angular-cli/tasks/serve-webpack.ts index 6b491071be97..42fe588e677e 100644 --- a/packages/angular-cli/tasks/serve-webpack.ts +++ b/packages/angular-cli/tasks/serve-webpack.ts @@ -98,7 +98,8 @@ export default Task.extend({ proxy: proxyConfig, compress: serveTaskOptions.target === 'production', watchOptions: { - poll: CliConfig.fromProject().config.defaults.poll + poll: CliConfig.fromProject().config.defaults && + CliConfig.fromProject().config.defaults.poll }, https: serveTaskOptions.ssl }; diff --git a/tests/e2e/tests/misc/minimal-config.ts b/tests/e2e/tests/misc/minimal-config.ts new file mode 100644 index 000000000000..20b8591263c5 --- /dev/null +++ b/tests/e2e/tests/misc/minimal-config.ts @@ -0,0 +1,14 @@ +import { writeFile } from '../../utils/fs'; +import { ng } from '../../utils/process'; + + +export default function () { + return Promise.resolve() + .then(() => writeFile('angular-cli.json', JSON.stringify({ + apps: [{ + root: 'src', + main: 'main.ts' + }] + }))) + .then(() => ng('build')); +}