بناء ونشر خادم GraphQL على AWS Lambda باستخدام Node.js و CloudFormation
مقدمة في عالم GraphQL و AWS Lambda
في عالم تطوير الواجهات البرمجية (APIs) سريع التطور، أصبحت المرونة والكفاءة مطلبين أساسيين. لقد أمضيت سنوات في بناء واجهات GraphQL البرمجية في بيئات لا خادمية (Serverless)، وأجد صعوبة في تخيل العودة إلى العمل مع واجهات RESTful APIs التقليدية. عندما تجمع قوة GraphQL مع قابلية التوسع اللامحدودة لخدمة AWS Lambda، تحصل على خادم قادر على التعامل مع كميات هائلة من حركة المرور بكفاءة لا مثيل لها.
في هذا الدليل الشامل، سنتعلم خطوة بخطوة كيفية بناء ونشر خادم GraphQL على AWS Lambda، والوصول إليه عبر نقطة نهاية (endpoint) من API Gateway. سنستخدم CloudFormation و AWS CLI لنشر جميع موارد AWS الخاصة بنا ورمز التطبيق البرمجي، مما يضمن عملية نشر آلية وقابلة للتكرار.
ماذا سنتناول في هذا الدليل؟
- بناء خادم
GraphQLباستخدامApollo Server. - نشر خادم
GraphQLهذا علىAWS Lambda. - استخدام
API Gatewayلترحيل الطلبات إلىLambda. - استخدام
CloudFormationلنشر حزمة التطبيق (application stack) علىAWS. - إعداد
Lambdaللعملية التطويرية المحلية.
ملاحظة سريعة: يمكنك الحصول على الكود المصدري الكامل للتطبيق من Github.
ما هو GraphQL؟
GraphQL هي لغة استعلام (query language) لوصف الواجهات البرمجية (APIs) باستخدام نظام مخطط (schema system) قوي ومحدد الأنواع. يقوم خادم GraphQL بتلبية هذه الاستعلامات باستخدام البيانات الموجودة. فيما يلي بعض المزايا الرئيسية لاستخدام GraphQL:
استعلام البيانات التي يحتاجها تطبيقك فقط
على عكس واجهات REST APIs، يُمكّن GraphQL العملاء من استعلام البيانات التي يحتاجونها بدقة فقط. يقوم الخادم بتلبية طلب العميل عن طريق إرجاع ما يطلبه العميل فقط، مما يقلل من حجم البيانات المنقولة ويزيد من كفاءة الاتصال.
نظام قوي ومحدد الأنواع
يُمكّن نظام GraphQL القوي والمحدد الأنواع المستخدمين من فحص المخطط (schema) بأكمله. تعمل واجهة GraphQL API كتوثيق واضح لقدرات الخادم وتُعلمك بالأخطاء أثناء عملية التطوير، مما يقلل من الأخطاء ويسرع عملية التطوير.
تجميع استعلاماتك في طلب واحد
مع GraphQL، يمكنك استعلام موارد متعددة والحصول على استجابات مجمعة بطلب واحد. بفضل عدد أقل من الطلبات، تعمل التطبيقات التي تستخدم GraphQL بشكل أسرع بكثير، مما يحسن تجربة المستخدم.
ما هي AWS Lambda؟
AWS Lambda هي خدمة حوسبة تقدمها AWS تتيح لك تشغيل رمز التطبيق الخاص بك دون الحاجة إلى إدارة أي خوادم. تتولى AWS جميع الأعباء العامة مثل البنية التحتية، والأمان، والموارد، ونظام التشغيل، والتصحيحات، حتى يتمكن المطورون من التركيز فقط على بناء التطبيق، مما يوفر وقتًا وجهدًا كبيرين.
لنبدأ العمل: إعداد المشروع
لنبدأ بإنشاء مجلد للمشروع. ثم، انتقل إلى المجلد وقم بتهيئة مشروع Node.js. في الأمثلة التالية، أستخدم Node 10.x. يمكنك تثبيت إصدار Node الذي تختاره باستخدام asdf.
mkdir apollo-server-lambda-nodejs
cd apollo-server-lambda-nodejs
yarn init
بعد ذلك، أنشئ مجلدًا يضم جميع الكود المصدري الخاص بنا.
mkdir src
أخيرًا، أنشئ ملف index داخل مجلد src الذي سيعمل كمعالج لـ Lambda (lambda handler).
cd src
touch index.js

املأ ملف index.js بالكود التالي:
exports.handler = async () => {
return {
body: 'Hello from Lambda'
};
};
الكود أعلاه هو معالج Lambda بسيط للغاية سيعيد Hello from Lambda عند استدعائه. لنقم أولاً بنشر الكود الخاص بنا إلى AWS Lambda.
تجهيز كود التطبيق للنشر
قبل أن نتمكن من نشر الكود الخاص بنا إلى Lambda، نحتاج إلى إنشاء ملف مضغوط (zip) لتطبيقنا وتحميله إلى سلة تخزين S3. سنستخدم AWS CLI لإنشاء السلة. إذا لم تكن قد قمت بإعداد AWS CLI بعد، فاتبع هذا الدليل لإعداده الآن.
أنشئ سلة S3 لاستخدامها في نشر الكود الخاص بنا إلى Lambda. اختر اسمًا فريدًا لسلة S3 الخاصة بك. أسماء السلات فريدة عالميًا عبر جميع مناطق AWS.
aws s3 mb s3://lambda-deploy-asln
أنشئ أرشيفًا للتطبيق باستخدام أمر zip وتحقق من الملفات داخل الملف المضغوط.
zip -rq dist-latest.zip src package.json
zipinfo dist-latest.zip
انسخ ملف zip إلى S3 باستخدام أمر AWS CLI.
aws s3 cp dist-latest.zip s3://lambda-deploy-asln/dist-latest.zip
أخيرًا، استخدم الأمر التالي للتحقق من وجود الملف في S3.
aws s3 ls s3://lambda-deploy-asln

الآن بعد أن قمنا بنشر التطبيق المعبأ إلى S3، نحتاج بعد ذلك إلى إعداد Lambda و API Gateway في AWS. في القسم التالي، سنستخدم CloudFormation لإعداد جميع موارد AWS الضرورية.
إعداد AWS Lambda مع تكامل API Gateway Proxy
CloudFormation هي خدمة AWS تساعدنا في كتابة البنية التحتية ككود (Infrastructure as Code). تجعل CloudFormation عملية إنشاء وإدارة موارد التطبيق بسيطة للغاية. دعنا نستخدم CloudFormation لتحديد حزمتنا (stack).
أنشئ ملفًا باسم cloudformation.yml في جذر المشروع.
touch cloudformation.yml
أضف الكود التالي إلى ملف cloudformation.yml:
---
Description: GraphQL server on AWS lambda
Parameters:
Version:
Description: Application version number
Type: String
BucketName:
Description: S3 bucket name where the source code lives
Type: String
Resources:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Code:
S3Bucket: !Ref BucketName
S3Key: !Sub dist-${Version}.zip
Handler: src/index.handler
Description: GraphQL Apollo Server
Role: !GetAtt LambdaExecutionRole.Arn
Runtime: nodejs10.x
Timeout: 10
LambdaExecutionRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
Policies:
- PolicyName: "LambdaFunctionPolicy"
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: "*"
GraphQLApi:
Type: 'AWS::ApiGateway::RestApi'
Properties:
Name: apollo-graphql-api
GraphQLApiResource:
Type: 'AWS::ApiGateway::Resource'
Properties:
ParentId: !GetAtt GraphQLApi.RootResourceId
RestApiId: !Ref GraphQLApi
PathPart: 'graphql'
GraphQLApiMethod:
Type: 'AWS::ApiGateway::Method'
Properties:
RestApiId: !Ref GraphQLApi
ResourceId: !Ref GraphQLApiResource
AuthorizationType: None
HttpMethod: POST
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations
GraphQLApiDeployment:
Type: 'AWS::ApiGateway::Deployment'
Properties:
RestApiId: !Ref GraphQLApi
StageName: v1
DependsOn:
- GraphQLApiResource
- GraphQLApiMethod
GraphQLApiPermission:
Type: 'AWS::Lambda::Permission'
Properties:
Action: lambda:invokeFunction
FunctionName: !GetAtt LambdaFunction.Arn
Principal: apigateway.amazonaws.com
SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${GraphQLApi}/*
Outputs:
ApiUrl:
Description: Invoke url of API Gateway endpoint
Value: !Sub https://${GraphQLApi}.execute-api.${AWS::Region}.amazonaws.com/v1/graphql
أعلم أن هناك الكثير يحدث في هذا القالب. دعنا نفحص الكود خطوة بخطوة.
معلمات القالب (Template Parameters)
أولاً، نحدد بعض المعلمات التي نستخدمها في القالب. يمكننا تمرير هذه المتغيرات كتجاوزات للمعلمات (parameter overrides) عند نشر حزمة CloudFormation.
Description: GraphQL server on AWS lambda
Parameters:
Version:
Description: Application version number
Type: String
BucketName:
Description: S3 bucket name where the source code lives
Type: String
دالة Lambda
نحدد دالة Lambda الخاصة بنا مع تحديد المسار الذي يجب أن تسحب منه كود التطبيق. هذه السلة هي نفسها التي أنشأناها سابقًا.
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Code:
S3Bucket: !Ref BucketName
S3Key: !Sub dist-${Version}.zip
Handler: src/index.handler
Description: GraphQL Apollo Server
Role: !GetAtt LambdaExecutionRole.Arn
Runtime: nodejs10.x
Timeout: 10
نريد أن تكون دالة Lambda الخاصة بنا قادرة على إرسال سجلات التطبيق إلى AWS CloudWatch. تتطلب Lambda أذونات خاصة لتتمكن من كتابة السجلات إلى CloudWatch. لذلك، نقوم بإنشاء دور (role) يُمكّن الكتابة إلى CloudWatch ونقوم بتعيينه لدالة Lambda.
LambdaExecutionRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
Policies:
- PolicyName: "LambdaFunctionPolicy"
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: "*"
API Gateway
نريد أيضًا نقطة نهاية HTTP لاستدعاء دالة Lambda. يمكن استخدام API Gateway لإنشاء نقطة نهاية HTTP. يمكننا بعد ذلك تكوين API Gateway لترحيل جميع الطلبات الواردة من العميل إلى دالة Lambda وإرسال الاستجابة من Lambda مرة أخرى إلى العميل.
أولاً، نقوم بإنشاء API Gateway RestApi.
GraphQLApi:
Type: 'AWS::ApiGateway::RestApi'
Properties:
Name: apollo-graphql-api
ثم، نقوم بإنشاء مورد API Gateway Resource، والذي يقبل الطلبات على المسار /graphql.
GraphQLApiResource:
Type: 'AWS::ApiGateway::Resource'
Properties:
ParentId: !GetAtt GraphQLApi.RootResourceId
RestApiId: !Ref GraphQLApi
PathPart: 'graphql'
بعد ذلك، نقوم بتكوين المورد لقبول طلبات POST عن طريق إنشاء API Gateway Method ثم ندمجه مع Lambda.
GraphQLApiMethod:
Type: 'AWS::ApiGateway::Method'
Properties:
RestApiId: !Ref GraphQLApi
ResourceId: !Ref GraphQLApiResource
AuthorizationType: None
HttpMethod: POST
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations
أخيرًا، نقوم بإنشاء API Gateway Deployment الذي ينشر الواجهة البرمجية إلى المرحلة المحددة (stage).
GraphQLApiDeployment:
Type: 'AWS::ApiGateway::Deployment'
Properties:
RestApiId: !Ref GraphQLApi
StageName: v1
DependsOn:
- GraphQLApiResource
- GraphQLApiMethod
أذونات Lambda / API Gateway
في هذه المرحلة، قمنا بتكوين كل من دالة Lambda و API Gateway بشكل صحيح. ومع ذلك، يحتاج API Gateway إلى إذن خاص لاستدعاء دالة Lambda. نسمح لـ API Gateway باستدعاء Lambda عن طريق إنشاء مورد Lambda Permission.
GraphQLApiPermission:
Type: 'AWS::Lambda::Permission'
Properties:
Action: lambda:invokeFunction
FunctionName: !GetAtt LambdaFunction.Arn
Principal: apigateway.amazonaws.com
SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${GraphQLApi}/*
أخيرًا، نقوم بتصدير عنوان URL الخاص بالواجهة البرمجية في نهاية القالب. يمكننا استخدام هذا العنوان لاستدعاء دالة Lambda.
Outputs:
ApiUrl:
Description: Invoke url of API Gateway endpoint
Value: !Sub https://${GraphQLApi}.execute-api.${AWS::Region}.amazonaws.com/v1/graphql
نشر حزمة CloudFormation إلى AWS
الآن بعد أن أصبح قالب CloudFormation جاهزًا، دعنا نستخدم أمر AWS CLI لنشره على AWS. قم بتشغيل الأمر التالي في سطر الأوامر الخاص بك. تأكد من تحديث قيمة BucketName إلى اسم السلة التي أنشأتها سابقًا.
aws cloudformation deploy \
--template-file ./cloudformation.yml \
--stack-name apollo-server-lambda-nodejs \
--parameter-overrides BucketName=lambda-deploy-asln Version=latest \
--capabilities CAPABILITY_IAM

قد يستغرق نشر الحزمة بعض الوقت. يجب أن تكون دالة Lambda جاهزة لبدء تلقي الطلبات عند الانتهاء من النشر.
التحقق من عمل API Gateway و Lambda كما هو متوقع
الآن بعد أن قمنا بنشر حزمة CloudFormation الخاصة بنا، دعنا نتحقق مما إذا كان كل شيء يعمل كما هو متوقع. نحتاج إلى عنوان URL الخاص بـ API Gateway لإرسال طلب إلى دالة Lambda الخاصة بنا. يأتي عنوان URL الخاص بالواجهة البرمجية الذي قمنا بتصديره في قالب CloudFormation مفيدًا هنا. قم بتشغيل الأمر التالي لطباعة عنوان URL الخاص بالواجهة البرمجية في سطر الأوامر.
aws cloudformation describe-stacks \
--stack-name=apollo-server-lambda-nodejs \
--query "Stacks[0].Outputs[?OutputKey=='ApiUrl'].OutputValue" \
--output text

الآن، استخدم أمر curl لاستدعاء عنوان URL الخاص بالواجهة البرمجية. يجب أن تحصل على Hello from Lambda مرة أخرى من الخادم.
curl -d '{}' https://o55ybz0sc5.execute-api.us-east-1.amazonaws.com/v1/graphql

إضافة سكريبت النشر لتسهيل العملية
ربما لاحظت أننا قمنا بتشغيل مجموعة كاملة من الأوامر لتعبئة ونشر تطبيقنا. سيكون من الممل جدًا تشغيل هذه الأوامر في كل مرة نقوم فيها بنشر التطبيق. دعنا نضيف سكريبت bash لتبسيط سير العمل هذا.
أنشئ دليلًا يسمى bin في جذر التطبيق وأضف ملفًا باسم deploy.
mkdir bin
touch bin/deploy
قبل أن نتمكن من تنفيذ السكريبت، نحتاج إلى تعيين أذونات الملف الصحيحة. دعنا نفعل ذلك عن طريق تشغيل الأمر التالي.
chmod +x bin/deploy

في هذه المرحلة، يجب أن تبدو بنية الدليل لدينا كما في لقطة الشاشة أدناه.

أضف الكود التالي إلى الملف:
#!/bin/bash
set -euo pipefail
OUTPUT_DIR=dist
CURRENT_DIR=$(pwd)
ROOT_DIR="$(dirname "${BASH_SOURCE[0]}")"/..
APP_VERSION=$(date +%s)
STACK_NAME=apollo-server-lambda-nodejs
cd $ROOT_DIR
echo "cleaning up old build.."
[ -d $OUTPUT_DIR ] && rm -rf $OUTPUT_DIR
mkdir dist
echo "zipping source code.."
zip -rq $OUTPUT_DIR/dist-$APP_VERSION.zip src node_modules package.json
echo "uploading source code to s3.."
aws s3 cp $OUTPUT_DIR/dist-$APP_VERSION.zip s3://$S3_BUCKET/dist-$APP_VERSION.zip
echo "deploying application.."
aws cloudformation deploy \
--template-file $ROOT_DIR/cloudformation.yml \
--stack-name $STACK_NAME \
--parameter-overrides Version=$APP_VERSION BucketName=$S3_BUCKET \
--capabilities CAPABILITY_IAM
# Get the api url from output of cloudformation stack
API_URL=$(aws cloudformation describe-stacks \
--stack-name=$STACK_NAME \
--query "Stacks[0].Outputs[?OutputKey=='ApiUrl'].OutputValue" \
--output text)
echo -e "\n$API_URL"
cd $CURRENT_DIR
حسنًا، دعنا نحلل ما يحدث في هذا السكريبت. نبدأ بتعريف بعض المتغيرات. نقوم بإنشاء ملف الأرشيف داخل دليل dist. نحدد إصدار التطبيق ليكون الطابع الزمني الحالي الذي يتم فيه تشغيل السكريبت. باستخدام الطابع الزمني، يمكننا التأكد من أن رقم الإصدار فريد ومتزايد دائمًا.
#!/bin/bash
set -euo pipefail
OUTPUT_DIR=dist
CURRENT_DIR=$(pwd)
ROOT_DIR="$(dirname "${BASH_SOURCE[0]}")"/..
APP_VERSION=$(date +%s)
STACK_NAME=apollo-server-lambda-nodejs
ثم نقوم بتنظيف أي إصدارات قديمة وإنشاء دليل dist جديد.
echo "cleaning up old build.."
[ -d $OUTPUT_DIR ] && rm -rf $OUTPUT_DIR
mkdir dist
بعد ذلك، نقوم بتشغيل أمر zip لأرشفة الكود المصدري وتبعياته.
echo "zipping source code.."
zip -rq $OUTPUT_DIR/dist-$APP_VERSION.zip src node_modules package.json
بعد ذلك، ننسخ ملف zip إلى سلة S3.
echo "uploading source code to s3.."
aws s3 cp $OUTPUT_DIR/dist-$APP_VERSION.zip s3://$S3_BUCKET/dist-$APP_VERSION.zip
ثم نقوم بنشر حزمة CloudFormation.
echo "deploying application.."
aws cloudformation deploy \
--template-file $ROOT_DIR/cloudformation.yml \
--stack-name $STACK_NAME \
--parameter-overrides Version=$APP_VERSION BucketName=$S3_BUCKET \
--capabilities CAPABILITY_IAM
أخيرًا، نستعلم حزمة CloudFormation للحصول على عنوان URL الخاص بالواجهة البرمجية من مخرجات CloudFormation ونطبعه في سطر الأوامر.
# Get the api url from output of cloudformation stack
API_URL=$(aws cloudformation describe-stacks \
--stack-name=$STACK_NAME \
--query "Stacks[0].Outputs[?OutputKey=='ApiUrl'].OutputValue" \
--output text)
echo -e "\n$API_URL"
النشر إلى AWS باستخدام سكريبت النشر
دعنا نجرب النشر باستخدام سكريبت النشر. يتوقع السكريبت وجود متغير البيئة S3_BUCKET. قم بتشغيل الأمر التالي لتشغيل النشر. عندما ينجح النشر، سيقوم السكريبت بإخراج عنوان URL الخاص بالواجهة البرمجية الذي يمكننا استخدامه لاستدعاء دالة Lambda.
S3_BUCKET=lambda-deploy-asln ./bin/deploy

لتبسيط هذا أكثر، دعنا نستدعيه باستخدام yarn. أضف ما يلي في ملف package.json الخاص بك.
"scripts": {
"deploy": "S3_BUCKET=lambda-deploy-asln ./bin/deploy"
}
بعد ذلك، يمكننا ببساطة تشغيل yarn deploy لبدء عمليات النشر.
تحسين سير العمل باستخدام Lambda و API Gateway المحليين
غالبًا ما نقوم بتعديل كود التطبيق أثناء العمل على تطبيقنا. حاليًا، يستغرق النشر إلى منطقة AWS us-east-1 حوالي 10 ثوانٍ بالنسبة لي، على اتصال إنترنت بسرعة تحميل 40 ميجابت/ثانية. يصبح وقت النشر أكثر أهمية مع نمو حجم التطبيق. الانتظار لمدة 10 ثوانٍ أو أكثر لإدراك أنني ارتكبت خطأً في بناء الجملة ليس منتجًا على الإطلاق. دعنا نصلح هذا عن طريق إعداد دالة Lambda محليًا واستدعائها باستخدام نقطة نهاية API محلية. يُمكّننا AWS SAM CLI من فعل ذلك تمامًا. اتبع التعليمات في هذه الصفحة لتثبيته. بمجرد الانتهاء، من جذر المشروع، قم بتشغيل الأمر التالي.
sam local start-api --template-file cloudformation.yml

نقطة النهاية المحلية متاحة الآن على http://localhost:3000. يمكننا استخدام نقطة النهاية هذه لإرسال طلبات إلى دالة Lambda المحلية الخاصة بنا. افتح طرفية أخرى وقم بتشغيل الأمر التالي لإرسال طلب. يجب أن ترى الاستجابة من دالة Lambda المحلية الخاصة بنا.
curl -d '{}' http://localhost:3000/graphql

أخيرًا، أضف الأسطر التالية في قسم scripts في ملف package.json.
"dev": "sam local start-api --template-file cloudformation.yml"
بعد ذلك، يمكننا تشغيل الأمر yarn dev لبدء خادم التطوير.
إعداد خادم GraphQL في Lambda
دون مزيد من الحديث، دعنا ننتقل مباشرة إلى الكود ونبني خادم GraphQL. ابدأ بتثبيت التبعيات. نستخدم Apollo Server لبناء خادم GraphQL الخاص بنا. Apollo Server هو تطبيق مفتوح المصدر لخادم GraphQL.
yarn add apollo-server-lambda graphql
استبدل محتوى ملف src/index.js بالكود التالي:
const { ApolloServer, gql } = require('apollo-server-lambda');
const typeDefs = gql`
type Query {
user: User
}
type User {
id: ID
name: String
}
`;
const resolvers = {
Query: {
user: () => ({ id: 123, name: 'John Doe' })
}
};
const server = new ApolloServer({ typeDefs, resolvers });
exports.handler = server.createHandler();
هنا، نحدد مخططًا (schema) يتكون من نوع User واستعلام user. ثم نحدد محللًا (resolver) لاستعلام user. من أجل التبسيط، يقوم المحلل بإرجاع مستخدم ثابت البيانات. أخيرًا، نقوم بإنشاء معالج GraphQL وتصديره.
لإجراء استعلامات على خادم GraphQL الخاص بنا، نحتاج إلى عميل GraphQL. Insomnia هو العميل المفضل لدي، ولكن أي عميل GraphQL آخر سيكون جيدًا. الآن، دعنا نجري استعلامًا للتأكد من أن خادمنا يعمل كما هو متوقع. أنشئ طلب GraphQL جديدًا في Insomnia.


أضف الاستعلام التالي في الجسم وأرسل الاستعلام إلى http://localhost:3000. بافتراض أن خادم التطوير الخاص بك لا يزال قيد التشغيل، يجب أن ترى الاستجابة التالية من خادم GraphQL.

الآن بعد أن تحققنا من أن كل شيء يعمل بشكل جيد في الخادم المحلي، دعنا نشغل الأمر التالي لنشر خادم GraphQL إلى AWS.
yarn deploy

يتم إخراج عنوان URL الخاص بالواجهة البرمجية في سطر الأوامر بمجرد اكتمال النشر. استبدل عنوان URL في Insomnia بالذي حصلت عليه من API Gateway. أعد تشغيل الاستعلام لترى أنه يتم حله.

الخلاصة التقنية
تهانينا! لقد نجحت في نشر خادم GraphQL على AWS Lambda بالكامل باستخدام CloudFormation. هذا الإنجاز يمثل خطوة مهمة نحو بناء تطبيقات حديثة وقابلة للتوسع. لقد أظهرنا كيف يمكن لخادمك استقبال طلبات GraphQL من العميل وإرجاع الاستجابات المناسبة بكفاءة عالية. الأهم من ذلك، قمنا بإعداد بيئة تطوير محلية قوية باستخدام AWS SAM CLI، مما يقلل بشكل كبير من أوقات الانتظار ويزيد من إنتاجية المطورين، دون الحاجة إلى إضافة الكثير من التبعيات المعقدة. هذا النهج يضمن دورة تطوير سريعة وفعالة، ويؤكد على قوة دمج التقنيات السحابية الحديثة مع أنماط الواجهات البرمجية المرنة.