cdk-nuxt 0.3.2 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +173 -3
- package/lib/cli/deploy.js +10 -3
- package/lib/cli/init.js +17 -0
- package/lib/stack/nuxt-app-static-assets.js +7 -3
- package/lib/stack/nuxt-app-static-assets.ts +6 -2
- package/lib/templates/stack-index.ts +48 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,5 +1,175 @@
|
|
|
1
|
-
#
|
|
1
|
+
# CDK Nuxt Plugin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p>
|
|
4
|
+
<a href="https://github.com/ferdinandfrank/cdk-nuxt/actions/workflows/publish.yml"><img alt="Build" src="https://img.shields.io/github/workflow/status/ferdinandfrank/cdk-nuxt/Publish?logo=github" /></a>
|
|
5
|
+
<a href="https://www.npmjs.com/package/cdk-nuxt"><img alt="Version" src="https://img.shields.io/npm/v/cdk-nuxt.svg" /></a>
|
|
6
|
+
<a href="https://www.npmjs.com/package/cdk-nuxt"><img alt="License" src="https://img.shields.io/npm/l/cdk-nuxt.svg" /></a>
|
|
7
|
+
</p>
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
Easily deploy a dynamic universal Nuxt application via CDK on AWS including the following features:
|
|
10
|
+
|
|
11
|
+
- Fast responses via [Lambda](https://aws.amazon.com/lambda/)
|
|
12
|
+
- Publicly available by a custom domain (or subdomain) via [Route53](https://aws.amazon.com/route53/) and [API Gateway](https://aws.amazon.com/api-gateway/)
|
|
13
|
+
- Automatic redirects from HTTP to HTTPS via [CloudFront](https://aws.amazon.com/cloudfront/)
|
|
14
|
+
- Automatic upload of the `client` build files for CSR and static assets to [S3](https://aws.amazon.com/s3/) with optimized caching rules
|
|
15
|
+
- Scheduled pings of the Nuxt app to keep the Lambda warm for fast responses via [EventBridge](https://aws.amazon.com/eventbridge/) rules
|
|
16
|
+
- Automatic cleanup of outdated static assets and build files
|
|
17
|
+
|
|
18
|
+
> :warning: **This package might not support every Nuxt config yet.** But feel free to give it a try and open an issue or a PR if necessary.
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
- This package currently relies on using [yarn](https://yarnpkg.com/) instead of npm for deployment. Therefore, make sure to have yarn available on the deployment system.
|
|
23
|
+
- You need an [AWS account](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/?nc1=h_ls) to create and deploy the required resources for the Nuxt app on AWS.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
1. Install the package and its required dependencies:
|
|
28
|
+
```bash
|
|
29
|
+
yarn add cdk-nuxt --dev # The package itself
|
|
30
|
+
yarn add ts-node typescript --dev # To compile the CDK stacks via typescript
|
|
31
|
+
yarn add aws-cdk@2.10.0 --dev # CDK cli with this exact version for the deployment
|
|
32
|
+
yarn add nuxt-aws-lambda nuxt-start # To make the Nuxt app renderable via AWS Lambda
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
2. Move the `nuxt` dependency to `devDependencies` as we installed `nuxt-start` to start our Nuxt app.<br/>Also, make sure that only the dependencies required for server-side rendering (SSR) are listed under `dependencies` to have the Lambda function and its layer as small as possible for better performance and to respect the [Lambda size limits](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html). Every other dependency should be under `devDependencies`.
|
|
36
|
+
|
|
37
|
+
3. Move the `devDependencies` section in the `package.json` file above the `dependencies` section. This enables the deployment code to fully remove the `devDependencies` section while installing the Lambda layer for the `node_modules` to only keep the modules required for SSR and to keep it as small as possible.
|
|
38
|
+
|
|
39
|
+
After the installation steps the `package.json` file should look something like this:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"name": "nuxt-app",
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"aws-cdk": "2.10.0",
|
|
46
|
+
"cdk-nuxt": "^X.X.X",
|
|
47
|
+
"nuxt": "^X.X.X",
|
|
48
|
+
"ts-node": "^X.X.X",
|
|
49
|
+
"typescript": "^X.X.X"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"nuxt-aws-lambda": "^X.X.X",
|
|
53
|
+
"nuxt-start": "^X.X.X"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Setup
|
|
59
|
+
|
|
60
|
+
1. Replace the `export default` part of your Nuxt configuration file (`nuxt.config.js`) with `module.exports =`, so it fits the following format:
|
|
61
|
+
```js
|
|
62
|
+
// Change "export default" => "module.exports ="
|
|
63
|
+
module.exports = {
|
|
64
|
+
target: 'server',
|
|
65
|
+
...
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
2. [Create an AWS account](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/?nc1=h_ls), if you don't have one yet. Then login into the AWS console and note the `Account ID`. You will need it in step 5.
|
|
69
|
+
3. [Create a hosted zone in Route53](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/AboutHZWorkingWith.html) for the desired domain, if you don't have one yet.<br/>This is required to create DNS records for the domain to make the Nuxt app publicly available on that domain.<br/>On the hosted zone details you should see the `Hosted zone ID` of the hosted zone. You will need it in step 5.
|
|
70
|
+
4. [Request a public certificate in the AWS Certificate Manager (ACM)](https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request-public.html) for the desired domain in `us-east-1` (global) and validate it, if you don't have one yet.<br/>This is required to provide the Nuxt app via HTTPS on the public internet.<br/>Take note of the displayed `ARN` for the certificate. You will need it in step 5.<br/>**Important: The certificate must be issued in us-east-1 (global) regardless of the region used for the Nuxt app itself as it will be attached to the Cloudfront distribution which works globally.**
|
|
71
|
+
5. Run the following command to automatically create the required CDK stack entrypoint at `stack/index.ts`. This file defines the config how the Nuxt app will be deployed via CDK. You should adapt the file to the project's needs, especially the props `env.account` (setup step 2), `hostedZoneId` (setup step 3) and `globalTlsCertificateArn` (setup step 4).
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
node_modules/.bin/cdk-nuxt-init
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
> :warning: It's recommended using a `.env` file or another secrets file to import the sensitive secrets into the `stack/index.ts` file.
|
|
78
|
+
|
|
79
|
+
## Build and Deploy
|
|
80
|
+
|
|
81
|
+
After the installation and the setup you are already good to go to build the Nuxt app and to deploy it to AWS with this package.
|
|
82
|
+
|
|
83
|
+
1. Install the dependencies for the Nuxt app including the `devDependencies` as these are required to successfully build the app:
|
|
84
|
+
```bash
|
|
85
|
+
yarn install --production=false
|
|
86
|
+
```
|
|
87
|
+
2. Build the Nuxt app with the build settings you need for the app:
|
|
88
|
+
```bash
|
|
89
|
+
yarn build
|
|
90
|
+
```
|
|
91
|
+
3. Run the CDK deployment:
|
|
92
|
+
```bash
|
|
93
|
+
node_modules/.bin/cdk-nuxt-deploy
|
|
94
|
+
```
|
|
95
|
+
The deployment script will take care of installing only the dependencies that are required for the Nuxt app and deploying the Nuxt build files to AWS according to the stack settings in `stack/index.ts`.<br/>See the section Used AWS Resources for details on which resources will exactly be created on AWS.
|
|
96
|
+
|
|
97
|
+
## Optional: Automatically deploy on every push (CD) via [GitHub Actions](https://github.com/features/actions)
|
|
98
|
+
|
|
99
|
+
Feel free to copy the following GitHub Actions YAML file content into a YAML file at `.github/workflows/deploy.yml` to automatically build and deploy the Nuxt app to AWS on every push to a specific branch.<br/>This only works if you're using GitHub for the project's VCS repository.
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
name: Deploy
|
|
103
|
+
|
|
104
|
+
on:
|
|
105
|
+
push:
|
|
106
|
+
branches:
|
|
107
|
+
- master # Feel free to use another branch name
|
|
108
|
+
|
|
109
|
+
jobs:
|
|
110
|
+
build:
|
|
111
|
+
runs-on: ubuntu-latest
|
|
112
|
+
strategy:
|
|
113
|
+
matrix:
|
|
114
|
+
node-version: [ 14.x ]
|
|
115
|
+
steps:
|
|
116
|
+
- name: Checkout source code
|
|
117
|
+
uses: actions/checkout@v2
|
|
118
|
+
|
|
119
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
120
|
+
uses: actions/setup-node@v1
|
|
121
|
+
with:
|
|
122
|
+
node-version: ${{ matrix.node-version }}
|
|
123
|
+
|
|
124
|
+
# Init cache to speed up yarn install
|
|
125
|
+
- name: Get yarn cache directory path
|
|
126
|
+
id: yarn-cache-dir-path
|
|
127
|
+
run: echo "::set-output name=dir::$(yarn cache dir)"
|
|
128
|
+
|
|
129
|
+
- uses: actions/cache@v2
|
|
130
|
+
with:
|
|
131
|
+
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
|
132
|
+
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
|
|
133
|
+
restore-keys: |
|
|
134
|
+
${{ runner.os }}-node-
|
|
135
|
+
|
|
136
|
+
# Optionally copy any secrets from the GitHub repository secrets to the deployment project directory right here
|
|
137
|
+
|
|
138
|
+
- name: Install dependencies
|
|
139
|
+
run: yarn install --production=false # Important to install devDependencies for the build
|
|
140
|
+
|
|
141
|
+
- name: Build project
|
|
142
|
+
run: yarn build # Should trigger 'nuxt build' according to the package.json
|
|
143
|
+
|
|
144
|
+
- name: Deploy to AWS
|
|
145
|
+
run: node_modules/.bin/nuxt-deploy
|
|
146
|
+
env:
|
|
147
|
+
# Create an IAM user on AWS for the deployment and create the appropriate secrets in the GitHub repository secrets
|
|
148
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
149
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
150
|
+
AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Advanced: Used AWS Resources
|
|
154
|
+
|
|
155
|
+
Two CDK stacks will be deployed to AWS using this package:
|
|
156
|
+
|
|
157
|
+
### NuxtAppStack
|
|
158
|
+
|
|
159
|
+
This is the main stack that is responsible for uploading all assets of the Nuxt app to AWS and to make it publicly reachable.
|
|
160
|
+
The following AWS resources will be created by this stack:
|
|
161
|
+
|
|
162
|
+
- [Lambda](https://aws.amazon.com/lambda/): A Lambda function to render the Nuxt app including a separated Lambda layer to provide the `node_modules` of the Nuxt app required for server-side rendering.
|
|
163
|
+
- [S3](https://aws.amazon.com/s3/): A bucket to store the client files of the Nuxt build (`.nuxt/dist/client`) and the custom static files of the Nuxt app (`static`) with optimized cache settings.
|
|
164
|
+
- [Route53](https://aws.amazon.com/route53/): Two DNS records (`A` for IPv4 and `AAAA` for IPv6) in the configured hosted zone to make the Nuxt app available on the internet via the configured custom domain.
|
|
165
|
+
- [API Gateway](https://aws.amazon.com/api-gateway/): An HTTP API to make the Nuxt Lambda function publicly available.
|
|
166
|
+
- [CloudFront](https://aws.amazon.com/cloudfront/): A distribution to route incoming requests to the Nuxt Lambda function (via the API Gateway) and the S3 bucket to serve the static assets for the Nuxt app.
|
|
167
|
+
- [EventBridge](https://aws.amazon.com/eventbridge/): A scheduled rule to ping the Nuxt app's Lambda function every 5 minutes in order to keep it warm and to speed up initial SSR requests.
|
|
168
|
+
|
|
169
|
+
### NuxtAppAssetsCleanupStack
|
|
170
|
+
|
|
171
|
+
This stack is responsible for deleting outdated static assets from the S3 deployment bucket created by the NuxtAppStack.
|
|
172
|
+
The following AWS resources will be created by this stack:
|
|
173
|
+
|
|
174
|
+
- [Lambda](https://aws.amazon.com/lambda/): A Lambda function that deletes the outdated static assets of the Nuxt app from S3.
|
|
175
|
+
- [EventBridge](https://aws.amazon.com/eventbridge/): A scheduled rule to trigger the stack's Lambda function every tuesday at 03:30 AM GMT.
|
package/lib/cli/deploy.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const shell = require("shelljs");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
|
|
6
|
-
const logPrefix = 'Nuxt Deployment';
|
|
6
|
+
const logPrefix = 'CDK Nuxt Deployment';
|
|
7
7
|
|
|
8
8
|
shell.echo(`${logPrefix}: Starting deployment...`);
|
|
9
9
|
|
|
@@ -54,8 +54,15 @@ shell.cp('.yarnclean', deploymentLayerFolder);
|
|
|
54
54
|
shell.cd(deploymentLayerFolder);
|
|
55
55
|
|
|
56
56
|
// We do not want to install any dependencies listed under 'devDendencies'
|
|
57
|
-
// Usually the --production flag should do the trick but somehow still installs
|
|
58
|
-
shell.exec('
|
|
57
|
+
// Usually the --production flag should do the trick but somehow still installs some dev dependencies in some cases
|
|
58
|
+
const osSystem = shell.exec('echo $OSTYPE');
|
|
59
|
+
const isMac = osSystem.startsWith('darwin')
|
|
60
|
+
if (isMac) {
|
|
61
|
+
shell.exec('sed -i \'\' \'/\\"devDependencies\\"/,/}/ d\' package.json')
|
|
62
|
+
} else {
|
|
63
|
+
shell.exec('sed -i \'/\\"devDependencies\\"/,/}/ d\' package.json')
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
if (shell.exec('yarn install --production --frozen-lockfile').code !== 0) {
|
|
60
67
|
shell.echo(`${logPrefix} Error: Installation of lambda layer failed.`);
|
|
61
68
|
shell.exit(1);
|
package/lib/cli/init.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const shell = require("shelljs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
|
|
7
|
+
const logPrefix = 'CDK Nuxt Init';
|
|
8
|
+
|
|
9
|
+
shell.echo(`${logPrefix}: Initializing CDK stack index file...`);
|
|
10
|
+
|
|
11
|
+
if (!fs.existsSync('stack')) {
|
|
12
|
+
shell.mkdir('-p', 'stack');
|
|
13
|
+
shell.cp(path.join(__dirname, '../templates/stack-index.ts'), 'stack/index.ts');
|
|
14
|
+
shell.echo(`${logPrefix}: CDK stack index file created. Please adapt the file at 'stack/index.ts' to the project's needs.`);
|
|
15
|
+
} else {
|
|
16
|
+
shell.echo(`${logPrefix}: CDK stack folder already exists.`);
|
|
17
|
+
}
|
|
@@ -9,9 +9,11 @@ const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
|
9
9
|
*/
|
|
10
10
|
const getNuxtAppStaticAssetConfigs = (nuxtConfig) => {
|
|
11
11
|
var _a, _b;
|
|
12
|
+
// The build assets required for CSR that are generated by 'nuxt build'
|
|
12
13
|
const buildAssetsSourcePath = './.nuxt/dist/client';
|
|
13
14
|
const buildAssetsTargetPath = (_b = (_a = nuxtConfig.build) === null || _a === void 0 ? void 0 : _a.publicPath) !== null && _b !== void 0 ? _b : '/_nuxt/'; // Must match 'build.publicPath' in nuxt.config.js
|
|
14
|
-
|
|
15
|
+
// The custom assets of the Nuxt app located in the src 'static' folder
|
|
16
|
+
const customAssetsSourcePath = `./${nuxtConfig.srcDir ? (nuxtConfig.srcDir + '/') : ''}static`;
|
|
15
17
|
const customAssetsTargetPath = '/';
|
|
16
18
|
return [
|
|
17
19
|
// Build Assets
|
|
@@ -91,13 +93,15 @@ const getNuxtAppStaticAssetConfigs = (nuxtConfig) => {
|
|
|
91
93
|
cacheControl: [aws_s3_deployment_1.CacheControl.setPublic(), aws_s3_deployment_1.CacheControl.maxAge(aws_cdk_lib_1.Duration.days(1))],
|
|
92
94
|
},
|
|
93
95
|
{
|
|
94
|
-
pattern: '
|
|
96
|
+
pattern: '*.js',
|
|
95
97
|
source: customAssetsSourcePath,
|
|
96
98
|
target: customAssetsTargetPath,
|
|
97
99
|
contentType: 'application/javascript; charset=UTF-8',
|
|
100
|
+
// The js files in the custom static directory are usually not versionized
|
|
101
|
+
// whereby we want to prevent any caching issues when updating them -> cache for only 2 days
|
|
98
102
|
cacheControl: [aws_s3_deployment_1.CacheControl.setPublic(), aws_s3_deployment_1.CacheControl.maxAge(aws_cdk_lib_1.Duration.days(2))],
|
|
99
103
|
},
|
|
100
104
|
];
|
|
101
105
|
};
|
|
102
106
|
exports.getNuxtAppStaticAssetConfigs = getNuxtAppStaticAssetConfigs;
|
|
103
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
107
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnV4dC1hcHAtc3RhdGljLWFzc2V0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm51eHQtYXBwLXN0YXRpYy1hc3NldHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBQTJEO0FBQzNELDZDQUFxQztBQStCckM7OztHQUdHO0FBQ0ksTUFBTSw0QkFBNEIsR0FBRyxDQUFDLFVBQXNCLEVBQXVCLEVBQUU7O0lBRXhGLHVFQUF1RTtJQUN2RSxNQUFNLHFCQUFxQixHQUFHLHFCQUFxQixDQUFDO0lBQ3BELE1BQU0scUJBQXFCLEdBQUcsTUFBQSxNQUFBLFVBQVUsQ0FBQyxLQUFLLDBDQUFFLFVBQVUsbUNBQUksU0FBUyxDQUFDLENBQUMsa0RBQWtEO0lBRTNILHVFQUF1RTtJQUN2RSxNQUFNLHNCQUFzQixHQUFHLEtBQUssVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQztJQUMvRixNQUFNLHNCQUFzQixHQUFHLEdBQUcsQ0FBQztJQUVuQyxPQUFPO1FBRUgsZUFBZTtRQUNmO1lBQ0ksT0FBTyxFQUFFLE1BQU07WUFDZixNQUFNLEVBQUUscUJBQXFCO1lBQzdCLE1BQU0sRUFBRSxxQkFBcUI7WUFDN0IsV0FBVyxFQUFFLHVDQUF1QztTQUN2RDtRQUNEO1lBQ0ksT0FBTyxFQUFFLFVBQVU7WUFDbkIsTUFBTSxFQUFFLHFCQUFxQjtZQUM3QixNQUFNLEVBQUUscUJBQXFCO1lBQzdCLFdBQVcsRUFBRSxpQ0FBaUM7U0FDakQ7UUFDRDtZQUNJLE9BQU8sRUFBRSxPQUFPO1lBQ2hCLE1BQU0sRUFBRSxxQkFBcUI7WUFDN0IsTUFBTSxFQUFFLHFCQUFxQjtZQUM3QixXQUFXLEVBQUUseUJBQXlCO1NBQ3pDO1FBRUQsaUNBQWlDO1FBQ2pDO1lBQ0ksT0FBTyxFQUFFLGlCQUFpQjtZQUMxQixNQUFNLEVBQUUscUJBQXFCO1lBQzdCLE1BQU0sRUFBRSxxQkFBcUI7WUFDN0IsV0FBVyxFQUFFLGlDQUFpQztTQUNqRDtRQUNEO1lBQ0ksT0FBTyxFQUFFLE9BQU87WUFDaEIsTUFBTSxFQUFFLHFCQUFxQjtZQUM3QixNQUFNLEVBQUUscUJBQXFCO1lBQzdCLFdBQVcsRUFBRSxlQUFlO1NBQy9CO1FBQ0Q7WUFDSSxPQUFPLEVBQUUsT0FBTztZQUNoQixNQUFNLEVBQUUscUJBQXFCO1lBQzdCLE1BQU0sRUFBRSxxQkFBcUI7WUFDN0IsV0FBVyxFQUFFLCtCQUErQjtTQUMvQztRQUNEO1lBQ0ksT0FBTyxFQUFFLE9BQU87WUFDaEIsTUFBTSxFQUFFLHFCQUFxQjtZQUM3QixNQUFNLEVBQUUscUJBQXFCO1lBQzdCLFdBQVcsRUFBRSx1QkFBdUI7U0FDdkM7UUFDRDtZQUNJLE9BQU8sRUFBRSxRQUFRO1lBQ2pCLE1BQU0sRUFBRSxxQkFBcUI7WUFDN0IsTUFBTSxFQUFFLHFCQUFxQjtZQUM3QixXQUFXLEVBQUUsV0FBVztTQUMzQjtRQUNEO1lBQ0ksT0FBTyxFQUFFLFNBQVM7WUFDbEIsTUFBTSxFQUFFLHFCQUFxQjtZQUM3QixNQUFNLEVBQUUscUJBQXFCO1lBQzdCLFdBQVcsRUFBRSxZQUFZO1NBQzVCO1FBRUQsdUJBQXVCO1FBQ3ZCO1lBQ0ksT0FBTyxFQUFFLE9BQU87WUFDaEIsTUFBTSxFQUFFLHNCQUFzQjtZQUM5QixNQUFNLEVBQUUsc0JBQXNCO1lBQzlCLFdBQVcsRUFBRSxXQUFXO1NBQzNCO1FBQ0Q7WUFDSSxPQUFPLEVBQUUsT0FBTztZQUNoQixNQUFNLEVBQUUsc0JBQXNCO1lBQzlCLE1BQU0sRUFBRSxzQkFBc0I7WUFDOUIsV0FBVyxFQUFFLFdBQVc7U0FDM0I7UUFDRDtZQUNJLE9BQU8sRUFBRSxZQUFZO1lBQ3JCLE1BQU0sRUFBRSxzQkFBc0I7WUFDOUIsTUFBTSxFQUFFLHNCQUFzQjtZQUM5QixXQUFXLEVBQUUsMkJBQTJCO1lBQ3hDLFlBQVksRUFBRSxDQUFDLGdDQUFZLENBQUMsU0FBUyxFQUFFLEVBQUUsZ0NBQVksQ0FBQyxNQUFNLENBQUMsc0JBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNsRjtRQUNEO1lBQ0ksT0FBTyxFQUFFLE1BQU07WUFDZixNQUFNLEVBQUUsc0JBQXNCO1lBQzlCLE1BQU0sRUFBRSxzQkFBc0I7WUFDOUIsV0FBVyxFQUFFLHVDQUF1QztZQUNwRCwwRUFBMEU7WUFDMUUsNEZBQTRGO1lBQzVGLFlBQVksRUFBRSxDQUFDLGdDQUFZLENBQUMsU0FBUyxFQUFFLEVBQUUsZ0NBQVksQ0FBQyxNQUFNLENBQUMsc0JBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNsRjtLQUNKLENBQUE7QUFDTCxDQUFDLENBQUM7QUFwR1csUUFBQSw0QkFBNEIsZ0NBb0d2QyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q2FjaGVDb250cm9sfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXMzLWRlcGxveW1lbnRcIjtcbmltcG9ydCB7RHVyYXRpb259IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHtOdXh0Q29uZmlnfSBmcm9tIFwiLi9udXh0LWNvbmZpZ1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFN0YXRpY0Fzc2V0Q29uZmlnIHtcbiAgICAvKipcbiAgICAgKiBUaGUgZmlsZSBwYXR0ZXJuIGZvciB0aGUgaW5jb21pbmcgcmVxdWVzdHMgdGhhdCBzaG91bGQgYmUgZm9yd2FyZGVkIHRvIHRoZSB0YXJnZXQgcGF0aCBpbiB0aGUgc3RhdGljIGFzc2V0cyBTMyBidWNrZXRcbiAgICAgKiB3aXRoIHRoZSBhcHByb3ByaWF0ZSBjYWNoZSBhbmQgY29udGVudCBzZXR0aW5ncyBkZWZpbmVkIGluIHRoZSBzYW1lIG9iamVjdC5cbiAgICAgKi9cbiAgICBwYXR0ZXJuOiBzdHJpbmcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgbG9jYWwgZGlyZWN0b3J5IHRvIHVwbG9hZCB0aGUgZmlsZXMgZnJvbS5cbiAgICAgKi9cbiAgICBzb3VyY2U6IHN0cmluZyxcblxuICAgIC8qKlxuICAgICAqIFRoZSByZW1vdGUgcGF0aCBhdCB3aGljaCB0byBtYWtlIHRoZSB1cGxvYWRlZCBmaWxlcyBmcm9tIHNvdXJjZSBhY2Nlc3NpYmxlLlxuICAgICAqL1xuICAgIHRhcmdldDogc3RyaW5nLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGNvbnRlbnQgdHlwZSB0byBzZXQgZm9yIHRoZSBmaWxlcyBpbiB0aGUgc291cmNlIGZvbGRlciB3aGVuIHVwbG9hZGluZyB0aGVtIHRvIHRoZSB0YXJnZXQuXG4gICAgICovXG4gICAgY29udGVudFR5cGU6IHN0cmluZyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBjYWNoZSBzZXR0aW5ncyB0byB1c2UgZm9yIHRoZSB1cGxvYWRlZCBzb3VyY2UgZmlsZXMgd2hlbiBhY2Nlc3NpbmcgdGhlbSBvbiB0aGUgdGFyZ2V0IHBhdGggd2l0aCB0aGUgc3BlY2lmaWVkIHBhdHRlcm4uXG4gICAgICovXG4gICAgY2FjaGVDb250cm9sPzogQ2FjaGVDb250cm9sW11cbn1cblxuLyoqXG4gKiBSZXRyaWV2ZXMgdGhlIHN0YXRpYyBhc3NldHMgb2YgdGhlIE51eHQgYXBwIHRoYXQgc2hhbGwgYmUgcHVibGljbHkgYXZhaWxhYmxlLlxuICogVGhlc2Ugc2hvdWxkIG1hdGNoIHRoZSBmaWxlcyBpbiAnLm51eHQvZGlzdC9jbGllbnQnIGFuZCAnc3RhdGljJy5cbiAqL1xuZXhwb3J0IGNvbnN0IGdldE51eHRBcHBTdGF0aWNBc3NldENvbmZpZ3MgPSAobnV4dENvbmZpZzogTnV4dENvbmZpZyk6IFN0YXRpY0Fzc2V0Q29uZmlnW10gPT4ge1xuXG4gICAgLy8gVGhlIGJ1aWxkIGFzc2V0cyByZXF1aXJlZCBmb3IgQ1NSIHRoYXQgYXJlIGdlbmVyYXRlZCBieSAnbnV4dCBidWlsZCdcbiAgICBjb25zdCBidWlsZEFzc2V0c1NvdXJjZVBhdGggPSAnLi8ubnV4dC9kaXN0L2NsaWVudCc7XG4gICAgY29uc3QgYnVpbGRBc3NldHNUYXJnZXRQYXRoID0gbnV4dENvbmZpZy5idWlsZD8ucHVibGljUGF0aCA/PyAnL19udXh0Lyc7IC8vIE11c3QgbWF0Y2ggJ2J1aWxkLnB1YmxpY1BhdGgnIGluIG51eHQuY29uZmlnLmpzXG5cbiAgICAvLyBUaGUgY3VzdG9tIGFzc2V0cyBvZiB0aGUgTnV4dCBhcHAgbG9jYXRlZCBpbiB0aGUgc3JjICdzdGF0aWMnIGZvbGRlclxuICAgIGNvbnN0IGN1c3RvbUFzc2V0c1NvdXJjZVBhdGggPSBgLi8ke251eHRDb25maWcuc3JjRGlyID8gKG51eHRDb25maWcuc3JjRGlyICsgJy8nKSA6ICcnfXN0YXRpY2A7XG4gICAgY29uc3QgY3VzdG9tQXNzZXRzVGFyZ2V0UGF0aCA9ICcvJztcblxuICAgIHJldHVybiBbXG5cbiAgICAgICAgLy8gQnVpbGQgQXNzZXRzXG4gICAgICAgIHtcbiAgICAgICAgICAgIHBhdHRlcm46ICcqLmpzJyxcbiAgICAgICAgICAgIHRhcmdldDogYnVpbGRBc3NldHNUYXJnZXRQYXRoLFxuICAgICAgICAgICAgc291cmNlOiBidWlsZEFzc2V0c1NvdXJjZVBhdGgsXG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2phdmFzY3JpcHQ7IGNoYXJzZXQ9VVRGLTgnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBwYXR0ZXJuOiAnKi5qcy5tYXAnLFxuICAgICAgICAgICAgdGFyZ2V0OiBidWlsZEFzc2V0c1RhcmdldFBhdGgsXG4gICAgICAgICAgICBzb3VyY2U6IGJ1aWxkQXNzZXRzU291cmNlUGF0aCxcbiAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCcsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIHBhdHRlcm46ICcqLmNzcycsXG4gICAgICAgICAgICB0YXJnZXQ6IGJ1aWxkQXNzZXRzVGFyZ2V0UGF0aCxcbiAgICAgICAgICAgIHNvdXJjZTogYnVpbGRBc3NldHNTb3VyY2VQYXRoLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICd0ZXh0L2NzczsgY2hhcnNldD1VVEYtOCcsXG4gICAgICAgIH0sXG5cbiAgICAgICAgLy8gTWFuaWZlc3QgY3JlYXRlZCBieSBQV0EgbW9kdWxlXG4gICAgICAgIHtcbiAgICAgICAgICAgIHBhdHRlcm46ICdtYW5pZmVzdC4qLmpzb24nLFxuICAgICAgICAgICAgdGFyZ2V0OiBidWlsZEFzc2V0c1RhcmdldFBhdGgsXG4gICAgICAgICAgICBzb3VyY2U6IGJ1aWxkQXNzZXRzU291cmNlUGF0aCxcbiAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCdcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgcGF0dGVybjogJyouc3ZnJyxcbiAgICAgICAgICAgIHRhcmdldDogYnVpbGRBc3NldHNUYXJnZXRQYXRoLFxuICAgICAgICAgICAgc291cmNlOiBidWlsZEFzc2V0c1NvdXJjZVBhdGgsXG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ2ltYWdlL3N2Zyt4bWwnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBwYXR0ZXJuOiAnKi5lb3QnLFxuICAgICAgICAgICAgdGFyZ2V0OiBidWlsZEFzc2V0c1RhcmdldFBhdGgsXG4gICAgICAgICAgICBzb3VyY2U6IGJ1aWxkQXNzZXRzU291cmNlUGF0aCxcbiAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vdm5kLm1zLWZvbnRvYmplY3QnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBwYXR0ZXJuOiAnKi50dGYnLFxuICAgICAgICAgICAgdGFyZ2V0OiBidWlsZEFzc2V0c1RhcmdldFBhdGgsXG4gICAgICAgICAgICBzb3VyY2U6IGJ1aWxkQXNzZXRzU291cmNlUGF0aCxcbiAgICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vZm9udC1zZm50JyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgcGF0dGVybjogJyoud29mZicsXG4gICAgICAgICAgICB0YXJnZXQ6IGJ1aWxkQXNzZXRzVGFyZ2V0UGF0aCxcbiAgICAgICAgICAgIHNvdXJjZTogYnVpbGRBc3NldHNTb3VyY2VQYXRoLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdmb250L3dvZmYnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBwYXR0ZXJuOiAnKi53b2ZmMicsXG4gICAgICAgICAgICB0YXJnZXQ6IGJ1aWxkQXNzZXRzVGFyZ2V0UGF0aCxcbiAgICAgICAgICAgIHNvdXJjZTogYnVpbGRBc3NldHNTb3VyY2VQYXRoLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdmb250L3dvZmYyJyxcbiAgICAgICAgfSxcblxuICAgICAgICAvLyBDdXN0b20gU3RhdGljIEFzc2V0c1xuICAgICAgICB7XG4gICAgICAgICAgICBwYXR0ZXJuOiAnKi5wbmcnLFxuICAgICAgICAgICAgc291cmNlOiBjdXN0b21Bc3NldHNTb3VyY2VQYXRoLFxuICAgICAgICAgICAgdGFyZ2V0OiBjdXN0b21Bc3NldHNUYXJnZXRQYXRoLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdpbWFnZS9wbmcnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBwYXR0ZXJuOiAnKi5qcGcnLFxuICAgICAgICAgICAgc291cmNlOiBjdXN0b21Bc3NldHNTb3VyY2VQYXRoLFxuICAgICAgICAgICAgdGFyZ2V0OiBjdXN0b21Bc3NldHNUYXJnZXRQYXRoLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdpbWFnZS9qcGcnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBwYXR0ZXJuOiAncm9ib3RzLnR4dCcsXG4gICAgICAgICAgICBzb3VyY2U6IGN1c3RvbUFzc2V0c1NvdXJjZVBhdGgsXG4gICAgICAgICAgICB0YXJnZXQ6IGN1c3RvbUFzc2V0c1RhcmdldFBhdGgsXG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ3RleHQvcGxhaW47IGNoYXJzZXQ9VVRGLTgnLFxuICAgICAgICAgICAgY2FjaGVDb250cm9sOiBbQ2FjaGVDb250cm9sLnNldFB1YmxpYygpLCBDYWNoZUNvbnRyb2wubWF4QWdlKER1cmF0aW9uLmRheXMoMSkpXSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgcGF0dGVybjogJyouanMnLFxuICAgICAgICAgICAgc291cmNlOiBjdXN0b21Bc3NldHNTb3VyY2VQYXRoLFxuICAgICAgICAgICAgdGFyZ2V0OiBjdXN0b21Bc3NldHNUYXJnZXRQYXRoLFxuICAgICAgICAgICAgY29udGVudFR5cGU6ICdhcHBsaWNhdGlvbi9qYXZhc2NyaXB0OyBjaGFyc2V0PVVURi04JyxcbiAgICAgICAgICAgIC8vIFRoZSBqcyBmaWxlcyBpbiB0aGUgY3VzdG9tIHN0YXRpYyBkaXJlY3RvcnkgYXJlIHVzdWFsbHkgbm90IHZlcnNpb25pemVkXG4gICAgICAgICAgICAvLyB3aGVyZWJ5IHdlIHdhbnQgdG8gcHJldmVudCBhbnkgY2FjaGluZyBpc3N1ZXMgd2hlbiB1cGRhdGluZyB0aGVtIC0+IGNhY2hlIGZvciBvbmx5IDIgZGF5c1xuICAgICAgICAgICAgY2FjaGVDb250cm9sOiBbQ2FjaGVDb250cm9sLnNldFB1YmxpYygpLCBDYWNoZUNvbnRyb2wubWF4QWdlKER1cmF0aW9uLmRheXMoMikpXSxcbiAgICAgICAgfSxcbiAgICBdXG59OyJdfQ==
|
|
@@ -36,10 +36,12 @@ export interface StaticAssetConfig {
|
|
|
36
36
|
*/
|
|
37
37
|
export const getNuxtAppStaticAssetConfigs = (nuxtConfig: NuxtConfig): StaticAssetConfig[] => {
|
|
38
38
|
|
|
39
|
+
// The build assets required for CSR that are generated by 'nuxt build'
|
|
39
40
|
const buildAssetsSourcePath = './.nuxt/dist/client';
|
|
40
41
|
const buildAssetsTargetPath = nuxtConfig.build?.publicPath ?? '/_nuxt/'; // Must match 'build.publicPath' in nuxt.config.js
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
// The custom assets of the Nuxt app located in the src 'static' folder
|
|
44
|
+
const customAssetsSourcePath = `./${nuxtConfig.srcDir ? (nuxtConfig.srcDir + '/') : ''}static`;
|
|
43
45
|
const customAssetsTargetPath = '/';
|
|
44
46
|
|
|
45
47
|
return [
|
|
@@ -123,10 +125,12 @@ export const getNuxtAppStaticAssetConfigs = (nuxtConfig: NuxtConfig): StaticAsse
|
|
|
123
125
|
cacheControl: [CacheControl.setPublic(), CacheControl.maxAge(Duration.days(1))],
|
|
124
126
|
},
|
|
125
127
|
{
|
|
126
|
-
pattern: '
|
|
128
|
+
pattern: '*.js',
|
|
127
129
|
source: customAssetsSourcePath,
|
|
128
130
|
target: customAssetsTargetPath,
|
|
129
131
|
contentType: 'application/javascript; charset=UTF-8',
|
|
132
|
+
// The js files in the custom static directory are usually not versionized
|
|
133
|
+
// whereby we want to prevent any caching issues when updating them -> cache for only 2 days
|
|
130
134
|
cacheControl: [CacheControl.setPublic(), CacheControl.maxAge(Duration.days(2))],
|
|
131
135
|
},
|
|
132
136
|
]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {App} from "aws-cdk-lib";
|
|
3
|
+
import {NuxtAppStack, NuxtAppStackProps, NuxtAppAssetsCleanupProps, NuxtAppAssetsCleanupStack, AppStackProps} from "cdk-nuxt";
|
|
4
|
+
const NuxtConfig = require('../nuxt.config');
|
|
5
|
+
|
|
6
|
+
const app: App = new App();
|
|
7
|
+
|
|
8
|
+
const commonProps: AppStackProps = {
|
|
9
|
+
// The AWS environment (account/region) where this stack will be deployed.
|
|
10
|
+
env: {
|
|
11
|
+
// The ID of your AWS account on which to deploy the stack.
|
|
12
|
+
account: 'XXXXXXXX',
|
|
13
|
+
|
|
14
|
+
// The AWS region where to deploy the Nuxt app.
|
|
15
|
+
region: 'eu-central-1'
|
|
16
|
+
},
|
|
17
|
+
// A string identifier for the project the Nuxt app is part of. A project might have multiple different services.
|
|
18
|
+
project: 'my-project',
|
|
19
|
+
// A string identifier for the project's service the Nuxt app is created for. This can be seen as the name of the Nuxt app.
|
|
20
|
+
service: 'nuxt-app',
|
|
21
|
+
// A string to identify the environment of the Nuxt app.
|
|
22
|
+
environment: 'dev',
|
|
23
|
+
// Stack tags that will be applied to all the taggable resources and the stack itself.
|
|
24
|
+
tags: {
|
|
25
|
+
service: 'nuxt-app'
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const appStackProps: NuxtAppStackProps = {
|
|
30
|
+
...commonProps,
|
|
31
|
+
// The domain (without the protocol) at which the Nuxt app shall be publicly available.
|
|
32
|
+
domain: 'example.com',
|
|
33
|
+
// The ARN of the certificate to use for the Nuxt app to make it accessible via HTTPS.
|
|
34
|
+
// The certificate must be issued for the specified domain in us-east-1 (global) regardless of the region used for the Nuxt app itself.
|
|
35
|
+
globalTlsCertificateArn: 'arn:aws:acm:us-east-1:XXXXXXXXXX:certificate/XXXXXXXXXXXXXXXXX',
|
|
36
|
+
// The id of the hosted zone to create a DNS record for the specified domain.
|
|
37
|
+
hostedZoneId: 'XXXXXXXXXXXXX',
|
|
38
|
+
|
|
39
|
+
nuxtConfig: NuxtConfig
|
|
40
|
+
};
|
|
41
|
+
const appStack = new NuxtAppStack(app, `${appStackProps.project}-${appStackProps.service}-${appStackProps.environment}-stack`, appStackProps);
|
|
42
|
+
|
|
43
|
+
const cleanupStackProps: NuxtAppAssetsCleanupProps = {
|
|
44
|
+
...commonProps,
|
|
45
|
+
service: `${appStackProps.service}-assets-cleanup`,
|
|
46
|
+
staticAssetsBucket: appStack.staticAssetsBucket,
|
|
47
|
+
};
|
|
48
|
+
new NuxtAppAssetsCleanupStack(app, `${cleanupStackProps.project}-${cleanupStackProps.service}-${cleanupStackProps.environment}-stack`, cleanupStackProps);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cdk-nuxt",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"lib",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"main": "index.js",
|
|
10
10
|
"types": "index.d.ts",
|
|
11
11
|
"bin": {
|
|
12
|
-
"nuxt-
|
|
12
|
+
"cdk-nuxt-init": "./lib/cli/init.js",
|
|
13
|
+
"cdk-nuxt-deploy": "./lib/cli/deploy.js"
|
|
13
14
|
},
|
|
14
15
|
"scripts": {
|
|
15
16
|
"build": "tsc"
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
"source-map-support": "^0.5.16"
|
|
31
32
|
},
|
|
32
33
|
"peerDependencies": {
|
|
33
|
-
"aws-cdk": "
|
|
34
|
+
"aws-cdk": "2.10.0",
|
|
34
35
|
"nuxt-aws-lambda": "^1.5.0",
|
|
35
36
|
"nuxt-start": "^2.15.8",
|
|
36
37
|
"ts-node": "^10.5.0",
|