I'm trying to solve memory leaks in my Node.js app and seems this code does leak
const ApolloClient = require('apollo-client').ApolloClient;
const fetch = require('node-fetch');
const createHttpLink = require('apollo-link-http').createHttpLink;
const InMemoryCache = require('apollo-cache-inmemory').InMemoryCache;
const httpLink = createHttpLink({
uri: 'http://xxxxxx',
fetch: fetch
});
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache()
});
module.exports = (app) => {
app.post('/graphql', async (req, res, next) => {
try {
const data = await client.query({
query: 'xxxxxxx',
variables: 'xxxxxxx'
});
return res.json(data);
} catch (err) {
return next('error');
}
});
};
so ApolloClient client recreates every time since it's a global. Is it better to define it inside the route? Won't it cause performance issues then?
const ApolloClient = require('apollo-client').ApolloClient;
const fetch = require('node-fetch');
const createHttpLink = require('apollo-link-http').createHttpLink;
const InMemoryCache = require('apollo-cache-inmemory').InMemoryCache;
module.exports = (app) => {
app.post('/graphql', async (req, res, next) => {
try {
let httpLink = createHttpLink({
uri: 'http://xxxxxx',
fetch: fetch
});
let client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache()
});
const data = await client.query({
query: 'xxxxxxx',
variables: 'xxxxxxx'
});
httpLink = null
client = null
return res.json(data);
} catch (err) {
return next('error');
}
});
};
Creating one ApolloClient instance and reusing it is better for many reasons.
Consider having 20 or more (N) endpoints/middlewares that needs to access some data that is stored in your database. Creating an ApolloClient instance for each one would mean N number of instances. This is not performant and violates and violates the 'Do not repeat yourself' coding rule.
On the other hand creating one instance and using it throughout the app is very handy. Consider this example:
const ApolloClient = require('apollo-client').ApolloClient;
const fetch = require('node-fetch');
const createHttpLink = require('apollo-link-http').createHttpLink;
const InMemoryCache = require('apollo-cache-inmemory').InMemoryCache;
const httpLink = createHttpLink({
uri: 'http://xxxxxx',
fetch: fetch
});
// instantiating
module.exports = new ApolloClient({
link: httpLink,
cache: new InMemoryCache()
});
a module:
const dbClient = require('./db_client')
module.exports = (app) => {
app.post('/graphql', async (req, res, next) => {
try {
const data = await dbClient.query({
query: 'xxxxxxx',
variables: 'xxxxxxx'
});
return res.json(data);
} catch (err) {
return next('error');
}
});
};
another module:
const dbClient = require('./db_client')
...
another module:
const dbClient = require('./db_client')
...
As can be seen, with just one instance we can achieve a more robust and performant application.