Scaffolding a Vue 3 + Vuetify + Amplify Project (2023)
Tags: aws, amplify, vue, webdev
Published: 2023-04-09 04:10:43

This article aims to provide the most recent step by step guide on how to scaffold a base project using Vue 3, Vuetify and Amplify components. Using amplify's Vue 3 getting started tutorial was a bit challenging in my opinion as certain steps (Injection of `window.global` script in index.html was confusing, `vite.config.js` setup was lacking import alias support, directory where `amplify init` should be triggered isn't clearly stated) on the guide were not detailed enough to be followed by somebody completely new with using Amplify.

After reading through this article, you'd be able to:

1. Run `npm run dev` successfully without facing import issues.
2. Get an amplify app in your AWS account.
3. Have a base scaffold that could easily be extended with other core amplify components (GraphQL API, Hosting, Cognito-based Auth)

### Pre-requisites

In order to follow this guide and the same exact scaffold, you will need to have the following CLIs installed on your machines.

- `Node 18` - I'm using the most latest version of NodeJS 18. I've installed mine using `nvm` (Node version manager).
- `amplify` cli - You'll need the amplify cli to initialize the amplify app and provision backend resources later on.
- `aws` cli - You'll need an AWS cli to configure pre-built AWS profiles that allows your machine to make changes on your AWS accounts.

### Initialise the Vue 3 projects

As with any Vue 3 + Vite project, we have to scaffold the base project by using the pre-built tools provided by the Vue JS.

```sh
npm init vue@3
```

### Install Dependencies

After the scaffolding of base components gets completed, navigate into the project's directory and install the dependencies required by the base application to run.

```sh
# Substitute this with your project name
cd ./aws-exam-trainer

npm install
```

### Add Dependencies

We also need to install the following dependencies:

1. `vuetify` - is the most popular UI library for VueJS projects. It requires literally no design skills to get you started in crafting visually decent frontend applications.
2. `aws-amplify` - is the base library used for accessing common integrations in Amplify such as API, Auth, Analytics, etc. This library is not coupled with UI-specific frameworks such as Vue and React JS.
3. `@aws-amplify/ui-vue` - is a VueJS-specific set of cloud connected components that makes trivial tasks (Upload to S3, Cognito-backed Integration, etc) easy and fast to implement.

```sh
npm install vuetify aws-amplify @aws-amplify/ui-vue
```

### Initialising Amplify App

The next step is to initialise the Amplify app. This is done by running the `amplify init` command inside the directory generated by the `npm init vue@3` command from the first step.



```sh
amplify init
```

Running the command will present you with the following prompt and most of the configurations for vue 3 projects will be pre-filled for us. Just agree with the default configurations for now.

```sh
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project awsexamtrainer
The following configuration will be applied:

Project information
| Name: awsexamtrainer
| Environment: dev
| Default editor: Visual Studio Code
| App type: javascript
| Javascript framework: vue
| Source Directory Path: src
| Distribution Directory Path: dist
| Build Command: npm run-script build
| Start Command: npm run-script serve

? Initialize the project with the above configuration? Yes
Using default provider  awscloudformation
```

The next important step is to configure the AWS named profile that will be used for provisioning the Amplify app. This profile will also be used for other operations that require changes to our AWS account, such as provisioning AppSync APIs and Cognito User Pools.

In my machine, I've configured a profile called `my-poc-profile` and just selected this on the guided CLI provided by AWS amplify

```sh
? Select the authentication method you want to use: AWS profile

For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html

? Please choose the profile you want to use my-poc-profile
Adding backend environment dev to AWS Amplify app: dvmifg83sjtwe

Deployment completed.
Deploying root stack awsexamtrainer [ ---------------------------------------- ] 0/4
        amplify-awsexamtrainer-dev-10… AWS::CloudFormation::Stack     CREATE_IN_PROGRESS             Sun Apr 09 2023 10:08:18…     
        DeploymentBucket               AWS::S3::Bucket                CREATE_IN_PROGRESS             Sun Apr 09 2023 10:08:21…     
        AuthRole                       AWS::IAM::Role                 CREATE_IN_PROGRESS             Sun Apr 09 2023 10:08:21…     
        UnauthRole                     AWS::IAM::Role                 CREATE_IN_PROGRESS             Sun Apr 09 2023 10:08:21…     

✔ Help improve Amplify CLI by sharing non sensitive configurations on failures (y/N) · no
Deployment state saved successfully.
✔ Initialized provider successfully.
✅ Initialized your environment successfully.

Your project has been successfully initialized and connected to the cloud!

Some next steps:
"amplify status" will show you what you've added already and if it's locally configured or deployed
"amplify add <category>" will allow you to add features like user login or a backend API
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify console" to open the Amplify Console and view your project status
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

Pro tip:
Try "amplify add api" to create a backend API and then "amplify push" to deploy everything
```

At this point, you should now have an amplify app configured on your AWS account.

### Plug Vuetify and Amplify to main.js file

In order to access Vuetify UI components and Amplify base libraries, we'll have to configure the default `main.js` file generated by the vue init process with the following code.

```js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import './assets/main.css'

// Vuetify
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'

// Amplify
import { Amplify } from 'aws-amplify'
import awsExports from './aws-exports'
import AmplifyVue from '@aws-amplify/ui-vue'

Amplify.configure(awsExports)

const vuetify = createVuetify({
  components,
  directives
})

const app = createApp(App)

app.use(vuetify)
app.use(AmplifyVue)
app.use(router)

app.mount('#app')
```

### Add window.global and global exports handle (Vite Users only) to index.html

In order to make use of the UI components provided by `@aws-amplify/ui-vue` library to our vite-based project, we'll have to inject the snippet below that adds `global` property to window and a global exports object required by Amplify components. 

Please inject it on the same position to avoid getting unwanted behaviours and errors later on the development. (This is one nasty mistake I've made on my initial attempts on using Amplify + VueJS projects).

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>
  <body>
    <div id="app"></div>
    <!--Add this snippet-->
    <script>
      window.global = window
      var exports = {}
    </script>
    <!--End of snippet to inject-->
    <script type="module" src="/src/main.js"></script>
  </body>
</html>
```

## Setup vite.config.js

We'll also have to configure the `vite.config.js` file so it would end up like this instead of the one provided by the amplify getting started docs for Vue JS. 

What makes this configuration better than the one provided by the amplify team is that it allows us to import vue components from `src` folder without having to use relative paths.

**Tip of the day**
Importing components using static path syntax makes VueJS projects easier to maintain by:

- Making refactoring of dependent components paths in large projects more resilient to bugs caused by relative imports failures.
- Regardless of the depth of the dependent component, static path imports make it easy reference shared components by having a standard import location.
- Removes the cognitive effort required from developers in mentally resolving the relative paths of components they like to import.

```js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'url'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: [
      {
        find: './runtimeConfig',
        replacement: './runtimeConfig.browser'
      },
      // This bit here is not mentioned in Amplify Docs
      { find: '@', replacement: fileURLToPath(new URL('./src', import.meta.url)) }
    ]
  }
})
```

### For TypeScript users

For typescript users, you will have to configure the `compilerOptions.skipLibCheck` option to your `tsconfig.json` files to skip type checking of declaration files.

This can save time during compilation at the expense of type-system accuracy. For example, two libraries could define two copies of the same type in an inconsistent way. Rather than doing a full check of all `d.ts` files, TypeScript will type check the code you specifically refer to in your app’s source code.

```json
...
  "compilerOptions": {
    "skipLibCheck": true,
...
```

### Testing the Base Scaffold

At this point, you should have a basic Vue 3 project that can access both Vuetify and Amplify components without facing compile issues.

```sh
npm run dev
```

You should be able to see the following web page on the port allocated to vite without errors.

![Base scaffold running without errors](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/15nykyik4qdqfxkary2b.png)

### What's Next?

On the next articles, I'll be showcasing how to:

1. Install and customize a Cognito-backed login interface.
2. Add an AppSync API that uses at least two types of resolvers (Lambda and DynamoDB)
3. Automate the deployment of changes from github repos to S3+CloudFront web hosting setup.

The final project aims to generate AWS exam reviewer questions using OpenAI prompts based from a user provided link (Ideally an AWS Documentation web page). 

What makes this project interesting is that AWS professionals can now generate reviewer questions in a matter of seconds, track their scores and generate reviewer content that changes over time. 

Till then, see you soon.