Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deploying Prisma with AWS Lambda and Webpack #2303

Open
dested opened this issue Apr 26, 2020 · 29 comments
Open

Deploying Prisma with AWS Lambda and Webpack #2303

dested opened this issue Apr 26, 2020 · 29 comments
Labels
bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. kind/bug A reported bug. team/client Issue for team Client. topic: deployment-platform topic: prisma-client topic: Query engine ... could not be found. Query engine ... for current platform ... could not be found. topic: serverless framework topic: serverless topic: webpack topic: windows

Comments

@dested
Copy link

dested commented Apr 26, 2020

Bug description

I want to start off by saying I am absolutely in love with the prisma platform, and everything it provides, and I can't state enough how much I appreciate the efforts of the entire team. Thank you.

I have spent the better part of a weekend trying in earnest to deploy a simple rest api using prisma2, unsuccessfully for one reason or another. While I am deploying and building on windows (which is obviously an issue with the binary), I have also tried to build and deploy from wsl, as well as github actions (both debian base, while lambda is centos based). I have tried every webpack configuration I could think of, including every possible binary I can scrounge up (for instance, manually copying query-engine-rhel-openssl-1.0.x into the directory), all with zero luck. I have tried outputting prisma client to a directory that is not node_modules, copying that, referencing it, all with no changes. My initial thinking was that because I am building on windows it was causing issues, and while it was causing an issue, not using windows did not solve my problems.

I know there are a handful of issues that address this in bits and pieces, some old, some really old, some about Windows, some about chmod, some about serverless, some about photon, I have been through all of them with no success.

The majority of the time my error is simply:

Query engine binary for current platform "rhel-openssl-1.0.x" could not be found.
This probably happens, because you built Prisma Client on a different platform.
(Prisma Client looked in "/query-engine-rhel-openssl-1.0.x")

Files in /:

  bin
  boot
  dev
  etc
  home
  lib
  lib64
  media
  mnt
  opt
  proc
  root
  run
  sbin
  srv
  sys
  tmp
  usr
  var

You already added the platforms "native", "rhel-openssl-1.0.x" to the "generator" block
in the "schema.prisma" file as described in https://pris.ly/d/client-generator,
but something went wrong. That's suboptimal.

Needless to say, it's been suboptimal. Before I continue down my journey into madness, my question is simply: is this a valid usecase? Is it possible to have prisma deployed to aws lambda (ideally using the serverless framework)?

How to reproduce

  1. Build a simple serverless app
  2. Add a simple prisma schema
  3. Deploy to aws lambda
  4. Attempt to query the database

Expected behavior

Query completes successfully

Prisma information

"@prisma/client": "^2.0.0-beta.3",
"@prisma/cli": "^2.0.0-beta.3",

Environment & setup

  • OS: Windows, WSL, and Ubuntu-latest via github actions

  • Database: PostgreSQL

  • Prisma version: @prisma/cli : 2.0.0-beta.3
    Current platform : windows
    Query Engine : query-engine 2fb8f44
    Migration Engine : migration-engine-cli 2fb8f44
    Introspection Engine : introspection-core 2fb8f44

  • Node.js version: v12.16.2

@dested
Copy link
Author

dested commented Apr 26, 2020

As is typical, all roads lead back to webpack!

I was finally able to get this working, although not exactly on windows (see below), although it does work with standard WSL. The main issue was serverless webpack running another yarn install prior to packaging, which was not running my prisma generate properly. This caused my @prisma/client to be either empty, or at least not include the required binaries. Moral of the story, you cannot simply let webpack package @prisma/client as it will roll in all the js, but not keep any binaries around.

Here is my final setup:

Serverless.aml

plugins:
  - serverless-webpack

provider:
  name: aws

custom:
  webpack:
    webpackConfig: 'webpack.config.js'
    includeModules: true # This is required
    packager: 'yarn'
    packagerOptions:
      scripts: # this is the magic
        - prisma generate 

webpack.config.js (standard serverless webpack stuff excluded)

const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  externals: [nodeExternals()], // this is required
  plugins: [
    new CopyWebpackPlugin(['./schema.prisma']), // without this the prisma generate above will not work
   ]
};

prisma.schema

generator client {
  provider      = "prisma-client-js"
  binaryTargets = ["native", "rhel-openssl-1.0.x"]
}

With these three things I was able to build and deploy the serverless api from osx while still using serverless-webpack. The real magic is the copy of the schema file, and running the prisma generate script post build.

Unfortunately I cannot deploy from windows currently as when I run primsa generate with the above schema it simply hangs forever. When I remove rhel-oplenssl-1.0x from the binaryTargets it succeeds, but only generates the windows binary. Ideally on windows it would be nice to be able to generate whichever binary is specified, even though it can't be ran.

I hope this helps someone in the future!

I am going to leave this open for now, at the discretion of the owners, as I still cannot deploy from windows, but the bulk of the issue (deploying prisma2 using serverless, serverless webpack, to aws lambda) has been solved.

@AmoDinho
Copy link

You are a hero bruv! 🔥

@mateo2181
Copy link

@dested Thanks!! 🙌

@AlissonEnz
Copy link

I'm getting the following error Error: yarn run script0 failed with code 1 😢

@dested
Copy link
Author

dested commented Apr 27, 2020

If you put SLS_DEBUG=* into your path itll give you the expanded error, but more than likely its due to prisma not being found. The only way I was able to get around this was making sure prisma cli was installed globally npm install -g @prisma/cli before running the command.

@AlissonEnz
Copy link

@dested installing @prisma/cli globally worked here! Thanks 😄

@divyenduz
Copy link
Contributor

divyenduz commented Apr 28, 2020

@dested Thanks for the great write up. You are using webpack to bundle your application and you need to copy the binaries over. In your case, you are using Prisma generate via webpack to do so, while that would also work, the faster way to do it will be to copy the binaries directly.

This is where we touch on that in the docs https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/module-bundlers

Does that make sense? Please feel free to ask further questions.

P.S. I edited the issue title to reflect its state better, please let me know if you do not agree with it.

@divyenduz divyenduz changed the title Is it possible to use prisma2 in an aws lambda environment? Deploying Prisma with AWS Lambda and Webpack Apr 28, 2020
@dested
Copy link
Author

dested commented Apr 28, 2020

@divyenduz, the new title is perfect.

So there are a couple of issues that I ran into along the way that makes simply using webpack copy insufficient, specifically that serverless-webpack runs its own yarn install --production, which by default does not kick off the postinstall script, which was clobbering my @prisma/client folder (causing the "prisma client not generated" error at runtime). The second was the location it searches for the binaries, and frankly access to the binaries themselves. It may have been my fault, but no amount of environment variable pathing for the query engine binary was enough to satisfy prisma. That is why I opted to lean on default behavior as much as possible and simply 1. force serverless webpack to run generate post install, 2. force webpack to not bundle up my @prisma/client using nodeExternals(), and 3. manually copy over my schema file (which tbh im not 100% sure is needed) afterwords.

On the note about simply copying over the binaryTargets for other platforms when on windows, it very strangely just fails silently. Because of this, to deploy I must switch to WSL, which is more annoying than anything. I will post that as a separate issue later today after I try to track down exactly what is failing.

Thanks for your support!

@Q00
Copy link

Q00 commented May 18, 2020

thank you very much @dested 🔥👍

@Q00
Copy link

Q00 commented May 18, 2020

thank you very much @dested 🔥👍
I finally decided to use docker with prisma. But I think copy-webpack-plugin is very good way to use serverless.

I have a one more question. @dested

I am getting this following error below
image

How can I do ?

This is my webpack.config.js

const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  entry: slsw.lib.entries,
  target: 'node',
  // Generate sourcemaps for proper error messages
  devtool: 'source-map',
  // Since 'aws-sdk' is not compatible with webpack,
  // we exclude all node dependencies
  externals: [nodeExternals()],
  mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
  optimization: {
    // We do not want to minimize our code.
    minimize: false,
  },
  performance: {
    // Turn off size warnings for entry points
    hints: false,
  },

  plugins: [
    new CopyWebpackPlugin(['./prisma/schema.prisma']), // without this the prisma generate above will not work
  ],
  // Run babel on all .js files and skip those in node_modules
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: __dirname,
        exclude: /node_modules/,
      },
    ],
  },
};

@Q00
Copy link

Q00 commented May 18, 2020

I solved

thank you very much @dested 🔥👍
I finally decided to use docker with prisma. But I think copy-webpack-plugin is very good way to use serverless.

I have a one more question. @dested

I am getting this following error below
image

How can I do ?

This is my webpack.config.js

const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  entry: slsw.lib.entries,
  target: 'node',
  // Generate sourcemaps for proper error messages
  devtool: 'source-map',
  // Since 'aws-sdk' is not compatible with webpack,
  // we exclude all node dependencies
  externals: [nodeExternals()],
  mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
  optimization: {
    // We do not want to minimize our code.
    minimize: false,
  },
  performance: {
    // Turn off size warnings for entry points
    hints: false,
  },

  plugins: [
    new CopyWebpackPlugin(['./prisma/schema.prisma']), // without this the prisma generate above will not work
  ],
  // Run babel on all .js files and skip those in node_modules
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: __dirname,
        exclude: /node_modules/,
      },
    ],
  },
};

I solved my issue

plugins: [
    new CopyWebpackPlugin({ patterns: ['./prisma/schema.prisma'] }), // without this the prisma generate above will not work
  ],

@manavm1990
Copy link

@dested Thanks for the great write up. You are using webpack to bundle your application and you need to copy the binaries over. In your case, you are using Prisma generate via webpack to do so, while that would also work, the faster way to do it will be to copy the binaries directly.

This is where we touch on that in the docs https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/module-bundlers

Does that make sense? Please feel free to ask further questions.

P.S. I edited the issue title to reflect its state better, please let me know if you do not agree with it.

  Query engine binary for current platform "darwin" could not be found.
This probably happens, because you built Prisma Client on a different platform.
(Prisma Client looked in "/query-engine-darwin")

Files in /:

Why in the heck is Prisma Client looking at the top path of my freaking 💻 ? 🗯️

I am configuring in webpack like this one:

plugins: [
    new CopyWebpackPlugin({
      patterns: [
        {
          from: path.join(
            __dirname,
            "node_modules/@prisma/cli/query-engine-darwin"
          ),

          // 'dist' is just the 'webpack' default
          to: path.join(__dirname, "dist"),
        },
      ],
    }),
  ],

It doesn't matter whether it copies or not because the code from 'dist/main.js' seems to always look 👀 at the top-level absolute path on my 💻 . Why???????? 😱

@sheldonj
Copy link

sheldonj commented Oct 20, 2020

Does someone have a working boilerplate of this somewhere I could inspect. Im still struggling at bit. Or could maybe spot something I'm doing wrong....

webpack config

const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
const CopyWebpackPlugin = require("copy-webpack-plugin");

module.exports = {
  entry: slsw.lib.entries,
  target: "node",
  // Generate sourcemaps for proper error messages
  devtool: "source-map",
  // Since 'aws-sdk' is not compatible with webpack,
  // we exclude all node dependencies
  externals: [nodeExternals()],
  mode: slsw.lib.webpack.isLocal ? "development" : "production",
  optimization: {
    // We do not want to minimize our code.
    minimize: false,
  },
  performance: {
    // Turn off size warnings for entry points
    hints: false,
  },

  plugins: [new CopyWebpackPlugin({ patterns: ["./prisma/schema.prisma"] })],
  // Run babel on all .js files and skip those in node_modules
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: "babel-loader",
        include: __dirname,
        exclude: /node_modules/,
      },
    ],
  },
};

serverless.yml

service: media-server-api

# Use the serverless-webpack plugin to transpile ES6
plugins:
  - serverless-webpack

custom:
  efsAccessPoint: ${env:efs_access_point}
  LocalMountPath: ${env:lambda_mount_point}
  subnetsId: ${env:lambda_subnet}
  securityGroup: ${env:lambda_security_grp}
  database_url: ${env:DATABASE_URL}

  webpack:
    webpackConfig: ./webpack.config.js
    includeModules: true
    packagerOptions:
      scripts: # this is the magic
        - prisma generate

  serverless-offline:
    port: 4000

provider:
  name: aws
  runtime: nodejs10.x
  memorySize: 512
  region: ${env:aws_region}
  profile: ${env:aws_profile}
  timeout: 900


functions:
  status:
    handler: src/index.handler
    environment:
      MNT_DIR: ${self:custom.LocalMountPath}
      DATABASE_URL: ${self:custom.database_url}
      DEBUG: prisma-client
    vpc:
      securityGroupIds:
        - ${self:custom.securityGroup}
      subnetIds:
        - ${self:custom.subnetsId}
    iamManagedPolicies:
      - arn:aws:iam::aws:policy/AmazonElasticFileSystemClientReadWriteAccess
    events:
      - http:
          method: GET
          path: /

resources:
  extensions:
    StatusLambdaFunction:
      Properties:
        FileSystemConfigs:
          - Arn: "${self:custom.efsAccessPoint}"
            LocalMountPath: "${self:custom.LocalMountPath}"

dependencies

  "dependencies": {
    "@prisma/client": "2.9.0",
    "aws-sdk": "^2.773.0",
    "dotenv": "^8.2.0",
    "lambda-router": "^2.10.0"
  },
  "devDependencies": {
    "@prisma/cli": "2.9.0",
    "serverless": "^2.8.0",
    "serverless-dotenv-plugin": "3.0.0",
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.4",
    "babel-plugin-source-map-support": "^1.0.0",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.7.0",
    "babel-preset-stage-3": "^6.24.1",
    "copy-webpack-plugin": "^5.1.1",
    "serverless-offline": "^3.25.6",
    "serverless-webpack": "^5.1.0",
    "webpack": "^4.16.2",
    "webpack-node-externals": "^1.6.0"
  },

And then the build on our CI server fails with an error like this. So something clearly wrong with my webpack config, or maybe the versions of dependencies are out of sync?

Serverless: Packing external modules: @prisma/client@2.9.0, lambda-router@^2.10.0
[10:25:55][Step 5/6]  
[10:25:55][Step 5/6]   Error --------------------------------------------------
[10:25:55][Step 5/6]  
[10:25:55][Step 5/6]   Error: npm run script0 failed with code 1
[10:25:55][Step 5/6]       at ChildProcess.<anonymous> (/data/teamcity/work/308be0f63058d463/node_modules/serverless-webpack/lib/utils.js:91:16)
[10:25:55][Step 5/6]       at ChildProcess.emit (events.js:310:20)
[10:25:55][Step 5/6]       at ChildProcess.EventEmitter.emit (domain.js:482:12)
[10:25:55][Step 5/6]       at maybeClose (internal/child_process.js:1021:16)
[10:25:55][Step 5/6]       at Process.ChildProcess._handle.onexit (internal/child_process.js:286:5)

@AmoDinho
Copy link

AmoDinho commented Oct 21, 2020

@sheldonj Here is a project I did early on in the year for you to look at: https://github.com/AmoDinho/prisma2-f1-demo

This is what my Webpack config looks like:


const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
const CopyWebpackPlugin = require("copy-webpack-plugin");

module.exports = {
  entry: slsw.lib.entries,
  target: "node",
  // Generate sourcemaps for proper error messages
  devtool: "source-map",
  // Since 'aws-sdk' is not compatible with webpack,
  // we exclude all node dependencies
  externals: [nodeExternals()],
  mode: slsw.lib.webpack.isLocal ? "development" : "production",
  optimization: {
    // We do not want to minimize our code.
    minimize: false,
  },
  performance: {
    // Turn off size warnings for entry points
    hints: false,
  },

  plugins: [
    new CopyWebpackPlugin(["./prisma/schema.prisma"]), // without this the prisma generate above will not work
  ],
  // Run babel on all .js files and skip those in node_modules
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: "babel-loader",
        include: __dirname,
        exclude: /node_modules/,
      },
    ],
  },
};

@manavm1990
Copy link

manavm1990 commented Oct 21, 2020

My previous issue is solved!

I didn't realize about webpack-node-externals and pathing.

const nodeExternals = require("webpack-node-externals");

module.exports = {
  mode: "development",
  target: "node",
  node: {
    __dirname: true,
  },
  externals: [nodeExternals()],
  module: {
    rules: [
      { test: /\.graphql?$/, loader: "webpack-graphql-loader" },
      {
        test: /\.js$/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [["@babel/preset-env", { targets: { node: true } }]],
          },
        },
      },
    ],
  },
  resolve: { modules: ["src", "node_modules"] },
};

@yeukfei02
Copy link

I encounter the same problem...using serverless-webpack to bundle the project and with prisma not found error.

serverless.yml

service: test-api

frameworkVersion: '2'
useDotenv: true

provider:
  name: aws
  runtime: nodejs12.x
  stage: dev
  region: ap-southeast-1
  apiName: test-api-dev
  tracing:
    apiGateway: true
    lambda: true
  environment:
    NODE_ENV: development
  iamRoleStatements:
    - Effect: 'Allow'
      Action:
        - 'xray:PutTraceSegments'
        - 'xray:PutTelemetryRecords'
      Resource:
        - '*'
  apiGateway:
    shouldStartNameWithService: true
    description: Test Api Staging
  lambdaHashingVersion: 20201221
  vpc:
    securityGroupIds:
      - xxx
    subnetIds:
      - xxx
  timeout: 30

package:
  individually: true

functions:
  main:
    handler: src/main/handler.main
    events:
      - http:
          path: /
          method: get
          cors: true

  login:
    handler: src/login/handler.login
    events:
      - http:
          path: /login
          method: post
          cors: true

  logout:
    handler: src/logout/handler.logout
    events:
      - http:
          path: /logout
          method: post
          cors: true

  authorize:
    handler: src/authorize/handler.authorize

  getSubOrders:
   ...

plugins:
  - serverless-webpack
  - serverless-prune-plugin
  # - serverless-plugin-typescript
  - serverless-offline
  - serverless-plugin-split-stacks

custom:
  webpack:
    webpackConfig: ./webpack.config.js
    includeModules: true
    packager: 'yarn'
    packagerOptions:
      scripts:
        - prisma generate
  prune:
    automatic: true
    number: 3

package.json

{
  "name": "test-api",
  "version": "0.1.0",
  "main": "app.js",
  "repository": "https://donaldwu05@bitbucket.org/keysocapp/test-api.git",
  "author": "Donald Wu <donald.wu@xxx.com>",
  "license": "MIT",
  "dependencies": {
    "@prisma/client": "^2.14.0",
    "aws-sdk": "^2.815.0",
    "aws-xray-sdk": "^3.2.0",
    "axios": "^0.21.1",
    "bcryptjs": "^2.4.3",
    "crypto": "^1.0.1",
    "dotenv": "^8.2.0",
    "jsonwebtoken": "^8.5.1",
    "lodash": "^4.17.20",
    "moment": "^2.29.1",
    "moment-timezone": "^0.5.32",
    "redis": "^3.0.2",
    "sidekiq": "^1.1.1",
    "uuid": "^8.3.2"
  },
  "devDependencies": {
    "@prisma/cli": "^2.14.0",
    "@types/aws-lambda": "^8.10.67",
    "@types/aws-sdk": "^2.7.0",
    "@types/bcryptjs": "^2.4.2",
    "@types/jest": "^26.0.19",
    "@types/jsonwebtoken": "^8.5.0",
    "@types/lambda-tester": "^3.6.1",
    "@types/lodash": "^4.14.165",
    "@types/moment-timezone": "^0.5.30",
    "@types/node": "^14.14.14",
    "@types/redis": "^2.8.28",
    "@types/serverless": "^1.78.19",
    "@types/uuid": "^8.3.0",
    "@typescript-eslint/eslint-plugin": "^4.11.0",
    "@typescript-eslint/parser": "^4.11.0",
    "aws-lambda": "^1.0.6",
    "codecov": "^3.8.1",
    "copy-webpack-plugin": "5.1.1",
    "eslint": "^7.16.0",
    "eslint-config-prettier": "^7.1.0",
    "eslint-plugin-prettier": "^3.3.0",
    "git-cz": "^4.7.6",
    "husky": "^4.3.6",
    "jest": "^26.6.3",
    "lambda-tester": "^4.0.1",
    "prettier": "^2.2.1",
    "serverless": "^2.19.0",
    "serverless-offline": "^6.8.0",
    "serverless-plugin-split-stacks": "^1.9.3",
    "serverless-plugin-typescript": "^1.1.9",
    "serverless-prune-plugin": "^1.4.3",
    "serverless-webpack": "5.3.1",
    "standard-version": "^9.0.0",
    "ts-jest": "^26.4.4",
    "ts-loader": "6.2.1",
    "ts-node": "^9.1.1",
    "typescript": "^4.1.3",
    "webpack": "4.41.4",
    "webpack-node-externals": "^2.5.2"
  },
  "scripts": {
    "dev": "serverless offline start",
    "deploy": "serverless deploy",
    "dashboard": "serverless dashboard",
    "package": "serverless package",
    "lint": "eslint '*/**/*.{ts,tsx}' --quiet --fix",
    "test": "jest --detectOpenHandles",
    "generate:prisma": "cd ./prisma && npx prisma introspect && npx prisma generate",
    "format:prisma": "cd ./prisma && npx prisma format",
    "prisma-studio": "npx prisma studio",
    "commit": "git-cz",
    "release": "standard-version"
  },
  "husky": {
    "hooks": {
      "pre-commit": "yarn lint && yarn run format:prisma",
      "pre-push": "yarn lint && yarn run format:prisma"
    }
  }
}

webpack.config.js

const path = require('path');
const slsw = require('serverless-webpack');
const isLocal = slsw.lib.webpack.isLocal;
const nodeExternals = require('webpack-node-externals');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  mode: isLocal ? 'development' : 'production',
  devtool: isLocal ? 'source-map' : 'none',
  entry: slsw.lib.entries,
  target: 'node',
  resolve: {
    extensions: ['.mjs', '.ts', '.js'],
  },
  output: {
    libraryTarget: 'commonjs2',
    path: path.join(__dirname, '.webpack'),
    filename: '[name].js',
  },
  externals: [nodeExternals()],
  plugins: [new CopyWebpackPlugin(['./prisma/schema.prisma'])],
  module: {
    rules: [
      {
        test: /\.(tsx?)$/,
        loader: 'ts-loader',
        exclude: [
          [
            path.resolve(__dirname, 'node_modules'),
            path.resolve(__dirname, '.serverless'),
            path.resolve(__dirname, '.webpack'),
          ],
        ],
        options: {
          transpileOnly: true,
          experimentalWatchApi: true,
        },
      },
    ],
  },
};

with the above config, I am able to see the schema.prisma inside .serverless folder after I unzip the zip file.
hope this help some people here!

@f0rr0
Copy link

f0rr0 commented Jan 27, 2021

I was able to bundle a vanilla app with prisma for Lambda with this webpack config without using /tmp or layers or anything else. Key things were setting node to false and modifying the permissions for the binary. Hope it helps someone

/// <reference path="./typings/webpack-permissions-plugin/index.d.ts" />

import glob from 'glob'
import path from 'path'
import { Configuration, IgnorePlugin } from 'webpack'
import { CleanWebpackPlugin } from 'clean-webpack-plugin'
import CopyPlugin from 'copy-webpack-plugin'
import PermissionsPlugin from 'webpack-permissions-plugin'

interface EntryOutput {
  entry: string
  output: {
    filename: string
    path: string
  }
}

const entries: EntryOutput[] = glob
  .sync('./src/handlers/*-handler.ts')
  .reduce((prev: EntryOutput[], curr: string): EntryOutput[] => {
    const filename = path.basename(curr, '.ts')
    return [
      ...prev,
      {
        entry: path.resolve(__dirname, curr),
        output: {
          filename: `${filename}.js`,
          path: path.resolve(__dirname, 'dist', filename),
        },
      },
    ]
  }, [])

const config: Configuration[] = entries.map(({ entry, output }) => ({
  entry,
  output: {
    ...output,
    libraryTarget: 'commonjs',
  },
  target: 'node',
  externals: {
    'aws-sdk': 'commonjs2 aws-sdk',
  },
  devtool: 'source-map',
  node: false,
  mode: 'production',
  resolve: {
    extensions: ['.ts', '.js', '.json'],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new IgnorePlugin({
      resourceRegExp: /encoding/,
    }),
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(
            __dirname,
            './node_modules/.prisma/client/query-engine-rhel-openssl-1.0.x'
          ),
          to: output.path,
        },
        {
          from: path.resolve(
            __dirname,
            './node_modules/.prisma/client/schema.prisma'
          ),
          to: output.path,
        },
      ],
    }),
    new PermissionsPlugin({
      buildFiles: [
        {
          path: path.resolve(
            __dirname,
            `${output.path}/query-engine-rhel-openssl-1.0.x`
          ),
          fileMode: '755',
        },
      ],
    }),
  ],
}))

export default config

I have another issue open which I have worked around in this config #5250

@mbryk
Copy link

mbryk commented Feb 19, 2021

@sheldonj

Does someone have a working boilerplate of this somewhere I could inspect. Im still struggling at bit. Or could maybe spot something I'm doing wrong....
And then the build on our CI server fails with an error like this. So something clearly wrong with my webpack config, or maybe the versions of dependencies are out of sync?

Serverless: Packing external modules: @prisma/client@2.17.0, apollo-server-lambda@^2.21.0, graphql@^15.5.0, graphql-iso-date@^3.6.1, nexus@^1.0.0, source-map-support@^0.5.19
[10:25:55][Step 5/6]  
[10:25:55][Step 5/6]   Error --------------------------------------------------
[10:25:55][Step 5/6]  
[10:25:55][Step 5/6]   Error: npm run script0 failed with code 1
[10:25:55][Step 5/6]       at ChildProcess.<anonymous> (/data/teamcity/work/308be0f63058d463/node_modules/serverless-webpack/lib/utils.js:91:16)
[10:25:55][Step 5/6]       at ChildProcess.emit (events.js:310:20)
[10:25:55][Step 5/6]       at ChildProcess.EventEmitter.emit (domain.js:482:12)
[10:25:55][Step 5/6]       at maybeClose (internal/child_process.js:1021:16)
[10:25:55][Step 5/6]       at Process.ChildProcess._handle.onexit (internal/child_process.js:286:5)

Did you ever figure this out? I'm getting the same error as you, with a similar setup:

"dependencies": {
    "@prisma/client": "2.17.0",
    "apollo-server-lambda": "^2.21.0",
    "copy-webpack-plugin": "^7.0.0",
    "graphql": "^15.5.0",
    "graphql-iso-date": "^3.6.1",
    "nexus": "^1.0.0",
    "source-map-support": "^0.5.19"
  },
  "devDependencies": {
    "@babel/core": "^7.12.17",
    "@babel/preset-env": "^7.12.17",
    "@prisma/cli": "^2.17.0",
    "babel-loader": "^8.2.2",
    "babel-plugin-source-map-support": "^2.1.3",
    "prisma": "2.17.0",
    "serverless-dotenv-plugin": "3.5.1",
    "serverless-offline": "^6.8.0",
    "serverless-webpack": "^5.3.5",
    "webpack": "^5.23.0",
    "webpack-node-externals": "^2.5.2"
  },

.babelrc

{
"plugins": ["source-map-support"],
  "presets": [
    ["@babel/preset-env", { "targets": { "node": "12" } }]
  ]
}

webpack config

const path = require("path");
const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
const CopyWebpackPlugin = require("copy-webpack-plugin");

module.exports = {
  entry: slsw.lib.entries,
  target: "node",
  devtool: "source-map",
  // node: false,
  externals: [nodeExternals()],
  output: {
    libraryTarget: "commonjs2",
    path: path.join(__dirname, ".webpack"),
    filename: "[name].js",
    sourceMapFilename: '[file].map'
  },
  mode: slsw.lib.webpack.isLocal ? "development" : "production",
  optimization: {
    minimize: false,
  },
  plugins: [
    new CopyWebpackPlugin({ patterns: ["./prisma/schema.prisma"] }),
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: "babel-loader",
        include: __dirname,
        exclude: /node_modules/,
      },
    ],
  },
};

serverless.yml


package:
  individually: true

plugins:
  - serverless-dotenv-plugin
  - serverless-webpack
  - serverless-offline

custom:
  webpack:
    webpackConfig: "webpack.config.js"
    includeModules: true # This is required
    keepOutputDirectory: true
    packager: "npm"
    packagerOptions:
      scripts: # this is the magic
        - prisma generate

@paulcookie
Copy link

Try to downgrade webpack to 4 version and all it deps, like copy-webpack-plugin to 6.4.0 to support webpack v4

@carlosherrera1113

This comment was marked as off-topic.

@janpio

This comment was marked as outdated.

@ChristianRich
Copy link

ChristianRich commented Mar 6, 2022

This was seriously doing my head in! Two days wasted of trying to deploy a TypeScript / Prisma / Serverless app to AWS Lambda.. It really shouldn't be that hard. Problem lies around copying the Prisma client including the binaries into the deployment package which is not all that transparent.

In the end this module saved me:
https://www.npmjs.com/package/serverless-webpack-prisma

serverless.yaml:

service: my-prisma-postgresql-rest-api

plugins:
  - serverless-webpack
  - serverless-webpack-prisma
  - serverless-offline

custom:
  webpack:
    includeModules: true
    packagerOptions:
      scripts:
        - prisma generate

provider:
  name: aws
  region: ap-southeast-2
  runtime: nodejs14.x
  environment:
    DATABASE_URL: ${ssm:/dev/my-app/my-connection}

functions:
  getUser:
    handler: src/handlers/getUser.handler
    events:
      - http:
          path: /users/{username}
          method: get

This is the results of my efforts:
https://github.com/ChristianRich/prisma-postgresql-typescript-setup

A working deployable bare-bones AWS Lambda function using TypeScript, Prisma and Amazon Aurora RDS PostgresQL.
Hope you find it useful.

@millsp millsp removed this from the 2.24.0 milestone Mar 7, 2022
@millsp millsp removed their assignment Mar 7, 2022
@janpio janpio added bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. kind/bug A reported bug. and removed kind/support labels Dec 14, 2022
@janpio janpio added topic: Query engine ... could not be found. Query engine ... for current platform ... could not be found. topic: serverless framework labels Jan 28, 2023
@jh-park-milban
Copy link

I was able to bundle a vanilla app with prisma for Lambda with this webpack config without using /tmp or layers or anything else. Key things were setting node to false and modifying the permissions for the binary. Hope it helps someone

/// <reference path="./typings/webpack-permissions-plugin/index.d.ts" />

import glob from 'glob'
import path from 'path'
import { Configuration, IgnorePlugin } from 'webpack'
import { CleanWebpackPlugin } from 'clean-webpack-plugin'
import CopyPlugin from 'copy-webpack-plugin'
import PermissionsPlugin from 'webpack-permissions-plugin'

interface EntryOutput {
  entry: string
  output: {
    filename: string
    path: string
  }
}

const entries: EntryOutput[] = glob
  .sync('./src/handlers/*-handler.ts')
  .reduce((prev: EntryOutput[], curr: string): EntryOutput[] => {
    const filename = path.basename(curr, '.ts')
    return [
      ...prev,
      {
        entry: path.resolve(__dirname, curr),
        output: {
          filename: `${filename}.js`,
          path: path.resolve(__dirname, 'dist', filename),
        },
      },
    ]
  }, [])

const config: Configuration[] = entries.map(({ entry, output }) => ({
  entry,
  output: {
    ...output,
    libraryTarget: 'commonjs',
  },
  target: 'node',
  externals: {
    'aws-sdk': 'commonjs2 aws-sdk',
  },
  devtool: 'source-map',
  node: false,
  mode: 'production',
  resolve: {
    extensions: ['.ts', '.js', '.json'],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new IgnorePlugin({
      resourceRegExp: /encoding/,
    }),
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(
            __dirname,
            './node_modules/.prisma/client/query-engine-rhel-openssl-1.0.x'
          ),
          to: output.path,
        },
        {
          from: path.resolve(
            __dirname,
            './node_modules/.prisma/client/schema.prisma'
          ),
          to: output.path,
        },
      ],
    }),
    new PermissionsPlugin({
      buildFiles: [
        {
          path: path.resolve(
            __dirname,
            `${output.path}/query-engine-rhel-openssl-1.0.x`
          ),
          fileMode: '755',
        },
      ],
    }),
  ],
}))

export default config

I have another issue open which I have worked around in this config #5250

You save me. Thank you so much.

@jharrell
Copy link
Member

Hi everyone!

Just wanted to provide an update in this thread. We don't believe this is a bug in Prisma, per se, but it's also not a feature. Unfortunately the issues we've been seeing with bundlers (webpack, esbuild, etc) is due to files that Prisma needs to function not being copied into resulting bundles.

To that end, we are looking to improve our documentation so that future individuals don't have to tread down the same very painful path that y'all have.

Our first pass at this is live. Please check out our new documentation on deploying with Serverless Framework and let us know what you think.

@Diboby
Copy link

Diboby commented Oct 15, 2023

Hi there!

Here's one approach to address this issue: place the query engine in the same directory as your serverless function file. To do this, follow these steps:

  1. Begin by incorporating the relevant engine into your prisma schema.
  2. Ensure that it is downloaded by running the command prisma generate.
  3. Afterward, copy the appropriate engine to the bundles folder if you are utilizing a bundler such as Webpack, or directly into the folder of your Lambda function.
  4. Do not forget to copy your prisma.schema also.

Here is an example with copy-webpack-plugin

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. kind/bug A reported bug. team/client Issue for team Client. topic: deployment-platform topic: prisma-client topic: Query engine ... could not be found. Query engine ... for current platform ... could not be found. topic: serverless framework topic: serverless topic: webpack topic: windows
Projects
None yet
Development

No branches or pull requests