stitch-js-sdk: window is not defined

I’m using babel transpiler

function StitchAuthImpl(requestClient, browserAuthRoutes, authStorage, appInfo, jsdomWindow) {
        if (jsdomWindow === void 0) { jsdomWindow = window; }
        ...
}

//error: window is not defined

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Comments: 32 (6 by maintainers)

Most upvoted comments

And for those on next.js, you can do it the same way but you’ll need to add a webpack alias resolve to your next.config.js file, like so! :

module.exports = {
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    if (!isServer) { config.resolve.alias = {
      ...config.resolve.alias,
      'mongodb-stitch-server-sdk': 'mongodb-stitch-browser-sdk'
    } }
    return config;
  }
};

Let me know!

Hey @phillipmalboeuf thanks for taking a look and finding a workaround for this! I’m sure this will be very helpful for a lot of users.

We still would like to eventually have a more clean and robust solution for SSR, so I’ll leave this issue open until we get a chance to investigate this further.

+1 for SSR support

I can verify that the workaround @phillipmalboeuf discovered also work with Nuxt js with the following small modification. In the nuxt.config.js file: build: { extend(config, ctx) { if (!ctx.isServer) { config.resolve.alias = { ...config.resolve.alias, 'mongodb-stitch-server-sdk': 'mongodb-stitch-browser-sdk' } } return config; } } Thus the only difference is that the webpack extension is different from Next js. You will still need to replace all import of ‘mongodb-stitch-browser-sdk’ with ‘mongodb-stitch-server-sdk’ as well as add the alias in package.json.

Looking forward to the day where the SDK supports SSR.

Hey @adamchel, @Ruegen, @maredudd, @agstover, so I got to a weird solution for this. It needs a couple of steps (note that I’m writing TypeScript and bundling with Parcel):

First, change all your references to the stitch sdk to 'mongodb-stitch-server-sdk'. Stick with me here:p

Second, in your package.json add an alias to point the sdk back to the browser:

{...,
  "alias": {
    "mongodb-stitch-server-sdk": "mongodb-stitch-browser-sdk"
  },
  {
    ...,
    "mongodb-stitch-browser-sdk": "^4.3.2",
    "mongodb-stitch-server-sdk": "^4.3.2",
    ...
  },
  ...
}

Third, if you’re on TS add to your tsconfig.json an alias path:

{
  "compilerOptions": {
    ...,
    "baseUrl": ".",
    "paths": {
      "mongodb-stitch-server-sdk": ["node_modules/mongodb-stitch-browser-sdk"]
    }
  }
}

And VOILÀ, bundling this for the browser and bundling this for Node and running those works just fine! This works because unlike bundling for the browser where the packages are all merged in, Node keeps the packages in a node_modules folder, and retrieves them from there. So Node looks for mongodb-stitch-server-sdk while the browser gets the aliased mongodb-stitch-browser-sdk packaged in!

I haven’t tried this with Next.js but I imagine it might work, let me know.

@ivanjeremic I’ve been looking everywhere for all of the auth API endpoints, thank you! These should be in the official documentation.

As for where to store it, I’ve been storing them in cookies. I store the user data, access_token and expiry date in one cookie, and the refresh_token in an http-only cookie. Then, I setup a /refresh-token endpoint that my client hits whenever it expires to get the new access_token (and updates the cookie).

You can refresh the token by sending a post request to https://stitch.mongodb.com/api/client/v2.0/auth/session with an Authorization: "Bearer <refresh token>" header.

I have not tested it yet but hitting the Stitch Client API directly should solve many problems in Nextjs, https://github.com/mongodb/stitch-specifications/blob/master/source/sdks/sdks.rst#userpasswordauthproviderclient.

We could create Nextjs API routes in the /api folder, for example, nextapp.com/api/login

In this route, we send a request to https://stitch.mongodb.com/api/client/v2.0/app/<client_app_id>/auth/providers/<provider_name>/login

the response will be access_token, refresh_token, user_id, device_id that we can handle then, has anyone an idea what the best method would be at this point to store or handle it?

@adamchel the dependencies are a good place to start. So I wrote this, might be the best way to test SSR compability (a .tsx/.jsx file):

import { Stitch } from 'mongodb-stitch-browser-sdk'
import React from 'react'
import ReactDOM from 'react-dom/server'

const client = Stitch.initializeDefaultAppClient('****')

const html = ReactDOM.renderToString(<div>
  {client.auth.isLoggedIn.toString()}
</div>)

console.log(html)

Running this in node returns a ReferenceError: self is not defined error from the whatwg-fetch package but I suspect it might not be the only culprit here.

Hi @adamchel, yes I’ve tried it however like Phillip I got the same errors. I got around it by only loading the package in on the client side - which involves a fair bit of trickery (not pretty), the server side can’t use the client side and vice versa. It would be better to have it load for SSR which would resolve a great deal of issues.

@phillipmalboeuf I believe the client side uses localstorage to save the credentials automatically.

Thanks @adamchel, using mongodb-stitch-server-sdk is not the solution, it’s difficult to have to juggle between two librairies. Even having something like this gives me a ReferenceError: self is not defined error:

export const client = process.env.production
  ? require('mongodb-stitch-server-core').Stitch.initializeDefaultAppClient('***')
  : require('mongodb-stitch-browser-core').Stitch.initializeDefaultAppClient('***')
export const db = client.getServiceClient(process.env.production
  ? require('mongodb-stitch-server-services-mongodb-remote').RemoteMongoClient.factory
  : require('mongodb-stitch-browser-services-mongodb-remote').RemoteMongoClient.factory, '***').db('***')

The current system setup isn’t SSR capable, and it’s not just a matter of the fetch library. I believe the credentials storage method would need to be polymorphic as well. I’ll see if I can open a PR sometime this week and do deeper dive:)

Update Would axios be fine as a polymorphic fetch library? NativeScript seems fine with it: https://www.nativescript.org/blog/make-http-requests-to-remote-web-services-in-a-nativescript-vue-app

In the future, we hope to have a universal JS SDK. However, in the interim, @agstover is right. A solution could be to make your own isomorphic multiplexer file, i.e., an isomorphic-stitch.js file that does if node return nodesdk else browser sdk.