Skip to content

"Unexpected token import" with angularfire2 on angular-cli, AOT, SSR, and firebase-functions #1073

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sdebaun opened this issue Jul 16, 2017 · 40 comments
Assignees

Comments

@sdebaun
Copy link

sdebaun commented Jul 16, 2017

Has anyone done this? I'm stuck, would love some suggestions, or pointers if I'm missing something obvious or misunderstanding the problem.

Version info

Angular: 4.2.4

Firebase: 4.1.3

AngularFire: 4.0.0-rc1

Firebase-functions: 0.5.9

How to reproduce these conditions

Using AOT compiling, and server-side rendering, as described in this blagpost:
https://medium.com/@evertonrobertoauler/angular-4-universal-app-with-angular-cli-db8b53bba07d

Repo:
https://github.com/SparksNetwork/exp-angular-firebase/tree/shared-code
(note I am working from the shared-code branch)
(the repo structure is kind of haphazard, everything lives in /functions because thats what firebase-functions requires)

Steps to set up and reproduce

App runs successfully JIT running ng serve.

Compile client and server with ng run build.

Serve via standalone node express server with ts-node src/server.ts or via firebase-functions local emulator with firebase serve --only functions.

Debug output

FirebaseError: Error occurred while parsing your function triggers.

/Users/sdebaun/exp-angular-firebase/functions/node_modules/angularfire2/app/firebase.app.module.js:1
(function (exports, require, module, __filename, __dirname) { import { InjectionToken, } from '@angular/core';
                                                              ^^^^^^
SyntaxError: Unexpected token import
    at createScript (vm.js:53:10)
    at Object.runInThisContext (vm.js:95:10)
    at Module._compile (module.js:543:28)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/Users/sdebaun/exp-angular-firebase/functions/fn/dist/dist/ngfactory/src/app/app.server.module.ngfactory.js:23:13)
i  functions: No HTTPS functions emulated. Support for other function types are coming soon.

Diagnosis

I suspect it's choking because the angularfire2 npm module is compiled with es2015 syntax which doesn't work in node (which firebase-functions is based on).

Possible fix?

I don’t know a lot about how NPM works, but I’m wondering if I:

  1. Fork angularfire2
  2. change the target and/or module settings in forked tsconfig until I find something that works
  3. in my app, npm install from my forked angularfire2

Only thing I don’t know how to do there is: how do I ensure that my forked angularfire2 gets built? There’s a bunch of stuff in the repo that has to do with the build process that is totally alien to me.

The only other thing I can think of is to try to write my own firebase wrapper for angular, with blackjack and hookers that compiles to commonjs. That sounds like an awful idea.

Things I’ve Tried

Using DI to swap out AngularFire2 on server

Per the discussion in this thread (angular/universal-starter#127 (comment)), I started writing a fake service that adhered to the angularfire2 interfaces that I could use in my app.server.module.ts. Quickly I realized that because all my services actually have to import from the real angularfire2 module, it still wouldn’t work, because the error gets thrown when the file is imported, not when it’s run.

Copying angularfire2/src into a local lib directory and building it with the project

When I try this, I get all sorts of errors about Zone not being found. I can’t figure out what needs to be included, or how, in order to get it to compile the ts.

@davideast
Copy link
Collaborator

@sdebaun I recently ran into this myself. I have a fix in the works but I just moved halfway across the country so my schedule is pretty jammed right now. I do expect to get something out next week.

There's a big overhaul needed in how we package these modules. We need a UMD bundle for each feature (auth, db) rather than one larger one. I'm looking into mimicking the structure that the main Angular repo uses with their package.json and tsconfig.files. A good example is with the HTTP module.

@sdebaun
Copy link
Author

sdebaun commented Jul 25, 2017

@davideast thankyouthankyouthankyouthankyouthankyouthankyouthankyou! I was so excited that I got a client/server monorepo working with SSR, and then wanted to cry when I found out angularfire didn't play nicely.

So I should just hold off for a bit, eventually angularfire will work with ssr?

YOURETHEBEST!!!

@justingrayston
Copy link

justingrayston commented Jul 31, 2017

I've just run into this too trying out universal build with angular-cli, so would love to know what your work around was. I was going to try to build targeting commonjs and pull in to packages.json direct from my own branch. Alternatively I was thinking about swapping out for the firebase admin sdk using getPlatform and some jigging about with the code.

Both seemed horrid options atm, the later in particular.

I haven't tried either yet. I'll keep my fingers crossed, in the mean time I will continue to play if I get the chance.

@davideast
Copy link
Collaborator

@justingrayston @sdebaun I'm close to a next release for this fix. If all goes well I'll be testing an Angular Universal build with the CLI. I'll keep you updated.

@KrGyan
Copy link

KrGyan commented Aug 2, 2017

@davideast when can we expect this release. I am using "angularfire2": "^4.0.0-rc.1" with "firebase": "^4.2.0" . AOT with angular cli . I am getting the same issue.

E:\Angular\designcourse\angular-seo\node_modules\angularfire2\app\firebase.app.module.js:1
(function (exports, require, module, __filename, __dirname) { import { InjectionToken, } from '@angular/core';
^^^^^^
SyntaxError: Unexpected token import
at Object.exports.runInThisContext (vm.js:76:16)
at Module._compile (module.js:542:28)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
at Object. (E:\Angular\designcourse\angular-seo\dist\ngfactory\src\app\app.server.module.ngfactory.ts:26:1)
at Module._compile (module.js:570:32)

Waiting eagerly for your positive response and next release as well. :)

@sdebaun
Copy link
Author

sdebaun commented Aug 2, 2017

@justingrayston my workaround was... disable SSR until the fix is posted :)

@KrGyan
Copy link

KrGyan commented Aug 4, 2017

@davideast , does rc2 fixes this issue ?

@davideast
Copy link
Collaborator

davideast commented Aug 4, 2017

@sdebaun @justingrayston @KrGyan

does rc2 fixes this issue ?

Yes and no. Mostly no. #1088 fixed the problem that @sdebaun ran into. The Angular Compiler used deep imports to import the feature modules, when I needed to use the UMD bundle. I spent a lot of time getting the packaging of each module correct.

Now, if you use AngularFire2 with Angular Universal, there will be no errors*. However, the data will not render on the server. You'll get back null in your templates. This is because AngularFire2 uses the Firebase SDK which uses websockets. Websockets are long-lived persistent connections. Angular Universal doesn't know when this socket will end. I can fix this by wrapping the calls for Universal, but that will be another PR. I plan on working on that next week.

*i think

@MichaelSolati
Copy link

@davideast when you say that you intend to wrap the calls, how do you plan on doing so? I imagine there is the possibility to wrap the socket connection into an RxJS websocket but I imagine that would require a lot of work and wouldn't be the right approach... If you want though I would love to help you in any endeavor/steps you want to move forward with this!

@SpeedoPasanen
Copy link

SpeedoPasanen commented Aug 11, 2017

Is the data null because Universal isn't waiting or because it doesn't even open the socket? If the first case, for now, I could grab the master and force Universal to wait - with a mock HTTP req, timeout or sth, until I got the first data?

@EreckGordon
Copy link

@davideast any progress with getting AngularFire2 to play nice with Universal?

@SpeedoPasanen
Copy link

SpeedoPasanen commented Sep 1, 2017

Got around the problem by providing firebase-admin to a FirebaseAdminService, then using that instead of Angularfire2 in a ServerDatabaseModule. Sorry, not a complete example but hope this gives you ideas:

https://gist.github.com/funkizer/6d6559787c17a88c60cf2ddc9ca06527
https://gist.github.com/funkizer/e162adff4191cae3c897e6bc5b7fd605

If you're hosting Universal on your own server, you might get away with not getting rid of all Angularfire2 stuff, but at least on Cloud Functions, you'll get ctor is not a constructor or other funny errors or timeouts because injectors fail, so I just got rid of everything related to FB client on server. Key thing is to run firebase-admin related things wrapped in zone.runOutsideAngular().

@AnthonyNahas
Copy link
Contributor

AnthonyNahas commented Sep 12, 2017

I fixed a similar problem in @ngx-translate/core. Please take a look to my comment
here.
or even better the full explanation
i did it locally too for the angularfire2 module.

I used the cli of babel to compile all js file into es5 - commonjs so that i can use them in nodejs (express) with angular universal --> finally no more SyntaxError: Unexpected token import!

@iiAtlas
Copy link

iiAtlas commented Oct 3, 2017

Any fix for this?

@patrickmichalina
Copy link

@davideast what is the timeframe for this? do you need any help with this? SSR is critical for the stuff we are building and I would love to use firebase for it.

@patrickmichalina
Copy link

I have Firebase Auth "working" in my starter project here:

code: https://github.com/patrickmichalina/fusebox-angular-universal-starter
demo: https://angular.patrickmichalina.com/login

@ncherian
Copy link

I tried to do SSR on Cloud functions with AngularFire2 included. There are no errors and data is fetched from RTDB as it can be seen printed in to the logs. But the html pages never render and soon timeout. @davideast Any updates on the possible fix you mentioned?

@paulogr
Copy link

paulogr commented Nov 7, 2017

Have same problem here, html pages never render when using AngularFire. @davideast any update?

@paulogr
Copy link

paulogr commented Nov 8, 2017

I was able to resolve the usage of angularfire2 on server side creating and injecting a "stub" version of AngularFireDatabase that uses the firebase rest api. As @davideast said the problem of timeouts or never render templates is the websocket that never finish and angular do not knows when finish rendering.

I didn't even include the angularfire modules on server side.

Hope it helps.

@jamesdaniels
Copy link
Member

jamesdaniels commented Nov 8, 2017

@ncherian @paulogr so the main problem is actually not the socket, but Zone.js, we have a bug in our handling. The microtasks are never allowing appRef isStable to go true, thus Universal never letting go of the rendering until Timeout and even once you do have a rendered page state restoration never happens.

If you wrap in a zone.runOutsideAngular() things work. I have on my list to fix.

@jamesdaniels jamesdaniels self-assigned this Nov 8, 2017
@jamesdaniels
Copy link
Member

There's also no node.js entry to firebase/app which is a bug + why Websockets aren't getting pulled in.

(global as any).WebSocket = require("ws"); in your server.ts works until I get that patched upstream ;)

@hiepxanh
Copy link
Contributor

hiepxanh commented Nov 9, 2017

so what should we do ? firebase is very important to me and without SSR to SEO, my angular 2 application is just a toys :(

@patrickmichalina
Copy link

@hiepxanh I know its not elegant, nor does it cover all scenarios, but it gets me by until the official supports lands in this library: https://github.com/patrickmichalina/fusebox-angular-universal-starter/blob/master/src/server/server.angular-fire.service.ts

@sureshprabhu2218
Copy link

We use angularfire2 and firestore in our application. Firestore does not render data as @davideast mentioned. From this conversation I understand its going to take time. @hiepxanh you can try other solutions. One which I saw recently is to use chrome's rendertron. Definitely not better than universal. But will work. Check this blog

@hamedbaatour
Copy link

Finally Server Side Rendering with Firebase 😊

angularfirelite-logo

🎉 Introducing AngularFire Lite 🎉

AnglularFire Lite is a very very simple library to use Angular with Firebase it supports server-side rendering out of the box for both firebase realtime database and firestore. It renders the SSR app and then switches to the non-SSR to receive real-time updates from firebase with no flickering at all when the angular app bootstraps.
Visit AngularFire Lite repo to get started today:

Get Started

Demo App

Please note that this is a personal initiative I started and it's still in very early beta so your help by contributing and supporting the library will be the only way to improve it.

@davideast
Copy link
Collaborator

@hamedbaatour This is really cool! I wish you would have contributed to this project however. We plan on adding support for the rest of the Firebase features soon.

I do have one question, is it actually lighter than AngularFire? AngularFire itself is really small, the DB API is 3kb. The Firestore API is 2.3kb. The Auth API is 950 bytes.

@hiepxanh
Copy link
Contributor

wow, you deserve this 🥇
I love that, finally, I can't wait to use this, thanks you for your initiative. That help me a lot and make my dream come true. I still didn't using any different database to only work with firebase

@khalid-halo
Copy link

Looking forward to SSR support

@hiepsieuviet
Copy link

hiepsieuviet commented Dec 14, 2017

well, without support for socket method from angular. We (angularfire, or anything use socket) cannot work with universal. That really bad news,

  1. there are some investment in socket.io with ssr from angular universal but look like very slow. They are trying to doing something with ZoneMacroTaskWrapper but i don't understand.

  2. Sir @jamesdaniels is trying to doing something different, Support Angular Universal he work with service worker and xmlhttprequest to make our dream come true. I hope that work. 👍 everything I can help, you just mention, sir.

@hiepxanh
Copy link
Contributor

still looking forward to make my web go production 👍 , event I have dedicated server, when calling to firebase, my data still not render with universal. I can't SEO

@kpsrinivas
Copy link

Quick question - can this not be resolved using Cloud apis on server - https://cloud.google.com/firestore/docs/reference/rest/ . With isPlatformBrowser, isPlatformServer can't we control it ?

@doczoidberg
Copy link

are there already results of an AngularFire Lite cooperation? When can we expect SSR in AngularFire?

@ceolinwill
Copy link

@doczoidberg there's a pull request (#1454) for that, so probably soon :)

@kpsrinivas
Copy link

"angularfire2": "^5.0.0-rc.6" seems to be working with ssr. Did anything change ?

@andreaaschei
Copy link

@kpsrinivas were you able to make the ssr work with rc.6?

@kpsrinivas
Copy link

@andreaaschei yes.

@jamesdaniels
Copy link
Member

jamesdaniels commented Apr 13, 2018 via email

@anasbaddyr
Copy link

Seems to be working with RC.7 although some modifications are needed to the official universal guide if you're using material and other libraries in the server.ts file. Thanks @jamesdaniels and the team at angular firebase for the very helpful video highly recommend checking it out.

https://www.youtube.com/watch?v=wij2-gyG12E

Still will need to test it further but great job guys!

@patrickmichalina
Copy link

SSR in the minimal sense. It still does not have state transfer nor does it have auth.

@jamesdaniels
Copy link
Member

jamesdaniels commented Apr 19, 2018 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests