Bekerja Dengan TypeScript dan Dukungan Jest: Tutorial AWS SAM

Diterbitkan: 2022-03-11

Alat canggih untuk membangun aplikasi tanpa server, AWS Serverless Application Model (SAM) sering dipasangkan dengan JavaScript: 62% pengembang di seluruh perusahaan menengah dan besar memilih JavaScript untuk kode tanpa server mereka. Namun, TypeScript melonjak dalam popularitas dan jauh mengungguli JavaScript sebagai bahasa ketiga yang paling disukai pengembang.

Meskipun boilerplate JavaScript tidak sulit ditemukan, memulai proyek AWS SAM dengan TypeScript lebih kompleks. Tutorial berikut menunjukkan cara membuat proyek AWS SAM TypeScript dari awal serta bagaimana bagian-bagian yang berbeda bekerja bersama. Pembaca hanya perlu sedikit terbiasa dengan fungsi AWS Lambda untuk mengikuti.

Memulai Proyek TypeScript AWS SAM Kami

Dasar dari aplikasi tanpa server kami mencakup berbagai komponen. Kami pertama-tama akan mengonfigurasi lingkungan AWS, paket npm kami, dan fungsionalitas Webpack–kemudian kami dapat membuat, memanggil, dan menguji fungsi Lambda kami untuk melihat aplikasi kami beraksi.

Siapkan Lingkungan

Untuk mengatur lingkungan AWS, kita perlu menginstal yang berikut ini:

  1. AWS CLI
  2. AWS SAM CLI
  3. Node.js dan npm

Perhatikan bahwa tutorial ini memerlukan penginstalan Docker selama langkah 2 di atas untuk menguji aplikasi kita secara lokal.

Inisialisasi Proyek Kosong

Mari buat direktori proyek, aws-sam-typescript-boilerplate , dan subfolder src untuk menyimpan kode. Dari direktori proyek, kami akan menyiapkan paket npm baru:

 npm init -y # -y option skips over project questionnaire

Perintah ini akan membuat file package.json di dalam proyek kita.

Tambahkan Konfigurasi Webpack

Webpack adalah bundler modul yang terutama digunakan untuk aplikasi JavaScript. Karena TypeScript dikompilasi ke JavaScript biasa, Webpack akan secara efektif menyiapkan kode kita untuk browser web. Kami akan menginstal dua perpustakaan dan pemuat khusus:

  • paket web: Pustaka inti
  • webpack-cli: Utilitas baris perintah untuk Webpack
  • ts-loader: pemuat TypeScript untuk Webpack
 npm i --save-dev webpack webpack-cli ts-loader

Perintah build AWS SAM CLI, sam build , memperlambat proses pengembangan karena mencoba menjalankan npm install untuk setiap fungsi, menyebabkan duplikasi. Kita akan menggunakan perintah build alternatif dari library aws-sam-webpack-plugin untuk mempercepat lingkungan kita.

 npm i --save-dev aws-sam-webpack-plugin

Secara default, Webpack tidak menyediakan file konfigurasi. Mari kita buat file konfigurasi khusus bernama webpack.config.js di folder root:

 /* eslint-disable @typescript-eslint/no-var-requires */ const path = require('path'); const AwsSamPlugin = require('aws-sam-webpack-plugin'); const awsSamPlugin = new AwsSamPlugin(); module.exports = { entry: () => awsSamPlugin.entry(), output: { filename: (chunkData) => awsSamPlugin.filename(chunkData), libraryTarget: 'commonjs2', path: path.resolve('.') }, devtool: 'source-map', resolve: { extensions: ['.ts', '.js'] }, target: 'node', mode: process.env.NODE_ENV || 'development', module: { rules: [{ test: /\.tsx?$/, loader: 'ts-loader' }] }, plugins: [awsSamPlugin] };

Sekarang mari kita periksa berbagai bagian:

  • entry : Ini memuat objek entri (tempat Webpack mulai membuat bundel) dari AWS::Serverless::Function resource.
  • output : Ini menunjuk ke tujuan keluaran build (dalam hal ini, .aws-sam/build ). Di sini kita juga menentukan perpustakaan target sebagai commonjs2 , yang memberikan nilai kembalian dari titik masuk ke module.exports . Titik masuk ini adalah default untuk lingkungan Node.js.
  • devtool : Ini membuat peta sumber, app.js.map , di tujuan keluaran build kami. Ini memetakan kode asli kita ke kode yang berjalan di browser web dan akan membantu debugging jika kita menyetel variabel lingkungan NODE_OPTIONS ke --enable-source-maps untuk Lambda kita.
  • resolve : Ini memberitahu Webpack untuk memproses file TypeScript sebelum file JavaScript.
  • target : Ini memberitahu Webpack untuk menargetkan Node.js sebagai lingkungan kita. Ini berarti Webpack akan menggunakan fungsi require Node.js untuk memuat potongan saat dikompilasi.
  • module : Ini menerapkan pemuat TypeScript ke semua file yang memenuhi kondisi test . Dengan kata lain, ini memastikan bahwa semua file dengan ekstensi .ts atau .tsx akan ditangani oleh loader.
  • plugins : Ini membantu Webpack mengidentifikasi dan menggunakan aws-sam-webpack-plugin kami.

Di baris pertama, kami telah menonaktifkan aturan ESLint tertentu untuk file ini. Aturan ESLint standar yang akan kami konfigurasikan nanti tidak disarankan untuk menggunakan pernyataan yang require . Kami lebih suka require import di Webpack jadi kami akan membuat pengecualian.

Siapkan Dukungan TypeScript

Menambahkan dukungan TypeScript akan meningkatkan pengalaman pengembang dengan:

  • Mencegah pesan peringatan tentang deklarasi tipe yang hilang.
  • Menyediakan validasi tipe.
  • Menawarkan pelengkapan otomatis di dalam IDE.

Pertama, kami akan menginstal TypeScript untuk proyek kami secara lokal (lewati langkah ini jika Anda telah menginstal TypeScript secara global):

 npm i --save-dev typescript

Kami akan menyertakan jenis untuk perpustakaan yang kami gunakan:

 npm i --save-dev @types/node @types/webpack @types/aws-lambda

Sekarang, kita akan membuat file konfigurasi TypeScript, tsconfig.json , di root proyek:

 { "compilerOptions": { "target": "ES2015", "module": "commonjs", "sourceMap": true, "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, }, "include": ["src/**/*.ts", "src/**/*.js"], "exclude": ["node_modules"] }

Di sini kita mengikuti konfigurasi default yang direkomendasikan oleh komunitas TypeScript. Kami telah menambahkan include untuk menambahkan file di bawah folder src ke program dan exclude untuk menghindari kompilasi TypeScript untuk folder node_modules —kami tidak akan menyentuh kode ini secara langsung.

Buat Fungsi Lambda

Kami belum menulis kode Lambda untuk aplikasi tanpa server kami sampai sekarang, jadi mari masuk. Di folder src yang kita buat sebelumnya, kita akan membuat subfolder test-lambda yang berisi file app.ts dengan fungsi Lambda ini:

 import { APIGatewayEvent } from 'aws-lambda'; export const handler = async (event: APIGatewayEvent) => { console.log('incoming event is', JSON.stringify(event)); const response = { statusCode: 200, body: JSON.stringify({ message: 'Request was successful.' }) }; return response; };

Fungsi placeholder sederhana ini mengembalikan respons 200 dengan badan. Kami akan dapat menjalankan kode setelah satu langkah lagi.

Sertakan File Template AWS

AWS SAM memerlukan file template untuk mengubah kode kami dan menerapkannya ke cloud. Buat file template.yaml di folder root:

 AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: AWS SAM Boilerplate Using TypeScript Globals: Function: Runtime: nodejs14.x # modify the version according to your need Timeout: 30 Resources: TestLambda: Type: AWS::Serverless::Function Properties: Handler: app.handler FunctionName: "Test-Lambda" CodeUri: src/test-lambda/ Events: ApiEvent: Type: Api Properties: Path: /test Method: get

File template ini menghasilkan fungsi Lambda yang dapat diakses dari HTTP GET API. Perhatikan bahwa versi yang dirujuk pada Runtime: baris mungkin perlu disesuaikan.

Jalankan Aplikasi

Untuk menjalankan aplikasi, kita harus menambahkan skrip baru di file package.json untuk membangun proyek dengan Webpack. File mungkin memiliki skrip yang sudah ada, seperti skrip pengujian kosong. Kita dapat menambahkan skrip build seperti ini:

 "scripts": { "build": "webpack-cli" }

Jika Anda menjalankan npm run build dari root proyek, Anda akan melihat folder build, .aws-sam , dibuat. Kita yang berada di lingkungan Mac mungkin perlu membuat file tersembunyi terlihat dengan menekan Command + Shift + . untuk melihat foldernya.

Kami sekarang akan memulai server HTTP lokal untuk menguji fungsi kami:

 sam local start-api

Saat kami mengunjungi titik akhir pengujian di browser web, kami akan melihat pesan sukses.

Browser web menunjukkan tautan "127.0.0.1:3000/test" di bilah alamat. Di bawah bilah alamat, laman web kosong kecuali pesan yang berbunyi '{"message": "Permintaan berhasil."}.

Konsol harus menunjukkan bahwa fungsi tersebut dipasang di wadah Docker sebelum dijalankan, itulah sebabnya kami menginstal Docker sebelumnya:

 Invoking app.handler (nodejs14.x) Skip pulling image and use local one: public.ecr.aws/sam/emulation-nodejs14.x:rapid-1.37.0-x86_64. Mounting /Users/mohammadfaisal/Documents/learning/aws-sam-typescript-boilerplate/.aws-sam/build/TestLambda as /var/task:ro, delegated inside runtime container

Meningkatkan Alur Kerja Pengembangan Kami untuk Pengaturan Profesional

Proyek kami sudah berjalan, menambahkan beberapa sentuhan akhir akan memastikan pengalaman pengembang yang luar biasa yang akan meningkatkan produktivitas dan kolaborasi.

Optimalkan Build Dengan Hot Reload

Sangat membosankan untuk menjalankan perintah build setelah setiap perubahan kode. Reload panas akan memperbaiki masalah ini. Kami dapat menambahkan skrip lain di package.json kami untuk melihat perubahan file:

 "watch": "webpack-cli -w"

Buka terminal terpisah dan jalankan npm run watch . Sekarang, proyek Anda akan dikompilasi secara otomatis ketika Anda mengubah kode apa pun. Ubah pesan kode, segarkan halaman web Anda, dan lihat hasil yang diperbarui.

Tingkatkan Kualitas Kode Dengan ESLint dan Lebih Cantik

Tidak ada proyek TypeScript atau JavaScript yang lengkap tanpa ESLint dan Prettier. Alat-alat ini akan menjaga kualitas dan konsistensi kode proyek Anda.

Mari kita instal dependensi inti terlebih dahulu:

 npm i --save-dev eslint prettier

Kami akan menambahkan beberapa dependensi pembantu sehingga ESLint dan Prettier dapat bekerja sama dalam proyek TypeScript kami:

 npm i --save-dev \ eslint-config-prettier \ eslint-plugin-prettier \ @typescript-eslint/parser \ @typescript-eslint/eslint-plugin

Selanjutnya, kita akan menambahkan linter kita dengan membuat file konfigurasi ESLint, .eslintrc , di dalam root proyek:

 { "root": true, "env": { "es2020": true, "node": true, "jest": true }, "parser": "@typescript-eslint/parser", "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended" ], "ignorePatterns": ["src/**/*.test.ts", "dist/", "coverage/", "test/"], "parserOptions": { "ecmaVersion": 2018, "sourceType": "module", "ecmaFeatures": { "impliedStrict": true } }, "rules": { "quotes": ["error", "single", { "allowTemplateLiterals": true }], "default-case": "warn", "no-param-reassign": "warn", "no-await-in-loop": "warn", "@typescript-eslint/no-unused-vars": [ "error", { "vars": "all", "args": "none" } ] }, "settings": { "import/resolver": { "node": { "extensions": [".js", ".jsx", ".ts", ".tsx"] } } } }

Perhatikan bahwa bagian ekstensi dari file kita harus menjaga konfigurasi plugin extends sebagai baris terakhir untuk menampilkan kesalahan Prettier karena kesalahan ESLint terlihat di editor kita. Kami mengikuti pengaturan yang direkomendasikan ESLint untuk TypeScript, dengan beberapa preferensi khusus ditambahkan di bagian rules . Jangan ragu untuk menelusuri aturan yang tersedia dan menyesuaikan pengaturan Anda lebih lanjut. Kami memilih untuk menyertakan:

  • Kesalahan jika kami tidak menggunakan string yang dikutip tunggal.
  • Peringatan ketika kami tidak memberikan case default dalam pernyataan switch .
  • Peringatan jika kami menetapkan kembali parameter suatu fungsi.
  • Peringatan jika kita memanggil pernyataan await di dalam satu lingkaran.
  • Kesalahan untuk variabel yang tidak digunakan, yang membuat kode tidak dapat dibaca dan rentan terhadap bug dari waktu ke waktu.

Kami telah menyiapkan konfigurasi ESLint kami untuk bekerja dengan format Prettier. (Informasi lebih lanjut tersedia di proyek eslint-config-prettier GitHub.) Sekarang, kita dapat membuat file konfigurasi Prettier, .prettierrc :

 { "trailingComma": "none", "tabWidth": 4, "semi": true, "singleQuote": true }

Pengaturan ini berasal dari dokumentasi resmi Prettier; Anda dapat memodifikasinya sesuai keinginan. Kami memperbarui properti berikut:

  • trailingComma : Kami mengubah ini dari es5 menjadi none untuk menghindari tanda koma.
  • semi : Kami mengubah ini dari false menjadi true karena kami lebih suka memiliki titik koma di akhir setiap baris.

Akhirnya, saatnya melihat ESLint dan Prettier beraksi. Dalam file app.ts kita, kita akan mengubah tipe variabel response dari const menjadi let . Menggunakan let bukanlah praktik yang baik dalam kasus ini karena kami tidak mengubah nilai response . Editor harus menampilkan kesalahan, aturan yang rusak, dan saran untuk memperbaiki kode. Jangan lupa untuk mengaktifkan ESLint dan Prettier di editor Anda jika belum disiapkan.

Editor menampilkan baris kode yang menetapkan nilai ke variabel "biarkan respons". Garis menunjukkan bola lampu kuning di sebelahnya, dan kata "respons" memiliki garis bawah merah dan pop-up kesalahan di atasnya. Munculan kesalahan pertama-tama mendefinisikan variabel "respons" dan berbunyi: "biarkan respons: { statusCode: number; body: string; }." Di bawah definisi, pesan kesalahan berbunyi: "'respons' is never reassigned. Gunakan 'const' sebagai gantinya. eslint(prefer-const)." Di bawah pesan kesalahan, dua opsi terbaca: "Lihat Masalah" atau "Perbaikan Cepat."

Pertahankan Kode Dengan Pengujian Jest

Banyak perpustakaan tersedia untuk pengujian, seperti Jest, Mocha, dan Storybook. Kami akan menggunakan Jest dalam proyek kami karena beberapa alasan:

  • Ini cepat untuk belajar.
  • Ini membutuhkan pengaturan minimal.
  • Ini menawarkan pengujian snapshot yang mudah digunakan.

Mari kita instal dependensi yang diperlukan:

 npm i --save-dev jest ts-jest @types/jest

Selanjutnya, kita akan membuat file konfigurasi Jest, jest.config.js , di dalam root proyek:

 module.exports = { roots: ['src'], testMatch: ['**/__tests__/**/*.+(ts|tsx|js)'], transform: { '^.+\\.(ts|tsx)$': 'ts-jest' } };

Kami menyesuaikan tiga opsi dalam file kami:

  • roots : Array ini berisi folder yang akan dicari untuk file pengujian—hanya memeriksa di bawah subfolder src kami.
  • testMatch : Array pola glob ini menyertakan ekstensi file yang akan dianggap sebagai file Jest.
  • transform : Opsi ini memungkinkan kita menulis pengujian dalam TypeScript menggunakan paket ts-jest .

Mari buat folder __tests__ baru di dalam src/test-lambda . Di dalamnya, kita akan menambahkan file handler.test.ts , di mana kita akan membuat pengujian pertama kita:

 import { handler } from '../app'; const event: any = { body: JSON.stringify({}), headers: {} }; describe('Demo test', () => { test('This is the proof of concept that the test works.', async () => { const res = await handler(event); expect(res.statusCode).toBe(200); }); });

Kami akan kembali ke file package.json kami dan memperbaruinya dengan skrip pengujian:

 "test": "jest"

Ketika kita pergi ke terminal dan menjalankan npm run test , kita akan disambut dengan tes kelulusan:

Bagian atas konsol menunjukkan indikator hijau "Lulus" dan nama file pengujian, "src/test-lambda/__tests__/handler.test.ts." Baris berikutnya berbunyi, "Tes demo." Baris berikutnya menunjukkan tanda centang hijau diikuti dengan "Ini adalah bukti konsep bahwa tes berhasil. (1 ms)." Setelah baris kosong, baris pertama berbunyi: "Ujian Suite: 1 lulus, 1 total." Yang kedua berbunyi: "Tes: 1 lulus, 1 total." Yang ketiga berbunyi: "Snapshots: 0 total." Yang keempat berbunyi: "Waktu: 0,959 s." Baris terakhir berbunyi: "Jalankan semua suite pengujian."

Menangani Kontrol Sumber Dengan .gitignore

Kita harus mengonfigurasi Git untuk mengecualikan file tertentu dari kontrol sumber. Kita dapat membuat file .gitignore menggunakan gitignore.io untuk melewati file yang tidak diperlukan:

 # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* .pnpm-debug.log* # Runtime data pids *.pid *.seed *.pid.lock npm-debug.log package.lock.json /node_modules .aws-sam .vscode # TypeScript cache *.tsbuildinfo # Optional npm cache directory .npm # Optional ESLint cache .eslintcache

Siap, Tetapkan, Bangun: Cetak Biru Kami untuk Sukses

Kami sekarang memiliki proyek boilerplate AWS SAM lengkap dengan TypeScript. Kami telah berfokus untuk mendapatkan dasar-dasar yang benar dan mempertahankan kualitas kode yang tinggi dengan dukungan ESLint, Prettier, dan Jest. Contoh dari tutorial AWS SAM ini dapat berfungsi sebagai cetak biru, menempatkan proyek besar Anda berikutnya di jalur yang benar sejak awal.

Blog Toptal Engineering mengucapkan terima kasih kepada Christian Loef karena telah meninjau contoh kode yang disajikan dalam artikel ini.

Logo AWS dengan kata "PARTNER" dan teks "Advanced Tier Services" di bawahnya.
Sebagai Mitra Konsultasi Tingkat Lanjut di Jaringan Mitra Amazon (APN), Toptal menawarkan perusahaan akses ke pakar bersertifikasi AWS, sesuai permintaan, di mana pun di dunia.