Im working an app using react for the frontend and apollo/client and graphql. It works perfectly on the localhost, but when I deploy to heroku it only works if I also have the app running on the localhost.
Here is what I have for the uri.
const client = new ApolloClient({
uri: 'https://localhost:5000/graphql',
cache: new InMemoryCache(),
});
I tried setting the uri localhost then if in production to set it to heroku:
let uri = https://localhost:5000/graphql
if (process.env.NODE_ENV === 'production') {
uri = https://denver-judo.herokuapp.com/graphql
}
I also tried uri = https://denver-judo.herokuapp.com/${PORT}/graphql
but nothing works.
This is my app.js file
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
import { useState } from 'react';
import {
Route,
Routes,
BrowserRouter as Router,
Outlet,
} from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import HomeScreen from './screens/HomeScreen';
import Container from 'react-bootstrap/Container';
import Navbar from 'react-bootstrap/Navbar';
import Nav from 'react-bootstrap/Nav';
import { LinkContainer } from 'react-router-bootstrap';
import Button from 'react-bootstrap/Button';
import AboutScreen from './screens/AboutScreen';
import AdminScreen from './screens/AdminScreen';
// Construct main GraphQL API endpoint
let uri = 'https://localhost:5000/graphql';
if (process.env.NODE_ENV === 'production') {
uri = `https://denver-judo.herokuapp.com/api/graphql`;
}
console.log(process.env.NODE_ENV);
console.log(uri);
const client = new ApolloClient({
uri: uri,
cache: new InMemoryCache(),
});
function App() {
const location = window.location.pathname;
const [sidebarIsOpen, setSidebarIsOpen] = useState(false);
return (
<ApolloProvider client={client}>
<Router>
<div
className={
sidebarIsOpen
? 'site-container active-cont d-flex flex-column'
: 'site-container d-flex flex-column'
}
>
<ToastContainer position="top-center" limit={1} />
<header>
<Navbar
expand="lg"
className={`navbar navbar-dark ${
location === '/' ? 'navbar-custom' : 'navbar-custom-light'
}`}
>
<Container>
<LinkContainer to="/">
<Navbar.Brand>
<img
className="ms-4"
src={
location === '/'
? 'assets/img/DJ-logo-black.png'
: 'assets/img/DJ-logo-white.png'
}
alt="Denver Judo"
style={{ width: '60px' }}
/>{' '}
</Navbar.Brand>
</LinkContainer>
<h1
className={
location === '/'
? 'navTitle-dark text-center'
: 'navTitle text-center'
}
>
Denver Judo
</h1>
<Button
style={{
backgroundColor: location === '/' ? '#d9d9d9' : '#262626',
}}
onClick={() => setSidebarIsOpen(!sidebarIsOpen)}
className="me-4"
>
<i
className="fa fa-bars fa-lg"
style={{
color: location === '/' ? '#262626' : '#d9d9d9',
}}
></i>
</Button>
</Container>
</Navbar>
</header>
<div
className={
sidebarIsOpen
? 'active-nav side-navbar d-flex justify-content-between flex-wrap flex-column'
: 'side-navbar d-flex justify-content-between flex-wrap flex-column'
}
>
<Nav className="flex-column text-white w-100 p-2">
<Nav.Item>
<strong>Denver Judo</strong>
</Nav.Item>
<LinkContainer to="/" onClick={() => (this.expand = '')}>
<Nav.Link
className={
location === '/' ? 'nav-text nav-text-bold' : 'nav-text'
}
>
Home
</Nav.Link>
</LinkContainer>
<LinkContainer to="/schedule" onClick={() => (this.expand = '')}>
<Nav.Link
className={
location === '/schedule'
? 'nav-text nav-text-bold'
: 'nav-text'
}
>
Schedule
</Nav.Link>
</LinkContainer>
<LinkContainer to="/about" onClick={() => (this.expand = '')}>
<Nav.Link
className={
location === '/about'
? 'nav-text nav-text-bold'
: 'nav-text'
}
>
About
</Nav.Link>
</LinkContainer>
</Nav>
<Outlet />
</div>
<main>
<Routes>
<Route index element={<HomeScreen />} />
<Route path="/about" element={<AboutScreen />} />
<Route path="_admin/*" element={<AdminScreen />} />
</Routes>
</main>
<footer>
<div className="text-center">
Denver Judo
<br />
All rights reserved
</div>
</footer>
</div>
</Router>
</ApolloProvider>
);
}
export default App;
Here is the server.js from the backend:
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const path = require('path');
const dotenv = require('dotenv');
const { typeDefs, resolvers } = require('./schemas');
const db = require('./config/connection');
require('dotenv');
dotenv.config();
const PORT = process.env.PORT || 5000;
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers,
});
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
console.log(process.env.NODE_ENV);
if (process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../client/build')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../client/build/index.html'));
});
}
// Create a new instance of an Apollo server with the GraphQL schema
const startApolloServer = async (typeDefs, resolvers) => {
await server.start();
server.applyMiddleware({ app });
db.once('open', () => {
app.listen(PORT, () => {
console.log(`API server running on port ${PORT}!`);
console.log(
`Use GraphQL at https://localhost:${PORT}${server.graphqlPath}`
);
});
});
};
// Call the async function to start the server
startApolloServer(typeDefs, resolvers);
3
2 Answers
It seems you are trying to access but aren’t setting the /api/graphql
path. Also the apollo-server-express
library is depreciated. I recommend following the Migrating to Apollo Server 4 guide which highlights how to set the graphql path using app.use
. Otherwise the default graphql path is /
in v3. In v4 it’s /graphql
.
In v4 it’s set like this:
app.use(
'/graphql',
cors<cors.CorsRequest>(),
json(),
expressMiddleware(server, {
context: async ({ req }) => ({ token: req.headers.token }),
}),
);
You have CORS issue. So you should allow cross origin requests.
const cors = require('cors')
app.use(cors())
Your frontend prod is available on Heroku URL
https://denver-judo.herokuapp.com/api/graphql
The backend on both envs is listened on https://localhost:PORT
So the client side makes requests to the different host
https://denver-judo.herokuapp.com/api/graphql
=> https://localhost:PORT
and browser is blocking it due to security risks (CORS policy)
This worked for my Angular+Nestjs+Graphql application.
What does your
Procfile
look like, as well as your index.js that startsApolloServer
?Feb 19 at 5:30
I updated the question with the app.js file where I have the apollo ApolloServer code but I don't hae a Procfile. I've never used one but haven't had this problem before.
Feb 19 at 13:21
Are you on Apollo 3 or 4?
Feb 19 at 15:53