Function cannot import relative .graphql type definition file

I’ve just rewritten a Node.js GraphQL API from an old version of graphql-yoga + prisma to using express, serverless-http, prisma, and apollo-server-express. I’ve got it working locally just fine as an Express app, but when I try to get it published on Netlify as Function, I get a “Cannot find module” error:

{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module './schema.graphql'\nRequire stack:\n- /var/task/bundle/index.js\n- /var/task/graphql.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",
"trace": [
"Runtime.ImportModuleError: Error: Cannot find module './schema.graphql'",
"Require stack:",
"- /var/task/bundle/index.js",
"- /var/task/graphql.js",
"- /var/runtime/UserFunction.js",
"- /var/runtime/index.js",
"    at _loadUserApp (/var/runtime/UserFunction.js:100:13)",
"    at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
"    at Object.<anonymous> (/var/runtime/index.js:43:30)",
"    at Module._compile (internal/modules/cjs/loader.js:1156:30)",
"    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1176:10)",
"    at Module.load (internal/modules/cjs/loader.js:1000:32)",
"    at Function.Module._load (internal/modules/cjs/loader.js:899:14)",
"    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)",
"    at internal/main/run_main_module.js:18:47"
]
}

I’ve tried multiple ways of importing these graphql files (graphql-imports, require.resolve, fs.readDirSync, etc.), but either it doesn’t work at all or it only works from the project root. require.resolve works from the project root locally, so I’m left thinking that this file just wasn’t included in the build. How can I tell what gets zipped?

My netlify.toml is:

[build]
  command = "npm run bundle"
  functions = "functions"

npm run bundle is basically cpx 'src/**/*' 'functions/bundle'and the files are visible locally in functions/bundle/schema.graphql and functions/bundle/generated/prisma.graphql.

My functions/graphql.js just takes the Express server and creates a lambda wrapper:

const serverlessHttp = require("serverless-http");

const { app } = require("./bundle/index.js");

exports.handler = serverlessHttp(app, {
  request(req, event, context) {
    req.event = event;
    req.context = context;
  }
});

“graphql-import” is super annoying because it only works from the root for the project, so copying the src/ files into functions/bundle/ changes the directory structure and those imports no longer work
Inside the functions/bundle/index.js, I try to require.resolve some .grapqhl type definition files:

const { importSchema } = require("graphql-import");

const typeDefs = importSchema(require.resolve("./schema.graphql"));
const prismaTypeDefs = importSchema(
  require.resolve("./generated/prisma.graphql")
);

const db = new Prisma({
  typeDefs: prismaTypeDefs,
  endpoint: process.env.PRISMA_ENDPOINT,
  secret: process.env.PRISMA_SECRET,
  debug: process.env.NODE_ENV === "development"
});

const schema = makeExecutableSchema({
  typeDefs: gql`
    ${typeDefs}
  `,
  resolvers: {
    Mutation,
    Query,
  },
  resolverValidationOptions: { requireResolversForResolveType: false }
});

Again, this works locally so I assume the file is just outright missing from the zipped files.

I’m at a loss. Any ideas??

Hi, so I think the issue is that you’re trying to require a file using a specific path but when it gets included in the function that path for that file has changed. I have a function (https://github.com/depadiernos/function-deploy-test/blob/master/lambda/zipped-function/zipped-function.js#L6) that shows the path where included files will be located. Let me know if that helps.

Hi @Dennis,

I’ll give that a try, but for some reason I can’t quite get all gears aligned to properly deploy anymore. Your repo was very helpful, though I’m still not able to get this working. I tried your /lambda/bundled-function way, but I kept getting errors about zip not being found on the system:

12:52:15 PM: zip I/O error: No such file or directory
12:52:15 PM: zip error: Could not create output file (./functions/graphql.zip)
12:52:15 PM: npm
12:52:15 PM:  ERR! code ELIFECYCLE
12:52:15 PM: npm
12:52:15 PM:  ERR!
12:52:15 PM: errno 15
12:52:15 PM: npm
12:52:15 PM: ERR! offroad-club-backend@1.0.0 bundle: `cd lambda; npm i; cd ..; zip -r ./functions/graphql.zip lambda`
12:52:15 PM: npm
12:52:15 PM: ERR! Exit status 15

I also tried your /lambda/zipped-function way, but I get errors about a Vue module not being found (?? I’m not using Vue anywhere):

12:59:39 PM: ModuleNotFoundError: Module not found: Error: Can't resolve 'vue' in '/opt/build/repo/node_modules/vue-template-compiler'
12:59:39 PM:     at factory.create (/opt/build/repo/node_modules/webpack/lib/Compilation.js:925:10)
12:59:39 PM:     at factory (/opt/build/repo/node_modules/webpack/lib/NormalModuleFactory.js:401:22)
12:59:39 PM:     at resolver (/opt/build/repo/node_modules/webpack/lib/NormalModuleFactory.js:130:21)
12:59:39 PM:     at asyncLib.parallel (/opt/build/repo/node_modules/webpack/lib/NormalModuleFactory.js:224:22)
12:59:39 PM:     at /opt/build/repo/node_modules/neo-async/async.js:2830:7
12:59:39 PM:     at /opt/build/repo/node_modules/neo-async/async.js:6877:13
12:59:39 PM:     at normalResolver.resolve (/opt/build/repo/node_modules/webpack/lib/NormalModuleFactory.js:214:25)
12:59:39 PM:     at doResolve (/opt/build/repo/node_modules/enhanced-resolve/lib/Resolver.js:213:14)
12:59:39 PM:     at hook.callAsync (/opt/build/repo/node_modules/enhanced-resolve/lib/Resolver.js:285:5)
12:59:39 PM:     at _fn0 (eval at create (/opt/build/repo/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
12:59:39 PM:     at resolver.doResolve (/opt/build/repo/node_modules/enhanced-resolve/lib/UnsafeCachePlugin.js:44:7)
12:59:39 PM:     at hook.callAsync (/opt/build/repo/node_modules/enhanced-resolve/lib/Resolver.js:285:5)
12:59:39 PM:     at _fn0 (eval at create (/opt/build/repo/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
12:59:39 PM:     at hook.callAsync (/opt/build/repo/node_modules/enhanced-resolve/lib/Resolver.js:285:5)
12:59:39 PM:     at _fn0 (eval at create (/opt/build/repo/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:27:1)
12:59:39 PM:     at resolver.doResolve (/opt/build/repo/node_modules/enhanced-resolve/lib/DescriptionFilePlugin.js:67:43)
12:59:39 PM: resolve 'vue' in '/opt/build/repo/node_modules/vue-template-compiler'

I’ve even tried various combinations of your /functions/zisi-function method, but that’s what led me to the original bundling problem to begin with. I’m just going in circles hah

Repo: https://github.com/cfree/offroad-api

@Dennis Any ideas? I’m not able to use Netlify because I can’t successfully deploy anything…

Hey @cfree,

This error…

12:52:15 PM: zip I/O error: No such file or directory
12:52:15 PM: zip error: Could not create output file (./functions/graphql.zip)

…would actually imply that it can’t find the .zip. Can you check that you’re in the correct directory when executing this command within your build command?

@Pieparker I gave up on this approach, so we can probably close this post. I eventually was able to get the netlify-lambda serve working locally, though that has its own issues: Netlify-lambda serve infinite loop

Hey @cfree,

Not a problem. We’ll keep the post up for posterity!

1 Like