使用 vite 从零搭建一个 vue3 应用

lxf2023-12-16 15:40:01

之前写了一篇 使用Vite初始化Vue3.x+TS项目,其中大部分内容可以正常使用,部分内容有点过时,主要是

  • elsint 的安装方式
  • vuex 不在推荐使用,推荐使用 pinia

其他地方还是可以参考使用的, 下面内容主要是介绍最新 eslint 配置、 pinia 的基本使用 和 vue3 测试相关简介

创建项目

使用下面命令创建项目

npm create vite@latest 

选择 vue + typescript

✔ Project name: myapp
✔ Select a framework: › Vue
✔ Select a variant: › TypeScript

安装依赖

cd myapp
pnpm i

这里我使用的是 pnpm 安装依赖,也可以使用 npm,下面安装依赖使用的都是 pnpm

启动项目

npm run dev

配置 eslint

首先 vscode 需要安装 eslint 这个插件,这样在编辑中技能查看到 eslit 所报的错误

使用 eslint 来规范我们的代码

安装 eslint

npm init @eslint/config

选择下面

✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · vue
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser
✔ What format do you want your config file to be in? · JavaScript

这里我们没有选择 eslint 来格式化我们的代码,因为 eslint 无法格式化我们的 jsx 代码片段,使用 prettier 可以格式化 tsx 文件中的所有代码。

如果我们没有使用 jsx ,也可以使用 eslint来格式化我们的代码,建议使用 prettier 来格式化代码

安装 prettier

首先 vscode 需要安装 prettier 这个插件

安装 prettier 及 eslint 相关的插件

pnpm i prettier eslint-config-prettier  eslint-plugin-prettier -D

将 prettier 配置到 eslint 中

{
  extends: [
    ...
    'plugin:prettier/recommended',
  ]
}

编写 prettier 配置文件, 新建 .prettierrc.cjs 文件

module.exports = {
  trailingComma: 'es5',
  tabWidth: 2,
  semi: false,
  singleQuote: true,
}

配置 eslint

首先需要安装

pnpm i vue-eslint-parser -D

默认生成的 eslint 配置文件时 parser 和 parserOptions 这样的

{
...
  parser: "@typescript-eslint/parser",
  parserOptions: {
    ecmaVersion: "latest",
    sourceType: "module",
  },
},
...

修改为下面

{
...
  parser: "vue-eslint-parser",
  parserOptions: {
    ecmaVersion: "latest",
    sourceType: "module",
    parser: "@typescript-eslint/parser",
  },
},
...

环境变量

vite 在 4.2 之后支持在 html 中使用环境变量,参考 .env 文件

<h1>%VITE_APP_TITLE%</h1>

pinia

pinia 的使用与 vuex 非常类似,使用起来比 vuex 更加简单,对 typescript 也更加友好

pnpm i pinia

两种使用方式

方式一

与 vuex 使用十分类似,没有 mutation, action 中可以写异步和同步

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => {
    return { count: 0 }
  },
  actions: {
    increment() {
      this.count++
    },
  },
})

方式二

这种方式更加简单,与 组件的 setup 十分类似

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  function increment() {
    count.value++
  }

  return { count, increment }
})

在组件中使用也十分简单

<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
// 直接调用 increment 方法
counter.increment()
</script>
<template>
  <!-- 直接从 store 中访问 state -->
  <div>Current Count: {{ counter.count }}</div>
</template>

更详细的使用方式可以参考 pinia 文档 pinia.vuejs.org

测试相关

测试工具我们可以使用 jest 和 vitest,这里我使用 vitest,它的使用方式大部分与 jest 都十分类似,而且可以复用 vite 的配置

安装

pnpm i vitest -D

在 package.json 中配置测试使用的命令

{
  "scripts": {
    "test": "vitest",
    "coverage": "vitest run --coverage"
  }
}

在 vite.config.ts 文件添加 vitest 配置

// 这里是为了能够提示 vitest相关配置, vite defineConfig 无法识别 test 选项的
/// <reference types="vitest" /> 
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': path.join(__dirname, 'src'),
    },
    conditions: process.env.VITEST ? ['node'] : [],
  },
  test: {
    environment: 'jsdom',
    coverage: {
      provider: 'c8', // 或 istanbul
    },
  },

我们还需要安装 jsdom 和 c8

pnpm i jsdom @vitest/coverage-c8 -D

我们要测试 vue 组件还需要安装 Vue Test Utils

pnpm i @vue/test-utils -D

编写测试文件

我们要测试下面组件

<script setup lang="ts">
import { ref } from 'vue'
defineProps<{ title: string }>()
const count = ref(0)
</script>
<template>
  <h1>{{ title }}</h1>
  <div class="card">
    <div>
      count is <span class="count">{{ count }}</span>
    </div>
    <button type="button" @click="count++">add</button>
  </div>
</template>

需要测试的功能有

  • h1 内容根据 props 显示正确的标题
  • span 下的 cout 初始值是0 ,点击一次 +1

根据上面的内容编写测试

// __test__/helloWorld.spec.ts
import { shallowMount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import Helloworld from '@/components/HelloWorld.vue'
describe('HelloWorld', () => {
  const wrapper = shallowMount(Helloworld, {
    props: {
      title: 'Hello world',
    },
  })
  it('test title', () => {
    expect(wrapper.get('h1').text()).toEqual('Hello world')

    const wrapper1 = shallowMount(Helloworld, {
      props: {
        title: 'Vue',
      },
    })
    expect(wrapper1.get('h1').text()).toEqual('Vue')
  })
  it('test add', async () => {
    await wrapper.get('button').trigger('click')
    expect(wrapper.get('.count').text()).toEqual('1')
    await wrapper.get('button').trigger('click')
    expect(wrapper.get('.count').text()).toEqual('2')
  })
})

有关测试的更多内容可以参考文档

  • vitest 文档 vitest.dev
  • Vue Test Utils 文档 test-utils.vuejs.org

其他相关

其他相关可以参考之前我写的文章 使用Vite初始化Vue3.x+TS项目

本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!