4

I am trying to write a deployment process for taking a ReasonML .bs.js output and deploying it as a Google Cloud function.

Here is the ReasonML code:

/*!
 * My first ReasonML Google cloud function.
 * Hadil G. Sabbagh
 */
open Express;

let helloworld2 = (req: Request.t) => (res: Response.t) => {
        Response.status(Response.StatusCode.Ok, res) |> 
Response.sendString("Hello world!");
};

I have successfully built a helloworld2.bs.js file. I have been trying to use webpack to pack everything needed into an index.js file that I can run as a Google Cloud Function, but I don't know how to expose my function name for use by GCP.

I am using Node.js 8 (beta).

glennsl
  • 28,186
  • 12
  • 57
  • 75

2 Answers2

1

Thanks for the information. My code relied on bs-express, which is actually a ReasonML layer over ExpressJS. This was buried in my node_modules folder which was causing the require statement in the generated .bs.js file to fail. However, I copied the dependency into my src directory and edited the helloworld2.bs.js file to point to it, it worked.

  • Ah, I see the problem, and it's tricky. At this point I don't have a better solution than you–maybe try in the Reason forum if you're interested? – Yawar Aug 30 '18 at 00:42
0

Deploying a ReasonML-compiled JavaScript module to Google Cloud Functions is much the same as deploying an EcmaScript module, so a good tutorial to understand the basics is https://cloud.google.com/functions/docs/tutorials/http#functions-update-install-gcloud-node8

The main thing you need to ensure is that Reason outputs a transpiled JavaScript module that looks like what GCF expects. I do foresee a problem using Webpack, however, because it will want to pack your local version of Express into the output JS and we don't want that–we want to use the Express that's provided by GCF.

To get around this problem, I would probably not use a JavaScript bundler and instead list bs-platform in the package.json dependencies section so that it's installed during the function deploy, and express in the peerDependencies section so that the deploy uses the provided Express version.

As per the reference, you may name the module file however you like as long as you list the name in package.json, with the line "main": "src/App.bs.js". In this example you may name your Reason source file src/App.re.

The next step is to make sure that your function conforms to what an Express routing handler must look like. If you'll notice, the tutorial I linked to shows this function shape in JavaScript: exports.foo = (req, res) => ...;. To compile a Reason function to this shape, we need an uncurried Reason function:

let helloworld2 = (. _req, res) => {
  open Express;

  res
  |> Response.status(Response.StatusCode.Ok)
  |> Response.sendString("Hello world!")
};

(The dot after the function parameter left parenthesis indicates that it's an uncurried function. Btw I also rearranged the function to a little more idiomatic Reason style.)

Finally, you deploy:

gcloud beta functions deploy helloworld2 --runtime nodejs8 --trigger-http

The helloworld2 tells the deploy command which function to run in the deployed module.

Yawar
  • 11,272
  • 4
  • 48
  • 80
  • The `require("bs-express/src/Express.js")` in `src/helloworld2.bs.js` causes the load to Google to fail. Can you elaborate on how to get around this? Thanks! – Hadil Sabbagh Aug 29 '18 at 04:34
  • The reason for the above is because bs-express is a ReasonML library and needs to be compiled. So I need to bring it with me... – Hadil Sabbagh Aug 29 '18 at 15:24