Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The root level resource request of service-worker.js does not forward to S3 bucket. #357

Open
krish-dev opened this issue Apr 13, 2020 · 9 comments

Comments

@krish-dev
Copy link

Describe the bug

  • nextjs PWA not working.
  • the root level request of service-worker.js does not forward to static/service-worker.js

To Reproduce
I have used next-offline for building pwa application. This plugin generates service-worker.js under static/service-worker.js

Expected behavior
Public resources. Requests to root level resources like /robots.txt, /favicon.ico, /manifest.json, etc. These are forwarded to S3. service-worker.js this is also a root level resources. So, this should forward to S3 as well.

@krish-dev
Copy link
Author

Expected behavior
Public resources. Requests to root level resources like /robots.txt, /favicon.ico, /manifest.json, etc. These are forwarded to S3. service-worker.js this is also a root level resources. So, this should forward to S3 as well.

I think the best approach should be if we allow adding this kind of custom strategy from the configuration (serverless.yml) file.

@ashbuilds
Copy link

ashbuilds commented May 26, 2020

For now I found the work around by changing default path of service-worker in next.config.js to public

 workboxOpts: {
    swDest: path.resolve(__dirname, './public/service-worker.js'),
  }

@krish-dev
Copy link
Author

@ashbuilds absolutly we can use public dir, In that case, service-worker might get installed successfully. But as the request not get routed through lambda so service worker will not get valid permission (AccessDenied) while accessing the internal js file and it will lead to following issue

service-worker.js:1 Uncaught (in promise) bad-precaching-response: bad-precaching-response :: [{"url":"https://xxxxxxxxxx.cloudfront.net/_next/static/chunks/6b2a94c785d9e2be08deadc3973900fa4d342531.60755c98fab970be950f.js","status":403}]
    at E.K (https://xxxxxxxxxx.cloudfront.net/service-worker.js:1:11535)
    at async Promise.all (index 5)
    at async E.install (https://xxxxxxxxxx.cloudfront.net/service-worker.js:1:10954)

Screenshot 2020-06-02 at 10 16 21 AM

I'm still using this configuration

workBoxConfig.workboxOpts['swDest'] = 'static/service-worker.js';

Just I added few lines into the here (default-handler.ts) of this plugin

  if (uri === "/service-worker.js") {
    s3Origin.path = "/_next/static";
    return request;
  }

@danielcondemarin while I open this issue, the description & expected behavior might not appropriate. But now I believe everything is clear. PWA is very popular nowadays and It will be very helpful to the community if we add support to this package. I'm exactly not sure about the other impact by adding this script into default-handler of lambda-at-edge package. If you think this is the correct approach, then please 🙏 add this little script.

Just thinking out loud, If we have the flexibility to configure the same path of service-worker through serverless.yml file as Vercel allowing through rewrites and it will also allow lots of other flexibility.

@krish-dev
Copy link
Author

Hi @danielcondemarin

As you mentioned in this comment. I did some analysis on that. I used serverless-next.js@1.12.0-alpha.8 to deploy the application and after that, I created the following configuration directly into AWS CloudFront console just for testing whether its working or not. Yes, It worked perfectly.

  1. First created an origin
    Screenshot 2020-06-05 at 6 00 11 PM

  2. Then create a behavior with for service-worker.js with ttl=0 and mapped with new created origin.
    Screenshot 2020-06-05 at 6 01 47 PM

Then tried to replicate the same configuration dynamically from serverless.yml but I got following error.

OperationAborted: A conflicting conditional operation is currently in progress against this resource. Please try again.

Here is my serverless.yml configuration

myapp:
  component: serverless-next.js@1.12.0-alpha.8
  inputs:
    name: xxxx-pwa-prod
    memory: 512
    bucketName: xxxx-pwa-prod
    build: true
    useServerlessTraceTarget: true
    # Custom cloudfront configuartion for service-worker
    cloudfront:
      origins:
        - url: https://xxxx-pwa-prod.s3.amazonaws.com/_next/static
          private: true
          pathPatterns:
            service-worker.js:
              ttl: 0

Just checking with you that did I made correct configuration into serverless.yml file to replicate the same as AWS console. If yes then I will do more analysis into this code that why we getting this error. Probably we are very close to resolving this issue.

FYI
Request url: https://xxxxxx.cloudfront.net/service-worker.js
Service Worker S3 Path: https://xxxx-pwa-prod.s3.amazonaws.com/_next/static/service-worker.js

@krish-dev
Copy link
Author

Update on top of previous comment

    cloudfront:
      origins:
        - url: /_next/static
          private: true
          pathPatterns:
            service-worker.js:
              ttl: 0

looks like this function works perfectly

    // If origin is relative path then prepend the bucketUrl
    // e.g. /path => http://bucket.s3.aws.com/path
    const expandRelativeUrls = origin => {
      const originUrl = typeof origin === "string" ? origin : origin.url;
      const fullOriginUrl =
        originUrl.charAt(0) === "/" ? `${bucketUrl}${originUrl}` : originUrl;

      if (typeof origin === "string") {
        return fullOriginUrl;
      } else {
        return {
          ...origin,
          url: fullOriginUrl
        };
      }
    };

however, now I'm getting this error

InvalidArgument: The parameter origin ID must be unique.

@krish-dev
Copy link
Author

krish-dev commented Jun 6, 2020

Updated 2 on top of the previous comment

Hi @danielcondemarin

used this configuration.

cloudfront:
      origins:
        - url: /_next/static
          private: true
          pathPatterns:
            service-worker.js:
              ttl: 0

Just add a log before const cloudFrontOutputs = await cloudFront({...});

here is the log.

{
    "defaults": {
        "ttl": 0,
        "forward": {
            "cookies": "all",
            "queryString": true
        },
        "allowedHttpMethods": [
            "HEAD",
            "GET"
        ],
        "lambda@edge": {
            "origin-request": "arn:aws:lambda:us-east-1:xxxxxxxxx:function:ffsfsjhusy-0faih5:41"
        }
    },
    "origins": [
        {
            "url": "http://xxxxxxxxx-pwa-prod.s3.amazonaws.com",
            "private": true,
            "pathPatterns": {
                "_next/*": {
                    "ttl": 86400
                },
                "static/*": {
                    "ttl": 86400
                }
            }
        },
        {
            "url": "http://xxxxxxxxx-pwa-prod.s3.amazonaws.com/_next/static",
            "private": true,
            "pathPatterns": {
                "service-worker.js": {
                    "ttl": 0
                }
            }
        }
    ]
}

error

InvalidArgument: The parameter origin ID must be unique.

@krish-dev
Copy link
Author

krish-dev commented Jun 8, 2020

I did more analysis on the issue and it looks like the issue is related to serverless-components/aws-cloudfront issue #18 and PR #19 is already there.

@danielcondemarin can you please merge the PR and publish a new release of serverless-components/aws-cloudfront and this plugin too 🚀

It's creating the same id for the same origin's different relative path.

{
  "Quantity": 2,
  "Items": [
    {
      "Id": "xxx-pwa-prod",
      "DomainName": "xxx-pwa-prod.s3.amazonaws.com",
      "CustomHeaders": {
        "Quantity": 0,
        "Items": []
      },
      "OriginPath": "",
      "S3OriginConfig": {
        "OriginAccessIdentity": "origin-access-identity/cloudfront/<identity>"
      }
    },
    {
      "Id": "xxx-pwa-prod",
      "DomainName": "xxx-pwa-prod.s3.amazonaws.com",
      "CustomHeaders": {
        "Quantity": 0,
        "Items": []
      },
      "OriginPath": "/_next/static",
      "S3OriginConfig": {
        "OriginAccessIdentity": "origin-access-identity/cloudfront/<identity>"
      }
    }
  ]
}

For this configuration.

{
    "defaults": {...},
    "origins": [
        {
            "url": "http://xxx-pwa-prod.s3.amazonaws.com",
            "private": true,
            "pathPatterns": {
                "_next/*": {
                    "ttl": 86400
                },
                "static/*": {
                    "ttl": 86400
                }
            }
        },
        {
            "url": "http://xxx-pwa-prod.s3.amazonaws.com/_next/static",
            "private": true,
            "pathPatterns": {
                "service-worker.js": {
                    "ttl": 0
                }
            }
        }
    ]
}

@lone-cloud
Copy link
Contributor

That aws-lambda's been abandoned for a while now, which is why it's a part of the project now. Feel free to create the PRs to fix your issues here.

@AmanRaj1608
Copy link

Hi @krish-dev,
were you able to resolve this issue?
Please update. I am also facing the same issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants