Bekerja Dengan TypeScript dan Dukungan Jest: Tutorial AWS SAM
Diterbitkan: 2022-03-11Alat 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:
- AWS CLI
- AWS SAM CLI
- 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) dariAWS::Serverless::Functionresource. -
output: Ini menunjuk ke tujuan keluaran build (dalam hal ini,.aws-sam/build). Di sini kita juga menentukan perpustakaan target sebagaicommonjs2, yang memberikan nilai kembalian dari titik masuk kemodule.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 lingkunganNODE_OPTIONSke--enable-source-mapsuntuk 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 fungsirequireNode.js untuk memuat potongan saat dikompilasi. -
module: Ini menerapkan pemuat TypeScript ke semua file yang memenuhi kondisitest. Dengan kata lain, ini memastikan bahwa semua file dengan ekstensi.tsatau.tsxakan ditangani oleh loader. -
plugins: Ini membantu Webpack mengidentifikasi dan menggunakanaws-sam-webpack-pluginkami.
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 typescriptKami 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-apiSaat kami mengunjungi titik akhir pengujian di browser web, kami akan melihat pesan sukses.
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 containerMeningkatkan 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 prettierKami 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
defaultdalam pernyataanswitch. - Peringatan jika kami menetapkan kembali parameter suatu fungsi.
- Peringatan jika kita memanggil pernyataan
awaitdi 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 daries5menjadinoneuntuk menghindari tanda koma. -
semi: Kami mengubah ini darifalsemenjaditruekarena 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.
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 subfoldersrckami. -
testMatch: Array pola glob ini menyertakan ekstensi file yang akan dianggap sebagai file Jest. -
transform: Opsi ini memungkinkan kita menulis pengujian dalam TypeScript menggunakan paketts-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:
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 .eslintcacheSiap, 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.
