在AWS无服务器平台上部署Laravel(laravel-mix)应用程序

11

我正在尝试在AWS无服务器平台上部署我的Laravel应用程序,我在我的laravel-mix中使用动态导入和代码拆分来编译资产。为了执行此操作,我按照bref package文档中的步骤安装了所需的库,并将我的公共目录与我的s3存储桶同步。

npm run prod
aws s3 sync public/ s3://<bucket-name>/ --delete --exclude index.php

并配置了我的.env文件为:

MIX_ASSET_URL=https://<bucket-name>.s3.amazonaws.com
ASSET_URL=https://<bucket-name>.s3.amazonaws.com

接下来,我配置了我的blade文件:

<script src="{{ asset('nits-assets/js/app.js') }}"></script>

我的webpack.mix.js文件包含:

const mix = require('laravel-mix')

const webpack = require('webpack');

const ASSET_URL = process.env.ASSET_URL + "/";

mix.js('resources/js/app.js', 'public/nits-assets/js')
    .postCss('resources/sass/app.css', 'public/nits-assets/css', [
        require("tailwindcss"),
    ])
    .webpackConfig({
        output: {
            chunkFilename: 'nits-assets/chunks/[name].[contenthash].js',
            publicPath: ASSET_URL
        },
        resolve: {
            symlinks: false,
            alias: {
                NitsModels: path.resolve(__dirname, 'Models'),
            },
        },  
        plugins: [
            new webpack.DefinePlugin({
                "process.env.ASSET_PATH": JSON.stringify(ASSET_URL)
            })
        ],
    }).sourceMaps().version();

由于我正在将代码拆分成块,因此我在获取块时遇到了麻烦,我的初始app.js文件从S3存储桶加载,但是为了加载块,它会尝试通过公共目录获取。

console error

我该如何配置laravel-mix,以从与我的公共目录同步的s3存储桶中加载块? 编辑: 如答案所建议,我更改了我的serverless.yml文件,现在它看起来像这样:
service: laravel

provider:
    name: aws
    # The AWS region in which to deploy (us-east-1 is the default)
    region: ap-south-1
    # The stage of the application, e.g. dev, production, staging… ('dev' is the default)
    stage: dev
    runtime: provided.al2
    environment:
      AWS_BUCKET: # environment variable for Laravel
        Ref: Storage
      iamRoleStatements:
        # Allow Lambda to read and write files in the S3 buckets
        - Effect: Allow
          Action:
            - s3:PutObject
            - s3:ListBucket
            - s3:GetObject
          Resource:
            - Fn::GetAtt: Storage.Arn # the storage bucket
            - Fn::Join: [ '', [ Fn::GetAtt: Storage.Arn, '/*' ] ] # everything in the storage bucket

resources:
  Resources:
    Storage:
      Type: AWS::S3::Bucket

package:
    # Directories to exclude from deployment
    exclude:
        - node_modules/**
        - public/storage
        - resources/assets/**
        - storage/**
        - tests/**

functions:
    # This function runs the Laravel website/API
    web:
        handler: public/index.php
        timeout: 28 # in seconds (API Gateway has a timeout of 29 seconds)
        layers:
            - ${bref:layer.php-74-fpm}
        events:
            -   httpApi: '*'
    # This function lets us run artisan commands in Lambda
    artisan:
        handler: artisan
        timeout: 120 # in seconds
        layers:
            - ${bref:layer.php-74} # PHP
            - ${bref:layer.console} # The "console" layer

plugins:
    # We need to include the Bref plugin
    - ./vendor/bref/bref

现在我遇到了以下问题:

出现错误:ArtisanLambdaFunction - 属性变量的值必须是一个具有字符串(或简单类型)属性的对象。

编辑2:

问题出现在serverless.yml文件中缩进(tab)的配置处:

environment:
  AWS_BUCKET: # environment variable for Laravel
    Ref: Storage
iamRoleStatements:
  # Allow Lambda to read and write files in the S3 buckets
  - Effect: Allow
    Action: s3:*

但现在出现了单独的问题:

enter image description here

错误:CloudFormation模板无效:模板错误:每个Fn :: GetAtt对象都需要两个非空参数,资源名称和资源属性。

1
以前没有使用过这个,但在某个地方解析配置时,它期望对象中的所有值都必须是简单类型或字符串,但发现了另一个对象、数组或函数,无法应用于该过程。 - KeitelDOG
可能在属性Resource: - Fn :: GetAtt中返回的是一个对象,而不仅仅是简单类型的字符串吗? - KeitelDOG
@KeitelDOG,我修复了之前的问题,但现在出现了“错误:CloudFormation模板无效:模板错误:每个Fn :: GetAtt对象都需要两个非空参数,资源名称和资源属性”的问题,你能帮我解决吗? - Nitish Kumar
Fn::GetAtt 需要 2 个参数。格式可以是 Fn::GetAtt: [资源的逻辑名称, 属性名称]。官方文档: https://docs.amazonaws.cn/en_us/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html资源的逻辑名称(也称为逻辑 ID),其中包含您想要的属性。资源特定属性的属性名称,其值您想要获取。有关该资源类型可用属性的详细信息,请参阅资源的参考页面。 - KeitelDOG
1
检查模板结构。确实有资源吗?也许你只想指定Resources.Storage [type: AWS::S3::Bucket, ...]并在Fn::GetAtt:["Storage","BucketName"]中指定有效的Bucket属性,或任何其他属性名称。 Fn :: GetAtt是从模板中获取资源属性的函数,以使它们可重用。因此,我认为它必须在您的模板上存在,隐含地来自AWS模板或来自您的语法。S3 Bucket属性:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html - KeitelDOG
1个回答

1

403错误提示您未经授权或存在某种权限错误。

根据此页面:

https://bref.sh/docs/frameworks/laravel.html

您能确认您已经为Lambda设置了适当的权限,以便从您使用的S3存储桶中读取和写入吗?

...

provider:
    ...
    environment:
        AWS_BUCKET: # environment variable for Laravel
            Ref: Storage
    iamRoleStatements:
        # Allow Lambda to read and write files in the S3 buckets
        -   Effect: Allow
            Action: s3:*
            Resource:
                - Fn::GetAtt: Storage.Arn # the storage bucket
                - Fn::Join: ['', [Fn::GetAtt: Storage.Arn, '/*']] # everything in the storage bucket

resources:
    Resources:
        Storage:
            Type: AWS::S3::Bucket

文档继续说,您需要在config/filesystems.php中添加以下片段中的令牌行。您这样做了吗?
's3' => [
            'driver' => 's3',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'token' => env('AWS_SESSION_TOKEN'),
            'region' => env('AWS_DEFAULT_REGION'),
            'bucket' => env('AWS_BUCKET'),
            'url' => env('AWS_URL'),
        ],

我不使用Laravel,因此上述建议仅基于查看您的错误和阅读文档。但如果您提供更多信息,我很乐意帮忙查看。


我已经添加了serverless.yml配置内容。现在我遇到了“发生错误:ArtisanLambdaFunction - 属性变量的值必须是具有字符串(或简单类型)属性的对象。” - Nitish Kumar
@NitishKumar,错误提示了问题所在 - 请检查您的属性变量。 - Rahul Iyer
我已经解决了之前的问题,但是现在我收到了 Error: The CloudFormation template is invalid: Template error: every Fn::GetAtt object requires two non-empty parameters, the resource name and the resource attribute 的错误,请问你能帮我吗? - Nitish Kumar
@NitishKumar 如果不看模板,我无法确定具体情况,但错误似乎指出了问题所在。请查看您使用 Fn::GetAtt 的位置。也许您遗漏了某个参数? - Rahul Iyer
1
@NitishKumar 如果您正在使用完整形式,语法为Fn :: GetAtt:[Resource的逻辑名称,属性名称] ...请参阅GetAtt的文档...如果您正在使用短格式,则应使用!GetAtt。 - Rahul Iyer
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接