I'm trying to deploy my application to a production environment, but having some trouble wiring it all together.
I've got a create-react-app for my frontend, which is served up by a simple express/serve server. On the backend, I've got NGINX proxying successfully to my API server, which is using Apollo to serve my data. The API is running on port 4000.
The Apollo-Server is as-follows, and works fine:
import { resolve } from "path";
import dotenv from "dotenv";
const envi = process.env.NODE_ENV;
dotenv.config({ path: resolve(__dirname, `../.${envi}.env`) });
import "reflect-metadata";
import { connect } from "./mongodb/connect";
import { buildSchema } from "type-graphql";
import { ApolloServer } from "apollo-server";
import { SenateCommitteeResolver, HouseCommitteeResolver } from "./resolvers";
import { populateDatabase } from "./util";
(async () => {
// Connect to MongoDB
await connect();
console.log(`š Databases connected`);
const schema = await buildSchema({
resolvers: [HouseCommitteeResolver, SenateCommitteeResolver],
emitSchemaFile: resolve(__dirname, "schema.gql"),
});
// If development, set database docs
envi === "development" && (await populateDatabase());
// Launch the server!
const server = new ApolloServer({
schema,
playground: true,
});
// Server listens at URL
const { url } = await server.listen(4000);
console.log(`š Server ready, at ${url}`);
})();
I'm trying to connect my express server to the Apollo Server, but that's where I'm running into problems. The application is supposed to connect using Apollo's Client and HTTP Link, because I'm using Apollo Client on the frontend too:
import React, { useEffect } from "react";
import { AppRouter } from "./routers";
import ReactGA from "react-ga";
import { ApolloProvider } from "#apollo/client";
import client from "./graphql/client";
import "./styles/index.scss";
function App(): React.ReactElement {
return (
<ApolloProvider client={client}>
<AppRouter />
</ApolloProvider>
);
}
export default App;
And here's the client file:
import { ApolloClient, InMemoryCache, createHttpLink } from "#apollo/client";
const httpLink = createHttpLink({ uri: process.env.REACT_APP_API as string });
const cache = new InMemoryCache();
const client = new ApolloClient({
link: httpLink,
cache,
connectToDevTools: true,
});
export default client;
However, when the user navigates to the site and the site itself tries to make a request to my backend, I'm getting a CORS error:
Access to fetch at 'https://www.cloture.app/' from origin 'https://cloture.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
What's going wrong? How can I connect Apollo's client with my Apollo Server on the backend?
Adding it here, because the suggestion requires some code.
Try adding :
const server = new ApolloServer({
schema,
playground: true,
cors: {
origin: "*" // it will allow any client to access the server, but you can add specific url also
}
});
Related
I have a react client that is instantiating new Configuration class and passing that configuration in the endpoints generated by codegen open api
import {
Configuration,
AuthApi,
MemeApi,
ConfigurationParameters,
} from "../generated-sources/openapi";
import Cookies from "js-cookie";
import { UserApi } from "../generated-sources/openapi/apis/UserApi";
import { useEffect } from "react";
const bearerToken = Cookies.get("bearer");
const apiConfigParams: ConfigurationParameters = {
credentials: "include",
basePath: "",
};
if (bearerToken) {
apiConfigParams.headers = { Authorization: "bearer " + bearerToken };
}
console.log("bearerAPI", bearerToken);
// Point to API
const configuration = new Configuration(apiConfigParams);
export const authApi = new AuthApi(configuration);
export const memeApi = new MemeApi(configuration);
export const userApi = new UserApi(configuration);
The problem I'm having is that after user logins in the authApi hook, I set the bearer token to the cookie however when I make a request to a route/endpoint that requires a bearer token, the configuration is not being updated with the new bearer token that I set to the cookie.
How can I make sure that this file, or this configuration listens to changes in the cookie and reinstate the calls?
I have a web app using aws appsync as backend and react + apollo client (v3) as front end. But when I try connecting apollo client to appsync, I get an error message from the library:
./node_modules/aws-appsync-react/lib/offline-helpers.js
Module not found: Can't resolve 'react-apollo' in '/Users/mypath/web/node_modules/aws-appsync-react/lib'
Here's the config for the client:
import AWSAppSyncClient from "aws-appsync";
import AppSyncConfig from "./aws-exports";
export const apolloClient = new AWSAppSyncClient({
url: AppSyncConfig.aws_appsync_graphqlEndpoint,
region: AppSyncConfig.aws_appsync_region,
auth: {
type: AppSyncConfig.aws_appsync_authenticationType,
apiKey: AppSyncConfig.aws_appsync_apiKey,
},
});
And the in my App.ts:
import { ApolloProvider } from "#apollo/client";
import { Rehydrated } from "aws-appsync-react";
import { apolloClient } from "./apollo";
...
<ApolloProvider client={apolloClient}>
<Rehydrated>
<MyApp />
</Rehydrated>
</ApolloProvider>
Looks like a compatibility issue?
I'm using "#apollo/client": "^3.1.3", "aws-appsync": "^4.0.0","aws-appsync-react": "^4.0.0",.
It is a compatibility issue. Current version of aws-appsync doesn't support apollo-client v3, see this thread for progress:
https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/448
Best workaround is this: Proper way to setup AWSAppSyncClient, Apollo & React
Note the workaround does use two deprecated libraries but can be slightly improved as:
import { ApolloClient, ApolloLink, InMemoryCache } from "#apollo/client";
import { createAuthLink } from "aws-appsync-auth-link";
import { createHttpLink } from "apollo-link-http";
import AppSyncConfig from "./aws-exports";
const url = AppSyncConfig.aws_appsync_graphqlEndpoint;
const region = AppSyncConfig.aws_project_region;
const auth = {
type: AppSyncConfig.aws_appsync_authenticationType,
apiKey: AppSyncConfig.aws_appsync_apiKey,
};
const link = ApolloLink.from([
// #ts-ignore
createAuthLink({ url, region, auth }),
// #ts-ignore
createHttpLink({ uri: url }),
]);
const client = new ApolloClient({
link,
cache: new InMemoryCache(),
});
export default client;
I am trying to use ApolloClient with a local IP as uri, but when I set it, it automatically changes it from http to https and, of course, it doesn't work locally.
I've tried 2 way of configuring Gatsby to use ApolloClient.
The first way is in gatsby-browser like so:
import React from 'react';
import 'core-js/modules/es6.set';
import 'core-js/modules/es6.map';
import 'raf/polyfill';
import Apollo from 'providers/Apollo';
export const wrapRootElement = ({ element }) => <Apollo>{element}</Apollo>;
And, the ApolloClient config:
import React from 'react';
import { ApolloProvider, ApolloClient, InMemoryCache } from '#apollo/client';
export default ({ children }) => {
const client = new ApolloClient({
uri: 'http://192.162.1.112:4000/graphql',
cache: new InMemoryCache(),
request: async operation => {
...
},
fetchOptions: {
mode: 'no-cors',
},
});
return <ApolloProvider client={client}>{children}</ApolloProvider>;
};
The second way is using the plugin gatsby-plugin-apollo in gatsby-config like so
{
resolve: 'gatsby-plugin-apollo',
options: {
uri: 'http://192.168.1.112:4000/graphql'
}
}
Notice both uri have http.
Also, it is either one or the other, not both. (Although I've tried with both and it the same result).
This is what I get trying to do a gql query in the network tab:
It is enforcing https and I can't test locally. How do can I make request to http using Gatsby and ApolloClient?
By the way, I set ApolloClient just like this in another project that doesn't use Gatsby (obviously not using the gatsby plugin either) and it works as expected.
There are a few confusing things in the way you are using apollo client.
There is no point in explaining something that has already been done.
You might want to check out this talk and demo by Jason Lengstorf. Here he explained how one can get started with gatsby + apollo client.
Youtube
gatsby-with-apollo
I finally finished my backend with apollo.
Now I moved to the frontend.
I made it work with the normal http connection and fetched some messages from the server (chat app).
Now I also tried to connect the subscription link to it (which was very confusing in itself because there are a few examples outside and everybody does it a bit differently, but neither worked).
So here is how my index file looks on react frontend:
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import { ApolloClient } from "apollo-client";
import { ApolloProvider } from "react-apollo";
import { WebSocketLink } from "apollo-link-ws";
import { ApolloLink } from "apollo-link";
import { HttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
const wsLink = new WebSocketLink({
uri: `ws://localhost:4000/graphql`,
options: {
reconnect: true
}
});
// Create an http link:
const httpLink = new HttpLink({
uri: "http://localhost:4000/graphql"
});
const link = ApolloLink.from([httpLink, wsLink]);
const client = new ApolloClient({
link,
cache: new InMemoryCache()
});
ReactDOM.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
document.getElementById("root")
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();
I also tried different methods for example with split from apollo-link like this:
const link = split(
// split based on operation type
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === "OperationDefinition" &&
definition.operation === "subscription"
);
},
wsLink,
httpLink
);
I also tried it with ApolloClient from apollo-boost instead of apollo-client.
Can somebody please help me out, because I can't get it to work.
Error message is always:
WebSocket connection to 'ws://localhost:4000/graphql' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
If you want to see the full code: https://github.com/SelfDevTV/graphql-simple-chat
I have a React app which is using Apollo Client. I'm using apollo-link-state and apollo-cache-persist and need to reset my store to its default values when client.resetStore() is called in my app.
The docs say that when creating a client you should call client.onResetStore(stateLink.writeDefaults) and this will do the job but writeDefaults is exposed by Apollo Link State which i don't have direct access to as Iām using Apollo Boost.
Here is my Apollo Client code:
import ApolloClient from 'apollo-boost';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { persistCache } from 'apollo-cache-persist';
import { defaults, resolvers } from "./store";
const cache = new InMemoryCache();
persistCache({
storage: window.localStorage,
debug: process.env.NODE_ENV !== 'production',
cache
});
const client = new ApolloClient({
uri: process.env.NODE_ENV === 'production' ? 'https://five-yards-api.herokuapp.com/graphql' : 'http://localhost:7777/graphql',
credentials: 'include',
clientState: {
defaults,
resolvers
},
cache
});
// TODO: Doesn't work as expected
client.onResetStore(client.writeDefaults);
export default client;
I use Apollo Client 2.x, and Apollo Boost may be the same.
I had the same problem with Apollo Client 2.x, and below was the solution for me.
In the root file where you configure your Apollo (e.g. App.js):
cache.writeData({data : defaultData }); # I assume you already have this to initialise your default data.
# Then, you just add below underneath.
client.onResetStore(() => {
cache.writeData({data : defaultData });
});
const App = () => (...
AFAIK the only way to this is to migrate from Apollo Boost which configures a lot of things under the hood for you and set up Apollo Client manually. After migrating I was able to call onResetStore() as per the docs and everything is working :)
Apollo Boost migration:
https://www.apollographql.com/docs/react/advanced/boost-migration.html