Skip to content

Commit

Permalink
plugins: Use dynamic import instead of manual intermediate functions
Browse files Browse the repository at this point in the history
We want to avoid loading usage reporting protobuf until as late as
possible. Previously we had a specific file src/plugins/index.ts full of
little wrapper functions that call `require`. Now we use dynamic
`import` (which is compiled to CJS as `require` by tsc) instead.

We use "exports" in package.json to let you do deep imports from
particular files (only). Note that this still only supports CJS!
  • Loading branch information
glasser committed Jun 15, 2022
1 parent b81d29b commit 89530f7
Show file tree
Hide file tree
Showing 17 changed files with 139 additions and 220 deletions.
45 changes: 43 additions & 2 deletions packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,49 @@
"name": "@apollo/server",
"version": "3.6.7",
"description": "Core engine for Apollo GraphQL server",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "commonjs",
"exports": {
".": {
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./standalone": {
"require": "./dist/standalone/index.js",
"types": "./dist/standalone/index.d.ts"
},
"./plugin/cacheControl": {
"require": "./dist/plugin/cacheControl/index.js",
"types": "./dist/plugin/cacheControl/index.d.ts"
},
"./plugin/disabled": {
"require": "./dist/plugin/disabled.js",
"types": "./dist/plugin/disabled.d.ts"
},
"./plugin/drainHttpServer": {
"require": "./dist/plugin/drainHttpServer/index.js",
"types": "./dist/plugin/drainHttpServer/index.d.ts"
},
"./plugin/inlineTrace": {
"require": "./dist/plugin/inlineTrace/index.js",
"types": "./dist/plugin/inlineTrace/index.d.ts"
},
"./plugin/landingPage/default": {
"require": "./dist/plugin/landingPage/default/index.js",
"types": "./dist/plugin/landingPage/default/index.d.ts"
},
"./plugin/landingPage/graphqlPlayground": {
"require": "./dist/plugin/landingPage/graphqlPlayground/index.js",
"types": "./dist/plugin/landingPage/graphqlPlayground/index.d.ts"
},
"./plugin/schemaReporting": {
"require": "./dist/plugin/schemaReporting/index.js",
"types": "./dist/plugin/schemaReporting/index.d.ts"
},
"./plugin/usageReporting": {
"require": "./dist/plugin/usageReporting/index.js",
"types": "./dist/plugin/usageReporting/index.d.ts"
}
},
"repository": {
"type": "git",
"url": "https://github.com/apollographql/apollo-server",
Expand Down
32 changes: 19 additions & 13 deletions packages/server/src/ApolloServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,6 @@ import type {
} from './externalTypes';
import { runPotentiallyBatchedHttpQuery } from './httpBatching';
import { InternalPluginId, pluginIsInternal } from './internalPlugin';
import {
ApolloServerPluginCacheControl,
ApolloServerPluginInlineTrace,
ApolloServerPluginLandingPageLocalDefault,
ApolloServerPluginLandingPageProductionDefault,
ApolloServerPluginSchemaReporting,
ApolloServerPluginSchemaReportingOptions,
ApolloServerPluginUsageReporting,
} from './plugin';
import {
preventCsrf,
recommendedCsrfPreventionRequestHeaders,
Expand Down Expand Up @@ -395,7 +386,7 @@ export class ApolloServer<TContext extends BaseContext = BaseContext> {
try {
// Now that you can't call addPlugin any more, add default plugins like
// usage reporting if they're not already added.
this.addDefaultPlugins();
await this.addDefaultPlugins();

const toDispose: (() => Promise<void>)[] = [];
const executor = await schemaManager.start();
Expand Down Expand Up @@ -853,7 +844,7 @@ export class ApolloServer<TContext extends BaseContext = BaseContext> {
this.internals.state = { phase: 'stopped', stopError: null };
}

private addDefaultPlugins() {
private async addDefaultPlugins() {
const { plugins, apolloConfig, logger, nodeEnv } = this.internals;
const isDev = nodeEnv !== 'production';

Expand All @@ -865,6 +856,9 @@ export class ApolloServer<TContext extends BaseContext = BaseContext> {
// Special case: cache control is on unless you explicitly disable it.
{
if (!alreadyHavePluginWithInternalId('CacheControl')) {
const { ApolloServerPluginCacheControl } = await import(
'./plugin/cacheControl'
);
plugins.push(ApolloServerPluginCacheControl());
}
}
Expand All @@ -879,6 +873,9 @@ export class ApolloServer<TContext extends BaseContext = BaseContext> {
// Keep this plugin first so it wraps everything. (Unfortunately despite
// the fact that the person who wrote this line also was the original
// author of the comment above in #1105, they don't quite understand why this was important.)
const { ApolloServerPluginUsageReporting } = await import(
'./plugin/usageReporting'
);
plugins.unshift(ApolloServerPluginUsageReporting());
} else {
logger.warn(
Expand All @@ -898,8 +895,10 @@ export class ApolloServer<TContext extends BaseContext = BaseContext> {
const enabledViaEnvVar = process.env.APOLLO_SCHEMA_REPORTING === 'true';
if (!alreadyHavePlugin && enabledViaEnvVar) {
if (apolloConfig.key) {
const options: ApolloServerPluginSchemaReportingOptions = {};
plugins.push(ApolloServerPluginSchemaReporting(options));
const { ApolloServerPluginSchemaReporting } = await import(
'./plugin/schemaReporting'
);
plugins.push(ApolloServerPluginSchemaReporting());
} else {
throw new Error(
"You've enabled schema reporting by setting the APOLLO_SCHEMA_REPORTING " +
Expand All @@ -921,6 +920,9 @@ export class ApolloServer<TContext extends BaseContext = BaseContext> {
// federated" mode. (This is slightly different than the
// pre-ApolloServerPluginInlineTrace where we would also avoid doing
// this if an API key was configured and log a warning.)
const { ApolloServerPluginInlineTrace } = await import(
'./plugin/inlineTrace'
);
plugins.push(
ApolloServerPluginInlineTrace({ __onlyIfSchemaIsFederated: true }),
);
Expand All @@ -944,6 +946,10 @@ export class ApolloServer<TContext extends BaseContext = BaseContext> {
'LandingPageDisabled',
);
if (!alreadyHavePlugin) {
const {
ApolloServerPluginLandingPageLocalDefault,
ApolloServerPluginLandingPageProductionDefault,
} = await import('./plugin/landingPage/default');
const plugin: ApolloServerPlugin<TContext> = isDev
? ApolloServerPluginLandingPageLocalDefault()
: ApolloServerPluginLandingPageProductionDefault();
Expand Down
6 changes: 2 additions & 4 deletions packages/server/src/__tests__/ApolloServer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ import { ApolloServer } from '..';
import type { ApolloServerOptions, GatewayInterface } from '..';
import type { GraphQLSchema } from 'graphql';
import type { ApolloServerPlugin, BaseContext } from '../externalTypes';
import {
ApolloServerPluginCacheControlDisabled,
ApolloServerPluginUsageReporting,
} from '../plugin';
import { ApolloServerPluginCacheControlDisabled } from '../plugin/disabled';
import { ApolloServerPluginUsageReporting } from '../plugin/usageReporting';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { HeaderMap } from '../runHttpQuery';
import { mockLogger } from './mockLogger';
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/__tests__/express/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import http from 'http';
import {
ApolloServer,
ApolloServerOptions,
ApolloServerPluginDrainHttpServer,
BaseContext,
expressMiddleware,
} from '../..';
import { ApolloServerPluginDrainHttpServer } from '../../plugin/drainHttpServer';
import { urlForHttpServer } from '../../utils/urlForHttpServer';
import type {
CreateServerForIntegrationTestsOptions,
Expand Down
18 changes: 11 additions & 7 deletions packages/server/src/__tests__/integration/apolloServerTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,6 @@ import {
ApolloServerOptions,
ApolloServer,
GatewayInterface,
ApolloServerPluginInlineTrace,
ApolloServerPluginUsageReporting,
ApolloServerPluginUsageReportingOptions,
ApolloServerPluginLandingPageDisabled,
ApolloServerPluginLandingPageGraphQLPlayground,
ApolloServerPluginLandingPageLocalDefault,
ApolloServerPluginUsageReportingDisabled,
SchemaLoadOrUpdateCallback,
BaseContext,
GraphQLExecutor,
Expand All @@ -57,6 +50,17 @@ import type {
} from '.';
import { mockLogger } from '../mockLogger';
import gql from 'graphql-tag';
import {
ApolloServerPluginUsageReportingOptions,
ApolloServerPluginUsageReporting,
} from '../../plugin/usageReporting';
import { ApolloServerPluginInlineTrace } from '../../plugin/inlineTrace';
import {
ApolloServerPluginLandingPageDisabled,
ApolloServerPluginUsageReportingDisabled,
} from '../../plugin/disabled';
import { ApolloServerPluginLandingPageLocalDefault } from '../../plugin/landingPage/default';
import { ApolloServerPluginLandingPageGraphQLPlayground } from '../../plugin/landingPage/graphqlPlayground';

const quietLogger = loglevel.getLogger('quiet');
quietLogger.setLevel(loglevel.levels.WARN);
Expand Down
6 changes: 3 additions & 3 deletions packages/server/src/__tests__/integration/httpServerTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ import type {
CreateServerForIntegrationTests,
CreateServerForIntegrationTestsOptions,
} from '.';
import {
import type {
ApolloServer,
ApolloServerOptions,
ApolloServerPluginCacheControl,
ApolloServerPluginCacheControlDisabled,
BaseContext,
GraphQLRequestContext,
GraphQLRequestListener,
PersistedQueryOptions,
} from '../..';
import { ApolloServerPluginCacheControl } from '../../plugin/cacheControl';
import { ApolloServerPluginCacheControlDisabled } from '../../plugin/disabled';
import { PersistedQueryNotFoundError } from '../../errors';

const QueryRootType = new GraphQLObjectType({
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/__tests__/logger.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ApolloServer } from '../..';
import { ApolloServer } from '..';
import gql from 'graphql-tag';
import loglevel from 'loglevel';
import { mockLogger } from './mockLogger';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { GraphQLError } from 'graphql';
import {
ApolloServer,
ApolloServerPluginCacheControl,
ApolloServerPluginCacheControlOptions,
CacheHint,
HTTPGraphQLResponse,
} from '../../..';
} from '../../../plugin/cacheControl';
import { ApolloServer, CacheHint, HTTPGraphQLResponse } from '../../..';

describe('plugin', () => {
describe('willSendResponse', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { GraphQLSchema } from 'graphql';
import { ApolloServer, CacheHint } from '../../..';
import {
ApolloServer,
ApolloServerPluginCacheControl,
ApolloServerPluginCacheControlOptions,
CacheHint,
} from '../../..';
} from '../../../plugin/cacheControl';

export async function collectCacheControlHintsAndPolicyIfCacheable(
schema: GraphQLSchema,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import {
ApolloServer,
ApolloServerPluginSchemaReporting,
ApolloServerPluginUsageReportingDisabled,
} from '../../..';
import { ApolloServer } from '../../..';
import { ApolloServerPluginUsageReportingDisabled } from '../../../plugin/disabled';
import { ApolloServerPluginSchemaReporting } from '../../../plugin/schemaReporting';

describe('end-to-end', () => {
it('fails for unparsable overrideReportedSchema', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ import { gunzipSync } from 'zlib';
import { HeaderMap } from '../../../runHttpQuery';
import {
ApolloServer,
ApolloServerPluginCacheControlDisabled,
ApolloServerPluginUsageReporting,
ApolloServerPluginUsageReportingOptions,
GraphQLRequestContextDidResolveOperation,
GraphQLRequestMetrics,
} from '../../..';
import {
ApolloServerPluginUsageReportingOptions,
ApolloServerPluginUsageReporting,
} from '../../../plugin/usageReporting';
import { ApolloServerPluginCacheControlDisabled } from '../../../plugin/disabled';

const quietLogger = loglevel.getLogger('quiet');
quietLogger.setLevel(loglevel.levels.WARN);
Expand Down
3 changes: 2 additions & 1 deletion packages/server/src/__tests__/standalone/integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ApolloServer, startStandaloneServer } from '../..';
import { ApolloServer } from '../..';
import type { ApolloServerOptions, BaseContext } from '../..';
import { startStandaloneServer } from '../../standalone';
import type {
CreateServerForIntegrationTestsOptions,
CreateServerForIntegrationTestsResult,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ApolloServer, startStandaloneServer } from '../..';
import { ApolloServer } from '../..';
import { startStandaloneServer } from '../../standalone';

describe('Typings: TContext inference', () => {
it('correctly infers BaseContext when no `context` function is provided', async () => {
Expand Down
7 changes: 0 additions & 7 deletions packages/server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,5 @@ export {

export { ApolloServer } from './ApolloServer';
export { expressMiddleware } from './express';
export { startStandaloneServer } from './standalone';

export * from './externalTypes';

export * from './plugin';

// TODO(AS4): We do need to export usage reporting protobuf for the purpose of
// gateway, but we really don't want that to be in top level. Look into this as
// part of #6243.
42 changes: 42 additions & 0 deletions packages/server/src/plugin/disabled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// TODO(AS4): Document this file
// TODO(AS4): Decide where it is imported from.
import type { BaseContext, ApolloServerPlugin } from '..';
import type {
InternalApolloServerPlugin,
InternalPluginId,
} from '../internalPlugin';

function disabledPlugin<TContext extends BaseContext>(
id: InternalPluginId,
): ApolloServerPlugin<TContext> {
const plugin: InternalApolloServerPlugin<TContext> = {
__internal_plugin_id__() {
return id;
},
};
return plugin;
}

export function ApolloServerPluginCacheControlDisabled<
TContext extends BaseContext,
>(): ApolloServerPlugin<TContext> {
return disabledPlugin('CacheControl');
}

export function ApolloServerPluginInlineTraceDisabled<
TContext extends BaseContext,
>(): ApolloServerPlugin<TContext> {
return disabledPlugin('InlineTrace');
}

export function ApolloServerPluginLandingPageDisabled<
TContext extends BaseContext,
>(): ApolloServerPlugin<TContext> {
return disabledPlugin('LandingPageDisabled');
}

export function ApolloServerPluginUsageReportingDisabled<
TContext extends BaseContext,
>(): ApolloServerPlugin<TContext> {
return disabledPlugin('UsageReporting');
}
Loading

0 comments on commit 89530f7

Please sign in to comment.