I'm trying to build my GCF project with Typescript from the ground up. My goal with this project (and this question) is to understand how cloud functions work and to perform all the setup steps manually, so that's why I'm not copying any sample code or using an automated tool.
First, here's my src/index.ts
file:
export const helloWorld = (req: any, res: any) => {
res.send('Hello, world 4');
}
After I run typescript compiler, I get this dist/index.js
file, which seems perfectly reasonable:
"use strict";
exports.__esModule = true;
exports.helloWorld = function (req, res) {
res.send('Hello, world 4');
};
My package.json
is set up to point to this file:
{
"main": "dist/index.js",
"scripts": {
"start": "npx tsc-watch --onSuccess 'npx @google-cloud/functions-framework --target=helloWorld'",
"deploy": "gcloud functions deploy helloWorld --runtime nodejs10 --trigger-http"
},
"dependencies": {
"@google-cloud/functions-framework": "^1.1.2",
"tsc-watch": "^2.2.1",
"typescript": "^3.5.3"
}
}
I wanted to setup local testing environment first, so I used functions framework. When I run it, it all works perfectly:
$ npx @google-cloud/functions-framework --target=helloWorld
Serving function...
Function: helloWorld
URL: http://localhost:8080/
However, when I try to deploy, I get this error:
$ gcloud functions deploy helloWorld --runtime nodejs10 --trigger-http
Created .gcloudignore file. See `gcloud topic gcloudignore` for details.
Deploying function (may take a while - up to 2 minutes)...failed.
ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Function failed on loading user code. Error message: Provided code is not a loadable module.
Could not load the function, shutting down.
Why does it say that my index.js
is not a loadable module and how can I fix this error?
Update
Turns out the gcloud
doesn't respect package.json
's main
field. When I specified that it should take dist
folder explicitly with the --source
flag, it deployed the file:
gcloud functions deploy helloWorld --source=dist/ --runtime nodejs10 --trigger-http
However, it still doesn't work because it seems to assume that everything, including package.json, is contained in this directory - so it doesn't link any of the library dependencies.
Turns out, .gitignore
by default is imported in GCF's .gcloudignore
file, and since I ignore js files in my .gitignore
, they never make it to GCF.
To fix it, just remove this line:
#!include:.gitignore
I have also created a small template project for using Typescript with GCF.
Add !/dist
after #!include:.gitignore
in your .gcloudignore
file.
In my opinion, it's better to leave the #!include:.gitnore
line in your .gcloudignore
file, so that when people add something to .gitignore
, it will be automatically included in the .gcloudignore
, too.
For files and directories where you want them to be ignored by git
but not by gcloud
, I would add them explicitly in the .gcloudignore
file.
Let's take my example, where I have a TypeScript project. I don't want the output of tsc
to be version-controlled, but I do want those files to include for gcloud
for obvious reasons: the files in the built
(or dist
) folder is actually my function (app).
### .gitignore
node_modules
built
### .gcloudignore file's content
#!include:.gitignore
# Do not ignore built (or dist) folder for gcloud:
!/built
!/dist
I prefer this solution because, by default, the ignored files from git are also ignored by gcloud, so I don't need to worry that people forget that we have multiple ignore files.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With