Skip to content

Commit

Permalink
fix(@schematics/angular): add standalone option to library library
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
alan-agius4 committed Apr 25, 2023
1 parent c272172 commit a5cb461
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';<% } %>
17 changes: 10 additions & 7 deletions packages/schematics/angular/library/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand All @@ -180,6 +182,7 @@ export default function (options: LibraryOptions): Rule {
flat: true,
path: sourceDir,
export: true,
standalone: options.standalone,
project: packageName,
}),
schematic('service', {
Expand Down
47 changes: 47 additions & 0 deletions packages/schematics/angular/library/index_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
});
});
});
6 changes: 6 additions & 0 deletions packages/schematics/angular/library/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
9 changes: 9 additions & 0 deletions tests/legacy-cli/e2e/tests/generate/library/library-basic.ts
Original file line number Diff line number Diff line change
@@ -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');
}
Original file line number Diff line number Diff line change
@@ -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');
}

0 comments on commit a5cb461

Please sign in to comment.