Deploying Laravel (laravel-mix) application on AWS Serverless platform
Asked Answered
K

1

11

I'm trying to deploy my Laravel application on AWS serverless platform, I'm using dynamic imports and code splitting in my laravel-mix to compile the assets, to execute this I followed the steps in the documentation of bref package I installed the required library as instructed, I also synced my public directory with my s3 bucket

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

and configured my .env file to:

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

Next I configured my blade file to :

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

And my webpack.mix.js file has:

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();

Since I'm splitting the code into chunks I'm facing trouble fetching the chunks, My initial app.js file loads from s3 bucket but for loading chunks it try to fetch through public directory.

console error

How can I configure my laravel-mix to load chunks from s3 bucket synced with my public directory?

Edit:

As suggested in the answer I changed my serverless.yml and it look like this:

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

Now I'm getting:

An error occurred: ArtisanLambdaFunction - Value of property Variables must be an object with String (or simple type) properties.

Edit 2:

Problem was with indent(tab) configuration in serverless.yml at :

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:*

But now getting seperate issue:

enter image description here

Error: The CloudFormation template is invalid: Template error: every Fn::GetAtt object requires two non-empty parameters, the resource name and the resource attribute

Kalimantan answered 12/12, 2020 at 5:5 Comment(5)
Haven't used this before, but somewhere at some place when parsing the config, it expect that all values in the object must be simple type or string, and it found another object, array or function, that can't be applied to the process.Ferous
Could it be on property Resource: - Fn::GetAtt returning an object instead of just string of simple type?Ferous
@Ferous I fixed the previous one but now I'm getting Error: The CloudFormation template is invalid: Template error: every Fn::GetAtt object requires two non-empty parameters, the resource name and the resource attribute issue can you help me with this?Kalimantan
Fn::GetAtt requires 2 parameters. Format can be like Fn::GetAtt: [ logicalNameOfResource, attributeName ]. Official doc: docs.amazonaws.cn/en_us/AWSCloudFormation/latest/UserGuide/… The logical name (also called logical ID) of the resource that contains the attribute that you want. The attribute name of the resource-specific attribute whose value you want. See the resource's reference page for details about the attributes available for that resource type.Ferous
Check for Template structure. Is there really resources.Resources? Maybe you want to specify only Resources.Storage [type: AWS::S3::Bucket , ...] and specify a valid property of Bucket in Fn::GetAtt: [ "Storage", "BucketName" ], or any other attribute name. Fn::GetAtt is a function that is getting a property of a resource in a template, to make them reusable. Therefore I think it must exist on your template, implicitly from AWS template or from your syntax. S3 Bucket properties: docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/…Ferous
E
1

A 403 error suggests that you are unauthorized or there is some kind of permissions error.

Based on this page:

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

Can you confirm that you have set appropriate permissions for lambda to read and write from s3 buckets that you use ?

...

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

The documentation goes on to say that you will have to add the the token line from the following snippet in config/filesystems.php . Have you done so?

'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'),
        ],

I don't use Laravel, so the above suggestions are just based on looking at your error and reading the documentation. But if you provide more information, I'm happy to take a look

Edora answered 1/1, 2021 at 10:24 Comment(8)
I've added the serverless.yml config contents. Now I'm getting An error occurred: ArtisanLambdaFunction - Value of property Variables must be an object with String (or simple type) properties.Kalimantan
@NitishKumar the error explains what the problem is - check your property variables.Edora
This error came after I configured my serverless.yml file. I'm new to this and don't know how to resolve. Before this error I was having An error occurred: WebLambdaFunction - Value of property Variables must be an object with String (or simple type) properties. I followed this link: forum.serverless.com/t/… now the error appears on ArtisanLambdaFunction Not able to find out a better solution.Kalimantan
@NitishKumar The error says that your variable must be an object or string.Just go through your file, through each entry line by line and check if any of the entries are in an incorrect format.Edora
I fixed the previous one but now I'm getting Error: The CloudFormation template is invalid: Template error: every Fn::GetAtt object requires two non-empty parameters, the resource name and the resource attribute issue can you help me with this?Kalimantan
@NitishKumar Without looking at the template I can’t say exactly, but the error seems to point out where the problem is. Look at where you’re using Fn::GetAtt Maybe you’ve left out a parameter?Edora
Hey, thanks for update. I've already have added the complete template (serverless.yml) file in the question. I've Fn::GetAtt only at two location Fn::GetAtt: Storage.Arn and Fn::Join: [ '', [ Fn::GetAtt: Storage.Arn, '/*' ] ] Hope you get the idea why I'm getting error, I copied from the documentation as it is mentioned, my PHPStorm format this with space.Kalimantan
@NitishKumar See the documentation for GetAtt... if you’re using the full form the syntax is Fn::GetAtt: [LogicalNameOfResource, attributeName] ... if you’re using the short form you should use !GetAttEdora

© 2022 - 2024 — McMap. All rights reserved.