I have an Angular 2 app I've dusted off and am wanting to fix some performance issues. I added webpack and webpack-cli to my package.json file using npm install. However when I run:
npm install
I get the following error message:
An unhandled exception occurred: No projects support the 'build' target, and the project name is 'undefined'. See "C:\Users\cmazz\AppData\Local\Temp\ng-sQvx2f\angular-errors.log" for further details.
angular-errors.log
[error] Error: No projects support the 'build' target.
at BuildCommand.initialize (C:\Users\cmazz\Sites\base-angular-app\node_modules\@angular\cli\models\architect-command.js:58:19)
at async BuildCommand.validateAndRun (C:\Users\cmazz\Sites\base-angular-app\node_modules\@angular\cli\models\command.js:127:9)
at async Object.runCommand (C:\Users\cmazz\Sites\base-angular-app\node_modules\@angular\cli\models\command-runner.js:204:24)
at async default_1 (C:\Users\cmazz\Sites\base-angular-app\node_modules\@angular\cli\lib\cli\index.js:80:31)
architecht-command.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArchitectCommand = void 0;
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const architect_1 = require("@angular-devkit/architect");
const node_1 = require("@angular-devkit/architect/node");
const core_1 = require("@angular-devkit/core");
const json_schema_1 = require("../utilities/json-schema");
const analytics_1 = require("./analytics");
const command_1 = require("./command");
const parser_1 = require("./parser");
class ArchitectCommand extends command_1.Command {
constructor() {
super(...arguments);
this.useReportAnalytics = false;
// If this command supports running multiple targets.
this.multiTarget = false;
}
async initialize(options) {
await super.initialize(options);
this._registry = new core_1.json.schema.CoreSchemaRegistry();
this._registry.addPostTransform(core_1.json.schema.transforms.addUndefinedDefaults);
this._registry.useXDeprecatedProvider(msg => this.logger.warn(msg));
if (!this.workspace) {
throw new Error('A workspace is required for an architect command.');
}
this._architectHost = new node_1.WorkspaceNodeModulesArchitectHost(this.workspace, this.workspace.basePath);
this._architect = new architect_1.Architect(this._architectHost, this._registry);
if (!this.target) {
if (options.help) {
// This is a special case where we just return.
return;
}
const specifier = this._makeTargetSpecifier(options);
if (!specifier.project || !specifier.target) {
throw new Error('Cannot determine project or target for command.');
}
return;
}
let projectName = options.project;
if (projectName && !this.workspace.projects.has(projectName)) {
throw new Error(`Project '${projectName}' does not exist.`);
}
const commandLeftovers = options['--'];
const targetProjectNames = [];
for (const [name, project] of this.workspace.projects) {
if (project.targets.has(this.target)) {
targetProjectNames.push(name);
}
}
if (targetProjectNames.length === 0) {
throw new Error(this.missingTargetError || `No projects support the '${this.target}' target, and the project name is '${projectName}'` );
}
if (projectName && !targetProjectNames.includes(projectName)) {
throw new Error(this.missingTargetError ||
`Project '${projectName}' does not support the '${this.target}' target.`);
}
if (!projectName && commandLeftovers && commandLeftovers.length > 0) {
const builderNames = new Set();
const leftoverMap = new Map();
let potentialProjectNames = new Set(targetProjectNames);
for (const name of targetProjectNames) {
const builderName = await this._architectHost.getBuilderNameForTarget({
project: name,
target: this.target,
});
if (this.multiTarget) {
builderNames.add(builderName);
}
const builderDesc = await this._architectHost.resolveBuilder(builderName);
const optionDefs = await json_schema_1.parseJsonSchemaToOptions(this._registry, builderDesc.optionSchema);
const parsedOptions = parser_1.parseArguments([...commandLeftovers], optionDefs);
const builderLeftovers = parsedOptions['--'] || [];
leftoverMap.set(name, { optionDefs, parsedOptions });
potentialProjectNames = new Set(builderLeftovers.filter(x => potentialProjectNames.has(x)));
}
if (potentialProjectNames.size === 1) {
projectName = [...potentialProjectNames][0];
// remove the project name from the leftovers
const optionInfo = leftoverMap.get(projectName);
if (optionInfo) {
const locations = [];
let i = 0;
while (i < commandLeftovers.length) {
i = commandLeftovers.indexOf(projectName, i + 1);
if (i === -1) {
break;
}
locations.push(i);
}
delete optionInfo.parsedOptions['--'];
for (const location of locations) {
const tempLeftovers = [...commandLeftovers];
tempLeftovers.splice(location, 1);
const tempArgs = parser_1.parseArguments([...tempLeftovers], optionInfo.optionDefs);
delete tempArgs['--'];
if (JSON.stringify(optionInfo.parsedOptions) === JSON.stringify(tempArgs)) {
options['--'] = tempLeftovers;
break;
}
}
}
}
if (!projectName && this.multiTarget && builderNames.size > 1) {
throw new Error(core_1.tags.oneLine `
Architect commands with command line overrides cannot target different builders. The
'${this.target}' target would run on projects ${targetProjectNames.join()} which have the
following builders: ${'\n ' + [...builderNames].join('\n ')}
`);
}
}
if (!projectName && !this.multiTarget) {
const defaultProjectName = this.workspace.extensions['defaultProject'];
if (targetProjectNames.length === 1) {
projectName = targetProjectNames[0];
}
else if (defaultProjectName && targetProjectNames.includes(defaultProjectName)) {
projectName = defaultProjectName;
}
else if (options.help) {
// This is a special case where we just return.
return;
}
else {
throw new Error(this.missingTargetError || 'Cannot determine project or target for command.');
}
}
options.project = projectName;
const builderConf = await this._architectHost.getBuilderNameForTarget({
project: projectName || (targetProjectNames.length > 0 ? targetProjectNames[0] : ''),
target: this.target,
});
const builderDesc = await this._architectHost.resolveBuilder(builderConf);
this.description.options.push(...(await json_schema_1.parseJsonSchemaToOptions(this._registry, builderDesc.optionSchema)));
// Update options to remove analytics from options if the builder isn't safelisted.
for (const o of this.description.options) {
if (o.userAnalytics && !analytics_1.isPackageNameSafeForAnalytics(builderConf)) {
o.userAnalytics = undefined;
}
}
}
async run(options) {
return await this.runArchitectTarget(options);
}
async runSingleTarget(target, targetOptions) {
// We need to build the builderSpec twice because architect does not understand
// overrides separately (getting the configuration builds the whole project, including
// overrides).
const builderConf = await this._architectHost.getBuilderNameForTarget(target);
const builderDesc = await this._architectHost.resolveBuilder(builderConf);
const targetOptionArray = await json_schema_1.parseJsonSchemaToOptions(this._registry, builderDesc.optionSchema);
const overrides = parser_1.parseArguments(targetOptions, targetOptionArray, this.logger);
const allowAdditionalProperties = typeof builderDesc.optionSchema === 'object' && builderDesc.optionSchema.additionalProperties;
if (overrides['--'] && !allowAdditionalProperties) {
(overrides['--'] || []).forEach(additional => {
this.logger.fatal(`Unknown option: '${additional.split(/=/)[0]}'`);
});
return 1;
}
await this.reportAnalytics([this.description.name], {
...await this._architectHost.getOptionsForTarget(target),
...overrides,
});
const run = await this._architect.scheduleTarget(target, overrides, {
logger: this.logger,
analytics: analytics_1.isPackageNameSafeForAnalytics(builderConf) ? this.analytics : undefined,
});
const { error, success } = await run.output.toPromise();
await run.stop();
if (error) {
this.logger.error(error);
}
return success ? 0 : 1;
}
async runArchitectTarget(options) {
const extra = options['--'] || [];
try {
const targetSpec = this._makeTargetSpecifier(options);
if (!targetSpec.project && this.target) {
// This runs each target sequentially.
// Running them in parallel would jumble the log messages.
let result = 0;
for (const project of this.getProjectNamesByTarget(this.target)) {
result |= await this.runSingleTarget({ ...targetSpec, project }, extra);
}
return result;
}
else {
return await this.runSingleTarget(targetSpec, extra);
}
}
catch (e) {
if (e instanceof core_1.schema.SchemaValidationException) {
const newErrors = [];
for (const schemaError of e.errors) {
if (schemaError.keyword === 'additionalProperties') {
const unknownProperty = schemaError.params.additionalProperty;
if (unknownProperty in options) {
const dashes = unknownProperty.length === 1 ? '-' : '--';
this.logger.fatal(`Unknown option: '${dashes}${unknownProperty}'`);
continue;
}
}
newErrors.push(schemaError);
}
if (newErrors.length > 0) {
this.logger.error(new core_1.schema.SchemaValidationException(newErrors).message);
}
return 1;
}
else {
throw e;
}
}
}
getProjectNamesByTarget(targetName) {
const allProjectsForTargetName = [];
// tslint:disable-next-line: no-non-null-assertion
for (const [name, project] of this.workspace.projects) {
if (project.targets.has(targetName)) {
allProjectsForTargetName.push(name);
}
}
if (this.multiTarget) {
// For multi target commands, we always list all projects that have the target.
return allProjectsForTargetName;
}
else {
// For single target commands, we try the default project first,
// then the full list if it has a single project, then error out.
// tslint:disable-next-line: no-non-null-assertion
const maybeDefaultProject = this.workspace.extensions['defaultProject'];
if (maybeDefaultProject && allProjectsForTargetName.includes(maybeDefaultProject)) {
return [maybeDefaultProject];
}
if (allProjectsForTargetName.length === 1) {
return allProjectsForTargetName;
}
throw new Error(`Could not determine a single project for the '${targetName}' target.`);
}
}
_makeTargetSpecifier(commandOptions) {
let project, target, configuration;
if (commandOptions.target) {
[project, target, configuration] = commandOptions.target.split(':');
if (commandOptions.configuration) {
configuration = commandOptions.configuration;
}
}
else {
project = commandOptions.project;
target = this.target;
if (commandOptions.prod) {
// The --prod flag will always be the first configuration, available to be overwritten
// by following configurations.
configuration = 'production';
}
if (commandOptions.configuration) {
configuration =
`${configuration ? `${configuration},` : ''}${commandOptions.configuration}`;
}
}
if (!project) {
project = '';
}
if (!target) {
target = '';
}
return {
project,
configuration: configuration || '',
target,
};
}
}
exports.ArchitectCommand = ArchitectCommand;
angular-cli.json
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
"name": "blogapp"
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico"
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.css"
],
"scripts": [],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"lint": [
{
"project": "src/tsconfig.app.json"
},
{
"project": "src/tsconfig.spec.json"
},
{
"project": "e2e/tsconfig.e2e.json"
}
],
"test": {
"karma": {
"config": "./karma.conf.js"
}
},
"defaults": {
"styleExt": "css",
"component": {}
}
}
Does anyone know the problem here? I'd appreciate it. Ironman