-
Notifications
You must be signed in to change notification settings - Fork 12k
fix(@schematics/angular): generate tsconfig.worker.json
outside of …
#14188
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ | |
* 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 | ||
*/ | ||
import { JsonParseMode, parseJsonAst, strings, tags } from '@angular-devkit/core'; | ||
import { JsonParseMode, join, normalize, parseJsonAst, strings, tags } from '@angular-devkit/core'; | ||
import { | ||
Rule, SchematicContext, SchematicsException, Tree, | ||
apply, applyTemplates, chain, mergeWith, move, noop, url, | ||
|
@@ -21,54 +21,16 @@ function addConfig(options: WebWorkerOptions, root: string, tsConfigPath: string | |
return (host: Tree, context: SchematicContext) => { | ||
context.logger.debug('updating project configuration.'); | ||
|
||
const tsConfigRules = []; | ||
|
||
// Add tsconfig.worker.json. | ||
const relativePathToWorkspaceRoot = root.split('/').map(x => '..').join('/'); | ||
tsConfigRules.push(mergeWith(apply(url('./files/worker-tsconfig'), [ | ||
applyTemplates({ ...options, relativePathToWorkspaceRoot }), | ||
move(root), | ||
]))); | ||
|
||
// Add project tsconfig.json. | ||
// The project level tsconfig.json with webworker lib is for editor support since | ||
// the dom and webworker libs are mutually exclusive. | ||
// Note: this schematic does not change other tsconfigs to use the project-level tsconfig. | ||
const projectTsConfigPath = `${root}/tsconfig.json`; | ||
if (host.exists(projectTsConfigPath)) { | ||
// If the file already exists, alter it. | ||
const buffer = host.read(projectTsConfigPath); | ||
if (buffer) { | ||
const tsCfgAst = parseJsonAst(buffer.toString(), JsonParseMode.Loose); | ||
if (tsCfgAst.kind != 'object') { | ||
throw new SchematicsException('Invalid tsconfig. Was expecting an object'); | ||
} | ||
const optsAstNode = findPropertyInAstObject(tsCfgAst, 'compilerOptions'); | ||
if (optsAstNode && optsAstNode.kind != 'object') { | ||
throw new SchematicsException( | ||
'Invalid tsconfig "compilerOptions" property; Was expecting an object.'); | ||
} | ||
const libAstNode = findPropertyInAstObject(tsCfgAst, 'lib'); | ||
if (libAstNode && libAstNode.kind != 'array') { | ||
throw new SchematicsException('Invalid tsconfig "lib" property; expected an array.'); | ||
} | ||
const newLibProp = 'webworker'; | ||
if (libAstNode && !libAstNode.value.includes(newLibProp)) { | ||
const recorder = host.beginUpdate(projectTsConfigPath); | ||
appendValueInAstArray(recorder, libAstNode, newLibProp); | ||
host.commitUpdate(recorder); | ||
} | ||
} | ||
} else { | ||
// Otherwise create it. | ||
tsConfigRules.push(mergeWith(apply(url('./files/project-tsconfig'), [ | ||
applyTemplates({ ...options, relativePathToWorkspaceRoot }), | ||
move(root), | ||
]))); | ||
} | ||
// todo: replace with the new helper method in a seperate PR | ||
// https://github.com/angular/angular-cli/pull/14207 | ||
const rootNormalized = root.endsWith('/') ? root.slice(0, -1) : root; | ||
const relativePathToWorkspaceRoot = | ||
rootNormalized | ||
? rootNormalized.split('/').map(x => '..').join('/') | ||
: '.'; | ||
|
||
// Add worker glob exclusion to tsconfig.app.json. | ||
const workerGlob = '**/*.worker.ts'; | ||
const workerGlob = 'src/**/*.worker.ts'; | ||
const buffer = host.read(tsConfigPath); | ||
if (buffer) { | ||
const tsCfgAst = parseJsonAst(buffer.toString(), JsonParseMode.Loose); | ||
|
@@ -80,17 +42,19 @@ function addConfig(options: WebWorkerOptions, root: string, tsConfigPath: string | |
throw new SchematicsException('Invalid tsconfig "exclude" property; expected an array.'); | ||
} | ||
|
||
if (filesAstNode && filesAstNode.value.indexOf(workerGlob) == -1) { | ||
if (filesAstNode && !filesAstNode.value.includes(workerGlob)) { | ||
const recorder = host.beginUpdate(tsConfigPath); | ||
appendValueInAstArray(recorder, filesAstNode, workerGlob); | ||
host.commitUpdate(recorder); | ||
} | ||
} | ||
|
||
return chain([ | ||
// Add tsconfigs. | ||
...tsConfigRules, | ||
]); | ||
return mergeWith( | ||
apply(url('./files/worker-tsconfig'), [ | ||
applyTemplates({ ...options, relativePathToWorkspaceRoot }), | ||
move(root), | ||
]), | ||
); | ||
}; | ||
} | ||
|
||
|
@@ -145,7 +109,7 @@ export default function (options: WebWorkerOptions): Rule { | |
throw new SchematicsException('Option "project" is required.'); | ||
} | ||
if (!options.target) { | ||
throw new SchematicsException('Option (target) is required.'); | ||
throw new SchematicsException('Option "target" is required.'); | ||
} | ||
|
||
const project = workspace.projects.get(options.project); | ||
|
@@ -169,11 +133,11 @@ export default function (options: WebWorkerOptions): Rule { | |
const parsedPath = parseName(options.path, options.name); | ||
options.name = parsedPath.name; | ||
options.path = parsedPath.path; | ||
const root = project.root || project.sourceRoot || ''; | ||
const root = project.root || ''; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAICT, this raises the following concerns (maybe they are not problems - I am not sure):
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While the first point itself is not a problem per see, the second one might be. Also this might be confusing for users to have multiple tsconfigs though I cannot think of an alternative and place the second tsconfig in the src folder. Ie:
@filipesilva, what are your thoughts about this? I don't think there is much we can do apart from creating the new There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also it seems that this tsconfig https://github.com/alan-agius4/angular-cli/blob/c6315fee4121ed29c7e25496e692cf2cc66ff27e/packages/schematics/angular/web-worker/files/project-tsconfig/tsconfig.json.template has both DOM and webworker. I was under the impression that they are mutually exclusive. Also this config has no include/exclude pattern which means that all Ts files within the project will be included. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also probably the worker tsconfig should inherit from the workspace tsconfig directly and not the ide tsconfig. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The general idea is that there is at least one tsconfig that is called just There are also at least three different known locations for app tsconfigs in the wild:
Also of note is that in CLI 8 the multi-project workspace story is "don't use your current one, but make a new one with The new Compounding on this problem is that So, back to the original questions:
I think the super correct answer to both 1 and 2 is the root This is non trivial and high risk. We don't know what configs inherit from the base one and missing any of them will cause that compilation to fail. Also when making new projects after this change, the new project would also need to know that the base tsconfig has incompatible typings and perform the same change. So the less risky approach is for 1 to be the root Another option is for 1 to be the root There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While for the compilation we do need a separate tsconfig as otherwise we'll get compilation errors like
For IDE support, we can use the triple slash lib reference Such an example is Writing something like: const _self = self; Would result in And hence to have proper typings one needs to explicitly set the type like: const _self: WorkerGlobalScope = self; This is because of what @filipesilva explained above, and the only way I can think to solve this, is that workers, are not created inside the features folders, but rather in a separate folder similar to Ie:
|
||
|
||
const needWebWorkerConfig = !projectTargetOptions.webWorkerTsConfig; | ||
if (needWebWorkerConfig) { | ||
const workerConfigPath = `${root.endsWith('/') ? root : root + '/'}tsconfig.worker.json`; | ||
const workerConfigPath = join(normalize(root), 'tsconfig.worker.json'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't this result in a normalized absolute path? If so, is that intended? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Project root is relative 😊 |
||
projectTargetOptions.webWorkerTsConfig = workerConfigPath; | ||
|
||
// add worker tsconfig to lint architect target | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: this is solely used for IDE purposes.