Razzle: Razzle و Serverless

تم إنشاؤها على ٣٠ مايو ٢٠١٨  ·  30تعليقات  ·  مصدر: jaredpalmer/razzle

أهلا !
أحاول تشغيل مشروع razzle (materialUI ، و Typescript ، و Apollo & After) بدون خادم.
ما هي أفضل طريقة للتعامل مع هذا الأمر مع Serverless؟

إذا كنت تعرف أي مثال هناك ، يسعدني إلقاء نظرة. شكرا !

التعليق الأكثر فائدة

هذه هي الطريقة التي أنشر بها تطبيقات Razzle في AWS Lambda باستخدام AWS CDK :

رازلستاك

import * as CDK from '@aws-cdk/core';
import * as S3 from '@aws-cdk/aws-s3';
import * as S3Deployment from '@aws-cdk/aws-s3-deployment';
import * as Lambda from '@aws-cdk/aws-lambda';
import * as APIGateway from '@aws-cdk/aws-apigateway';
import * as SSM from '@aws-cdk/aws-ssm';
import * as SecretsManager from '@aws-cdk/aws-secretsmanager';

import { ConfigProps, getParam, ModeStack } from '../helpers';

export class RazzleStack extends ModeStack {
  constructor(app: CDK.App, id: string, props: ConfigProps) {
    super(app, id, props);

    /**
     * S3 bucket to the /public folder
     */
    const publicBucketName = `my-razzle-app-bucket-public-files-${this.mode}`;
    const bucketPublicFiles = new S3.Bucket(this, publicBucketName, {
      publicReadAccess: true,
      bucketName: publicBucketName.toLowerCase(),
    });

    /**
     * Store S3 bucket name
     */
    new SSM.StringParameter(this, `MyRazzleAppBucketAssetsName${this.Mode}`, {
      description: `My Razzle App S3 Bucket Name for Assets on ${this.Mode}`,
      parameterName: `/${props.name}/S3/Assets/Name`,
      stringValue: bucketPublicFiles.bucketName,
    });

    /**
     * Store S3 domainName name
     */
    new SSM.StringParameter(this, `MyRazzleAppBucketAssetsDomainName${this.Mode}`, {
      description: `My Razzle App S3 Bucket DomainName for Assets on ${this.Mode}`,
      parameterName: `/${props.name}/S3/Assets/DomainName`,
      stringValue: bucketPublicFiles.bucketDomainName,
    });

    /**
     * Deploy public folder of build to `my-razzle-app-bucket-public-files-${this.mode}` bucket
     */
    new S3Deployment.BucketDeployment(this, `${publicBucketName}-deploy`, {
      sources: [S3Deployment.Source.asset('./build/public')],
      destinationBucket: bucketPublicFiles,
    });

    /**
     * Environment Variables for SSR Function
     */
    const environmentKeys = [
      'NODE_ENV',
      'RAZZLE_GRAPHQL_URL',
      'RAZZLE_MAPBOX_ACCESS_TOKEN',
      'RAZZLE_GOOGLE_RECAPTCHA_SITE',
      'RAZZLE_GA_ID',
    ];

    const environmentSecret = SecretsManager.Secret.fromSecretAttributes(
      this,
      `MyRazzleAppEnvironmentSecret${this.Mode}`,
      {
        secretArn: getParam(this, `MyRazzleAppSecretsArn${this.Mode}`),
      },
    );

    let environment: { [key: string]: string } = {};
    for (const key of environmentKeys) {
      environment[key] = environmentSecret.secretValueFromJson(key).toString();
    }

    /**
     * Razzle SSR Function
     */
    const myRazzleAppSsrFunction = new Lambda.Function(this, `MyRazzleAppSSRFunction${this.Mode}`, {
      description: `Lambda Function that runs My Razzle App SSR on ${this.Mode}`,
      code: Lambda.Code.fromAsset('./build', {
        exclude: ['public', 'static', '*.json'],
      }),
      handler: 'server.handler',
      runtime: Lambda.Runtime.NODEJS_12_X,
      memorySize: 512,
      timeout: CDK.Duration.seconds(5),
      environment,
      tracing: Lambda.Tracing.ACTIVE,
    });

    /**
     * Razzle ApiGateway
     */
    const razzleSsrApiGatewayName = `MyRazzleAppSSRApiGateway${this.Mode}`;
    const api = new APIGateway.RestApi(this, razzleSsrApiGatewayName, {
      description: `ApiGateway that exposes My Razzle App SSR on ${this.Mode}`,
      binaryMediaTypes: ['*/*'],
      endpointTypes: [APIGateway.EndpointType.REGIONAL],
      deployOptions: {
        stageName: this.mode,
      },
    });
    const integration = new APIGateway.LambdaIntegration(myRazzleAppSsrFunction);
    const root = api.root;
    const pathApi = api.root.addResource('{proxy+}');

    root.addMethod('GET', integration);
    pathApi.addMethod('ANY', integration);

    /**
     * Razzle ApiGateway ID
     */
    new SSM.StringParameter(this, `MyRazzleAppAPIGatewayRestId${this.Mode}`, {
      description: `My Razzle App ApiGateway ID on ${this.Mode}`,
      parameterName: `/${props.name}/APIGateway/ApiId`,
      stringValue: api.restApiId,
    });
  }
}

ال 30 كومينتر

شخص ما فعل هذا وغرّد عنه سيكون مثال رائع

لا يمكن العثور على التغريدة! هل تمتلكه ؟

كانت تغريدتي - لقد استبدلت للتو index.js (حيث يحدث كل التحميل السريع) بـ

import awsServerlessExpress from 'aws-serverless-express'
import app from './server'
const binaryMimeTypes = [
  'application/octet-stream',
  'font/eot',
  'font/opentype',
  'font/otf',
  'image/jpeg',
  'image/png',
  'image/svg+xml',
]
const server = awsServerlessExpress.createServer(app, null, binaryMimeTypes)

export const handler = (event, context, callback) => {
  awsServerlessExpress.proxy(server, event, context)
}

يمكنك بعد ذلك تشغيل npm run build ، ونسخ node_modules/ إلى build/ ، وضغط server.js مع المجلد node_modules/ ، وتحميل ذلك إلى AWS Lambda. يتم تحميل كل شيء public/ بعد ذلك إلى S3 وإرساله عبر Cloudfront.

بالنسبة إلى Lambda -> البنية التحتية لبوابة API ، استخدمت Terraform واتبعت هذا الدليل: https://www.terraform.io/docs/providers/aws/guides/serverless-with-aws-lambda-and-api-gateway.html

لا يزال غير مثالي بالرغم من ذلك - الحصول على هذا الخطأ عند التحميل من حزمة جانب العميل (https://static.jobsok.io/):

image


تحديث:
أنا لا أفعل ذلك ، فقد أعطاني حذف node_modules وإعادة التثبيت:

File sizes after gzip:

  210.38 KB (+8 B)  build/static/js/bundle.1a960add.js
  1.96 KB           build/static/css/bundle.5865fae5.css

مع عدم وجود تغييرات في الكود - اجعل الحزمة من جانب العميل تعمل مرة أخرى

handler.js (أو index.js) هو نفسه.
بعد ذلك ، أقوم ببناء كل شيء باستخدام حزمة الويب (مشروع + عقدة_مودولات). (ما عليك سوى تعديل razzle.config.js لذلك)

أنا أعمل مع خادم ، وليس terraform. في الأساس نفس الشيء. تحتاج فقط إلى استيراد حزمة نسبية للمعالج (لسبب ما ، لا يحزم webpack هذه الحزمة ، ربما لأنه على ملف / مسار مختلف ، سيتم إصلاحه لاحقًا).

تحميل Serverless كل هذا ، وهذا كل شيء. يمكنك رؤية المشروع هنا: https://github.com/CuistotduCoin/cuistot

إنه بعيد عن الكمال ، ويمسح.

بالمناسبة ، @ jaredpalmer ، هل يمكنك مساعدتي في تكوين razzle / webpack؟
أرغب في تضمين كل ما هو مطلوب في الحزمة ، (متضمنة node_modules) بأفضل أداء. أي أمثلة / نصائح؟ (مع تكوين Typescript)

rozenmd هل يمكنك مشاركة razzle.config الخاص بك؟

منجم romainquellec فارغ - لا يوجد تكوين إضافي يتجاوز ما يوفره razzle

حسنًا ، لا أعرف السبب ، لكن لا يمكنني الوصول إلى aws-serverless-express المحدد في التبعيات (ربما أكثر).
ولتحسين كل ذلك ، أريد استبعاد aws-sdk من الإنشاء النهائي (إنه متاح دائمًا في وظيفة lambda ، وسأرى ذلك لاحقًا على الرغم من ذلك)

أعتقد أنه قادم من الخارج ، لكنني لا أستطيع فهمه.

نعم ، لدي نفس المشكلة. كان الحل الوحيد بالنسبة لي هو ضغط ملف server.js بكل وحدات node_modules

لا أستطيع على لامدا. حجم الحد الرسمي هو 50 شهرًا.
سؤال عام للجميع: كيفية تجميع وحدات node_modules بأداء جيد مع روعة. شكرا !

لا نستخدم lambda ، لكننا نجمع كل وحداتنا node_modules عن طريق إزالة خيار العناصر الخارجية الافتراضية في razzle.config.js. هذا أمر رائع لأنه يعني أن مجلد الإنشاء هو أداة بناء فعالة. ثم نضعه في s3 ثم تقوم مهمة Jenkins بسحب المجلد الجديد على كل خادم وإعادة تشغيل pm2.

jaredpalmer - هل هناك فرصة لنشر فكرة بهذا razzle.config.js ؟

بإزالة خيار العناصر الخارجية الافتراضية في razzle.config.js:

مثل هذا ؟
modify(config, { target, dev }) { if (target === 'node' && !dev) { config.externals = []; } return config; }

Romainquellec الذي يعمل !!

module.exports = {
  modify: (config, { target, dev }, webpack) => {
    // do something to config
    const appConfig = config // stay immutable here

    if (target === 'node' && !dev) {
      appConfig.externals = []
    }

    return appConfig
  },
}

انها تعمل. حسن ! 👍 👍
من العدل إضافة مثال! سوف أنظر إلى ذلك في نهاية هذا الأسبوع. هل تمانع في المشاركة rozenmd ؟

لسوء الحظ ، لن يكون لدي وقت فراغ في نهاية هذا الأسبوع

أنا أغلق هذا. سوف يقدم PR في أقرب وقت ممكن.

romainquellec هل سبق لك الالتفاف حول تقديم طلب السحب هذا؟ هل ما زلت تدير مشروع Razzle في بيئة لا تحتاج إلى خادم؟ لقد بدأت للتو في استكشاف هذا الاحتمال وتعثرت في هذا الموضوع :)

mbrochh لم أشاهد طلب سحب في النهاية ، لكنني ما زلت أستخدم Razzle على https://onlineornot.com لجميع عرض جانبي الخوادم بدون خادم.

لقد وجدت للتو منشور المدونة هذا: https://medium.com/@RozenMD/build-your-own-app-with-reaction-graphql-and-serverless-architecture-part-1-server-side-rendering-f0d0144ff5f

أعتقد أنني سأضطر إلى الغوص في الرأس ومحاولة متابعة هذا المنشور :)

شكرا على المنشور!

https://maxrozen.com/2018/08/08/start-your-own-app-with-react-part-1 ربما يكون رابطًا أفضل لتنسيق الكود.

و شكرا! :ابتسامة:

هل قام أي شخص بنشر Razzle في AWS lambda؟

أبحث أيضًا عن مثال لـ Razzle على AWS lambda. إذا فعل أي شخص ذلك وسعد بمشاركته معنا ، فسيكون ممتنًا حقًا.

هذه هي الطريقة التي أنشر بها تطبيقات Razzle في AWS Lambda باستخدام AWS CDK :

رازلستاك

import * as CDK from '@aws-cdk/core';
import * as S3 from '@aws-cdk/aws-s3';
import * as S3Deployment from '@aws-cdk/aws-s3-deployment';
import * as Lambda from '@aws-cdk/aws-lambda';
import * as APIGateway from '@aws-cdk/aws-apigateway';
import * as SSM from '@aws-cdk/aws-ssm';
import * as SecretsManager from '@aws-cdk/aws-secretsmanager';

import { ConfigProps, getParam, ModeStack } from '../helpers';

export class RazzleStack extends ModeStack {
  constructor(app: CDK.App, id: string, props: ConfigProps) {
    super(app, id, props);

    /**
     * S3 bucket to the /public folder
     */
    const publicBucketName = `my-razzle-app-bucket-public-files-${this.mode}`;
    const bucketPublicFiles = new S3.Bucket(this, publicBucketName, {
      publicReadAccess: true,
      bucketName: publicBucketName.toLowerCase(),
    });

    /**
     * Store S3 bucket name
     */
    new SSM.StringParameter(this, `MyRazzleAppBucketAssetsName${this.Mode}`, {
      description: `My Razzle App S3 Bucket Name for Assets on ${this.Mode}`,
      parameterName: `/${props.name}/S3/Assets/Name`,
      stringValue: bucketPublicFiles.bucketName,
    });

    /**
     * Store S3 domainName name
     */
    new SSM.StringParameter(this, `MyRazzleAppBucketAssetsDomainName${this.Mode}`, {
      description: `My Razzle App S3 Bucket DomainName for Assets on ${this.Mode}`,
      parameterName: `/${props.name}/S3/Assets/DomainName`,
      stringValue: bucketPublicFiles.bucketDomainName,
    });

    /**
     * Deploy public folder of build to `my-razzle-app-bucket-public-files-${this.mode}` bucket
     */
    new S3Deployment.BucketDeployment(this, `${publicBucketName}-deploy`, {
      sources: [S3Deployment.Source.asset('./build/public')],
      destinationBucket: bucketPublicFiles,
    });

    /**
     * Environment Variables for SSR Function
     */
    const environmentKeys = [
      'NODE_ENV',
      'RAZZLE_GRAPHQL_URL',
      'RAZZLE_MAPBOX_ACCESS_TOKEN',
      'RAZZLE_GOOGLE_RECAPTCHA_SITE',
      'RAZZLE_GA_ID',
    ];

    const environmentSecret = SecretsManager.Secret.fromSecretAttributes(
      this,
      `MyRazzleAppEnvironmentSecret${this.Mode}`,
      {
        secretArn: getParam(this, `MyRazzleAppSecretsArn${this.Mode}`),
      },
    );

    let environment: { [key: string]: string } = {};
    for (const key of environmentKeys) {
      environment[key] = environmentSecret.secretValueFromJson(key).toString();
    }

    /**
     * Razzle SSR Function
     */
    const myRazzleAppSsrFunction = new Lambda.Function(this, `MyRazzleAppSSRFunction${this.Mode}`, {
      description: `Lambda Function that runs My Razzle App SSR on ${this.Mode}`,
      code: Lambda.Code.fromAsset('./build', {
        exclude: ['public', 'static', '*.json'],
      }),
      handler: 'server.handler',
      runtime: Lambda.Runtime.NODEJS_12_X,
      memorySize: 512,
      timeout: CDK.Duration.seconds(5),
      environment,
      tracing: Lambda.Tracing.ACTIVE,
    });

    /**
     * Razzle ApiGateway
     */
    const razzleSsrApiGatewayName = `MyRazzleAppSSRApiGateway${this.Mode}`;
    const api = new APIGateway.RestApi(this, razzleSsrApiGatewayName, {
      description: `ApiGateway that exposes My Razzle App SSR on ${this.Mode}`,
      binaryMediaTypes: ['*/*'],
      endpointTypes: [APIGateway.EndpointType.REGIONAL],
      deployOptions: {
        stageName: this.mode,
      },
    });
    const integration = new APIGateway.LambdaIntegration(myRazzleAppSsrFunction);
    const root = api.root;
    const pathApi = api.root.addResource('{proxy+}');

    root.addMethod('GET', integration);
    pathApi.addMethod('ANY', integration);

    /**
     * Razzle ApiGateway ID
     */
    new SSM.StringParameter(this, `MyRazzleAppAPIGatewayRestId${this.Mode}`, {
      description: `My Razzle App ApiGateway ID on ${this.Mode}`,
      parameterName: `/${props.name}/APIGateway/ApiId`,
      stringValue: api.restApiId,
    });
  }
}

jgcmarins حول هذا الإعداد razzletack. هل يمكنك أن تفعل خطوة بخطوة كيفية استخدام هذا؟ أود إضافته إلى مستندات razzle.

https://razzle-git-canary.jared.vercel.app/deployment-options/aws

أحتاج إلى بعض المساعدة في هذا ، هل يمكن لأي شخص أن يساعدني؟

fivethreeo ستكون الخطوة بخطوة هي إعداد CDK في حساب AWS وتشغيل cdk deploy مع بعض العلامات الإضافية وهو مباشر \ o /

هل هناك أي شيء آخر مفقود من https://razzle-git-canary.jared.vercel.app/deployment-options/aws
؟

أود أن أقوم بالمرحلة باستخدام مجال بدلاً من مسار. ربما تكون مثالًا كاملًا مميزًا باستخدام rds ، وتناوب المفتاح ، و TypeOrm ، و typegraphql ، و Formik و jwt ولكن ليس كمثال في razzle نفسه.

لا شيء في عداد المفقودين خلاف ذلك.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

pseudo-su picture pseudo-su  ·  3تعليقات

howardya picture howardya  ·  5تعليقات

charlie632 picture charlie632  ·  4تعليقات

mhuggins picture mhuggins  ·  3تعليقات

MaxGoh picture MaxGoh  ·  4تعليقات