【问题标题】:Reduce the size of the node-modules zip sent by the serverless framework减小无服务器框架发送的节点模块 zip 的大小
【发布时间】:2017-12-17 22:15:22
【问题描述】:

我正在使用 the serverless framework 编写一些 nodejs 函数。 package.json 文件需要一些依赖项:

{
  "name": "adam-test-sls",
  "version": "0.1.0",
  "description": "Test package to play with sls/lambda",
  "main": "handler.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Adam Matan <adam@binaris.com>",
  "license": "UNLICENSED",
  "dependencies": {
    "aws-sdk": ">= 2.0.9",
    "json": "^9.0.6",
    "underscore": "^1.8.3",
    "uuid": "^3.1.0"
  },
  "devDependencies": {
    "eslint": "^4.2.0",
    "eslint-config-airbnb": "^15.0.2",
    "eslint-config-airbnb-base": "^11.2.0",
    "eslint-plugin-import": "^2.7.0"
  }
}

node-modules 目录的大小几乎是 50mb:

# du -smc node_modules
47  node_modules
47  total

部署时间超过 35 秒,压缩包大小约为 9.5MB:

# time serverless deploy function --function hello -v
Serverless: Packaging function: hello...
Serverless: Uploading function: hello (9.46 MB)...
Serverless: Successfully deployed function: hello
serverless deploy function --function hello -v  4.28s user 1.15s system 15% cpu 35.165 total

这有点低效 - 我只更改一个文件,但只要我做最轻微的更改,我就必须打包所有未更改的依赖项。

知道如何减小 zip 大小(可能删除 devDependencies),或者只上传更改的文件吗?

【问题讨论】:

    标签: node.js npm dependencies aws-lambda serverless-framework


    【解决方案1】:

    您可以使用无服务器功能排除一些您不需要的包(例如,您可以保证here the manual

    不幸的是,自 1.16 版以来,似乎存在忽略这些排除项的问题(1.15.1 版创建了小得多的 zip,而自 1.16 版起,该 zip 包含您的 node_modules 中的任何内容)。我打开了issue,但仍未得到答复。

    【讨论】:

      【解决方案2】:

      aws-sdk 在 24MB 附近,你不需要它,因为 it's already available 到 lambda 函数。一种选择是将其移动到 dev-dependencies,然后将您的 dev-dependencies 放在父目录的 package.json 中。

      还有一些工具可以提供帮助:

      serverless-plugin-include-dependencies 插件 - 如果排除功能被破坏,我不确定它的工作情况:https://github.com/dougmoscrop/serverless-plugin-include-dependencies

      Webpack 也可以与 serverless-webpack 插件一起使用来控制依赖关系。 Webpack 的死代码消除可以产生相当大的影响。

      不理想,但您也可以在部署之前运行npm prune --production。 (之后您需要再次运行npm install

      【讨论】:

      • 为什么运行npm prune --production不理想?
      【解决方案3】:

      为了解决这个问题,我使用了一个名为 serverless-plugin-scripts 的插件,并编写了一个在 after:package:createDeploymentArtifacts 挂钩上运行的 shell 脚本。

      脚本解包部署包,removes node_modules 目录,运行npm install --only=prod 并将所有内容打包回来。出于某种原因,npm prune --production 根本不适合我。

      这是配置(serverless.yml):

      service: my-service-name
      provider:
        name: aws
        runtime: nodejs8.10
        region: us-east-1
        environment:
          NODE_ENV: ${self:custom.stage}
      
      custom:
        stage: ${opt:stage, self:provider.stage}
        region: ${opt:region, self:provider.region}
        scripts:
          hooks:
            'after:package:createDeploymentArtifacts': >
              printf "[after:package:createDeploymentArtifacts hook] Removing development dependencies " &&
              (cd .serverless && unzip -qq my-service-name.zip -d my-service-name)          && printf "." &&
              (cd .serverless && rm -rf my-service-name/node_modules)                       && printf "." &&
              (cd .serverless/my-service-name && npm install --only=prod > /dev/null 2>&1)  && printf "." &&
              (cd .serverless/my-service-name/ && zip -q -FSr ../my-service-name.zip .)     && printf ".\n" &&
              rm -rf .serverless/my-service-name/ &&
              printf "[after:package:createDeploymentArtifacts hook] Done\n"
      
      functions:  
        scheduledHandler:
          handler: src/handlers.scheduledHandler
          events:
            - schedule: rate(10 minutes)
      
      package:
        exclude:
        - .vscode/**
        - .idea/**
        - test/**
        - build/**
        - .build/**
      
      plugins:
        - serverless-plugin-scripts
      

      【讨论】:

      • 我试过这种方式,但我的函数在使用 node_modules 的 sls deploy 中达到 73MB。
      【解决方案4】:

      我为此使用了层:层用于以层的形式引入额外的代码和内容。这将使您的 lambda 函数保持较小,并在运行时从层中提取依赖项。 p>

      第 1 步: 在某处创建一个名为nodejs的文件夹

      cd Desktop
      mkdir nodejs
      cd nodejs
      npm init
      

      第 2 步: 在此文件夹中安装您的依赖项,这些依赖项很大。例如:

      npm install --save geoip-lite
      

      第 3 步: 压缩它,给出你选择的名字。

      第 4 步: 登录到 aws 控制台,转到 lambda 服务,然后选择创建层。然后上传您创建的 zip 文件。 (正如它所说,您可以将此 zip 文件上传到 S3,以防其大于 10 mb)

      在这一步,您可以通过进入 lambda 函数并添加您从上述步骤创建的自定义层来将层分配给 lambda。

      如果你有兴趣添加层是 yml 配置

      functions:
        hello:
         handler: handler.hello
         layers:
          - arn:aws:lambda:region:XXXXXX:layer:LayerName:Y
      

      【讨论】:

        猜你喜欢
        • 2023-01-19
        • 2019-11-06
        • 2021-01-21
        • 2018-04-03
        • 2019-05-21
        • 2013-06-17
        • 1970-01-01
        • 1970-01-01
        • 2016-06-28
        相关资源
        最近更新 更多