Skip to content

Commit a5cb461

Browse files
committed
fix(@schematics/angular): add standalone option to library library
This commit fixes an issue were libraries could not be created with standalone APIs. Standalone libraries do not have an an NgModule. When consumed users need to import the needed components, pipes, and directives. It is also recommended not to avoid grouping exports as this typically indicates bad architecture and may also hinder tree-shaking. **Don't** ```ts export const COMPONENTS = [ FooComponent, BarComponent, ] ``` **Do** ```ts export { FooComponent } from './foo/foo.component'; export { BarComponent } from './bar/bar.component'; ``` (cherry picked from commit 0c9d137)
1 parent c272172 commit a5cb461

File tree

6 files changed

+83
-9
lines changed

6 files changed

+83
-9
lines changed

packages/schematics/angular/library/files/src/__entryFile__.ts.template

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
*/
44

55
export * from './lib/<%= dasherize(name) %>.service';
6-
export * from './lib/<%= dasherize(name) %>.component';
7-
export * from './lib/<%= dasherize(name) %>.module';
6+
export * from './lib/<%= dasherize(name) %>.component';<% if (!standalone) { %>
7+
export * from './lib/<%= dasherize(name) %>.module';<% } %>

packages/schematics/angular/library/index.ts

+10-7
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,15 @@ export default function (options: LibraryOptions): Rule {
165165
addLibToWorkspaceFile(options, libDir, packageName),
166166
options.skipPackageJson ? noop() : addDependenciesToPackageJson(),
167167
options.skipTsConfig ? noop() : updateTsConfig(packageName, distRoot),
168-
schematic('module', {
169-
name: options.name,
170-
commonModule: false,
171-
flat: true,
172-
path: sourceDir,
173-
project: packageName,
174-
}),
168+
options.standalone
169+
? noop()
170+
: schematic('module', {
171+
name: options.name,
172+
commonModule: false,
173+
flat: true,
174+
path: sourceDir,
175+
project: packageName,
176+
}),
175177
schematic('component', {
176178
name: options.name,
177179
selector: `${prefix}-${options.name}`,
@@ -180,6 +182,7 @@ export default function (options: LibraryOptions): Rule {
180182
flat: true,
181183
path: sourceDir,
182184
export: true,
185+
standalone: options.standalone,
183186
project: packageName,
184187
}),
185188
schematic('service', {

packages/schematics/angular/library/index_spec.ts

+47
Original file line numberDiff line numberDiff line change
@@ -390,4 +390,51 @@ describe('Library Schematic', () => {
390390
'@angular-devkit/build-angular:ng-packagr',
391391
);
392392
});
393+
394+
describe('standalone', () => {
395+
const defaultStandaloneOptions = { ...defaultOptions, standalone: true };
396+
397+
it('should create correct files', async () => {
398+
const tree = await schematicRunner.runSchematic(
399+
'library',
400+
defaultStandaloneOptions,
401+
workspaceTree,
402+
);
403+
404+
const files = tree.files;
405+
expect(files).toEqual(
406+
jasmine.arrayContaining([
407+
'/projects/foo/ng-package.json',
408+
'/projects/foo/package.json',
409+
'/projects/foo/README.md',
410+
'/projects/foo/tsconfig.lib.json',
411+
'/projects/foo/tsconfig.lib.prod.json',
412+
'/projects/foo/src/my-index.ts',
413+
'/projects/foo/src/lib/foo.component.spec.ts',
414+
'/projects/foo/src/lib/foo.component.ts',
415+
'/projects/foo/src/lib/foo.service.spec.ts',
416+
'/projects/foo/src/lib/foo.service.ts',
417+
]),
418+
);
419+
});
420+
421+
it('should not add reference to module file in entry-file', async () => {
422+
const tree = await schematicRunner.runSchematic(
423+
'library',
424+
defaultStandaloneOptions,
425+
workspaceTree,
426+
);
427+
expect(tree.readContent('/projects/foo/src/my-index.ts')).not.toContain('foo.module');
428+
});
429+
430+
it('should create a standalone component', async () => {
431+
const tree = await schematicRunner.runSchematic(
432+
'library',
433+
defaultStandaloneOptions,
434+
workspaceTree,
435+
);
436+
const componentContent = tree.readContent('/projects/foo/src/lib/foo.component.ts');
437+
expect(componentContent).toContain('standalone: true');
438+
});
439+
});
393440
});

packages/schematics/angular/library/schema.json

+6
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747
"projectRoot": {
4848
"type": "string",
4949
"description": "The root directory of the new library."
50+
},
51+
"standalone": {
52+
"description": "Creates a library based upon the standalone API, without NgModules.",
53+
"type": "boolean",
54+
"default": false,
55+
"x-user-analytics": "ep.ng_standalone"
5056
}
5157
},
5258
"required": ["name"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { ng } from '../../../utils/process';
2+
import { useCIChrome } from '../../../utils/project';
3+
4+
export default async function () {
5+
await ng('generate', 'library', 'lib-ngmodule', '--no-standalone');
6+
await useCIChrome('lib-ngmodule', 'projects/lib-ngmodule');
7+
await ng('test', 'lib-ngmodule', '--no-watch');
8+
await ng('build', 'lib-ngmodule');
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { ng } from '../../../utils/process';
2+
import { useCIChrome } from '../../../utils/project';
3+
4+
export default async function () {
5+
await ng('generate', 'library', 'lib-standalone', '--standalone');
6+
await useCIChrome('lib-standalone', 'projects/lib-standalone');
7+
await ng('test', 'lib-standalone', '--no-watch');
8+
await ng('build', 'lib-standalone');
9+
}

0 commit comments

Comments
 (0)