Búsqueda de sitios web

Cómo escribir funciones de Google Cloud en TypeScript con webpack


Estoy tratando de escribir el código para una Google Cloud Function en TypeScript. La idea es que el repositorio de origen tenga funciones handler definidas para múltiples Cloud Functions, cada una en un archivo diferente, y algo de código compartido por todos los handlers. Puedo compilar mis fuentes con tsc, pero necesito usar webpack para generar un único index.js que Cloud Functions cargará. Así que necesito que webpack fusione los handlers en un solo archivo.

Este es mi tsconfig.json:

{
  "compilerOptions": {
    "incremental": true,
    "target": "es2016",
    "module": "commonjs",
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node"
  },
  "include": ["src/**/*.ts"]
}

Aquí está el código de un manejador de src/TheHandler.ts:

import { EventFunction } from "@google-cloud/functions-framework";

export const TheHandler: EventFunction = (
  message,
  context
) => {
  console.log(message);
  console.log(context);
};

Esto se compila a JavaScript sin problema.

Ahora lo introduzco en webpack. Aquí está mi webpack.config.js:

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

const files = fs
  .readdirSync("src")
  .filter((item) => item.match(/\.ts$/))
  .map((file) => `./src/${file}`);

module.exports = {
  mode: "production",
  entry: files,
  externalsPresets: { node: true },
  externals: [nodeExternals()],
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: "ts-loader",
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: [".ts"],
  },
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
  },
};

Esto resulta en que dist/bundle.js esté vacío, como se confirma en la salida de webpack:

asset bundle.js 0 bytes [compared for emit] [minimized] (name: main)
./src/TheHandler.ts 612 bytes [built] [code generated]
webpack 5.50.0 compiled successfully in 1937 ms

¿Es este un problema de formato de módulo o webpack intentando empaquetar todo antes de que ts-loader compile src/TheHandler.ts? ¿O algo más?

Respuesta #1

Tuve que agregar libraryTarget: "commonjs2" a output en webpack.config.js.

Respuesta #2

Como encontraste, necesitas configurar libraryTarget para poder construir un paquete de webpack que pueda ser importado por otro módulo fuera de la construcción de webpack (por ejemplo, desde funciones en la nube).

Podrías tener un tiempo más fácil (y una mejor experiencia de desarrollador en términos de HMR confiable) usando webpack-cloud-functions (del cual soy el autor). Esto abstrae gran parte de la configuración que necesitas para usar webpack con funciones en la nube, incluida la configuración del libraryTarget.