-
Notifications
You must be signed in to change notification settings - Fork 12k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(@schematics/angular): add optional migration to use application …
…builder This commits adds an optional migration to migration existing projects to use the vite and esbuild based application builder. The migration can be opted-in when running `ng update @angular/cli --name=use-application-builder`
- Loading branch information
1 parent
03985a4
commit b513d89
Showing
28 changed files
with
1,251 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
201 changes: 201 additions & 0 deletions
201
packages/schematics/angular/migrations/update-17/use-application-builder.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC 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 | ||
*/ | ||
|
||
import { workspaces } from '@angular-devkit/core'; | ||
import { | ||
Rule, | ||
SchematicContext, | ||
SchematicsException, | ||
chain, | ||
externalSchematic, | ||
} from '@angular-devkit/schematics'; | ||
import { dirname } from 'node:path'; | ||
import { JSONFile } from '../../utility/json-file'; | ||
import { TreeWorkspaceHost, allTargetOptions, getWorkspace } from '../../utility/workspace'; | ||
import { Builders, ProjectType } from '../../utility/workspace-models'; | ||
|
||
export default function (): Rule { | ||
return async (tree, context) => { | ||
const rules: Rule[] = []; | ||
const workspace = await getWorkspace(tree); | ||
|
||
for (const [name, project] of workspace.projects) { | ||
if (project.extensions.projectType !== ProjectType.Application) { | ||
// Only interested in application projects since these changes only effects application builders | ||
continue; | ||
} | ||
|
||
const buildTarget = project.targets.get('build'); | ||
if (!buildTarget || buildTarget.builder === Builders.Application) { | ||
continue; | ||
} | ||
|
||
if ( | ||
buildTarget.builder !== Builders.BrowserEsbuild && | ||
buildTarget.builder !== Builders.Browser | ||
) { | ||
context.logger.error( | ||
`Cannot update project "${name}" to use the application builder.` + | ||
` Only "${Builders.BrowserEsbuild}" and "${Builders.Browser}" can be automatically migrated.`, | ||
); | ||
|
||
continue; | ||
} | ||
|
||
// Update builder target and options | ||
buildTarget.builder = Builders.Application; | ||
const hasServerTarget = project.targets.has('server'); | ||
|
||
for (const [, options] of allTargetOptions(buildTarget, false)) { | ||
// Show warnings for using no longer supported options | ||
if (usesNoLongerSupportedOptions(options, context, name)) { | ||
continue; | ||
} | ||
|
||
// Rename and transform options | ||
options['browser'] = options['main']; | ||
if (hasServerTarget && typeof options['browser'] === 'string') { | ||
options['server'] = dirname(options['browser']) + '/main.server.ts'; | ||
} | ||
options['serviceWorker'] = options['ngswConfigPath'] ?? options['serviceWorker']; | ||
|
||
if (typeof options['polyfills'] === 'string') { | ||
options['polyfills'] = [options['polyfills']]; | ||
} | ||
|
||
if (typeof options['outputPath'] === 'string') { | ||
options['outputPath'] = options['outputPath']?.replace(/\/browser\/?$/, ''); | ||
} | ||
|
||
// Delete removed options | ||
delete options['deployUrl']; | ||
delete options['vendorChunk']; | ||
delete options['commonChunk']; | ||
delete options['resourcesOutputPath']; | ||
delete options['buildOptimizer']; | ||
delete options['main']; | ||
delete options['ngswConfigPath']; | ||
} | ||
|
||
// Merge browser and server tsconfig | ||
if (hasServerTarget) { | ||
const browserTsConfig = buildTarget?.options?.tsConfig; | ||
const serverTsConfig = project.targets.get('server')?.options?.tsConfig; | ||
|
||
if (typeof browserTsConfig !== 'string') { | ||
throw new SchematicsException( | ||
`Cannot update project "${name}" to use the application builder` + | ||
` as the browser tsconfig cannot be located.`, | ||
); | ||
} | ||
|
||
if (typeof serverTsConfig !== 'string') { | ||
throw new SchematicsException( | ||
`Cannot update project "${name}" to use the application builder` + | ||
` as the server tsconfig cannot be located.`, | ||
); | ||
} | ||
|
||
const browserJson = new JSONFile(tree, browserTsConfig); | ||
const serverJson = new JSONFile(tree, serverTsConfig); | ||
|
||
const filesPath = ['files']; | ||
|
||
const files = new Set([ | ||
...((browserJson.get(filesPath) as string[] | undefined) ?? []), | ||
...((serverJson.get(filesPath) as string[] | undefined) ?? []), | ||
]); | ||
|
||
// Server file will be added later by the means of the ssr schematic. | ||
files.delete('server.ts'); | ||
|
||
browserJson.modify(filesPath, Array.from(files)); | ||
|
||
const typesPath = ['compilerOptions', 'types']; | ||
browserJson.modify( | ||
typesPath, | ||
Array.from( | ||
new Set([ | ||
...((browserJson.get(typesPath) as string[] | undefined) ?? []), | ||
...((serverJson.get(typesPath) as string[] | undefined) ?? []), | ||
]), | ||
), | ||
); | ||
|
||
// Delete server tsconfig | ||
tree.delete(serverTsConfig); | ||
} | ||
|
||
// Update main tsconfig | ||
const rootJson = new JSONFile(tree, 'tsconfig.json'); | ||
rootJson.modify(['compilerOptions', 'esModuleInterop'], true); | ||
rootJson.modify(['compilerOptions', 'downlevelIteration'], undefined); | ||
rootJson.modify(['compilerOptions', 'allowSyntheticDefaultImports'], undefined); | ||
|
||
// Update server file | ||
const ssrMainFile = project.targets.get('server')?.options?.['main']; | ||
if (typeof ssrMainFile === 'string') { | ||
tree.delete(ssrMainFile); | ||
|
||
rules.push( | ||
externalSchematic('@schematics/angular', 'ssr', { | ||
project: name, | ||
skipInstall: true, | ||
}), | ||
); | ||
} | ||
|
||
// Delete package.json helper scripts | ||
const pkgJson = new JSONFile(tree, 'package.json'); | ||
['build:ssr', 'dev:ssr', 'serve:ssr', 'prerender'].forEach((s) => | ||
pkgJson.remove(['scripts', s]), | ||
); | ||
|
||
// Delete all redundant targets | ||
for (const [key, target] of project.targets) { | ||
switch (target.builder) { | ||
case Builders.Server: | ||
case Builders.Prerender: | ||
case Builders.AppShell: | ||
case Builders.SsrDevServer: | ||
project.targets.delete(key); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
// Save workspace changes | ||
await workspaces.writeWorkspace(workspace, new TreeWorkspaceHost(tree)); | ||
|
||
return chain(rules); | ||
}; | ||
} | ||
|
||
function usesNoLongerSupportedOptions( | ||
{ deployUrl, resourcesOutputPath }: Record<string, unknown>, | ||
context: SchematicContext, | ||
projectName: string, | ||
): boolean { | ||
let hasUsage = false; | ||
if (typeof deployUrl === 'string') { | ||
hasUsage = true; | ||
context.logger.warn( | ||
`Skipping migration for project "${projectName}". "deployUrl" option is not available in the application builder.`, | ||
); | ||
} | ||
|
||
if (typeof resourcesOutputPath === 'string' && /^\/?media\/?$/.test(resourcesOutputPath)) { | ||
hasUsage = true; | ||
context.logger.warn( | ||
`Skipping migration for project "${projectName}". "resourcesOutputPath" option is not available in the application builder.` + | ||
`Media files will be output into a "media" directory within the output location.`, | ||
); | ||
} | ||
|
||
return hasUsage; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
tests/legacy-cli/e2e/assets/17-ssr-project-webpack/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# See http://help.github.com/ignore-files/ for more about ignoring files. | ||
|
||
# Compiled output | ||
/dist | ||
/tmp | ||
/out-tsc | ||
/bazel-out | ||
|
||
# Node | ||
/node_modules | ||
npm-debug.log | ||
yarn-error.log | ||
|
||
# IDEs and editors | ||
.idea/ | ||
.project | ||
.classpath | ||
.c9/ | ||
*.launch | ||
.settings/ | ||
*.sublime-workspace | ||
|
||
# Visual Studio Code | ||
.vscode/* | ||
!.vscode/settings.json | ||
!.vscode/tasks.json | ||
!.vscode/launch.json | ||
!.vscode/extensions.json | ||
.history/* | ||
|
||
# Miscellaneous | ||
/.angular/cache | ||
.sass-cache/ | ||
/connect.lock | ||
/coverage | ||
/libpeerconnection.log | ||
testem.log | ||
/typings | ||
|
||
# System files | ||
.DS_Store | ||
Thumbs.db |
27 changes: 27 additions & 0 deletions
27
tests/legacy-cli/e2e/assets/17-ssr-project-webpack/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# 17SsrProjectWebpack | ||
|
||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 16.2.10. | ||
|
||
## Development server | ||
|
||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. | ||
|
||
## Code scaffolding | ||
|
||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. | ||
|
||
## Build | ||
|
||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. | ||
|
||
## Running unit tests | ||
|
||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). | ||
|
||
## Running end-to-end tests | ||
|
||
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. | ||
|
||
## Further help | ||
|
||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. |
Oops, something went wrong.