Solution for large bundle size
See original GitHub issueHi There
First, a huge thank you to @manueliglesias - absolutely love appsync.
The problem (as others have pointed out) is the bundle size. It is huge, and the reason it is big is mainly because the entire AWS-SDK is imported. Even if one is not using any feature on the client that needs it. I have two suggestions:
- Allow consumers to consume the raw “unprocessed” version, and then in our build process, we can use something like Webpack that would minify and treeshake.
- Setup the project in such a way that allows a consumer to configure their options and therefore they can opt out of the expensive (in terms of size) options.
Unfortunately, I could not wait: Using aws-appsync-client in it’s current state adds almost 500kb (uncompressed) to our build, which was a blocker. Therefore I stripped things down (and things seem to work). I will provide my solution here for anyone interested, and also @manueliglesias I would appreciate it if you could comment on it.
The following code will create an Apollo client that users openId tokens for auth and subscriptions:
import ApolloClient from 'apollo-client';
import fetch from 'isomorphic-fetch';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';
import { setContext } from 'apollo-link-context';
import { ApolloLink } from 'apollo-link';
import { getMainDefinition } from 'apollo-utilities';
import { SubscriptionHandshakeLink } from 'aws-appsync/lib/link/subscription-handshake-link'; // importing directly so AWS-SDK does not get introduced
import { NonTerminatingHttpLink } from 'aws-appsync/lib/link/non-terminating-http-link';
import { onError } from 'apollo-link-error';
import { logError } from 'client/common/log';
// The singleton client instance
let apolloClient = null;
// Polyfill fetch() on the server (used by apollo-client)
if (!process.browser) {
global.fetch = fetch;
}
const createApolloClient = (jwtTokenFunc, initialState) => {
// Allows for custom logic when a GraphQL or network error occurs
const onErrorLink = onError(({ graphQLErrors, networkError, response }) => {
if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path }) => {
const error = new Error(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`);
logError(error);
});
}
if (networkError) logError(new Error(`[Network error]: ${networkError}`));
response.errors = null;
});
// This is very simple auth middleware - if using openId auth token
// you really only need to provide the token as an authorization field
// in the header
const authOpenIdConnectLink = setContext((_, { headers }) => (
jwtTokenFunc()
.then(idToken => ({
headers: {
...headers,
authorization: idToken || '',
},
}))
));
// This logic (mostly) copied from appsync's apollo client creation
const link = ApolloLink.from([
authOpenIdConnectLink,
onErrorLink,
ApolloLink.split(
(operation) => {
const { query } = operation;
const { kind, operation: graphqlOperation } = getMainDefinition(query);
const isSubscription = kind === 'OperationDefinition' && graphqlOperation === 'subscription';
return isSubscription;
},
ApolloLink.from([
new NonTerminatingHttpLink('subsInfo', { uri: GRAPHQL_URL }, true),
new SubscriptionHandshakeLink('subsInfo'),
]),
ApolloLink.from([
new HttpLink({ uri: GRAPHQL_URL }),
]),
),
]);
return new ApolloClient({
connectToDevTools: process.browser,
ssrMode: !process.browser, // Disables forceFetch on the server (so queries are only run once)
link,
cache: new InMemoryCache().restore(initialState),
});
};
Issue Analytics
- State:
- Created 5 years ago
- Reactions:17
- Comments:7
Top GitHub Comments
I would love a comment on this too. I’m looking so much forward to getting to build apps with AppSync. With people calling the aws-appsync library “merely a wrapper of the apollo-client”, it surprises me to see the apollo-client only taking up 7% of the bundle size.
Any comments?
We use appsync too but we put it under a feature module which save like ~55% (1MB) from the main bundle.