To create a local development setup follow the next steps:
- Open the local
hostsfile and add the folowing content at the end of the file:
# Start of Autovantage
127.0.0.1 app.test
# End of Autovantage
- Go to
dockerfolder of the project - Create a copy of
.env.exampledocument and rename the copy to.env - In the
.envfile add the node version you want/require in theENV_NODE_VERSIONvariable - In the
.envadd the port you use for development in theENV_NGINX_HOST_HTTP_PORTvariable - Build the container
docker-compose build
- Start the containers
docker-compose up
- Connect to the container:
docker-compose exec frontend bash
- Run the following commands:
npm install
- Finished!
npm installnpm run devnpm run buildRun Unit Tests with Vitest
npm run test:unitLint with ESLint
npm run lintFormat with Prettier
npm run formatEven though we have commands for linting and formatting. This is done automatically per file on save.
See Vite Configuration Reference.
IDE : VSCode
Volar (and disable Vetur): main extension for vue3 TypeScript Vue Plugin (Volar): typescript enabler for vue 3 projects
Tailwind CSS IntelliSense: extension used for tailwind in order to have autocompletion
for tailwind classes, linting for errors and hover explanation for classes. One caveat. In order for tailwind to detect tailwind classes outside of html markup,
we have to add /*tw*/ comment in front of that string in order for tailwind to detect those classes (see theme.ts file in src folder).
ESLint: linting extension
Prettier: formatting extension
Format Code Action: linting and formatting on save enabler.
Created the template using the npm init vue@latest which configures typescript by default. Had to adjust the tsconfig files in order to account for all the issues that appeared. resolveJsonModule set to true in order to import json into typescript.
TypeScript cannot handle type information for .vue imports by default, so we replace the tsc CLI with vue-tsc for type checking. In editors, we need TypeScript Vue Plugin (Volar) to make the TypeScript language service aware of .vue types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a Take Over Mode that is more performant. You can enable it by the following steps:
- Disable the built-in TypeScript Extension
- Run
Extensions: Show Built-in Extensionsfrom VSCode's command palette - Find
TypeScript and JavaScript Language Features, right click and selectDisable (Workspace)
- Run
- Reload the VSCode window by running
Developer: Reload Windowfrom the command palette.
Framework agnostic bundler that is a leaner and faster version of webpack. Good vue support through a multitude of plugins.
Utility classes for fast prototyping
A Vue form building framework that simplifies form structure, generation, validation, theming, submission, error handling, and more.
Vue component framework that includes components that are fully unstyled, but feature and accessibility ready. Styling can be done with tailwind as they are from the same publisher.
Basic vue routing library from the vue ecosystem
A leaner vuex with better typescript experience. Stores can be created the same way as in vuex (- mutations) or in a composition api like fashion (like setup function in options api). Each file is a store, not a module like in vuex, and there is no root store. Each store can be composed with another store.
Installed plugins vue-i18n and @intlify/vite-plugin-vue-i18n to support translations. Created a root i18n file to import all the translation files into.
VueUse is a collection of useful composables that wrap common apis and functionalities from the browser in simple functions.
There is a composable called useAxios that is a wrapper for axios itself for ease of use.
With the help of the useLocalStorage composable, we have reactive and persisted state in pinia.
Most of them are from formkit, but additionaly:
- Select: based on the headless ui combobox component, still needs some tweaks to include multiple, maybe change for vue multiselect until formkit includes the option.
- props:
- v-model: the currently selected option.
- options: the list of options for the select. (need to type those as generic, but dont know how to do this yet)
- label: the label of the select
- props:
- Toggle: based on the headless ui switch component
- props:
- v-model: whether the toggle is checked or not
- labelLeft: the left label for the toggle
- labelRight: the right label for the toggle
- error: the error label if the toggle is not checked
- props:
- Modal:
- props: opened (if the modal should be opened or not)
- slots:
- title
- body
- footer
- Alert:
- props:
- opened (if the modal should be opened or not)
- alertText (the text content of the alert )
- alertType (the type of the alert, success or error)
- props:
For linting I have used eslint and for formatting I have used prettier. Both have config files for overrides in the root of the folder. In addition to those two files, there is an additional file called .editorconfig that also does some formating for us on save.
I have implemented a minimal setup for all the basic auth flow. The requests have been sent to the template-backend repo made with laravel.
- vue: ^3.2.32
- vue-i18n: ^9.1.9
- vue-router: ^4.0.14
- pinia: ^2.0.13
- axios: ^0.26.1
- @headlessui/vue: ^1.5.0
- @vueuse/core: ^8.2.5
- @vueuse/integrations: ^8.2.5
- uuid: ^8.3.2
- @formkit/themes": ^1.0.0-beta.8,
- @formkit/vue": ^1.0.0-beta.8,
- @intlify/vite-plugin-vue-i18n: ^3.4.0,
- @rushstack/eslint-patch: ^1.1.0,
- @tailwindcss/forms: ^0.5.0,
- @types/jsdom: ^16.2.14,
- @types/node: ^16.11.26,
- @types/uuid: ^8.3.4,
- @vitejs/plugin-vue: ^2.3.1,
- @vue/eslint-config-prettier: ^7.0.0,
- @vue/eslint-config-typescript: ^10.0.0,
- @vue/test-utils: ^2.0.0-rc.18,
- @vue/tsconfig: ^0.1.3,
- autoprefixer: ^10.4.4,
- eslint: ^8.5.0,
- eslint-plugin-vue: ^8.2.0,
- jsdom: ^19.0.0,
- postcss: ^8.4.12,
- prettier: ^2.5.1,
- prettier-plugin-tailwindcss: ^0.1.8,
- tailwindcss: ^3.0.23,
- typescript: ~4.6.3,
- vite: ^2.9.1,
- vitest: ^0.8.1,
- vue-tsc: ^0.33.9
- assets
- images
- styles
- fonts
- components: reusable components throughout the app
- common: like modals and alerts
- form: synthetic inputs like toggle and select with search
- composables: reusable vue 3 specific functionality
- locales: translation files
- models: reusable typescript types and interfaces
- router: routing configuration for the project
- stores: contains pinia stores, each file is a store
- utils: diverse utility functions
- views: all the pages
- theme.ts: theming file for formkit using tailwind utility classes
- main.ts: vue starting point file
- shims.d.ts: vue specific file to enable typescript
- i18n.ts: internationalization plugin file
I have set the project up in github as a template. Instead of cloning the project, github provides a button where you can start a new repository from this template.
- VITE_API_URL: env variable for setting up the api url
- Issue in github regarding useLocalStorage in pinia store
- FormKit Pro: they are currently working on further syntetic inputs like the following: "toggle, dropdown, autocomplete, tag list, repeater, multi-step wizard, star rating, button group, date range picker. After that we'll continue to roll out more." We could implement our own stuff until these get out. Unfortunately the pro version is going to be paid, but having every type of input from the same provider would be nice.
Because the npm installation needs java, we have to find other ways to install the open api generator. For MacOs we can install the openapi-generator through brew. This way the open api is installed globally and there is no error with java (probabil it comes with java by default?).
With the open api generator installed through brew, we can run the follwing command to generate the client:
openapi-generator generate -i jsonplaceholder.yaml -g typescript-axios -o gen/api --config=api.json
- The generate is the command
- -i is the input yaml configuration (jsonplaceholder.yaml is just an example)
- -g is the generator, in this case we want to generate a typescript-axios client
- -o is the output folder
- --config is the config file we have in the root for the generate command
After we generate the client code in our repo, we have to add a line of configuration in the tsconfig.json file in the client folder:
"moduleResolution": "Node"
After we add this line we can run:
npm install
and then
npm run build
so that the api client is being installed as a dependency.
After being built, we can add the dependency to the root package.json with the name specified inside api.json, like so:
"typescript-axios": "file:gen/api" ("pakage-name from api.json" : "file: the folder where the client is")
Then we have to configure the client. It takes 3 parameters: configuration object, baseURL and axios instance. In the axiosConfig.ts we have to create an axios instance where we set up our intercepters, etc and then pass it to the client togheter with the baseURL and for the client configuration object we pass an undefined object as we might not want to mess with that.
Typescript might throw a type error when supplying the axios instance to the client. This might be because the axios from the client is a different version than the in the root package.json. These versions have to be the same in order for that error to go away.