Skip to content

Commit b34fe8a

Browse files
authored
Latency optimizations (#204)
1 parent 468cac1 commit b34fe8a

File tree

3 files changed

+83
-71
lines changed

3 files changed

+83
-71
lines changed

cloudformation/logs.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,6 @@ Resources:
1515
Fn::Sub: /aws/lambda/${LambdaFunctionName}
1616
RetentionInDays:
1717
Ref: LogRetentionDays
18-
EdgeLambdaLogGroup:
19-
Type: AWS::Logs::LogGroup
20-
Properties:
21-
LogGroupName:
22-
Fn::Sub: /aws/lambda/${LambdaFunctionName}-edge
23-
RetentionInDays: 7
2418
AppAuditLog:
2519
Type: "AWS::DynamoDB::Table"
2620
DeletionPolicy: "Retain"

cloudformation/main.yml

Lines changed: 72 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,9 @@ Resources:
619619
Type: AWS::S3::Bucket
620620
Properties:
621621
BucketName: !Sub ${S3BucketPrefix}-ui
622+
WebsiteConfiguration:
623+
IndexDocument: index.html
624+
ErrorDocument: index.html
622625

623626
AppCloudfrontS3OAC:
624627
Type: AWS::CloudFront::OriginAccessControl
@@ -672,9 +675,10 @@ Resources:
672675
Cookies:
673676
Forward: none
674677
CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 # caching-optimized
675-
LambdaFunctionAssociations:
676-
- EventType: origin-request
677-
LambdaFunctionARN: !Ref AppFrontendEdgeLambdaVersion
678+
FunctionAssociations:
679+
- EventType: viewer-request
680+
FunctionARN: !GetAtt AppFrontendViewerRequestFunction.FunctionARN
681+
678682
CacheBehaviors:
679683
- PathPattern: "/api/v1/events*"
680684
TargetOriginId: LambdaOrigin
@@ -747,11 +751,21 @@ Resources:
747751
- Effect: Allow
748752
Principal:
749753
Service: cloudfront.amazonaws.com
750-
Action: s3:GetObject
754+
Action:
755+
- s3:GetObject
751756
Resource: !Sub "${AppFrontendS3Bucket.Arn}/*"
752757
Condition:
753758
StringEquals:
754759
AWS:SourceArn: !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/${AppFrontendCloudfrontDistribution}"
760+
- Effect: Allow
761+
Principal:
762+
Service: cloudfront.amazonaws.com
763+
Action:
764+
- s3:ListBucket
765+
Resource: !Sub "${AppFrontendS3Bucket.Arn}"
766+
Condition:
767+
StringEquals:
768+
AWS:SourceArn: !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/${AppFrontendCloudfrontDistribution}"
755769

756770
CloudfrontNoCachePolicy:
757771
Type: AWS::CloudFront::CachePolicy
@@ -796,36 +810,32 @@ Resources:
796810
CookiesConfig:
797811
CookieBehavior: none
798812

799-
AppFrontendEdgeLambda:
800-
Type: AWS::Lambda::Function
801-
DependsOn:
802-
- AppLogGroups
813+
AppFrontendViewerRequestFunction:
814+
Type: AWS::CloudFront::Function
803815
Properties:
804-
FunctionName: !Sub ${ApplicationPrefix}-lambda-edge
805-
Handler: "index.handler"
806-
Role: !GetAtt AppSecurityRoles.Outputs.EdgeFunctionRoleArn
807-
Runtime: nodejs22.x
808-
Code:
809-
ZipFile: |
810-
'use strict';
811-
exports.handler = async (event) => {
812-
const request = event.Records[0].cf.request;
813-
const uri = request.uri;
814-
if (uri === '/docs') {
815-
request.uri = "/docs/index.html";
816-
}
817-
if (!uri.startsWith('/api') && !uri.match(/\.\w+$/)) {
818-
request.uri = "/index.html";
819-
}
820-
return request;
821-
};
822-
MemorySize: 128
823-
Timeout: 5
816+
Name: !Sub ${ApplicationPrefix}-url-rewrite-function
817+
AutoPublish: true
818+
FunctionConfig:
819+
Comment: "Handles SPA routing by rewriting URIs to index.html"
820+
Runtime: cloudfront-js-2.0
821+
FunctionCode: |
822+
function handler(event) {
823+
var request = event.request;
824+
var uri = request.uri;
825+
826+
// Rewrite /docs or /docs/ to the documentation index file
827+
if (uri === '/docs' || uri === '/docs/') {
828+
request.uri = '/docs/index.html';
829+
return request;
830+
}
824831
825-
AppFrontendEdgeLambdaVersion:
826-
Type: AWS::Lambda::Version
827-
Properties:
828-
FunctionName: !Ref AppFrontendEdgeLambda
832+
// Rewrite paths for the SPA, excluding /api and files with extensions
833+
if (!uri.startsWith('/api') && !uri.includes('.')) {
834+
request.uri = '/index.html';
835+
}
836+
837+
return request;
838+
}
829839
830840
AppIcalCloudfrontDistribution:
831841
Type: AWS::CloudFront::Distribution
@@ -897,40 +907,40 @@ Resources:
897907
KeyValueStoreAssociations:
898908
- KeyValueStoreARN: !Sub '${LinkryRecordsCloudfrontStore.Arn}'
899909
FunctionCode: !Sub |
900-
import cf from 'cloudfront';
901-
const kvsId = '${LinkryRecordsCloudfrontStore.Id}';
902-
const kvs = cf.kvs(kvsId);
903-
904-
async function handler(event) {
905-
const request = event.request;
906-
const path = request.uri.replace(/^\/+/, '');
907-
if (path === "") {
908-
return {
909-
statusCode: 301,
910-
statusDescription: 'Found',
911-
headers: {
912-
'location': { value: "https://core.acm.illinois.edu/linkry" }
910+
import cf from 'cloudfront';
911+
const kvsId = '${LinkryRecordsCloudfrontStore.Id}';
912+
const kvs = cf.kvs(kvsId);
913+
914+
async function handler(event) {
915+
const request = event.request;
916+
const path = request.uri.replace(/^\/+/, '');
917+
if (path === "") {
918+
return {
919+
statusCode: 301,
920+
statusDescription: 'Found',
921+
headers: {
922+
'location': { value: "https://core.acm.illinois.edu/linkry" }
923+
}
913924
}
914925
}
915-
}
916-
let redirectUrl = "https://acm.illinois.edu/404";
917-
try {
918-
const value = await kvs.get(path);
919-
if (value) {
920-
redirectUrl = value;
926+
let redirectUrl = "https://acm.illinois.edu/404";
927+
try {
928+
const value = await kvs.get(path);
929+
if (value) {
930+
redirectUrl = value;
931+
}
932+
} catch (err) {
933+
console.log(`KVS key lookup failed for $!{path}: $!{err}`);
921934
}
922-
} catch (err) {
923-
console.log('KVS key lookup failed');
935+
var response = {
936+
statusCode: 302,
937+
statusDescription: 'Found',
938+
headers: {
939+
'location': { value: redirectUrl }
940+
}
941+
};
942+
return response;
924943
}
925-
var response = {
926-
statusCode: 302,
927-
statusDescription: 'Found',
928-
headers: {
929-
'location': { value: redirectUrl }
930-
}
931-
};
932-
return response;
933-
}
934944
AutoPublish: true
935945

936946
AppLinkryCloudfrontDistribution:

src/ui/vite.config.mjs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,29 @@ export default defineConfig({
3636
manualChunks(id) {
3737
const HugeLibraries = [
3838
"@mantine",
39+
"moment-timezone",
40+
"moment",
3941
"@azure",
4042
"@tabler",
4143
"axios",
42-
"react-pdf",
44+
"react-router",
4345
]; // modify as required based on libraries in use
4446
if (
4547
HugeLibraries.some((libName) =>
4648
id.includes(`node_modules/${libName}`),
4749
)
4850
) {
49-
return id
51+
return `vendor/${id
5052
.toString()
5153
.split("node_modules/")[1]
5254
.split("/")[0]
53-
.toString();
55+
.toString()}`;
56+
}
57+
if (id.includes("node_modules")) {
58+
return `vendor/main`;
59+
}
60+
if (id.includes("src/common")) {
61+
return "common";
5462
}
5563
},
5664
},

0 commit comments

Comments
 (0)