diff --git a/sample/angular.json b/sample/angular.json index 81178df28..bd7dc84a9 100644 --- a/sample/angular.json +++ b/sample/angular.json @@ -129,37 +129,7 @@ "main": "server.ts", "tsConfig": "tsconfig.server.json", "bundleDependencies": true, - "externalDependencies": [ - "firebase", - "@firebase/analytics", - "@firebase/analytics-types", - "@firebase/app", - "@firebase/app-types", - "@firebase/auth", - "@firebase/auth-interop-types", - "@firebase/auth-types", - "@firebase/component", - "@firebase/database", - "@firebase/database-types", - "@firebase/firestore", - "@firebase/firestore-types", - "@firebase/functions", - "@firebase/functions-types", - "@firebase/installations", - "@firebase/installations-types", - "@firebase/logger", - "@firebase/messaging", - "@firebase/messaging-types", - "@firebase/performance", - "@firebase/performance-types", - "@firebase/polyfill", - "@firebase/remote-config", - "@firebase/remote-config-types", - "@firebase/storage", - "@firebase/storage-types", - "@firebase/util", - "@firebase/webchannel-wrapper" - ] + "externalDependencies": [ ] }, "configurations": { "production": { diff --git a/sample/firebase.json b/sample/firebase.json index 0ab55f5ae..65ed0707c 100644 --- a/sample/firebase.json +++ b/sample/firebase.json @@ -15,6 +15,14 @@ "value": "public,max-age=31536000,immutable" } ] + }, { + "source": "*-sw.js", + "headers": [ + { + "key": "Cache-Control", + "value": "no-cache" + } + ] } ], "rewrites": [ @@ -26,7 +34,7 @@ } ], "functions": { - "source": "functions" + "source": "dist/sample" }, "emulators": { "functions": { diff --git a/sample/firestore-protos.ts b/sample/firestore-protos.ts new file mode 100644 index 000000000..3ce361529 --- /dev/null +++ b/sample/firestore-protos.ts @@ -0,0 +1,8 @@ +module.exports = { + path: './node_modules/@firebase/firestore/dist/src/protos', + filter: /\.proto$/, + pathTransform: (path: string) => { + const name = path.split('./node_modules/@firebase/firestore/dist/')[1]; + return `file-loader?name=${name}!${path}`; + } +}; diff --git a/sample/package.json b/sample/package.json index dd5383d56..bc0b2860f 100644 --- a/sample/package.json +++ b/sample/package.json @@ -50,6 +50,7 @@ "@types/jasminewd2": "~2.0.3", "codelyzer": "^6.0.0", "concurrently": "^5.3.0", + "dir-loader": "^0.3.0", "express": "^4.17.1", "express-serve-static-core": "^0.1.1", "firebase-admin": "^8.13.0", diff --git a/sample/server.ts b/sample/server.ts index c59772b10..a82723a8c 100644 --- a/sample/server.ts +++ b/sample/server.ts @@ -4,7 +4,7 @@ import { ngExpressEngine } from '@nguniversal/express-engine'; import * as express from 'express'; import { join } from 'path'; -import { AppServerModule } from './src/main.server'; +import { AppServerModule, } from './src/main.server'; import { APP_BASE_HREF } from '@angular/common'; import { existsSync } from 'fs'; @@ -14,6 +14,9 @@ global['XMLHttpRequest'] = require('xhr2'); global['WebSocket'] = require('ws'); /* tslint:enable:no-string-literal */ +// include the protos required to bundle firestore +import 'dir-loader!./firestore-protos'; + // The Express app is exported so that it can be used by serverless Functions. export function app() { const server = express(); @@ -22,7 +25,7 @@ export function app() { // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine) server.engine('html', ngExpressEngine({ - bootstrap: AppServerModule, + bootstrap: AppServerModule })); server.set('view engine', 'html'); diff --git a/sample/src/app/app-routing.module.ts b/sample/src/app/app-routing.module.ts index e3eeded12..750e62d3c 100644 --- a/sample/src/app/app-routing.module.ts +++ b/sample/src/app/app-routing.module.ts @@ -2,14 +2,15 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { ProtectedComponent } from './protected/protected.component'; -import { AngularFireAuthGuard } from '@angular/fire/auth-guard'; +import { AngularFireAuthGuard, canActivate, isNotAnonymous } from '@angular/fire/auth-guard'; import { SecondaryComponent } from './secondary/secondary.component'; const routes: Routes = [ - { path: '', component: HomeComponent, outlet: 'primary' }, - { path: '', component: SecondaryComponent, outlet: 'secondary' }, - { path: '', component: SecondaryComponent, outlet: 'tertiary' }, + { path: '', component: HomeComponent, outlet: 'primary', pathMatch: 'prefix' }, + { path: '', component: SecondaryComponent, outlet: 'secondary', pathMatch: 'prefix' }, + { path: '', component: SecondaryComponent, outlet: 'tertiary', pathMatch: 'prefix' }, { path: 'protected', component: ProtectedComponent, canActivate: [AngularFireAuthGuard] }, + { path: 'lazy', loadChildren: () => import('./protected-lazy/protected-lazy.module').then(m => m.ProtectedLazyModule) }, { path: 'protected-lazy', loadChildren: () => import('./protected-lazy/protected-lazy.module').then(m => m.ProtectedLazyModule), canActivate: [AngularFireAuthGuard] }, @@ -17,7 +18,7 @@ const routes: Routes = [ { path: 'protected', component: ProtectedComponent, canActivate: [AngularFireAuthGuard], outlet: 'tertiary' }, { path: 'protected-lazy', loadChildren: () => import('./protected-lazy/protected-lazy.module').then(m => m.ProtectedLazyModule), - canActivate: [AngularFireAuthGuard], + ...canActivate(() => isNotAnonymous), outlet: 'secondary' }, ]; diff --git a/sample/src/app/app.component.ts b/sample/src/app/app.component.ts index dbe6cbc6c..9b6ffc97c 100644 --- a/sample/src/app/app.component.ts +++ b/sample/src/app/app.component.ts @@ -4,11 +4,21 @@ import { FirebaseApp } from '@angular/fire'; @Component({ selector: 'app-root', template: ` - Home | Protected | Protected Lazy | Protected Lazy Deep | Protected Lazy Deep +
protected-lazy works!
+lazy works!
secondary works!
+I'm another outlet!
diff --git a/sample/tsconfig.server.json b/sample/tsconfig.server.json index 4383fc80f..4b6cf6c42 100644 --- a/sample/tsconfig.server.json +++ b/sample/tsconfig.server.json @@ -10,7 +10,8 @@ }, "files": [ "src/main.server.ts", - "server.ts" + "server.ts", + "firestore-protos.ts" ], "angularCompilerOptions": { "entryModule": "./src/app/app.server.module#AppServerModule" diff --git a/sample/yarn.lock b/sample/yarn.lock index a91db3508..e4f5c774c 100644 --- a/sample/yarn.lock +++ b/sample/yarn.lock @@ -230,7 +230,7 @@ tslib "^2.0.0" "@angular/fire@../dist/packages-dist": - version "6.1.0" + version "6.1.1" dependencies: tslib "^2.0.0" @@ -2890,6 +2890,11 @@ big-integer@^1.6.17: resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e" integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w== +big.js@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" + integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -4728,6 +4733,14 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +dir-loader@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/dir-loader/-/dir-loader-0.3.0.tgz#715b4a129a34e8e371c533625f3d7dc8428f2abe" + integrity sha1-cVtKEpo06ONxxTNiXz19yEKPKr4= + dependencies: + loader-utils "^0.2.9" + object-assign "^4.0.1" + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -7562,6 +7575,11 @@ json3@^3.3.2: resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== +json5@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -7897,6 +7915,16 @@ loader-utils@2.0.0, loader-utils@^2.0.0: emojis-list "^3.0.0" json5 "^2.1.2" +loader-utils@^0.2.9: + version "0.2.17" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" diff --git a/src/auth/public_api.ts b/src/auth/public_api.ts index f570236a4..bc441937a 100644 --- a/src/auth/public_api.ts +++ b/src/auth/public_api.ts @@ -1,2 +1,5 @@ + +import 'firebase/auth'; // removed in build process when not UMD + export * from './auth'; export * from './auth.module'; diff --git a/src/firestore/firestore.ts b/src/firestore/firestore.ts index 4d7a9b974..cbf68b8cb 100644 --- a/src/firestore/firestore.ts +++ b/src/firestore/firestore.ts @@ -24,8 +24,8 @@ import { FirebaseApp } from '@angular/fire'; import { isPlatformServer } from '@angular/common'; -import 'firebase/firestore'; import firebase from 'firebase/app'; +import 'firebase/firestore'; import { USE_EMULATOR as USE_AUTH_EMULATOR } from '@angular/fire/auth'; import { ɵfetchInstance, ɵlogAuthEmulatorError } from '@angular/fire'; diff --git a/src/functions/public_api.ts b/src/functions/public_api.ts index ebea7ec53..1c3bb1655 100644 --- a/src/functions/public_api.ts +++ b/src/functions/public_api.ts @@ -1,2 +1,5 @@ + +import 'firebase/functions'; // removed in build process when not UMD + export * from './functions'; export * from './functions.module'; diff --git a/tools/build.ts b/tools/build.ts index 93149fc5e..b7cf5e0d0 100644 --- a/tools/build.ts +++ b/tools/build.ts @@ -94,6 +94,28 @@ async function measure(module: string) { return { size, gzip }; } +async function fixImportForLazyModules() { + await Promise.all(LAZY_MODULES.map(async module => { + const packageJson = JSON.parse((await readFile(dest(module, 'package.json'))).toString()); + const entries = Array.from(new Set(Object.values(packageJson).filter(v => typeof v === 'string' && v.endsWith('.js')))) as string[]; + // TODO don't hardcode esm2015 here, perhaps we should scan all the entry directories + // e.g, if ng-packagr starts building other non-flattened entries we'll lose the dynamic import + entries.push(`../esm2015/${module}/public_api.js`); // the import isn't pulled into the ESM public_api + await Promise.all(entries.map(async path => { + const source = (await readFile(dest(module, path))).toString(); + let newSource: string; + if (path.endsWith('.umd.js')) { + // in the UMD for lazy modules replace the dyanamic import + newSource = source.replace(`import('firebase/${module}')`, 'rxjs.of(undefined)'); + } else { + // in everything else get rid of the global side-effect import + newSource = source.replace(new RegExp(`^import 'firebase/${module}'.+$`, 'gm'), ''); + } + await writeFile(dest(module, path), newSource); + })); + })); +} + async function buildLibrary() { await proxyPolyfillCompat(); await spawnPromise('npx', ['ng', 'build']); @@ -103,7 +125,8 @@ async function buildLibrary() { copy(join(process.cwd(), 'docs'), dest('docs')), compileSchematics(), replacePackageJsonVersions(), - replacePackageCoreVersion() + replacePackageCoreVersion(), + fixImportForLazyModules(), ]); }