fix: keep graphql import as require in cjs (#2258)

This commit is contained in:
Artem Zakharchenko
2024-09-04 10:11:40 +02:00
committed by GitHub
parent d5b87b353f
commit bdcb4df522
3 changed files with 44 additions and 7 deletions
@@ -0,0 +1,34 @@
import fs from 'fs/promises'
import type { Plugin } from 'esbuild'
/**
* A plugin to replace `require('graphql')` statements with `await import('graphql')`
* only for ESM bundles. This makes the GraphQL module to be imported lazily
* while maintaining the CommonJS compatibility.
* @see https://github.com/mswjs/msw/issues/2254
*/
export function graphqlImportPlugin(): Plugin {
return {
name: 'graphql-import-plugin',
setup(build) {
if (build.initialOptions.format !== 'esm') {
return
}
build.onLoad({ filter: /\.ts$/ }, async (args) => {
const contents = await fs.readFile(args.path, 'utf-8')
const match = /require\(['"]graphql['"]\)/g.exec(contents)
if (match) {
return {
loader: 'ts',
contents:
contents.slice(0, match.index - 1) +
`await import('graphql').catch((error) => {console.error('[MSW] Failed to parse a GraphQL query: cannot import the "graphql" module. Please make sure you install it if you wish to intercept GraphQL requests. See the original import error below.'); throw error})` +
contents.slice(match.index + match[0].length),
}
}
})
},
}
}
@@ -40,12 +40,14 @@ export function parseDocumentNode(node: DocumentNode): ParsedGraphQLQuery {
}
async function parseQuery(query: string): Promise<ParsedGraphQLQuery | Error> {
const { parse } = await import('graphql').catch((error) => {
devUtils.error(
'Failed to parse a GraphQL query: cannot import the "graphql" module. Please make sure you install it if you wish to intercept GraphQL requests. See the original import error below.',
)
throw error
})
/**
* @note Use `require` to get the "graphql" module here.
* It has to be scoped to this function because this module leaks to the
* root export. It has to be `require` because tools like Jest have trouble
* handling dynamic imports. It gets replaced with a dynamic import on build time.
*/
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { parse } = require('graphql')
try {
const ast = parse(query)
+2 -1
View File
@@ -7,6 +7,7 @@ import {
} from './config/plugins/esbuild/copyWorkerPlugin'
import { resolveCoreImportsPlugin } from './config/plugins/esbuild/resolveCoreImportsPlugin'
import { forceEsmExtensionsPlugin } from './config/plugins/esbuild/forceEsmExtensionsPlugin'
import { graphqlImportPlugin } from './config/plugins/esbuild/graphQLImportPlugin'
import packageJson from './package.json'
// Externalize the in-house dependencies so that the user
@@ -33,7 +34,7 @@ const coreConfig: Options = {
sourcemap: true,
dts: true,
tsconfig: path.resolve(__dirname, 'src/tsconfig.core.build.json'),
esbuildPlugins: [forceEsmExtensionsPlugin()],
esbuildPlugins: [graphqlImportPlugin(), forceEsmExtensionsPlugin()],
}
const nodeConfig: Options = {