Functions Framework for Node.js

repository·main·Indexed 23 days ago

https://github.com/googlecloudplatform/functions-framework-nodejs

An open source FaaS (Function as a Service) framework based on Express for writing portable Node.js functions. It allows functions to run on Google Cloud Run functions, local machines, Cloud Run, or Knative-based environments. The framework supports HTTP and event-style signatures, including the CloudEvents spec, and provides tools for local debugging, Docker containerization, and testing with the Pub/Sub emulator.

Tokens
10.9K
Snippets
34
Records
61
Agent score
80%

What's inside functions-framework-nodejs

  1. How event-style function signatures work

    main

    To process Google Cloud Functions events, you must use the event-style signature where the function accepts data and context arguments. You must also set the signature type to event via the --signature-type flag or FUNCTION_SIGNATURE_TYPE environment variable to enable automatic unmarshalling.

    exports.helloEvents = (data, context) => {
      console.log(data);
      console.log(context);
    };
  2. How CloudEvents work in the Functions Framework

    main

    The framework supports the CloudEvents spec. To use it, use the functions.cloudEvent registration method. The function receives a single cloudevent object containing the event metadata (like id, source, type, etc.).

    const functions = require('@google-cloud/functions-framework');
    
    functions.cloudEvent('helloCloudEvents', (cloudevent) => {
      console.log(cloudevent.specversion);
      console.log(cloudevent.type);
      console.log(cloudevent.source);
      console.log(cloudevent.subject);
      console.log(cloudevent.id);
      console.log(cloudevent.time);
      console.log(cloudevent.datacontenttype);
    });
  3. Quickstart: Set up a new project with npm start

    main

    For a standard project setup, use the @google-cloud/functions-framework programmatic API to register your function and use an npm start script for local development.

    // index.js
    const functions = require('@google-cloud/functions-framework');
    
    functions.http('helloWorld', (req, res) => {
      res.send('Hello, World');
    });

    In your package.json:

    "scripts": {
      "start": "functions-framework --target=helloWorld"
    }

    Then run:

    npm start
  4. Quickstart: Run Hello World locally with npx

    main

    To quickly test a function without setting up a full project, create an index.js file and use npx to run the framework directly, specifying the exported function name with the --target flag.

    // index.js
    exports.helloWorld = (req, res) => {
      res.send('Hello, World');
    };
    npx @google-cloud/functions-framework --target=helloWorld
  5. Quickstart: Build a deployable container using buildpacks

    main

    You can package your function into a container image using the pack tool and Google Cloud buildpacks. This is useful for deploying to Knative-based environments or Cloud Run.

    pack build \
      --builder gcr.io/buildpacks/builder:v1 \
      --env GOOGLE_FUNCTION_SIGNATURE_TYPE=http \
      --env GOOGLE_FUNCTION_TARGET=helloWorld \
      my-first-function
    
    # To run the container locally:
    docker run --rm -p 8080:8080 my-first-function
  6. Configure the Functions Framework for CloudEvents

    main

    To test functions that expect event-driven signatures (like CloudEvents), you must configure the functions-framework with the --signature-type=event flag.

    When this mode is enabled, the function is no longer accessible via standard HTTP GET requests from a browser. Instead, it expects POST requests where the body conforms to the expected event schema (e.g., a Pub/Sub push subscription payload).

    {
      "scripts": {
        "start": "functions-framework --target=helloPubSub --signature-type=event"
      }
    }
  7. Deploy a containerized function to Cloud Run

    main

    To deploy your container to Cloud Run, build the image with a tag pointing to your Google Container Registry (gcr.io/$GOOGLE_CLOUD_PROJECT/image-name), push the image, and then use gcloud run deploy to launch it. Replace $GOOGLE_CLOUD_PROJECT with your actual project ID.

    docker build -t gcr.io/$GOOGLE_CLOUD_PROJECT/helloworld .
    docker push gcr.io/$GOOGLE_CLOUD_PROJECT/helloworld
    gcloud run deploy helloworld --image gcr.io/$GOOGLE_CLOUD_PROJECT/helloworld --region us-central1
  8. Debug a function locally using the Node.js inspector

    main

    You can debug your functions using standard Node.js debugging tools by running the Functions Framework through the node executable with the --inspect flag. This allows you to attach an IDE (like VS Code) or Chrome DevTools to the running process.

    To debug, you must run the symlinked executable located in node_modules/.bin/functions-framework directly via node --inspect rather than using the functions-framework command directly. This ensures the debugger attaches to the correct entrypoint.

  9. Develop a function in TypeScript

    main

    To develop a function using TypeScript with the Functions Framework, follow these steps to set up your project environment, compiler, and build scripts.

    1. Initialize the project:

      mkdir typescript-function && cd typescript-function
      npm init -y
    2. Install dependencies: Install the framework and TypeScript as a development dependency:

      npm install @google-cloud/functions-framework
      npm install --save-dev typescript
    3. Configure TypeScript: Create a tsconfig.json in your root directory:

      {
        "compilerOptions": {
          "target": "es2016",
          "module": "commonjs",
          "esModuleInterop": true,
          "strict": true,
          "outDir": "dist"
        },
        "include": ["src/**/*"],
        "exclude": ["node_modules"]
      }
    4. Configure package.json: Set the main field to your compiled entry point (e.g., dist/index.js) and add scripts for building and running. Use the gcp-build script to ensure devDependencies like typescript are used during deployment on Google Cloud Functions.

      {
        "main": "dist/index.js",
        "scripts": {
          "build": "tsc",
          "start": "functions-framework --target=TypescriptFunction",
          "prestart": "npm run build",
          "gcp-build": "npm run build"
        }
      }
    5. Configure .gitignore: Ensure node_modules/ and your output directory (e.g., dist/) are ignored to prevent them from being uploaded during deployment.

      node_modules/
      dist/
    mkdir typescript-function && cd typescript-function
    npm init -y
    npm install @google-cloud/functions-framework
    npm install --save-dev typescript
  10. Run a Function in a Docker Container

    main

    To containerize your function, create a Dockerfile that sets up a Node.js environment, installs production dependencies, and uses npm start to launch the Functions Framework web service.

    Follow this pattern to optimize build times: copy package.json and package-lock.json separately before copying the rest of your source code. This ensures that npm install is only re-run when your dependencies change, rather than on every code change.

    To run the container locally:

    1. Build the image using docker build.
    2. Run the container using docker run, mapping the container's port (typically 8080) to your host machine.
    # Use the official Node.js 10 image.
    # https://hub.docker.com/_/node
    FROM node:10
    # Create and change to the app directory.
    WORKDIR /usr/src/app
    # Copy application dependency manifests to the container image.
    # A wildcard is used to ensure both package.json AND package-lock.json are copied.
    # Copying this separately prevents re-running npm install on every code change.
    COPY package.json package*.json ./
    # Install production dependencies.
    RUN npm install --only=production
    # Copy local code to the container image.
    COPY . .
    # Run the web service on container startup.
    CMD [ "npm", "start" ]
  11. Simulate Pub/Sub messages via POST requests

    main

    You can locally test a Pub/Sub-triggered function by sending a POST request containing a JSON payload that mimics a Pub/Sub push subscription.

    1. Create a JSON file (e.g., mockPubsub.json) containing the message and subscription keys.
    2. Use curl to send the file as the request body.
    3. You must include specific CloudEvent headers to ensure the framework processes the request correctly as an event.
    {
      "message": {
        "attributes": {
          "key": "value"
        },
        "data": "SGVsbG8gQ2xvdWQgUHViL1N1YiEgSGVyZSBpcyBteSBtZXNzYWdlIQ==",
        "messageId": "136969346945"
      },
      "subscription": "projects/myproject/subscriptions/mysubscription"
    }