Или как я улучшил бессерверный шаблон AWS NodeJS Typescript (aws-nodejs-typescript) с точки зрения как времени сборки, так и размера пакета, настроив настройку машинописного текста, webpack, serverless.yml и eslint.

Если ваш машинописный текст, eslint или webpack настраиваются медленно, вы можете воспользоваться приведенными ниже советами, чтобы оптимизировать их.

Оптимизация машинописного текста - tsconfig.json

  1. Включить только **/*.ts файлы и исключить node_modules и каталоги сборки.
  2. Удалите комментарии из пакета, установив “removeComments”: true в compilerOptions.
  3. Включите инкрементные API-интерфейсы и API-интерфейсы для просмотра.
// tsconfig.json

{
  "compilerOptions": {
  "lib": [
    "es2017"
  ],
  "removeComments": true,
  "moduleResolution": "node",
  "resolveJsonModule": true,
  "noUnusedLocals": false,
  "noUnusedParameters": false,
  "sourceMap": true,
  "allowSyntheticDefaultImports": true,
  "forceConsistentCasingInFileNames": true,
  "importHelpers": true,
  "incremental": true,
  "watch": true,
  "target": "es2017",
  "outDir": "lib"
},
"include": [
  "./**/*.ts"
],
"exclude": [
  "node_modules/**/*",
  ".serverless/**/*",
  ".webpack/**/*",
  "_warmup/**/*",
  ".vscode/**/*",
  "*.config.js",
  "**/*.js"
 ]
}

Оптимизация eslint - .eslintrc.js

Теперь, когда tslint устарел, мы должны вместо него использовать eslint с typescript-eslint. Однако я не мог не заметить разницу в производительности после переключения, eslint был медленнее, чем tslint из коробки. Вот что вы можете сделать, чтобы извлечь из этого максимальную пользу:

  1. Настройте .eslintignore файл так, чтобы он игнорировал node_modules, а также файлы сборки и файлы без машинописного текста.
  2. Используйте флаг --cache при запуске eslint, например: eslint --cache **/*.ts.
  3. Не расширяйте дорогостоящую "plugin:@typescript-eslint/recommended-requiring-type-checking" конфигурацию в конфигурации eslint.
  4. Добавьте .eslintignore файл, чтобы игнорировать node_modules и каталоги сборки
//.eslintrc.js
module.exports = {
"extends": [
  "eslint:recommended",
  "plugin:@typescript-eslint/eslint-recommended",
  "plugin:@typescript-eslint/recommended",
  "standard"
],
"env": {
  "node": true
},
"parser": "@typescript-eslint/parser",
"plugins": [
  "@typescript-eslint",
],
"settings": {
  "import/parsers": {
    "@typescript-eslint/parser": [
    ".ts",
    ".tsx"
  ]
  },
  "import/resolver": {
    "typescript": {} 
  }
},
"parserOptions": {
  "project": "./tsconfig.json",
  "tsconfigRootDir": "./",
  "sourceType": "module",
  "ecmaVersion": 2018
},
"rules": {
  "@typescript-eslint/no-explicit-any": "off",
  }
}

Добавьте .eslintignore файл, чтобы игнорировать файлы, отличные от src, которые не нужно линтировать

//.eslintignore
node_modules
.serverless
.vscode
*.config.js
.webpack
_warmup
**/*.js

Оптимизация webpack.config.js

  1. Установите webpack-node-externals, чтобы удалить неиспользуемые node_modules из сборки.
  2. Установите devtool на cheap-module-eval-source-map для разработки / локальных сборок.
  3. Удалите ненужные расширения из свойства «разрешить».
  4. Исключите node_modules, а также каталоги build / non-src из правил загрузчика.
  5. Оптимизируйте производительность сборки вашего веб-пакета с помощью этих советов.
  6. Отключите проверку типов в ts-loader и включите новый API часов.
  7. Используйте fork-ts-webpack-checker-plugin для запуска проверки типов в отдельном процессе.
// webpack.config.js
const path = require('path');
const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

module.exports = {
  context: __dirname,
  mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
  entry: slsw.lib.entries,
  devtool: slsw.lib.webpack.isLocal ? 'cheap-module-eval-source-map' : 'source-map',
  resolve: {
    extensions: ['.mjs', '.json', '.ts'],
    symlinks: false,
    cacheWithContext: false,
  },
  output: {
    libraryTarget: 'commonjs',
    path: path.join(__dirname, '.webpack'),
    filename: '[name].js',
  },
  target: 'node',
  externals: [nodeExternals()],
  module: {
    rules: [
      // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
      {
        test: /\.(tsx?)$/,
        loader: 'ts-loader',
        exclude: [
          [
            path.resolve(__dirname, 'node_modules'),
            path.resolve(__dirname, '.serverless'),
            path.resolve(__dirname, '.webpack'),
          ],
        ],
        options: {
          transpileOnly: true,
          experimentalWatchApi: true,
        },
      },
    ],
  },
  plugins: [
    // new ForkTsCheckerWebpackPlugin({
    //   eslint: true,
    //   eslintOptions: {
    //     cache: true
    //   }
    // })
  ],
};

8. (Бонус) Обновление до webpack v5 https://webpack.js.org/migrate/5/

Оптимизация serverless.yml

  1. Для правильной настройки внешних узлов с помощью serverless-webpack plugin вам необходимо установить параметр custom: webpack: includeModules в файле serverless.yml, как указано здесь плагином serverless-webpack, чтобы правильно поддерживать плагин внешних компонентов узла webpack
  2. Включите сжатие GZip, чтобы минимизировать размер возвращаемого ответа, установив apiGateway:minimumCompressionSize: 1024 в serverless.yml файле
  3. Включите повторное использование соединений AWS, установив для environment: AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1 значение повторно использовать соединения HTTP
//serverless.yml
service:
  name: aws-nodejs-typescript
# app and org for use with dashboard.serverless.com
#app: your-app-name
#org: your-org-name

custom:
  webpack:
    webpackConfig: ./webpack.config.js
    includeModules: true

# Add the serverless-webpack plugin
plugins:
  - serverless-webpack

provider:
  name: aws
  runtime: nodejs10.x
  apiGateway:
    minimumCompressionSize: 1024 # Enable gzip compression for responses > 1 KB
  environment:
    AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          method: get
          path: hello

Полученные результаты:

Теперь давайте посмотрим на результаты после реализации вышеуказанных оптимизаций. Спасибо пользователю github sapher за его собственный отзыв о большом проекте после моего pull request. Это его результаты

До:

После:

Как видите, разница в размере файла 37 000% с 5,9 МБ до 13,8 КБ для первого файла, а 3410 % увеличение скорости сборки (с 45,5 секунды до 1,3 секунды!).

И это результаты в шаблоне проекта hello world без зависимостей.

Я сделал запрос на перенос здесь с этими изменениями в бессерверном репозитории, который уже был объединен в ноябре 2019 года.

Если ваш проект был создан ранее, вы можете обновить настройку вручную, посмотрев на изменения в запросе на вытягивание, на самом деле они очень небольшие, но, как вы можете видеть, весьма значительны.

Оптимизация общего размера пакета и скорости развертывания

Позже я смог сократить свои упакованные zip-файлы более чем наполовину и ускорить упаковку и развертывание за счет:

  1. Обновление до webpack v5
  2. используйте ускорение передачи s3 с помощью флага aws-s3-accelerate при запуске sls deploy для более быстрой загрузки в s3 за дополнительную плату.
  3. переключение с npm на yarn, чтобы использовать функцию autoclean, запустив yarn autoclean — init и yarn autoclean — force, которые очищают мои node_modules и удаляют оттуда ненужные файлы благодаря этой проблеме github в serverless-webpack.
  4. Настроить serverless-webpack плагин для использования yarn autoclean для включенного node_modules и использовать мой настроенный .yarnclean файл, добавив его в мой serverless.yml
//serverless.yml
webpack:
webpackConfig: ./webpack.config.js
includeModules: true
forceExclude:
- aws-sdk
packager: "yarn"
packagerOptions:
scripts:
- yarn autoclean --init
- rm .yarnclean && cat ../../.yarnclean >> .yarnclean && echo '\n*.ts' >> .yarnclean
- rm -rf node_modules/aws-sdk
- yarn autoclean --force

6. Настройка более продвинутого .yarnclean файла, чем тот, который был создан с помощью yarn autoclean — init, который также использует файлы, удаленные с помощью node-prune.

7. Принудительное удаление aws-sdk из моих пакетов с помощью packagerOptions.scripts serverless-webpack Я заметил, что даже несмотря на то, что aws-sdk был заявлен как devDependency и исключался внешним pugin, он все еще добавлялся в мои пакеты через aws-xray-sdk-core, в котором указано aws-sdk в качестве зависимости вместо peerDependency, чтобы она все еще попала в мой пакет, для этого уже есть проблема с github в aws-xray-sdk.

Вышеупомянутые шаги помогли уменьшить размер пакета для одной из моих лямбда-выражений с 18 МБ до 7 МБ, а для других - с 11 МБ до 2,7 МБ.