Vue3+Vite+Ts Project Combat 01 Vite Create Project, ESLint+TS+GitCommit Configuration, Vue3 New Features Introduction

forward declaration:

  • Vue3 and Vite are still being updated, and the Chinese documentation is still not complete. The content of this note may become outdated in the future. It is recommended to refer to the English documentation and use the latest version.
  • The back-end API service used in this case is based on Express and uses json files to manage data, Git warehouses and usage documents .
  • This case aims to learn Vite and Vue3 to build configuration applications, and does not develop complete business functions.

Project initialization

Create a project with Vite

Vite Official Chinese Documentation (vitejs.dev)

Official statement: Vite requires Node.js version >= 12.0.0. However, some templates require a higher version of Node to run properly. When your package manager warns you, please upgrade your version of Node.

In this example, the Node.js 12 version executes the build command and reports an error, so the Node.js 16 version is used instead. Remember to switch versions npm installto avoid dependencies that have not been updated.

# 创建
npm init vite@latest
√ Project name: ... shop-admin # 项目名称
√ Select a framework: » vue # 选择框架
√ Select a variant: » vue-ts # 选择 vue 或 vue-ts

cd ./shop-admin
git init
npm install
npm run dev

accesshttp://localhost:3000/

Description of the initial directory structure

├─ public # 存放不需要编译构建的静态资源
│   └─ favicon.ico
├─ src # 存放需要编译构建的文件
│   ├─ assets
│   │   └─ logo.png # 需要编译构建的静态资源
│   ├─ components
│   │   └─ HelloWorld.vue
│   ├─ App.vue
│   ├─ env.d.ts # ts 类型声明
│   └─ main.ts # 启动入口文件
├─ .gitignore # git 忽略文件
├─ index.html # 单页文件的模板文件
├─ package-lock.json
├─ package.json
├─ README.md
├─ tsconfig.json # ts 配置文件
├─ tsconfig.node.json
└─ vite.config.ts # vite 配置文件

package.json

{
    
    
  "scripts": {
    
    
    // 启动开发服务器
    "dev": "vite",
    // 构建生产环境产物:校验 ts 类型,通过后执行 vite 打包命令
    "build": "vue-tsc --noEmit && vite build",
    // 本地预览生产构建产物:以前需要将打包文件配置到 nginx 等服务器中才能预览,vite 简化了这个流程
    "preview": "vite preview"
  },
}

About the reason for the build failure

When writing this note, running npm run buildwill report a lot of errors:

Cannot access ambient const enums when the '--isolatedModules' flag is provided.

The reason is that Vite officially recommends configuring the TypeScript compiler option: isolatedModules to true.

{
    
    
  "compilerOptions": {
    
    
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    // "isolatedModules": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"]
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{
    
     "path": "./tsconfig.node.json" }]
}

Due to the compilation error caused by this, the Issue has not been resolved. For the time being, it can only be set to falseor delete this option.

Add a custom directory structure

srcAdd some folders under the directory :

├─ api # API 接口封装
├─ styles # 全局样式
├─ utils # 工具模块
├─ plugins # 插件
├─ views # 路由页面
├─ router # 路由模块
├─ store # vuex 容器模块
├─ layout # 公共布局组件
└─ composables # 项目中提取出来的组合式 API 函数模块

Code Standards and ESLint

ESLint is not integrated by default in projects created by Vite, and currently there is no official content related to ESLint, so manual integration and configuration of ESLint is required.

basic configuration

# 安装 eslint(当前版本 8.5.0)
npm i eslint -D
# 初始化 eslint 配置文件
npm init @eslint/config

# 如何使用 ESLint
? How would you like to use ESLint? ...
# 检查语法 找到问题 强制代码规范
> To check syntax, find problems, and enforce code style
# 项目中使用的 JS 模块规范
√ What type of modules does your project use? · esm
# 前端框架
√ Which framework does your project use? · vue
# 是否使用 TS
√ Does your project use TypeScript? · No / Yes
# 代码运行环境
√ Where does your code run? · browser
# 代码规范
? How would you like to define a style for your project? ...
# 使用一个流行的代码规范
> Use a popular style guide
> Standard: https://github.com/standard/standard
# 配置文件生成 js 类型的文件
√ What format do you want your config file to be in? · JavaScript
# ...

Generated eslint configuration file:

// .eslintrc.js
module.exports = {
    
    
  env: {
    
    
    browser: true,
    es2021: true
  },
  extends: [
    'plugin:vue/essential',
    'standard'
  ],
  parserOptions: {
    
    
    ecmaVersion: 'latest',
    parser: '@typescript-eslint/parser',
    sourceType: 'module'
  },
  plugins: [
    'vue',
    '@typescript-eslint'
  ],
  rules: {
    
    
  }
}

Based on my personal habits, I modified two rules:

rules: {
    
    
  // 要求或禁止函数圆括号之前有一个空格
  'space-before-function-paren': [2, {
    
    
    anonymous: 'always',
    named: 'never',
    asyncArrow: 'always'
  }],
  // 要求组件名(文件名)必须是多单词的
  'vue/multi-word-component-names': 0
}

package.jsonAdd a validation script in:

"scripts": {
    
    
  ...
  // 检查代码和自动修复
  "lint": "eslint src/**/*.{js,jsx,vue,ts,tsx} --fix"
},

npm run lintRun eslint validation:

# App.vue 和 components/HelloWorld.vue 验证失败,template 只能包含一个根节点
error  The template root requires exactly one element  vue/no-multiple-template-root

This rule applies to Vue 2, Vue 3 does not have this limitation. View the plugins used in the eslint configuration file plugin:vue/assential, from eslint-plugin-vuethe package, view eslint-plugin-vue\libthe directory ( official introduction ):

├─ base.js
├─ essential.js # 当前配置的验证规则
├─ no-layout-rules.js
├─ recommended.js
├─ strongly-recommended.js
# 以上是 Vue2 的验证规则
# 以下是 Vue3 的验证规则
├─ vue3-essential.js
├─ vue3-recommended.js
└─ vue3-strongly-recommended.js

Configure eslint as the validation rule for Vue 3 (this article uses the strictest):

// .eslintrc.js
module.exports = {
    
    
  ...
  extends: [
    // 'plugin:vue/essential',
    // 使用 vue3 规则
    'plugin:vue/vue3-strongly-recommended',
    'standard'
  ],
  ...
}

Compile macros and defineProps, defineEmits, no-undef rule warnings

run again npm run lint:

# HelloWorld.vue 报错
error  'defineProps' is not defined    no-undef

definePropsand are compiler macros ( compiler macros ) defineEmitsdefined by Vue3 , which can only be used in (the outermost layer). They do not need to be imported, and will be compiled when processing.<script setup><script setup>

However, when eslint checks, it is treated as an undefined variable and an error is reported, which can be displayed and imported in the file:

import {
    
     defineProps, defineEmits } from 'vue'

Or declare them as global variables when eslint checks:

// .eslintrc.js
module.exports = {
    
    
  globals: {
    
    
    defineProps: "readonly",
    defineEmits: "readonly",
    defineExpose: "readonly",
    withDefaults: "readonly"
  },
  ...
}

You can also use the eslint-plugin-vue official solution (the source code is the same as the global variable configuration above):

// .eslintrc.js
module.exports = {
    
    
  env: {
    
    
    browser: true,
    es2021: true,
    // 添加:
    'vue/setup-compiler-macros': true
  },
  ...
}

If vscode reports an error Environment key "vue/setup-compiler-macros" is unknown, please check eslint-plugin-vuewhether there is this rule, if not, the version may be too old, you can update the version (the version installed in this article is 8.5.0).

Run again npm run lint, no error reported.

Editor integration

Editor integration mainly implements two functions:

  1. How to see the error message that does not meet the specification
  2. How to format according to the requirements of ESLint rules in the project

Implementation steps:

1. Uninstall/disable vetur plugin (Vue2 plugin)

2. Install the volar plugin (Vue Language Features - equivalent to vetur that supports Vue3, and supports TypeScript prompts)

3. Install the ESLint plugin

As long as this plugin is installed and enabled, it will automatically find the eslint configuration specification in the project and give a verification prompt.

At the same time, the ESLint plug-in provides a formatting tool, but it needs to be manually configured. Open the file-preferences-settings (shortcut key Ctrl+,), find the extension-ESLint, check it Format: Enable, and enable the ESLint formatting tool:

insert image description here

You can also directly modify vscode settings.json, add "eslint.format.enable": true.

Then continue to configure eslint.validateoptions to specify the file types that eslint can check (by default only checks .jsand .jsxfiles):

{
    
    
  "eslint.format.enable": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "vue"
  ],
  ...
}

Then select the file formatting tool as ESLint, open the file to be formatted, right-click the code view-use... format the document-configure the default formatter..., and select ESLint.

After the configuration is complete, you can use Alt+Shift+Fto format the document.

PS: Installing and enabling the ESLint plug-in, modifying the configuration file will re-register with the IDE, which may cause a delay or even no display. It is best to reload after the modification: , Ctrl+Ptype>reload

Configure git pre-commit hook

Configure the pre-commit hook, add the lint command to the development and build process, and perform lint verification before git submission to prevent non-compliant code from being submitted to the git repository.

Tools used: okonet/lint-staged

npx mrm@2 lint-staged
# 会安装两个 npm 包
#	husky - 提供 git 钩子功能,拦截 git 命令
#	lint-staged - 获取 git 暂存区中的代码进行lint验证

After the execution is complete, it will be modified package.json:

1. Installed two npm packages

  • husky - Provides git hook functionality
  • lint-staged - Get the code in the git staging area for lint verification

2. Add a script

After installing the dependencies, execute prepare, execute the huskey command, and install the hook to ensure that each person who clones the project will initialize the husky hook to the local once the dependency is installed, so that everyone can perform lint verification before submitting git.

npx mrm@2 lint-stagedIt will also be executed after the execution is completed husky install, so it must be .gitexecuted in the directory where it is located, otherwise it will report an error and cannot find it .git.

husky installHook that will initialize husky:

  1. Modify the hooks directory by configuring .git/configin hooksPath(default .git/hooks)
  2. Create a folder under the project root directory .huskyto store custom hook execution files
"scripts": {
    
    
  ...
  "prepare": "husky install"
},

3. Added lint-staged configuration

You can modify and customize your own lint command on this basis:

"lint-staged": {
    
    
  // 执行 eslint 命令验证 js 文件
  "*.js": "eslint --cache --fix"
}

change into:

"lint-staged": {
    
    
  // 提交指定文件时执行 lint 脚本进行验证,如果有 fix 修复的内容会自动 git add
  "*.{js,jsx,vue,ts,tsx}": [
    "npm run lint"
  ]
}

Now when the command is executed git commit, lint will be performed to check the code in the temporary storage area first, and if any code does not meet the specification, it will not be executed git commit.

Note: The prerequisites to ensure that the team will execute the pre-commit hook are:

  1. Execute husky installinitialization .huskyfolder and configure git hooks directory address
  2. The project contains .husky/pre-committhe hook execution file, so make sure this file will be submitted to the git repository

Code specification verification during development and construction

In fact, ESLint is integrated into the compilation and construction process developed by vite to provide real-time ESLint verification.

Currently Vite does not provide ESLint-related plug-ins. You can develop a plug-in by yourself, or use someone else's.

Official website navigation Links - Awesome Vite lists some high-quality resources related to Vite. It is recommended to use gxmari007/vite-plugin-eslint

# 安装
npm install vite-plugin-eslint --save-dev

Load the plugin in the vite configuration file:

// vite.config.ts
import {
    
     defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import eslintPlugin from 'vite-plugin-eslint'

// https://vitejs.dev/config/
export default defineConfig({
    
    
  plugins: [
    vue(),
    eslintPlugin({
    
    
      /* 配置选项 */
      // 禁用 eslint 缓存
      cache: false
    })
  ]
})

cacheIt is recommended to turn off the caching function, because sometimes eslint may still read the results in the cache after repairing the code that fails the verification, and eslint will only verify the currently modified file, not all files, so not using the cache has little impact.

reboot npm run dev.

Now when compiling and building the code in the development phase, both the command line tool and the page will verify and prompt a failure message. And it will be verified when building the production environment ( npm run build).

Git Commit specification

Introduction to submission specifications

Reference: Commit message and Change log writing guide - Ruan Yifeng

Every time Git submits code, it must write a Commit message to explain the specific meaning of this submission.

git commit -m 'hello world'

Git itself does not require the format of the Commit message. If you write it casually, it will be very troublesome when you need to retrieve a commit record in the history through the Commit message in the history.

Unify the team's Git Commit message standard, which is convenient for subsequent code review, version release, and automatic log generation, etc. For details, please refer to Ruan Yifeng's article.

Currently the most popular is the Angular commit specification

Related tools:

  1. Compose tool ( commitizen ) - Helps compose commit messages that conform to the specification. (When you get used to the specification, you don't need this tool)
  2. Verification tool ( commitlint ) - configure git hooks, use the tool to verify whether the Commit message meets the specification before committing
  3. Log generation tool ( conventional-changelog ) - generate logs through git metadata, generally used by open source projects

Configure the commitlint validation tool

# windows 下安装 cli 和 常用规范
npm install --save-dev @commitlint/config-conventional @commitlint/cli
# 配置 commitlint 使用常用规范
# 建议手动创建 commitlint.config.js 文件并填充内容,命令可能创建的并不是 utf8 编码的文件,eslint 会报错 `Parsing error: Invalid character`
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js

# 安装和初始化 husky(上面配置 eslint 校验钩子时已经完成)
# npm i husky -D
# npx husky install

# 创建 commit-msg 钩子
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'

If ./husky/commit-msgthe file cannot be created using the command, it can be created manually and populated with the following:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx --no -- commitlint --edit $1

Execute the submit command test:

git add .
git commit -m 'commitlint 配置巴拉巴拉巴拉'

verification failed:

insert image description here

Specification message:

git commit -m 'chore: commitlint 配置巴拉巴拉巴拉'

Authentication succeeded:

insert image description here

TS environment description in Vite

Vite has already configured the TypeScript environment when creating the project, please refer to the official documentation for details .

A few points to note are listed below.

TypeScript type checking

Vite only performs .tstranslation of the file and does not perform any type checking.

let count: number = 100
count = 200
// 不会报错
count = 'hello'
  • devDuring the development phase, Vite assumes that the IDE is configured with type checking, and Vite itself is not responsible for this task.
  • buildvue-tsc --noEmitDuring the build phase, type checking will be performed through the command

Since the official vue-tsc (using esbuild to translate TypeScript to JavaScript) does not support the monitoring function, there is no good plug-in support for real-time type verification during the development stage.

type declaration

When Vite creates a project, it will generate a src/env.d.tstype declaration file (the previous version was two files shimes-vue.d.tsand vite-env.d.ts):

/// <reference types="vite/client" />

declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
  const component: DefineComponent<{}, {}, any>
  export default component
}

The first line is used to add the type declaration in the client code environment. To be on the safe side, it is recommended to follow the official instructions and add it vite/clientunder the tsconfigin compilerOptions.types:

{
    
    
  "compilerOptions": {
    
    
    "types": ["vite/client"]
  }
}

The following content is .vueto add a type declaration for the resource file, because TypeScript does not recognize .vuethe file by default, so when importing Vue components in a project using TypeScript, .vuethe suffix must be added.

TS support in Vue 3

The official Vue document "Using Vue with TypeScript" introduces how to integrate TypeScript into the project, recommended configuration, and some other content that Vite has completed when creating the project. Here are a few parts about the use of TS.

1. To use TypeScript in a single-file component, you need to <script>add lang="ts"the attribute to the tag. Added if using JSX lang="tsx".

2. In order for TypeScript to correctly deduce the types in component options, we need to defineComponent()define components through this global API.

import {
    
     defineComponent } from 'vue'

export default defineComponent({
    
    
  // 启用了类型推导
  props: {
    
    
    name: String,
    msg: {
    
     type: String, required: true }
  },
  data() {
    
    
    return {
    
    
      count: 1
    }
  },
  mounted() {
    
    
    this.name // 类型:string | undefined
    this.msg // 类型:string
    this.count // 类型:number
  }
})

3. When <script setup>the composition API is not combined, it also supports the derivation of the prop defineComponent()passed tosetup()

import {
    
     defineComponent } from 'vue'

export default defineComponent({
    
    
  // 启用了类型推导
  props: {
    
    
    message: String
  },
  // 不需要声明 props 参数的类型
  setup(props) {
    
    
    props.message // 类型:string | undefined
  }
})

4. Vue3 provides PropTypeauxiliary tools to mark more complex prop types

import {
    
     defineComponent, PropType } from 'vue'

interface Book {
    
    
  title: string
  author: string
  year: number
}

export default defineComponent({
    
    
  props: {
    
    
    book: {
    
    
      // 提供相对 `Object` 更确定的类型
      type: Object as PropType<Book>,
      required: true
    },
    // 也可以标记函数
    callback: Function as PropType<(id: number) => void>
  },
  mounted() {
    
    
    this.book.title // string
    this.book.year // number

    // TS Error: argument of type 'string' is not
    // assignable to parameter of type 'number'
    this.callback?.('123')
  }
})

5. The type of ref will be deduced according to the value at the time of initialization, and the type can also be manually passed in.

<template>
  <h1 ref="title">
    {
   
   { msg }}
  </h1>
  <HelloWorld
    ref="hellowWorld"
    msg="Hello Vue 3 + TypeScript + Vite"
  />
</template>

<script lang="ts">
import {
      
       defineComponent, onMounted, ref } from 'vue'
import HelloWorld from '../components/HelloWorld.vue'

export default defineComponent({
      
      
  components: {
      
       HelloWorld },
  setup () {
      
      
    // 自动推断
    const msg = ref('Hello H1')

    // 指定 HTML 元素类型
    const title = ref<HTMLHeadElement>()

    // 指定实例类型
    const hellowWorld = ref<InstanceType<typeof HelloWorld>>()

    onMounted(() => {
      
      
      console.log(title.value?.innerHTML)
      console.log(hellowWorld.value?.$props.msg)
    })

    return {
      
      
      msg,
      title,
      hellowWorld
    }
  }
})
</script>

6. Reactive is the same as ref, and the computed property will automatically infer the type.

7. The native DOM event processing function recommends adding type annotations to the event

<script setup lang="ts">
function handleChange(event: Event) {
      
      
  console.log((event.target as HTMLInputElement).value)
}
</script>

<template>
  <input type="text" @change="handleChange" />
</template>

<script setup>Syntax in Vue 3

Vue 3 supports three ways to write the logic of components:

Optional API

Optional API is the style adopted by Vue2

<template>
  <h1>{
   
   { msg }}</h1>
  <button
    type="button"
    @click="increment"
  >
    count is: {
   
   { count }}
  </button>
</template>

<script lang="ts">
import {
      
       defineComponent } from 'vue'

export default defineComponent({
      
      
  name: 'HelloWorld',
  props: {
      
      
    msg: {
      
      
      type: String,
      default: ''
    }
  },
  data () {
      
      
    return {
      
      
      count: 0
    }
  },
  mounted () {
      
      
    console.log('Mounted')
  },
  methods: {
      
      
    increment () {
      
      
      this.count++
    }
  }
})
</script>

Composite API

Composition APIs can encapsulate related logic together for extraction as separate modules

<script lang="ts">
import {
      
       defineComponent, ref } from 'vue'

export default defineComponent({
      
      
  name: 'HelloWorld',
  props: {
      
      
    msg: {
      
      
      type: String,
      default: ''
    }
  },
  setup () {
      
      
    const count = ref(0)
    const increment = () => {
      
      
      count.value++
    }

    return {
      
      
      count,
      increment
    }
  }
})
</script>

<script setup>

When the number of businesses written using the combined API increases, you will find that a large amount of code is concentrated in setup()the function, and some simple businesses need to write more code. For this reason, Vue 3 later introduced <script setup>the syntax, which is the syntactic sugar of the combined API.

<!--
  1. 可以认为 <script setup> 中的代码都会包裹在 setup() 函数中
  2. 并且只能使用组合式 API
  3. 不需要 export 导出对象
  4. 声明的变量和 props 会自动暴露出来,不需要 return
-->
<script setup lang="ts">
import {
      
       ref } from 'vue'

/* 定义 props */
const props = defineProps({
      
      
  msg: {
      
      
    type: String,
    default: ''
  }
})
console.log(props.msg)
// 模板中也可以通过 props.msg 访问
// 建议:变量取名 props,模板中使用 props 访问,便于阅读

/* 定义对外发布的自定义事件 */
const emit = defineEmits(['increment'])

/* 定义 data 和 methods */
const count = ref(0)
const increment = () => {
      
      
  count.value++

  // 对外发布事件
  emit('increment')
}

</script>

Imported components can be used directly, and the name of the component will be automatically inferred:

<script setup>
import MyComponent from './MyComponent.vue'
import Foo from './Bar.vue'
</script>

<template>
  <MyComponent />
  <Foo />
</template>

Supports top-level await:

<script setup>
const post = await fetch(`/api/post/1`).then((r) => r.json())
</script>

Can be <script>used with , <script setup>the content in will be converted into export default {}code and <script>merged with the code in .

<script>
// 代码会追加到 <script setup> 生成的 export default {} 代码前
runSideEffectOnce()

// 如果也导出了对象,则会和 <script setup> 生成的 export default {} 导出的对象合并在一起
export default {
      
      
  inheritAttrs: false,
  customOptions: {
      
      }
}
</script>

<script setup>
// ...
</script>

For more information, please refer to the official documentation.

compile macros in <script setup>

<script setup>The defineProps() and defineEmits() used in syntactic sugar , and defineExpose()and withDefaults()) do not need importto be used alone (and can only be <script setup>used in ).

They are actually defined as compiled macros , which can be understood as built-in APIs.

Single-file components <script setup>are automatically processed at compile time, replacing them with the corresponding code.

ESLint does not recognize them by default, and you can configure ESLint globalsto recognize them as global APIs (refer to the previous "compile macros and defineProps, defineEmits, no-undef rule warnings").

Configure Transform JSX and TSX

Official Documentation: Render Functions & JSX | Vue.js (vuejs.org)

Vue3 can provide JSX support through the official plugin @vue/babel-plugin-jsx , please refer to the documentation for detailed usage.

Projects created by Vite do not support JSX by default and need to be configured separately.

Vite officially provides @vitejs/plugin-vue-jsx plugin configuration JSX support, which is actually used internally @vue/babel-plugin-jsx

# 安装插件
npm i -D @vitejs/plugin-vue-jsx

Configure the plugin:

// vite.config.ts
import {
    
     defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import eslintPlugin from 'vite-plugin-eslint'
import vueJsx from '@vitejs/plugin-vue-jsx'

// https://vitejs.dev/config/
export default defineConfig({
    
    
  plugins: [
    vue(),
    eslintPlugin({
    
    
      /* 配置选项 */
      // 禁用 eslint 缓存
      cache: false
    }),
    vueJsx({
    
    
      /* 配置选项 */
    })
  ]
})

test:

<!-- src\components\HelloWorld.vue -->
<template>
  <comp />
</template>

<script setup lang="tsx">
const comp = <h1>Hello World</h1>
</script>

// src\components\Foo.tsx
// 选项式 API
import { defineComponent } from 'vue'

export default defineComponent({
  props: {
    msg: {
      type: String,
      required: true
    }
  },
  render () {
    return <h2>{this.msg}</h2>
  }
})

// src\components\Bar.tsx
// 组合式 API
import { defineComponent } from 'vue'

interface PropsType {
  msg: string
}

export default defineComponent({
  props: {
    msg: {
      type: String,
      required: true
    }
  },
  setup() {
    // 官方还没有未这种方式的 props 参数添加类型推断
    // 需要手动声明 TS 类型
    return (props: PropsType) => <h2>{props.msg}</h2>
  }
})

<!-- src\App.vue -->
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
import Foo from './components/Foo'
import Bar from './components/Bar'
</script>

<template>
  <HelloWorld />
  <Foo msg="Hello Foo" />
  <Bar msg="Hello Bar" />
</template>

Configure aliases in Vite

The project created by Vite does not have @an alias configured by default and needs to be configured manually.

// vite.config.ts
...
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
    
    
  ...
  resolve: {
    
    
    // https://vitejs.dev/config/#resolve-alias
    alias: [
      {
    
    
        find: '@',
        replacement: path.join(__dirname, 'src')
      }
    ]
  }
})

At this time, import path from 'path'an error may be reported:

insert image description here

This is because path is a node.js module that follows the CommonJS specification and is not exported by default export default. In fact, Babel automatically adds this type of module during conversion module.exports.default, and the IDE prompts that the type check does not recognize it.

allowSyntheticDefaultImportsAccording to the prompt, you can configure TypeScript trueto recognize this type of module import operation.

Note vite.config.tsthat the TypeScript configuration for is in tsconfig.node.json:

// tsconfig.node.json
{
    
    
  "compilerOptions": {
    
    
    "composite": true,
    "module": "esnext",
    "moduleResolution": "node",
    // 允许处理默认 import
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}

PS: It can also be @types/nodeidentified by installing .

The file can now be imported like this .vue:

// JS 中使用
import HelloWorld from '@/components/HelloWorld.vue'

// HTML 中使用
<img src="@/assets/logo.png">
    
// css 中使用
background: url(@/assets/logo.png);

But when importing .tsxthe file, TypeScript will report an error:

// 找不到模块“@/components/Foo”或其相应的类型声明。
import Foo from '@/components/Foo' // 省略了 .tsx 后缀

// 导入路径不能以“.tsx”扩展名结束。考虑改为导入“@/components/Bar.js”。
import Bar from '@/components/Bar.tsx'

So you also need to configure TypeScript's import mapping ( baseUrland paths):

// tsconfig.json
{
    
    
  "compilerOptions": {
    
    
    ...

    // https://www.typescriptlang.org/tsconfig#paths
    // 必须定义 baseUrl
    "baseUrl": ".",
    // paths 设置相对于 baseUrl 的一系列映射路径
    "paths": {
    
    
      "@/*": ["src/*"]
    }
  },
  ...
}

As for the problem of using .tsxexplicit extensions to report errors, it is sufficient not to use extensions.

.vueRegarding the issue that imported components must have suffixes in Vite

Vite does not ignore .vuethe extension by default. Although it can be ignored by configuration, it is not recommended to do so because **"will affect IDE and type support"**, refer to resolve.extensions

You Da also stated in Vite Issue #178 that the import .vuefile cannot omit the suffix, which is **"intentional design"**, and in the next major version, it will stop supporting Vue import without extension in Vue CLI.

insert image description here

So it is recommended to import Vue components with .vuethe extension.

Guess you like

Origin blog.csdn.net/u012961419/article/details/124299803