From 171b5bbc788f589053a1a33e6c761d2e713bb362 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 2 Sep 2020 16:16:10 +0100 Subject: [PATCH] fix(localize): install `@angular/localize` in `devDependencies` by default Previously this package was installed in the default `dependencies` section of `package.json`, but this meant that its dependencies are treated as dependencies of the main project - Babel, for example. Generally, $localize` is not used at runtime - it is compiled out by the translation tooling, so there is no need for it to be a full dependency. This commit changes the default location of the package to be the `devDependencies` section, but gives the user a prompt to choose otherwise. Fixes #38329 --- packages/localize/schematics/ng-add/README.md | 6 ++++- packages/localize/schematics/ng-add/index.ts | 24 +++++++++++++++++++ .../localize/schematics/ng-add/index_spec.ts | 23 ++++++++++++++++++ .../localize/schematics/ng-add/schema.d.ts | 7 ++++++ .../localize/schematics/ng-add/schema.json | 8 +++++-- 5 files changed, 65 insertions(+), 3 deletions(-) diff --git a/packages/localize/schematics/ng-add/README.md b/packages/localize/schematics/ng-add/README.md index e6078ad36ae3c..394ff4ef8a59d 100644 --- a/packages/localize/schematics/ng-add/README.md +++ b/packages/localize/schematics/ng-add/README.md @@ -3,4 +3,8 @@ This schematic will be executed when an Angular CLI user runs `ng add @angular/localize`. It will search their `angular.json` file, and find polyfills and main files for server builders. -Then it will add the `@angular/localize/init` polyfill that `@angular/localize` needs to work. \ No newline at end of file +Then it will add the `@angular/localize/init` polyfill that `@angular/localize` needs to work. + +If the user specifies that they want to use `$localize` at runtime then the dependency will be +added to the `depdendencies` section of `package.json` rather than in the `devDependencies` which +is the default. \ No newline at end of file diff --git a/packages/localize/schematics/ng-add/index.ts b/packages/localize/schematics/ng-add/index.ts index 823c68b0ca8d3..2dbebe97a4b39 100644 --- a/packages/localize/schematics/ng-add/index.ts +++ b/packages/localize/schematics/ng-add/index.ts @@ -10,6 +10,8 @@ import {virtualFs, workspaces} from '@angular-devkit/core'; import {chain, Rule, SchematicsException, Tree} from '@angular-devkit/schematics'; +import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks'; +import {addPackageJsonDependency, NodeDependencyType, removePackageJsonDependency} from '@schematics/angular/utility/dependencies'; import {getWorkspace} from '@schematics/angular/utility/workspace'; import {Builders} from '@schematics/angular/utility/workspace-models'; @@ -95,6 +97,22 @@ function prependToTargetFiles( }; } +function moveToDependencyType(type: NodeDependencyType): Rule { + return (host, context) => { + debugger; + if (host.exists('package.json')) { + // Remove the previous dependency and add in a new one under the desired type. + removePackageJsonDependency(host, '@angular/localize'); + addPackageJsonDependency( + host, {name: '@angular/localize', type, version: `^0.0.0-PLACEHOLDER`}); + + // Add a task to run the package manager. This is necessary because we updated + // "package.json" and we want lock files to reflect this. + context.addTask(new NodePackageInstallTask()); + }; + }; +} + export default function(options: Schema): Rule { return async (host: Tree) => { if (!options.name) { @@ -114,9 +132,15 @@ export default function(options: Schema): Rule { ${localizePolyfill} `; + // If `$localize` will not be used at runtime then we can install `@angular/localize` as a + // devDependency. + const dependencyType = + options.useAtRuntime ? NodeDependencyType.Default : NodeDependencyType.Dev; + return chain([ prependToTargetFiles(project, Builders.Browser, 'polyfills', localizeStr), prependToTargetFiles(project, Builders.Server, 'main', localizeStr), + moveToDependencyType(dependencyType), ]); }; } diff --git a/packages/localize/schematics/ng-add/index_spec.ts b/packages/localize/schematics/ng-add/index_spec.ts index 5f5690f4ffd25..99350e3ee2206 100644 --- a/packages/localize/schematics/ng-add/index_spec.ts +++ b/packages/localize/schematics/ng-add/index_spec.ts @@ -33,6 +33,11 @@ export { renderModule, renderModuleFactory } from '@angular/platform-server';`; beforeEach(() => { host = new UnitTestTree(new HostTree()); + host.create('package.json', `{ + "dependencies": { + "@angular/localize": "old-version" + } + }`); host.create('src/polyfills.ts', polyfillsContent); host.create('src/another-polyfills.ts', polyfillsContent); host.create('src/unrelated-polyfills.ts', polyfillsContent); @@ -166,4 +171,22 @@ export { renderModule, renderModuleFactory } from '@angular/platform-server';`; })); await schematicRunner.runSchematicAsync('ng-add', defaultOptions, host).toPromise(); }); + + it('should add package to `devDependencies` by default', async () => { + host = await schematicRunner.runSchematicAsync('ng-add', defaultOptions, host).toPromise(); + const packageJsonText = host.readContent('/package.json'); + expect(JSON.parse(packageJsonText).devDependencies?.['@angular/localize']) + .toBe('^0.0.0-PLACEHOLDER'); + expect(JSON.parse(packageJsonText).dependencies?.['@angular/localize']).toBeUndefined(); + }); + + it('should add package to `dependencies` if `useAtRuntime` is `true`', async () => { + host = await schematicRunner + .runSchematicAsync('ng-add', {...defaultOptions, useAtRuntime: true}, host) + .toPromise(); + const packageJsonText = host.readContent('/package.json'); + expect(JSON.parse(packageJsonText).dependencies?.['@angular/localize']) + .toBe('^0.0.0-PLACEHOLDER'); + expect(JSON.parse(packageJsonText).devDependencies?.['@angular/localize']).toBeUndefined(); + }); }); diff --git a/packages/localize/schematics/ng-add/schema.d.ts b/packages/localize/schematics/ng-add/schema.d.ts index d7bb6dc32610f..a96090d97e1e5 100644 --- a/packages/localize/schematics/ng-add/schema.d.ts +++ b/packages/localize/schematics/ng-add/schema.d.ts @@ -11,4 +11,11 @@ export interface Schema { * The name of the project. */ name?: string; + /** + * Will this project use $localize at runtime? + * + * If true then the dependency is included in the `dependencies` section of packge.json, rather + * than `devDependencies`. + */ + useAtRuntime?: boolean; } diff --git a/packages/localize/schematics/ng-add/schema.json b/packages/localize/schematics/ng-add/schema.json index 775cbfcb51999..9013d316cbcc7 100644 --- a/packages/localize/schematics/ng-add/schema.json +++ b/packages/localize/schematics/ng-add/schema.json @@ -10,8 +10,12 @@ "$default": { "$source": "projectName" } + }, + "useAtRuntime": { + "type": "boolean", + "description": "If true then the dependency is included in the `dependencies` section of packge.json, rather than `devDependencies`.", + "x-prompt": "Will this project use $localize at runtime?" } }, - "required": [ - ] + "required": [] }