Azure Functions の Cold start 問題に関しては、App Service Plan
+ Always On
option を使う方法があるが、それに加えて、node の場合は、webpack
を使うと良さげ。C# の場合はプリコンパイルオプション。今日はさらっと試しただけのなので、明日以降色々試してみたい。
- Cold start of Azure Function with large npm module trees is slow in Consumption plan #298
- Cold Start and Warm Start on Consumption Plan #131
まずはwebpackについてちょっと試してみた。
Webpack でビルドしてみる
ここに便利なリポジトリがあった。
ちょっとインストラクションが古いけど、下記のようにすればできる。clone して下記のようにする。Azure Functions CLIはインストールずみのこと。
npm install
npm run build
func init
func host start
これで、サーバーが動く

webpack の実態をみる。
webpack のやりたいことは、すぐにわかる。build/index.js
というファイルができてるのでみてみよう。
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
: 以下続く
webpack の今回の目的での効能
つまり、一つのファイルに、node_moduleの下にあるライブラリをまとめている。もともと、webpack
の Azure Functions
による使用のきっかけは、consumption plan
での起動が、webpack
をするとかなり早くなるという話だった。
つまり、ファイルを1つにまとめることで、起動時のスピードが早くなるらしい。これが、どんな感じになっているか、各ファイルをみてみよう。
webpack のやること
build
をみると、単純に、webpack
を実行している。
$ cat package.json
{
"name": "asdf",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"author": "",
"license": "ISC",
"dependencies": {
"lodash": "^4.17.4",
"ms-rest-azure": "^1.15.4"
},
"devDependencies": {
"webpack": "^2.2.1"
}
}
webpack は、webpack.config.js
を見てライブラリをまとめる作業を実施。どこに、結果を吐き出すかも書いている。
$ cat webpack.config.js
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: './index.js',
target: 'node',
output: {
path: path.join(__dirname, "build"),
filename: 'index.js',
library: "index",
libraryTarget: "commonjs2"
},
node: {
__filename: false,
__dirname: false,
},
}
ちなみに、参照されている、./index.js
は、各functions を参照。
$ cat index.js
var HttpTriggerJS = require('./HttpTriggerJS/index')
var HTTPJS2 = require('./HTTPJS2/index')
module.exports = {
HttpTriggerJS: HttpTriggerJS,
HTTPJS2: HTTPJS2
}
そして、各functions は、生成された build/index.js
を参照している。
function.json
$ cat function.json
{
"disabled": false,
"scriptFile":"../build/index.js",
"entryPoint":"HttpTriggerJS",
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}
functions の記述は変更がない。
$ cat index.js
let msRestAzure = require('ms-rest-azure');
let _ = require('lodash');
module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
if (req.query.name || (req.body && req.body.name)) {
res = {
// status: 200, /* Defaults to 200 */
body: "Hello " + (req.query.name || req.body.name)
};
}
else {
res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
context.done(null, res);
};
このように、webpack を使うと、ライブラリが1つのファイルにまとめられて、立ち上げが高速課されるようだなぁ。とわかった。