diff --git a/packages/schematics/angular/library/files/src/__entryFile__.ts.template b/packages/schematics/angular/library/files/src/__entryFile__.ts.template index b4d46cdc0330..d88dc4f34551 100644 --- a/packages/schematics/angular/library/files/src/__entryFile__.ts.template +++ b/packages/schematics/angular/library/files/src/__entryFile__.ts.template @@ -3,5 +3,5 @@ */ export * from './lib/<%= dasherize(name) %>.service'; -export * from './lib/<%= dasherize(name) %>.component'; -export * from './lib/<%= dasherize(name) %>.module'; +export * from './lib/<%= dasherize(name) %>.component';<% if (!standalone) { %> +export * from './lib/<%= dasherize(name) %>.module';<% } %> diff --git a/packages/schematics/angular/library/index.ts b/packages/schematics/angular/library/index.ts index 9101741bdbfd..ffe13689ac80 100644 --- a/packages/schematics/angular/library/index.ts +++ b/packages/schematics/angular/library/index.ts @@ -165,13 +165,15 @@ export default function (options: LibraryOptions): Rule { addLibToWorkspaceFile(options, libDir, packageName), options.skipPackageJson ? noop() : addDependenciesToPackageJson(), options.skipTsConfig ? noop() : updateTsConfig(packageName, distRoot), - schematic('module', { - name: options.name, - commonModule: false, - flat: true, - path: sourceDir, - project: packageName, - }), + options.standalone + ? noop() + : schematic('module', { + name: options.name, + commonModule: false, + flat: true, + path: sourceDir, + project: packageName, + }), schematic('component', { name: options.name, selector: `${prefix}-${options.name}`, @@ -180,6 +182,7 @@ export default function (options: LibraryOptions): Rule { flat: true, path: sourceDir, export: true, + standalone: options.standalone, project: packageName, }), schematic('service', { diff --git a/packages/schematics/angular/library/index_spec.ts b/packages/schematics/angular/library/index_spec.ts index 31eea5d84afc..dcfa251de67b 100644 --- a/packages/schematics/angular/library/index_spec.ts +++ b/packages/schematics/angular/library/index_spec.ts @@ -390,4 +390,51 @@ describe('Library Schematic', () => { '@angular-devkit/build-angular:ng-packagr', ); }); + + describe('standalone', () => { + const defaultStandaloneOptions = { ...defaultOptions, standalone: true }; + + it('should create correct files', async () => { + const tree = await schematicRunner.runSchematic( + 'library', + defaultStandaloneOptions, + workspaceTree, + ); + + const files = tree.files; + expect(files).toEqual( + jasmine.arrayContaining([ + '/projects/foo/ng-package.json', + '/projects/foo/package.json', + '/projects/foo/README.md', + '/projects/foo/tsconfig.lib.json', + '/projects/foo/tsconfig.lib.prod.json', + '/projects/foo/src/my-index.ts', + '/projects/foo/src/lib/foo.component.spec.ts', + '/projects/foo/src/lib/foo.component.ts', + '/projects/foo/src/lib/foo.service.spec.ts', + '/projects/foo/src/lib/foo.service.ts', + ]), + ); + }); + + it('should not add reference to module file in entry-file', async () => { + const tree = await schematicRunner.runSchematic( + 'library', + defaultStandaloneOptions, + workspaceTree, + ); + expect(tree.readContent('/projects/foo/src/my-index.ts')).not.toContain('foo.module'); + }); + + it('should create a standalone component', async () => { + const tree = await schematicRunner.runSchematic( + 'library', + defaultStandaloneOptions, + workspaceTree, + ); + const componentContent = tree.readContent('/projects/foo/src/lib/foo.component.ts'); + expect(componentContent).toContain('standalone: true'); + }); + }); }); diff --git a/packages/schematics/angular/library/schema.json b/packages/schematics/angular/library/schema.json index 95c97f1732d4..4d6638f04937 100644 --- a/packages/schematics/angular/library/schema.json +++ b/packages/schematics/angular/library/schema.json @@ -47,6 +47,12 @@ "projectRoot": { "type": "string", "description": "The root directory of the new library." + }, + "standalone": { + "description": "Creates a library based upon the standalone API, without NgModules.", + "type": "boolean", + "default": false, + "x-user-analytics": "ep.ng_standalone" } }, "required": ["name"] diff --git a/tests/legacy-cli/e2e/tests/generate/library/library-basic.ts b/tests/legacy-cli/e2e/tests/generate/library/library-basic.ts new file mode 100644 index 000000000000..efc74694ea00 --- /dev/null +++ b/tests/legacy-cli/e2e/tests/generate/library/library-basic.ts @@ -0,0 +1,9 @@ +import { ng } from '../../../utils/process'; +import { useCIChrome } from '../../../utils/project'; + +export default async function () { + await ng('generate', 'library', 'lib-ngmodule', '--no-standalone'); + await useCIChrome('lib-ngmodule', 'projects/lib-ngmodule'); + await ng('test', 'lib-ngmodule', '--no-watch'); + await ng('build', 'lib-ngmodule'); +} diff --git a/tests/legacy-cli/e2e/tests/generate/library/library-standalone.ts b/tests/legacy-cli/e2e/tests/generate/library/library-standalone.ts new file mode 100644 index 000000000000..0b9754644bf5 --- /dev/null +++ b/tests/legacy-cli/e2e/tests/generate/library/library-standalone.ts @@ -0,0 +1,9 @@ +import { ng } from '../../../utils/process'; +import { useCIChrome } from '../../../utils/project'; + +export default async function () { + await ng('generate', 'library', 'lib-standalone', '--standalone'); + await useCIChrome('lib-standalone', 'projects/lib-standalone'); + await ng('test', 'lib-standalone', '--no-watch'); + await ng('build', 'lib-standalone'); +}