Skip to content
This repository was archived by the owner on Jan 28, 2025. It is now read-only.

Commit ff90c65

Browse files
author
Daniel Balogh
committed
Adress feedback
1 parent 8aa2d52 commit ff90c65

File tree

7 files changed

+119
-76
lines changed

7 files changed

+119
-76
lines changed

packages/s3-static-assets/src/index.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,24 @@ import { IMMUTABLE_CACHE_CONTROL_HEADER } from "./lib/constants";
77
import S3ClientFactory, { Credentials } from "./lib/s3";
88
import pathToPosix from "./lib/pathToPosix";
99
import getPublicAssetCacheControl, {
10-
PublicAssetCacheControl
10+
PublicDirectoryCache
1111
} from "./lib/getPublicAssetCacheControl";
1212

13-
type Options = {
14-
publicAssetCache?: PublicAssetCacheControl;
15-
};
16-
1713
type UploadStaticAssetsOptions = {
1814
bucketName: string;
1915
nextConfigDir: string;
2016
nextStaticDir?: string;
2117
credentials: Credentials;
22-
options: Options;
18+
publicDirectoryCache?: PublicDirectoryCache;
2319
};
2420

2521
const uploadStaticAssets = async (
26-
config: UploadStaticAssetsOptions
22+
options: UploadStaticAssetsOptions
2723
): Promise<AWS.S3.ManagedUpload.SendData[]> => {
28-
const { bucketName, nextConfigDir, nextStaticDir = nextConfigDir } = config;
24+
const { bucketName, nextConfigDir, nextStaticDir = nextConfigDir } = options;
2925
const s3 = await S3ClientFactory({
3026
bucketName,
31-
credentials: config.credentials
27+
credentials: options.credentials
3228
});
3329

3430
const dotNextDirectory = path.join(nextConfigDir, ".next");
@@ -75,7 +71,7 @@ const uploadStaticAssets = async (
7571

7672
const uploadPublicOrStaticDirectory = async (
7773
directory: "public" | "static",
78-
options: Options
74+
publicDirectoryCache?: PublicDirectoryCache
7975
): Promise<Promise<AWS.S3.ManagedUpload.SendData>[]> => {
8076
const directoryPath = path.join(nextStaticDir, directory);
8177
if (!(await fse.pathExists(directoryPath))) {
@@ -92,19 +88,19 @@ const uploadStaticAssets = async (
9288
),
9389
cacheControl: getPublicAssetCacheControl(
9490
fileItem.path,
95-
options.publicAssetCache
91+
publicDirectoryCache
9692
)
9793
})
9894
);
9995
};
10096

10197
const publicDirUploads = await uploadPublicOrStaticDirectory(
10298
"public",
103-
config.options
99+
options.publicDirectoryCache
104100
);
105101
const staticDirUploads = await uploadPublicOrStaticDirectory(
106102
"static",
107-
config.options
103+
options.publicDirectoryCache
108104
);
109105

110106
const allUploads = [
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export const IMMUTABLE_CACHE_CONTROL_HEADER =
22
"public, max-age=31536000, immutable";
33

4-
export const DEFAULT_ASSET_CACHE_CONTROL_HEADER = "public, max-age=31536000, must-revalidate";
5-
export const DEFAULT_ASSET_CACHE_REGEX = /\.(gif|jpe?g|jp2|tiff|png|webp|bmp|svg)$/i;
4+
export const DEFAULT_PUBLIC_DIR_CACHE_CONTROL =
5+
"public, max-age=31536000, must-revalidate";
6+
export const DEFAULT_PUBLIC_DIR_CACHE_REGEX = /\.(gif|jpe?g|jp2|tiff|png|webp|bmp|svg|ico)$/i;

packages/s3-static-assets/src/lib/getPublicAssetCacheControl.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
11
import path from "path";
22
import regexParser from "regex-parser";
33
import {
4-
DEFAULT_ASSET_CACHE_CONTROL_HEADER,
5-
DEFAULT_ASSET_CACHE_REGEX
4+
DEFAULT_PUBLIC_DIR_CACHE_CONTROL,
5+
DEFAULT_PUBLIC_DIR_CACHE_REGEX
66
} from "./constants";
77

8-
export type PublicAssetCacheControl =
8+
export type PublicDirectoryCache =
99
| boolean
1010
| {
1111
test?: string;
1212
value?: string;
1313
};
1414

15+
/**
16+
* If options is not present, or is explicitly set to true, returns a default Cache-Control configuration for image types.
17+
* If options is explicitly set to false, it returns undefined.
18+
* If assigned an options object, it uses whichever value is defined there, falling back to the default if one is not present.
19+
*/
1520
const getPublicAssetCacheControl = (
1621
filePath: string,
17-
options?: PublicAssetCacheControl
22+
options?: PublicDirectoryCache
1823
): string | undefined => {
19-
if (!options) {
24+
if (options === false) {
2025
return undefined;
2126
}
2227

23-
let value: string = DEFAULT_ASSET_CACHE_CONTROL_HEADER;
24-
let test: RegExp = DEFAULT_ASSET_CACHE_REGEX;
28+
let value: string = DEFAULT_PUBLIC_DIR_CACHE_CONTROL;
29+
let test: RegExp = DEFAULT_PUBLIC_DIR_CACHE_REGEX;
2530

2631
if (typeof options === "object") {
2732
if (options.value) {

packages/s3-static-assets/tests/upload-assets.test.ts

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import path from "path";
22
import uploadStaticAssets from "../src/index";
33
import {
44
IMMUTABLE_CACHE_CONTROL_HEADER,
5-
DEFAULT_ASSET_CACHE_CONTROL_HEADER
5+
DEFAULT_PUBLIC_DIR_CACHE_CONTROL
66
} from "../src/lib/constants";
77
import AWS, {
88
mockGetBucketAccelerateConfigurationPromise,
@@ -18,14 +18,12 @@ jest.mock("aws-sdk", () => require("./aws-sdk.mock"));
1818
const upload = (
1919
nextConfigDir: string,
2020
nextStaticDir?: string,
21-
options?: {
22-
publicAssetCache?:
23-
| boolean
24-
| {
25-
test?: string;
26-
value?: string;
27-
};
28-
}
21+
publicAssetCache?:
22+
| boolean
23+
| {
24+
test?: string;
25+
value?: string;
26+
}
2927
): Promise<AWS.S3.ManagedUpload.SendData[]> => {
3028
let staticDir = nextStaticDir;
3129

@@ -42,7 +40,7 @@ const upload = (
4240
secretAccessKey: "fake-secret-key",
4341
sessionToken: "fake-session-token"
4442
},
45-
options: options || {}
43+
publicDirectoryCache: publicAssetCache
4644
});
4745
};
4846

@@ -193,19 +191,25 @@ describe.each`
193191
}
194192
);
195193

196-
describe("Content upload options", () => {
197-
describe.each([
198-
[undefined, undefined],
199-
[true, DEFAULT_ASSET_CACHE_CONTROL_HEADER],
200-
[{ value: "public, max-age=36000" }, "public, max-age=36000"]
201-
])("publicAssetCache", (input, expected) => {
194+
describe.each`
195+
publicDirectoryCache | expected
196+
${undefined} | ${DEFAULT_PUBLIC_DIR_CACHE_CONTROL}
197+
${false} | ${undefined}
198+
${true} | ${DEFAULT_PUBLIC_DIR_CACHE_CONTROL}
199+
${{ value: "public, max-age=36000" }} | ${"public, max-age=36000"}
200+
${{ value: "public, max-age=36000", test: "/.(txt|xml)$/i" }} | ${undefined}
201+
`(
202+
"Public directory cache settings - publicDirectoryCache=$publicDirectoryCache, expected=$expected",
203+
({ publicDirectoryCache, expected }) => {
202204
beforeEach(async () => {
203-
await upload("./fixtures/app-with-images", undefined, {
204-
publicAssetCache: input
205-
});
205+
await upload(
206+
"./fixtures/app-with-images",
207+
undefined,
208+
publicDirectoryCache
209+
);
206210
});
207211

208-
it(`sets ${expected} for value of ${input}`, () => {
212+
it(`sets ${expected} for input value of ${publicDirectoryCache}`, () => {
209213
expect(mockUpload).toBeCalledWith(
210214
expect.objectContaining({
211215
Key: "public/1x1.png",
@@ -222,5 +226,5 @@ describe("Content upload options", () => {
222226
})
223227
);
224228
});
225-
});
226-
});
229+
}
230+
);

packages/serverless-component/README.md

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ A zero configuration Nextjs 9.0 [serverless component](https://github.com/server
2020
- [Custom Cloudfront configuration](#custom-cloudfront-configuration)
2121
- [Custom domain name](#custom-domain-name)
2222
- [AWS Permissions](#aws-permissions)
23-
- [Public asset configuration](#public-asset-configuration)
23+
- [Public directory caching](#public-directory-caching)
2424
- [Architecture](#architecture)
2525
- [Inputs](#inputs)
2626
- [FAQ](#faq)
@@ -129,7 +129,7 @@ myNextApplication:
129129
ttl: 10
130130
```
131131

132-
The example above adds headers that can be forwarded to the SSR lambda, and sets the _ttl_ for api lambdas.
132+
The example above adds headers that can be forwarded to the SSR lambda, and sets the `ttl` for api lambdas.
133133

134134
### Custom domain name
135135

@@ -226,31 +226,33 @@ myNextApplication:
226226
apiLambda: fooApiLambda
227227
```
228228

229-
### Public asset configuration
229+
### Public directory caching
230230

231-
By default, assets under `/public` or `/static` don't have cache control applied. However, you can overwrite this by setting `publicAssetCache`.
232-
Simply setting it to `true` will use the default of setting `Cache-Control=public, max-age=31536000, must-revalidate` on the following image formats: `gif|jpe?g|jp2|tiff|png|webp|bmp|svg`:
231+
By default, common image formats(`gif|jpe?g|jp2|tiff|png|webp|bmp|svg|ico`) under `/public` or `/static` folders
232+
have a one-year `Cache-Control` policy applied(`public, max-age=31536000, must-revalidate`).
233+
234+
You may customize either the `Cache-Control` header `value` and the regex of which files to `test`, with `publicDirectoryCache`:
233235

234236
```yaml
235237
myNextApplication:
236238
component: serverless-next.js
237239
inputs:
238-
publicAssetCache: true
240+
publicDirectoryCache:
241+
value: public, max-age=604800
242+
test: /\.(gif|jpe?g|png|txt|xml)$/i
239243
```
240244

241-
To customize either or both, you can:
245+
`value` must be a valid `Cache-Control` policy and `test` must be a valid `regex` of the types of files you wish to test.
246+
247+
If you don't want browsers to cache assets from the public directory, you can disable this:
242248

243249
```yaml
244250
myNextApplication:
245251
component: serverless-next.js
246252
inputs:
247-
publicAssetCache:
248-
value: public, max-age=604800
249-
test: /\.(gif|jpe?g|png|txt|xml)$/i
253+
publicDirectoryCache: false
250254
```
251255

252-
`value` must be a valid `Cache-Control` policy and `test` must be a valid regex of the types of files you wish to test.
253-
254256
### Architecture
255257

256258
![architecture](./arch_no_grid.png)
@@ -273,23 +275,23 @@ The fourth cache behaviour handles next API requests `api/*`.
273275

274276
### Inputs
275277

276-
| Name | Type | Default Value | Description |
277-
| ---------------- | ----------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
278-
| cloudfront | `object` | `{}` | Sets cloudfront cache options for both SSR and api lambdas. Options are defined in the [aws-cloudfront component](https://github.com/serverless-components/aws-cloudfront) | |
279-
| domain | `Array` | `null` | For example `['admin', 'portal.com']` |
280-
| bucketName | `string` | `null` | Custom bucket name where static assets are stored. By default is autogenerated. |
281-
| nextConfigDir | `string` | `./` | Directory where your application `next.config.js` file is. This input is useful when the `serverless.yml` is not in the same directory as the next app. <br>**Note:** `nextConfigDir` should be set if `next.config.js` `distDir` is used |
282-
| nextStaticDir | `string` | `./` | If your `static` or `public` directory is not a direct child of `nextConfigDir` this is needed |
283-
| memory | `number\|object` | `512` | When assigned a number, both the default and api lambdas will assigned memory of that value. When assigned to an object, values for the default and api lambdas can be separately defined | |
284-
| timeout | `number\|object` | `10` | Same as above |
285-
| name | `string\|object` | / | When assigned a string, both the default and api lambdas will assigned name of that value. When assigned to an object, values for the default and api lambdas can be separately defined |
286-
| publicAssetCache | `boolean\|object` | `false` | Sets `Cache-Control` policy on files under the `/public`/`/static` folders. When assigned `true`, a default caching is applied to all images, this can be customized by assigning an object, with a `test` regex and/or a different `value` for the caching policy. |
287-
| build | `boolean\|object` | `true` | When true builds and deploys app, when false assume the app has been built and uses the `.next` `.serverless_nextjs` directories in `nextConfigDir` to deploy. If an object is passed `build` allows for overriding what script gets called and with what arguments. |
288-
| build.cmd | `string` | `node_modules/.bin/next` | Build command |
289-
| build.args | `Array\|string` | `['build']` | Arguments to pass to the build |
290-
| build.cwd | `string` | `./` | Override the current working directory |
291-
| build.enabled | `boolean` | `true` | Same as passing `build:false` but from within the config |
292-
| build.env | `object` | `{}` | Add additional environment variables to the script |
278+
| Name | Type | Default Value | Description |
279+
| -------------------- | ----------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
280+
| cloudfront | `object` | `{}` | Sets cloudfront cache options for both SSR and api lambdas. Options are defined in the [aws-cloudfront component](https://github.com/serverless-components/aws-cloudfront) |
281+
| domain | `Array` | `null` | For example `['admin', 'portal.com']` |
282+
| bucketName | `string` | `null` | Custom bucket name where static assets are stored. By default is autogenerated. |
283+
| nextConfigDir | `string` | `./` | Directory where your application `next.config.js` file is. This input is useful when the `serverless.yml` is not in the same directory as the next app. <br>**Note:** `nextConfigDir` should be set if `next.config.js` `distDir` is used |
284+
| nextStaticDir | `string` | `./` | If your `static` or `public` directory is not a direct child of `nextConfigDir` this is needed |
285+
| memory | `number\|object` | `512` | When assigned a number, both the default and api lambdas will assigned memory of that value. When assigned to an object, values for the default and api lambdas can be separately defined |
286+
| timeout | `number\|object` | `10` | Same as above |
287+
| name | `string\|object` | / | When assigned a string, both the default and api lambdas will assigned name of that value. When assigned to an object, values for the default and api lambdas can be separately defined |
288+
| publicDirectoryCache | `boolean\|object` | `true` | Customize the `public`/`static` folder asset caching policy. Assigning an object with `value` and/or `test` lets you customize the caching policy and the types of files being cached. Assigning false disables caching |
289+
| build | `boolean\|object` | `true` | When true builds and deploys app, when false assume the app has been built and uses the `.next` `.serverless_nextjs` directories in `nextConfigDir` to deploy. If an object is passed `build` allows for overriding what script gets called and with what arguments. |
290+
| build.cmd | `string` | `node_modules/.bin/next` | Build command |
291+
| build.args | `Array\|string` | `['build']` | Arguments to pass to the build |
292+
| build.cwd | `string` | `./` | Override the current working directory |
293+
| build.enabled | `boolean` | `true` | Same as passing `build:false` but from within the config |
294+
| build.env | `object` | `{}` | Add additional environment variables to the script |
293295

294296
Custom inputs can be configured like this:
295297

0 commit comments

Comments
 (0)