diff --git a/tools/gulp/packages.ts b/tools/gulp/packages.ts index bf8d61a82..e06b78dba 100644 --- a/tools/gulp/packages.ts +++ b/tools/gulp/packages.ts @@ -5,3 +5,8 @@ export const flexLayoutPackage = new BuildPackage('flex-layout', []); // To avoid refactoring of the project the Flex-Layout package will map to the source path `lib/`. flexLayoutPackage.sourceDir = join(buildConfig.packagesDir, 'lib'); + +// Re-export secondary entry-points at the root. We don't want to require users to add +// UMD bundles for each secondary entry-points. +flexLayoutPackage.exportsSecondaryEntryPointsAtRoot = true; +flexLayoutPackage.exportsSecondaryEntryPointsAtRootExcludes = ['server']; diff --git a/tools/package-tools/build-bundles.ts b/tools/package-tools/build-bundles.ts index a1f46aaa5..b9bb84104 100644 --- a/tools/package-tools/build-bundles.ts +++ b/tools/package-tools/build-bundles.ts @@ -17,7 +17,13 @@ const bundlesDir = join(buildConfig.outputDir, 'bundles'); /** Utility for creating bundles from raw ngc output. */ export class PackageBundler { - constructor(private buildPackage: BuildPackage) {} + + /** Name of the AMD module for the primary entry point of the build package. */ + private readonly primaryAmdModuleName: string; + + constructor(private buildPackage: BuildPackage) { + this.primaryAmdModuleName = this.getAmdModuleName(buildPackage.name); + } /** Creates all bundles for the package and all associated entry points (UMD, ES5, ES2015). */ async createBundles() { @@ -36,7 +42,7 @@ export class PackageBundler { entryFile: this.buildPackage.entryFilePath, esm5EntryFile: join(this.buildPackage.esm5OutputDir, 'index.js'), importName: `@angular/${this.buildPackage.name}`, - moduleName: `ng.${this.buildPackage.name}`, + moduleName: this.primaryAmdModuleName, esm2015Dest: join(bundlesDir, `${packageName}.js`), esm5Dest: join(bundlesDir, `${packageName}.es5.js`), umdDest: join(bundlesDir, `${packageName}.umd.js`), @@ -45,21 +51,20 @@ export class PackageBundler { } /** Bundles a single secondary entry-point w/ given entry file, e.g. @angular/cdk/a11y */ - private async bundleSecondaryEntryPoint(entryPoint: string) { + private async bundleSecondaryEntryPoint(entryPointName: string) { const packageName = this.buildPackage.name; - const entryFile = join(this.buildPackage.outputDir, entryPoint, 'index.js'); - const esm5EntryFile = join(this.buildPackage.esm5OutputDir, entryPoint, 'index.js'); - const dashedEntryName = dashCaseToCamelCase(entryPoint); + const entryFile = join(this.buildPackage.outputDir, entryPointName, 'index.js'); + const esm5EntryFile = join(this.buildPackage.esm5OutputDir, entryPointName, 'index.js'); return this.bundleEntryPoint({ entryFile, esm5EntryFile, - importName: `@angular/${this.buildPackage.name}/${dashedEntryName}`, - moduleName: `ng.${packageName}.${dashedEntryName}`, - esm2015Dest: join(bundlesDir, `${packageName}`, `${entryPoint}.js`), - esm5Dest: join(bundlesDir, `${packageName}`, `${entryPoint}.es5.js`), - umdDest: join(bundlesDir, `${packageName}-${entryPoint}.umd.js`), - umdMinDest: join(bundlesDir, `${packageName}-${entryPoint}.umd.min.js`), + importName: `@angular/${this.buildPackage.name}/${entryPointName}`, + moduleName: this.getAmdModuleName(packageName, entryPointName), + esm2015Dest: join(bundlesDir, `${packageName}`, `${entryPointName}.js`), + esm5Dest: join(bundlesDir, `${packageName}`, `${entryPointName}.es5.js`), + umdDest: join(bundlesDir, `${packageName}-${entryPointName}.umd.js`), + umdMinDest: join(bundlesDir, `${packageName}-${entryPointName}.umd.min.js`), }); } @@ -150,7 +155,7 @@ export class PackageBundler { // secondary entry-points from the rollup globals because we want the UMD for this package // to include *all* of the sources for those entry-points. if (this.buildPackage.exportsSecondaryEntryPointsAtRoot && - config.moduleName === `ng.${this.buildPackage.name}`) { + config.moduleName === this.primaryAmdModuleName) { const importRegex = new RegExp(`@angular/${this.buildPackage.name}/.+`); external = external.filter(e => !importRegex.test(e)); @@ -181,8 +186,18 @@ export class PackageBundler { return map; }, {} as {[key: string]: string}); } -} + /** Gets the AMD module name for a package and an optional entry point. */ + private getAmdModuleName(packageName: string, entryPointName?: string) { + let amdModuleName = `ng.${dashCaseToCamelCase(packageName)}`; + + if (entryPointName) { + amdModuleName += `.${dashCaseToCamelCase(entryPointName)}`; + } + + return amdModuleName; + } +} /** Configuration for creating library bundles. */ interface BundlesConfig { diff --git a/tools/package-tools/build-package.ts b/tools/package-tools/build-package.ts index 7b985a0bd..22931c822 100644 --- a/tools/package-tools/build-package.ts +++ b/tools/package-tools/build-package.ts @@ -29,6 +29,9 @@ export class BuildPackage { /** Whether this package will re-export its secondary-entry points at the root module. */ exportsSecondaryEntryPointsAtRoot = false; + /** List of secondary entry points that should not be re-exported in the primary entry point. */ + exportsSecondaryEntryPointsAtRootExcludes: string[] = []; + /** Whether the secondary entry-point styles should be copied to the release output. */ copySecondaryEntryPointStylesToRoot = false; @@ -52,6 +55,12 @@ export class BuildPackage { } private _secondaryEntryPoints?: string[]; + /** Secondary entry points that should be re-exported in the primary entry point. */ + get reexportedSecondaryEntryPoints(): string[] { + return this.secondaryEntryPoints + .filter(p => !this.exportsSecondaryEntryPointsAtRootExcludes.includes(p)); + } + constructor(readonly name: string, readonly dependencies: BuildPackage[] = []) { this.sourceDir = join(packagesDir, name); this.outputDir = join(outputDir, 'packages', name); diff --git a/tools/package-tools/build-release.ts b/tools/package-tools/build-release.ts index f3fc35f3d..ef3a591dd 100644 --- a/tools/package-tools/build-release.ts +++ b/tools/package-tools/build-release.ts @@ -62,7 +62,7 @@ export function composeRelease(buildPackage: BuildPackage) { if (buildPackage.exportsSecondaryEntryPointsAtRoot) { // Add re-exports to the root d.ts file to prevent errors of the form // "@angular/material/material has no exported member 'MATERIAL_SANITY_CHECKS." - const es2015Exports = buildPackage.secondaryEntryPoints + const es2015Exports = buildPackage.reexportedSecondaryEntryPoints .map(p => `export * from './${p}';`).join('\n'); appendFileSync(join(releasePath, `${name}.d.ts`), es2015Exports, 'utf-8'); @@ -70,7 +70,7 @@ export function composeRelease(buildPackage: BuildPackage) { // re-exports everything. createMetadataReexportFile( releasePath, - buildPackage.secondaryEntryPoints.concat(['typings/index']).map(p => `./${p}`), + buildPackage.reexportedSecondaryEntryPoints.concat(['typings/index']).map(p => `./${p}`), name, importAsName); } diff --git a/tools/package-tools/rollup-globals.ts b/tools/package-tools/rollup-globals.ts index 047a0c61b..26b402c0d 100644 --- a/tools/package-tools/rollup-globals.ts +++ b/tools/package-tools/rollup-globals.ts @@ -12,6 +12,7 @@ const flexLayoutSecondaryEntryPoints = getSubdirectoryNames(join(buildConfig.pac /** Object with all flex layout entry points in the format of Rollup globals. */ const rollupFlexLayoutEntryPoints = flexLayoutSecondaryEntryPoints .reduce((globals: any, entryPoint: string) => { + // Note that this needs to be in sync with the UMD module name format in "build-bundles.ts". globals[`@angular/flex-layout/${entryPoint}`] = `ng.flexLayout.${dashCaseToCamelCase(entryPoint)}`; return globals; @@ -42,6 +43,7 @@ export const rollupGlobals = { '@angular/cdk/platform': 'ng.cdk.platform', // Some packages are not really needed for the UMD bundles, but for the missingRollupGlobals rule. + // Note that this needs to be in sync with the UMD module name format in "build-bundles.ts". '@angular/flex-layout': 'ng.flexLayout', // Include secondary entry-points of the cdk and material packages