Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

SSR Angular Universal 12 and Firebase troubles #2877

johanchouquet started this conversation in General
Discussion options

Hi everyone,

Not sure if this is a bug for AngularFire to be honest, but this might be the case so, here it is.

I have an app which i could deploy with Angular 11 and Firebase.
I had to put in place the solution with protos described in #2686.
As you can see, the firestore-protos.ts file returns file-loader?name=..., which is a command for webpack 4, with the loader file-loader.

But, in Angular 12, webpack 4 is gone, and we have webpack 5 support, awesome! But, the solution with dir-loader!./firestore-protos simply doesn't work any more.

1st encountered issue:

I get this error:

./node_modules/dir-loader/index.js!./apps/website/firestore-protos.ts - Error: Module build failed (from ./node_modules/dir-loader/index.js):
TypeError: this.exec is not a function
 at Object.module.exports (C:\Users\jct\code00円-wekicards\wekicards\node_modules\dir-loader\index.js:10:22)

And the line in the dir-loader lib:

var options = this.exec(source, this.resource);

So, I've been looking for a solution for quite some time now and I really can't find anything on the subject.

I saw that in the sample app example from angularfire repo, @jamesdaniels removed the use of dir-loader, which seems a good option indeed.
What's the best workaround to do the same thing as the couple [dir-loader / file-loader] to load firestore protos ?

2nd encountered issue:

I also tried to just remove the use of dir-loader by adding a list of externalDependencies in the angular.json file, just like this:

"externalDependencies": [
 "firebase",
 "@firebase/app",
 "@firebase/firestore",
 "@firebase/analytics",
 "@firebase/auth",
 "@firebase/functions",
 "@firebase/installations",
 "@firebase/messaging",
 "@firebase/storage",
 "@firebase/performance",
 "@firebase/remote-config",
 "@firebase/util"
],

But when I try this, I get another error when building my cloud function (well, it's more a Warning at first, but later on deployment it turns into an error):

WARNING in ./apps/functions/dist/website/server/fr/main.js 91:90
Module parse failed: The keyword 'let' is reserved (91:90)
File was processed with these loaders:
 * ./node_modules/ts-loader/index.js
You may need an additional loader to handle the result of these loaders.
| constructor() { super(...arguments), this.overrides = { pinch: { enable: !1 }, rotate: { enable: !1 } }; } 
| }
> exports.MyHammerConfig = MyHammerConfig, MyHammerConfig.\u0275fac = function () { let \u0275MyHammerConfig_BaseFactory; return function MyHammerConfig_Factory(t) { return (\u0275MyHammerConfig_BaseFactory || (\u0275MyHammerConfig_BaseFactory = 
i0.\u0275\u0275getInheritedFactory(MyHammerConfig)))(t || MyHammerConfig); }; }(), MyHammerConfig.\u0275prov = i0.\u0275\u0275defineInjectable({ token: MyHammerConfig, factory: MyHammerConfig.\u0275fac });
| const customConfig = { include: ["facebook", "twitter", "whatsapp", "linkedin", "email", "sms"], gaTracking: !0, sharerMethod: ngx_sharebuttons_1.SharerMethod.Window };
| class AppModule {
WARNING in ./apps/functions/dist/website/server/en/main.js 91:90
Module parse failed: The keyword 'let' is reserved (91:90)
File was processed with these loaders:
 * ./node_modules/ts-loader/index.js
You may need an additional loader to handle the result of these loaders.
| constructor() { super(...arguments), this.overrides = { pinch: { enable: !1 }, rotate: { enable: !1 } }; } 
| }
> exports.MyHammerConfig = MyHammerConfig, MyHammerConfig.\u0275fac = function () { let \u0275MyHammerConfig_BaseFactory; return function MyHammerConfig_Factory(t) { return (\u0275MyHammerConfig_BaseFactory || (\u0275MyHammerConfig_BaseFactory = 
i0.\u0275\u0275getInheritedFactory(MyHammerConfig)))(t || MyHammerConfig); }; }(), MyHammerConfig.\u0275prov = i0.\u0275\u0275defineInjectable({ token: MyHammerConfig, factory: MyHammerConfig.\u0275fac });
| const customConfig = { include: ["facebook", "twitter", "whatsapp", "linkedin", "email", "sms"], gaTracking: !0, sharerMethod: ngx_sharebuttons_1.SharerMethod.Window };
| class AppModule {
! functions: package.json indicates an outdated version of firebase-functions.
Please upgrade using npm install --save firebase-functions@latest in your functions directory.
=== Deploying to 'myproject-staging'...
i deploying functions
+ functions: Finished running predeploy script.
i functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i functions: ensuring required API cloudbuild.googleapis.com is enabled...
+ functions: required API cloudbuild.googleapis.com is enabled
+ functions: required API cloudfunctions.googleapis.com is enabled
i functions: preparing / directory for uploading...
Error: Error occurred while parsing your function triggers.
Error: Module parse failed: The keyword 'let' is reserved (91:90)
File was processed with these loaders:
 * ./node_modules/ts-loader/index.js
You may need an additional loader to handle the result of these loaders.
| constructor() { super(...arguments), this.overrides = { pinch: { enable: !1 }, rotate: { enable: !1 } }; } 
| }
> exports.MyHammerConfig = MyHammerConfig, MyHammerConfig.\u0275fac = function () { let \u0275MyHammerConfig_BaseFactory; return function MyHammerConfig_Factory(t) { return (\u0275MyHammerConfig_BaseFactory || (\u0275MyHammerConfig_BaseFactory = 
i0.\u0275\u0275getInheritedFactory(MyHammerConfig)))(t || MyHammerConfig); }; }(), MyHammerConfig.\u0275prov = i0.\u0275\u0275defineInjectable({ token: MyHammerConfig, factory: MyHammerConfig.\u0275fac });
| const customConfig = { include: ["facebook", "twitter", "whatsapp", "linkedin", "email", "sms"], gaTracking: !0, sharerMethod: ngx_sharebuttons_1.SharerMethod.Window };
| class AppModule {
 at Object.<anonymous> (C:\Users\jct\code\mypath\repo\dist\apps\functions\main.js:211:7)
 at __webpack_require__ (C:\Users\jct\code\mypath\repo\dist\apps\functions\main.js:20:30)
 at webpackContext (C:\Users\jct\code\mypath\repo\dist\apps\functions\main.js:190:9)
 at C:\Users\jct\code\mypath\repo\dist\apps\functions\main.js:166:61
 at Array.forEach (<anonymous>)
 at Object.<anonymous> (C:\Users\jct\code\mypath\repo\dist\apps\functions\main.js:165:19)
 at __webpack_require__ (C:\Users\jct\code\mypath\repo\dist\apps\functions\main.js:20:30)
 at Object.<anonymous> (C:\Users\jct\code\mypath\repo\dist\apps\functions\main.js:121:52)
 at __webpack_require__ (C:\Users\jct\code\mypath\repo\dist\apps\functions\main.js:20:30)
 at Object.<anonymous> (C:\Users\jct\code\mypath\repo\dist\apps\functions\main.js:109:18)

The problem here is that the main.js files in the 'fr' or 'en' folder are all minified so I can't know exactly the origin of the problem.

A note: the functions app is a node app in our monorepo, which contains the cloud functions to deploy.

And a reminder: everything deploys correctly with Angular Universal 11, and after upgrade to version 12, it stopped at build time for the Cloud Function part.

Also: I did manage to easily migrate all other apps from the monorepo from Angular 11 to Angular 12. All apps started locally, build, and deployed without trouble.
So, I really narrowed down to the problem to SSR Universal, with AngularFire and Firebase (which is kind of very large scope, i know ^^).

Version info

Angular: 12

Firebase: 8.6.1

AngularFire: 6.1.5

Node: 12.22.3 (same in 14.17.3)

** Windows 10 **

Other (e.g. Ionic/Cordova, Node, browser, operating system):

Expected behavior

I expect the SSR Universal to not broke the workflow, when dealing with those protos / dir-loader / webpack 5.

Actual behavior

It's a no go for now for the adoption of Angular 12, because of those points.

You must be logged in to vote

Replies: 4 comments 3 replies

This comment has been hidden.

Comment options

If you update your Firebase JS SDK to the latest version I don't think you need the proto-loader or to bundle the dependencies anymore. I'm going to be testing this more now that I'm back from leave.

You must be logged in to vote
3 replies
Comment options

Thanks for your reply @jamesdaniels.

I've tried to do just that too in my trials. But then, I got into some issues about the functions folder. For now, for our cloud functions, we have a node app in apps\functions in which we build the Cloud Functions, and we're using a single package.json to manage our Nx monorepo. The thing with the latest versions of Firebase, is that it expects to have a package.json within the same folder as the functions (if i remember well), which is not the case in our monorepo. So, quite uneasy migration for me.

But I'll give that a shot when I can.

Comment options

Ah yeah, I've not done any work to support NX in the schematics & no doubt firebase CLI is unhappy too. If you get things working in NX LMK, would love for that to be on the happy path but I don't have the bandwidth to look into it myself.

Comment options

Sure.
What I know is that it's working with Angular 11.2.1 and Firebase 8.6.1, within a Nx 12.0.6 monorepo. The functions folder for our Cloud Functions is a node app. We manage mulitple functional projects, each one with 2 or 3 staging environments with 2-3 firebase projects behind. Everything works fine.
On one of our project, we need to do SSR with i18n, and there comes the complexity, using Universal with Firebase Cloud Functions and i18n was quite tricky.
Up until now, I was able to migrate the whole stack for each version increment. But, this one is quite a bit tricky I have to say.
I also tried to use the experimental clover way for doing SSR instead of Universal, but I struggled with i18n... So for now, all tries and directions taken were dead ends... Hoping to find a way to innovation and better performances soon ^^.

Comment options

Hi @jamesdaniels , I wonder if you had any time to investigate a bit in this blocking issue. From my side, I'll be able to test latest versions of firebase. What package from firebase should I update ? Only firebase ?

You must be logged in to vote
0 replies
Comment options

Hi @JamesDaniel, I upgraded as suggested to latest version of firebase sdk and removed the code for dealing with protos, and added the externaldependencies within the angular.json. Unfortunately, it ended up like this:

✔ Server application bundle generation complete.
✔ Localized bundle generation complete.
Initial Chunk Files | Names | Size
main.js | main | 10.21 MB
 | Initial Total | 10.21 MB
Lazy Chunk Files | Names | Size
682.js | - | 170 bytes
977.js | - | 170 bytes
Build at: 2021年08月04日T09:22:28.196Z - Hash: b98510291ad31142d487 - Time: 89449ms
Warning: C:/Users/jct/code/path/apps/website/firestore-protos.ts is part of the TypeScript compilation but it's unused.
Add only entry points to the 'files' or 'include' properties in your tsconfig.
> wekicards@0.8.0 lint:functions C:\Users\jct\code\path
> npm run lint functions
> wekicards@0.8.0 lint C:\Users\jct\code\path
> nx workspace-lint && ng lint "functions"
TSLint's support is discontinued and we're deprecating its support in Angular CLI.
To opt-in using the community driven ESLint builder, see: https://github.com/angular-eslint/angular-eslint#migrating-an-angular-cli-project-from-codelyzer-and-tslint.
Linting "functions"...
All files pass linting.
src C:\Users\jct\code\path/dist/website
copy C:\Users\jct\code\path/apps/functions/dist/website
> wekicards@0.8.0 build:asprod:functions:forWebsite C:\Users\jct\code\path
> node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng build functions -c=production,wkc-website
> NX Using webpack 5. Reason: detected version 5 in node_modules/webpack/package.json
Found an outdated version of webpack-node-externals
If you want to use webpack 5, try installing compatible versions of the plugins.
See: https://nx.dev/guides/webpack-5
> NX Falling back to webpack 4 due to incompatible plugin versions
Hash: 294d8063e08956cb2bc9
Built at: 08/04/2021 11:24:33
Entrypoint main = main.js
chunk {0} main.js (main) 44.8 KiB [entry] [rendered]
WARNING in ./apps/functions/dist/website/server/en/main.js 96:90
Module parse failed: The keyword 'let' is reserved (96:90)
File was processed with these loaders:
 * ./node_modules/ts-loader/index.js
You may need an additional loader to handle the result of these loaders.
| constructor() { super(...arguments), this.overrides = { pinch: { enable: !1 }, rotate: { enable: !1 } }; } 
| }
> exports.MyHammerConfig = MyHammerConfig, MyHammerConfig.\u0275fac = function () { let \u0275MyHammerConfig_BaseFactory; return function MyHammerConfig_Factory(t) { return (\u0275MyHammerConfig_BaseFactory || (\u0275MyHammerConfig_BaseFactory = i0.\u0275\u0275getInheritedFactory(MyHammerConfig)))(t || MyHammerConfig); }; }(), MyHammerConfig.\u0275prov = i0.\u0275\u0275defineInjectable({ token: MyHammerConfig, factory: MyHammerConfig.\u0275fac });
| const customConfig = { include: ["facebook", "twitter", "whatsapp", "linkedin", "email", "sms"], gaTracking: !0, sharerMethod: ngx_sharebuttons_1.SharerMethod.Window };
| class AppModule {
WARNING in ./apps/functions/dist/website/server/fr/main.js 96:90
Module parse failed: The keyword 'let' is reserved (96:90)
File was processed with these loaders:
 * ./node_modules/ts-loader/index.js
You may need an additional loader to handle the result of these loaders.
| constructor() { super(...arguments), this.overrides = { pinch: { enable: !1 }, rotate: { enable: !1 } }; } 
| }
> exports.MyHammerConfig = MyHammerConfig, MyHammerConfig.\u0275fac = function () { let \u0275MyHammerConfig_BaseFactory; return function MyHammerConfig_Factory(t) { return (\u0275MyHammerConfig_BaseFactory || (\u0275MyHammerConfig_BaseFactory = i0.\u0275\u0275getInheritedFactory(MyHammerConfig)))(t || MyHammerConfig); }; }(), MyHammerConfig.\u0275prov = i0.\u0275\u0275defineInjectable({ token: MyHammerConfig, factory: MyHammerConfig.\u0275fac });
| const customConfig = { include: ["facebook", "twitter", "whatsapp", "linkedin", "email", "sms"], gaTracking: !0, sharerMethod: ngx_sharebuttons_1.SharerMethod.Window };
| class AppModule {
! functions: package.json indicates an outdated version of firebase-functions.
Please upgrade using npm install --save firebase-functions@latest in your functions directory.
=== Deploying to 'project-staging'...
i deploying functions
+ functions: Finished running predeploy script.
i functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i functions: ensuring required API cloudbuild.googleapis.com is enabled...
+ functions: required API cloudbuild.googleapis.com is enabled
+ functions: required API cloudfunctions.googleapis.com is enabled
i functions: preparing / directory for uploading...
Error: Error occurred while parsing your function triggers.
Error: Module parse failed: The keyword 'let' is reserved (96:90)
File was processed with these loaders:
 * ./node_modules/ts-loader/index.js
You may need an additional loader to handle the result of these loaders.
| constructor() { super(...arguments), this.overrides = { pinch: { enable: !1 }, rotate: { enable: !1 } }; } 
| }
> exports.MyHammerConfig = MyHammerConfig, MyHammerConfig.\u0275fac = function () { let \u0275MyHammerConfig_BaseFactory; return function MyHammerConfig_Factory(t) { return (\u0275MyHammerConfig_BaseFactory || (\u0275MyHammerConfig_BaseFactory = i0.\u0275\u0275getInheritedFactory(MyHammerConfig)))(t || MyHammerConfig); }; }(), MyHammerConfig.\u0275prov = i0.\u0275\u0275defineInjectable({ token: MyHammerConfig, factory: MyHammerConfig.\u0275fac });
| const customConfig = { include: ["facebook", "twitter", "whatsapp", "linkedin", "email", "sms"], gaTracking: !0, sharerMethod: ngx_sharebuttons_1.SharerMethod.Window };
| class AppModule {
 at Object.<anonymous> (C:\Users\jct\code\path\dist\apps\functions\main.js:211:7)
 at __webpack_require__ (C:\Users\jct\code\path\dist\apps\functions\main.js:20:30)
 at webpackContext (C:\Users\jct\code\path\dist\apps\functions\main.js:190:9)
 at C:\Users\jct\code\path\dist\apps\functions\main.js:166:61
 at Array.forEach (<anonymous>)
 at Object.<anonymous> (C:\Users\jct\code\path\dist\apps\functions\main.js:165:19)
 at __webpack_require__ (C:\Users\jct\code\path\dist\apps\functions\main.js:20:30)
 at Object.<anonymous> (C:\Users\jct\code\path\dist\apps\functions\main.js:121:52)
 at __webpack_require__ (C:\Users\jct\code\path\dist\apps\functions\main.js:20:30)
 at Object.<anonymous> (C:\Users\jct\code\path\dist\apps\functions\main.js:109:18)
npm ERR! code ELIFECYCLE
npm ERR! errno 1

From main.js (line 166):

SUPPORTED_LOCALES.forEach((locale) => {
 const translatedAppServerModule = __webpack_require__(7)(`./${locale}/main.js`);
 server.use(`/${locale}`, translatedAppServerModule.app(locale));
});
exports.globalSsr = functions.https.onRequest(server);

What I find odd is that the output of server generation is that I now have 2 files of 170 bytes (682.js and 977.js) in the /dist/website/server/${locale}/ folder.
With the same build, at server target, I had 2 files for firebase-auth.js, and firebase-vendors.js.

More over, to get to this point I added in angular.json the external dependencies for the server target, the same as @JamesDaniel in the sample folder. I therefore removed all logic with dir-loader and firestore-protos.

I also, as suggested, updated to latest version my firebase sdk (v8.8.1).
The version of firebase-functions is 3.13.2.

Yesterday, I updated to latest version of nrwl/nx (v.12.3.6). Initially, I was with 12.0.6.

I also checked the proposed link for debug from NX https://nx.dev/guides/webpack-5, and tried to install webpack-5 plugins for node apps, as the functions app is a node app: npx nx g @nrwl/node:webpack5. This failed to install anything.

[error] Error: Cannot find module 'webpack'
Require stack:
- C:\Users\jct\code\path\node_modules\@angular-devkit\build-webpack\src\webpack\index.js
- C:\Users\jct\code\path\node_modules\@angular-devkit\build-webpack\src\index.js
- C:\Users\jct\code\path\node_modules\@angular-devkit\build-angular\src\browser\index.js
- C:\Users\jct\code\path\node_modules\@angular\cli\node_modules\@angular-devkit\architect\node\node-modules-architect-host.js
- C:\Users\jct\code\path\node_modules\@angular\cli\node_modules\@angular-devkit\architect\node\index.js
- C:\Users\jct\code\path\node_modules\@angular\cli\models\architect-command.js
- C:\Users\jct\code\path\node_modules\@angular\cli\commands\build-impl.js
- C:\Users\jct\code\path\node_modules\@angular\cli\node_modules\@angular-devkit\schematics\tools\export-ref.js
- C:\Users\jct\code\path\node_modules\@angular\cli\node_modules\@angular-devkit\schematics\tools\index.js
- C:\Users\jct\code\path\node_modules\@angular\cli\utilities\json-schema.js
- C:\Users\jct\code\path\node_modules\@angular\cli\models\command-runner.js
- C:\Users\jct\code\path\node_modules\@angular\cli\lib\cli\index.js
- C:\Users\jct\code\path\node_modules\@angular\cli\lib\init.js
- C:\Users\jct\code\path\node_modules\@angular\cli\bin\ng
 at Function.Module._resolveFilename (internal/modules/cjs/loader.js:815:15)
 at Function.Module._load (internal/modules/cjs/loader.js:667:27)
 at Module.require (internal/modules/cjs/loader.js:887:19)
 at require (internal/modules/cjs/helpers.js:74:18)
 at Object.<anonymous> (C:\Users\jct\code\path\node_modules\@angular-devkit\build-webpack\src\webpack\index.js:37:35)
 at Module._compile (internal/modules/cjs/loader.js:999:30)
 at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
 at Module.load (internal/modules/cjs/loader.js:863:32)
 at Function.Module._load (internal/modules/cjs/loader.js:708:14)
 at Module.require (internal/modules/cjs/loader.js:887:19)

I had to revert it back with npm install.

So, basically, I'm back with what seems to be the root cause of 1st set of logs:

Error: Module parse failed: The keyword 'let' is reserved (96:90)
File was processed with these loaders:
 * ./node_modules/ts-loader/index.js
You may need an additional loader to handle the result of these loaders.

Do you happen to have some clues to proceed further with that migration ng11 -> ng12 ?

Something clearly broke our deploy process:

  • before: webpack 4 under the hood with ng11,
  • now: webpack5 with ng12,
  • before and now: i18n and angular-universal
You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Converted from issue

This discussion was converted from issue #2874 on July 12, 2021 15:35.

AltStyle によって変換されたページ (->オリジナル) /