This article has been translated on the basis of machine translation. If there are any mistakes, please fix it.pull request

Building a Vue3 Typescript Environment with Vite

Building a Typescript Vue3 environment using the No bundle tool Vite, along with ESLint and Prettier configuration to create a high DX environment.

10/10/20217 min read
..
hero image

Introduction

Vite is a build tool developed by Evan You, the author of Vue. It uses native ES Module imports to provide a fast running development environment with no bundling required. Vue3, React and Preact are also supported.

In this article, I'll build a Vue3 project environment using Vite.

You can find the template in here.

Things to do

The goal is to get you close to the default vue/cli template, and I'll implement the necessary tools for development. I'm going to walk you through each of these tools so that you can introduce them individually.

  • Typescript
  • ESLint
  • Prettier
  • Stylelint
  • husky and lint-staged
  • Path Alias
  • vue-tsc

Building Environments

Verified in the next version:

1
@vitejs/create-app@2.4.5
bash

First, let's expand the vite template.

1
2
3
yarn create @vitejs/app <project-name> --template vue-ts
cd <project-name>
yarn
bash

Once the development server is up, you'll be impressed by how fast it is.

⤵️ No longer needed.

Typescript

Next, let's make your project Typescripted. Since Vue3 has Typescript by default, you only need to do the following three things.

1.Add lang="ts" to the script tag in all .vue files. 2.Change main.js to main.ts. 3.Change the src of the script tag of index.html to /src/main.ts.

Now you can start up the development server and see that it runs without any problem.

It will actually work on its own, but you can add more settings to improve the user experience in the editor.

If you're using VSCode, you should see a main.ts with a ts(2307) error.

To fix this, need to create a type declaration file for vue.

1
2
3
4
5
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<Record<string,unknown>, Record<string,unknown>, unknown>
export default component
}
src/shims-vue.d.tsts

Place the tsconfig.json in your project root. This will tell the editor to recognize the project as a Typescript project.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"paths": {
"/@/*": [ // / to begin with.
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
],
"exclude": [
"node_modules"
]
}
tsconfig.jsonjson

That's the end of Typescript.

Introducing ESLint

Development without a linter is tough, so be sure to install it.

1
yarn add -D eslint eslint-plugin-vue @vue/eslint-config-typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin
bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"root": true,
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"plugin:vue/vue3-recommended",
"eslint:recommended",
"@vue/typescript/recommended"
],
"parserOptions": {
"ecmaVersion": 2021
},
"plugins": [
],
"rules": {
}
}
.eslintrcjson

This will result in an error, so we will modify the type definition.

1
2
3
4
5
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<Record<string,unknown>, Record<string,unknown>, unknown>
export default component
}
src/shims-vue.d.tsts

It is easy to prepare a linting command in the script of the package.json for later.

1
2
3
"scripts": {
"lint:script": "eslint --ext .ts,vue --ignore-path .gitignore ."
}
package.jsonjson

Personally, I don't want to fix some situations, so I use --fix from outside.

Now let's run this.

1
yarn lint:script --fix
bash

VSCode users can also set up the following settings to make the automatic formatting work. An extension to ESLint is required, so if you don't have it, please install it see here.

1
2
3
4
5
{
"editor.codeActionsOnSave": {
"source.fixAll": true
}
}
.vscode/settings.jsonjson

This allowed me to format the file on save.

Configuring husky and lint-staged

Before committing, let's run a static check to make sure you can't commit the error code.

1
yarn add -D husky lint-staged
bash

Add the following to package.json.

1
2
3
4
5
6
7
8
9
10
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{ts,vue}": "eslint --fix"
}
}
package.jsonjson

This causes ESLint to run against any files with the appropriate extensions in the commit file before you commit.

Of course, on a linting error, the commit is canceled.

Configuring Prettier

Let Prettier do the formatting for your entire project. Also, let Prettier automatically remove semicolons in Typescript code.

1
yarn add -D prettier eslint-plugin-prettier @vue/eslint-config-prettier
bash
1
2
3
4
5
{
"singleQuote": true,
"semi": false,
"vueIndentScriptAndStyle": true
}
.prettierrcjson

When ESLint and Prettier are used together, I need to fix the .eslintrc to avoid duplicate rules.

1
2
3
4
5
6
7
8
9
10
{
"extends": [
"plugin:vue/vue3-recommended",
"eslint:recommended",
"@vue/typescript/recommended",
// Add under other rules
"@vue/prettier",
"@vue/prettier/@typescript-eslint"
]
}
.eslintrcjson

command to execute the formatter.

1
yarn prettier -w -u .
bash

I want to apply automatic formatting before committing, so add the setting to lint-staged.

1
2
3
4
5
6
{
"lint-staged": {
"*.{ts,vue}": "eslint --fix",
"*": "prettier -w -u" // Set prettier to last
}
}
package.jsonjson

VSCode users can format it automatically with the following settings. Also, an extension is required, so if it is not available, please install it here.

1
2
3
4
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
.vscode/settings.jsonjson

Configuring Stylelint

Let's make the style a target for linting as well.

1
yarn add -D stylelint stylelint-config-recommended stylelint-config-standard
bash
1
2
3
{
"extends": ["stylelint-config-recommended", "stylelint-config-standard"]
}
.stylelintrcjson

Edit the package.json and set the commands and lint-staged.

1
2
3
4
5
6
7
8
9
10
{
"scripts": {
"lint:style": "stylelint src/**/*.{css,scss,vue}"
},
"lint-staged": {
"*.{ts,tsx}": "eslint --fix",
"*.{css,scss,vue}": "stylelint --fix",
"*": "prettier -w -u"
}
}
package.jsonjson

VSCode users can format it automatically with the following settings. Extensions are required, so if you don't have them, install them see here.

That's the end of the basic setup of the linker and formatter.

Configuring Path Alias

The import of the module is relative by default, but you want to set an alias to always refer to the same root.

1
2
3
4
5
6
7
8
9
10
11
12
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
plugins: [vue()]
})
vite.config.tsts

Also change tsconfig.json.

1
2
3
4
5
6
7
8
9
{
"compilerOptions": {
//...
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
tsconfig.jsonjson

Now you can set up alias. I'll use it like this.

1
2
3
<script lang="ts">
import HelloWorld from '@/components/HelloWorld.vue'
</script>
App.vuehtml

Checking template statically with vue-tsc

You can statically check your template tags with vue-tsc.

It is installed when the template is generated. However, as of @vue/runtime-dom@3.1.4, it does not work unless skipLibCheck in tsconfig.json is set to true.

1
2
3
4
5
6
{
"compilerOptions": {
//...
"skipLibCheck": true
},
}
tsconfig.jsonjson
1
2
3
4
5
6
{
"scripts": {
//...
"lint:markup": "vue-tsc --noEmit",
}
}
package.jsonjson

I recommend running static checks in CI rather than before committing, as static checks can take quite a bit of time as the number of Vue files increases.

That's the minimum environment you'll need to build.


Edit this page on GitHub

Other Article

Comments