关于前端:Vite开发环境搭建

50次阅读

共计 11995 个字符,预计需要花费 30 分钟才能阅读完成。

Vite当初堪称是煊赫一时,可能很多小伙伴还没有应用过 Vite,然而我置信大多数小伙伴曾经在应用Vite 了,因为是太香了有没有。可能在应用过程中很多货色 Vite 不是配置好的,并不像 Vue-cli 配置的很周全,那么明天就说一下如何配置开发环境,其中次要波及到的点有一下几个:

  • TypeScript
  • Vuex
  • Vue-Router
  • E2E

    • Cypress
  • Test unit

    • Jest
    • vtu
  • Eslint + Perttite
  • verify git commit message
  • CI
  • alias

Vite 初始化我的项目

在开始之前首先要先应用 Vite 创立我的项目,如果小伙伴曾经对 Vite 曾经有了肯定的理解,那么能够跳过。依据 Vite 官网介绍能够应用 npmyarn来创立我的项目。

应用 NPM:

npm init vite@latest

应用 Yarn:

yarn create vite

应用 PNPM:

pnpx create-vite

输出完命令之后而后依照提醒操作即可,因为在我的项目要反对 TypeScript 所以我这里就抉择的是 vue-ts。创立好之后Vite 会帮忙咱们把我的项目给创立好,能够发现 Vite 所创立好的我的项目其实与应用 Vue-cli 所创立的我的项目目录构造其实是差不多的,这里也就不多赘述了。

集成 Vue-Router

Vue-Router是大多数我的项目中比不可少的工具之一了,Vue-Router能够让构建单页面利用变得更加的容易。蕴含的性能有:

  • 嵌套的路由 / 视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查问、通配符
  • 基于 Vue.js 过渡零碎的视图过渡成果
  • 细粒度的导航管制
  • 带有主动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中主动降级
  • 自定义的滚动条行为

以上截取自 Vue-router 官网

装置 Vue-Router:

应用 NPM:

npm install vue-router@next --save

应用 Yarn:

yarn add vue-router@next --save

装置实现之后在 src 目录下创立文件夹 router/index.ts,创立实现之后须要在Vue-Router 中对 Vue-Router 进行初始化配置。咱们临时把初始化的工作搁置一下,先须要创立 pages 文件夹,把须要展现的页面创立实现。

创立实现之后,接下来就是欠缺 router/index.ts 中文件的初始化工作了:

import {createRouter, createWebHashHistory} from "vue-router";

const router = createRouter({history: createWebHashHistory(),
  routes: [
    {
      path: "/home",
      name: "Home",
      alias: "/",
      component: () => import("../pages/Home.vue")
    },
    {
      path: "/about",
      name: "About",
      component: () => import("../pages/About.vue")
    }
  ]
})

export default router;

接下来在 main.ts 文件中集成Vue-Router

import {createApp} from 'vue';
import App from './App.vue';

import router from "./router";

const app = createApp(App);
app.use(router);
app.mount('#app');

测试一下,这里批改一下 App.vue 的代码,测试一下咱们的路由是否曾经能够失常应用了。

<template>
  <router-link to="/home">Home</router-link>
  <router-link to="/about">About</router-link>
  <router-view></router-view>
</template>

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

export default defineComponent({name: 'App'})
</script>

接下来启动服务就能够看到所配置的页面了,阐明配置的路由曾经失效了。Good Job,真的很不错~~~

集成 Vuex

VuexVue 所反对的状态管理工具,在在理论利用过程中也有很大的作用,当多个组件之间的数据流转变得十分艰难,因而须要集中的对状态进行治理,Vuex的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地失去高效更新。

装置 Vuex:

应用 NPM:

npm install vuex@next --save

应用 Yarn:

yarn add vuex@next --save

装置实现之后,首先增加 store/index.ts 来初始化 Vuex。须要留神的是,如下示例应用了Vuex 命名空间。可能在理论我的项目中应用命名空间相对来说还是比拟广泛的,防止进行状态治理的时候导致变量净化。

import {createStore} from "vuex";

const store = createStore({
  modules: {
    home: {
      namespaced: true,
      state: {count: 1},
      mutations: {add(state){state.count++;}
      }
    }
  }
})

export default store;

集成到 Vue 中:

import {createApp} from 'vue';
import App from './App.vue';

import router from "./router";
import store from "./store";

const app = createApp(App);
app.use(router);
app.use(store);
app.mount('#app');

当初 Vuex 就曾经被集成到 Vue 中了为了保障集成的 Vuex 是无效地,那么须要对此进行测试:

pages/Home.vue

<template>
  <h1>Home</h1>
  <h2>{{count}}</h2>
  <button @click="handleClick">click</button>
</template>

<script lang="ts">
import {defineComponent, computed} from 'vue';
import {useStore} from 'vuex';

export default defineComponent({setup () {const store = useStore();
    const count = computed(() => store.state.home.count);
    const handleClick = () => {store.commit('home/add');
    };
    return {
      handleClick,
      count
    };
  }
})
</script>

当点击按钮的时候,就能够发现 count 值也随着点击每次递增,那么 store 是能够失常应用。Good Job,真的很不错~~~

集成单元测试

在开发过程中为了保障程序的健壮性,就须要对程序进行单元测试,所以在我的项目初始化的时候,同样就须要为单元测试进行配置。配置中应用的工具是jest,如果对于单元测试不太理解的,请自行百度学习,脱离本文重点,不多赘述。

装置相干依赖:

应用 NPM:

npm install jest -D                  # 单元测试工具 ^26.6.3
npm install @types/jest -D           # 单元测试类型文件
npm install babel-jest -D            # 反对 es6 模块 ^26.6.3
npm install @babel/preset-env -D     # 反对 es6 模块 ^7.14.7
npm install vue-jest@next -D         # 反对 Vue 文件 ^5.0.0-alpha.8
npm install ts-jest -D               # 反对 Ts      ^26.5.1
npm install @vue/test-utils@next     # Vue 官网测试工具 2.0.0-rc.6
npm install @vue/test-utils@next -D  # 2.0.0-rc.6
npm install @babel/preset-typescript # 反对 Ts ^7.12.17

应用 Yarn:

yarn add jest --dev                  # 单元测试工具 ^26.6.3
yarn add @types/jest --dev           # 单元测试类型文件
yarn add babel-jest --dev            # 反对 es6 模块 ^26.6.3
yarn add @babel/preset-env --dev     # 反对 es6 模块 ^7.14.7
yarn add vue-jest@next --dev         # 反对 Vue 文件 ^5.0.0-alpha.8
yarn add ts-jest --dev               # 反对 Ts      ^26.5.1
yarn add @vue/test-utils@next        # Vue 官网测试工具 2.0.0-rc.6
yarn add @babel/preset-typescript    # 反对 Ts ^7.12.17

依赖装置实现之后,在 src 目录下创立 tests 文件夹,这个文件夹用来寄存对于测试相干的文件,因为咱们岂但有单元测试还有 E2E 测试,所以要对两者进行辨别。

因为在装置配置的时候可能会导致版本不兼容,导致的报错,所以在配置的时候添肯定要留神版本号,在下面曾经正文了版本号,须要留神一下。装置完所依赖之后,接下来就须要对单元测试进行配置。

在根目录创立 jest.config.jsJest进行初始化的根本配置:

module.exports = {
  transform: {  //  babel 预设
    "^.+\\.vue$": "vue-jest",       //  反对导入 Vue 文件
    "^.+\\.jsx?$": "babel-jest",    //  反对 import 语法
    '^.+\\.tsx?$': 'ts-jest'        //  反对 ts
  }
};

批改tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "types": ["vite/client", "jest"]    //  指定类型为 jest
  },
  "include": [
    "src/**/*.ts", 
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue", 
    "tests"     // 指定单元测试门路
  ]
}

因为 Node 无奈运行 TypeScript 这里须要应用 babelTypeScript进行编译,要配置 babel 的相干配置,在根目录创立babel.config.js


module.exports = {
  transform: {
    "^.+\\.vue$": "vue-jest",
    "^.+\\.jsx?$": "babel-jest",
    '^.+\\.tsx?$': 'ts-jest'
  },
  testMatch: [  //  匹配单元测试规定
    "**/?(*.)+(test).[jt]s?(x)"
  ]
};

下面根本曾经对单元测试的配置实现了,接下来就是测试是否可能失常运行单元测试,在根目录上面创立 tests/unit 等文件夹(文件):

index.test.ts

import {mount} from "@vue/test-utils";
import demo from "./demo";
import Foo from "../../src/components/Foo.vue";

test("1+1=2", () => {console.log(demo);
  console.log(mount(Foo));
  expect(1+1).toBe(2);
});

demo.ts

export default {a: 1};

之后就是运行单元测试,在 package.json 中增加命令:

{
  "scripts": {"test:unit": "jest"}
}

运行一下就能够看到输入得后果,那么就代表咱们的单元测试能够失常运行了,Good Job,真的很不错~~~

集成 E2E 测试

可能很多小伙伴对于 E2E 测试不是特地的相熟,E2E即端对端测试,属于黑盒测试,通过编写测试用例,自动化模仿用户操作,确保组件间通信失常,程序流数据传递如预期。

既然对 E2E 有了肯定的理解之后呢,那么就须要装置 E2E 测试相干的模块的依赖,E2E测试应用是 cypress 依赖,首次装置的时候可能会慢,要急躁期待:

应用 NPM:

yarn add cypress -D             # e2e 测试工具

应用 Yarn:

yarn add cypress --dev          # e2e 测试工具

装置依赖实现之后须要对 cypress 进行初始化,这个时候咱们须要在 package.json 中增加命令:

{
  "scripts": {"test:e2e": "cypress open"}
}

执行实现之后呢会在根目录下创立一个 cypress 文件夹,该文件夹外面蕴含了很多目录相干的文件,临时先不论,之后在 tests 文件夹中增加 e2e 文件夹,把 cypress 所有内容剪切到 tests/e2e 中。

实现上述操作之后咧?cypress在运行的时候会默认的去 cypress 文件中去找相干依赖,然而当初曾经把 cypress 中的文件曾经挪走了,那么咱们就须要对 cypress 进行配置,批改 cypress 的根底门路,并指向到 tests/e2e 文件即可。

在根目录创立 cypress.json 文件:

{
  "pluginsFile": "tests/e2e/plugins/index.ts",
  "video": false    //  关掉视频录制默认行为
}

仔细的小伙伴可能曾经发现了,下面所以援用的文件是以 .ts 结尾的,然而在对应目录上面是 .js 文件,这是为什么?因为咱们的我的项目是以 TypeScript 为根底的我的项目,所以咱们 E2E 测试也应该应用 TypeScript,这个时候咱们应该把E2E 文件夹下所有 .js 文件改为 .ts(须要留神的是,把integration 改成specs,并删除外面所有测试用例)。

更改 plugin 文件夹上面的index.ts

module.exports = (on, config) => {return Object.assign({}, config, {
    fixturesFolder: 'tests/e2e/fixtures',
    integrationFolder: 'tests/e2e/specs',
    screenshotsFolder: 'tests/e2e/screenshots',
    videosFolder: 'tests/e2e/videos',
    supportFile: 'tests/e2e/support/index.ts'
  });
};

针对 cypress 的单元测试曾经实现了,然而方才曾经删除了测试用例,接下来就写一下测试用例,在 tests/e2e/specs 文件夹上面创立:

first.specs.ts

describe("First", () => {it("before", () => {cy.visit("http://localhost:3000/");
    cy.get("button").click();});

});

须要留神的是,因为 cypress 是须要在我的项目启动的时候进行测试的,所以咱们须要把本地的服务运行起来才能够。测试用例变现实现之后,就能够运行了。在弹出页面中会看到所有用例的文件,点击对应文件,就会在浏览器中关上了,浏览器左侧则是对应测试的步骤了。

通过上述的配置 E2E 的配置曾经根本实现了,因为两个测试全处于 tests 中两个测试会相互影响么?

插曲

既然 E2E 测试和单元测试都曾经实现了,那么别离运行一下单元测试和 E2E 测试,当运行单元测试后的时候,就会抛出一个谬误。

  ● Test suite failed to run

    tests/unit/index.spec.ts:8:15 - error TS2339:
        Property 'toBe' does not exist on type 'Assertion'.

    8   expect(1+1).toBe(2);
                    ~~~~

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        3.234 s
Ran all test suites.
error Command failed with exit code 1.

很显著,咱们的单元测试收到 E2E 测试的影响,运行失败了,能够依据文件提醒找到对应的地位,因为两个测试库的 expect 抵触了,所以导致单元测试下 expect 返回的对象内容不在是原来单元测试 expect 了。

既然呈现问题了就须要解决问题 ing,在下面配置单元测试的时候,为了让单元测试反对 TypeScripttsconfig.json中增加了测试的门路,咱们如果只指向到单元测试外面这个问题是不是就解决了,然而如果这样的话,cypress无奈再反对 TypeScript 了,其实咱们能够在 E2E 再创立一个 tsconfig.json 这个文件只利用于E2E

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "types": ["vite/client", "jest"]
  },
  "include": [
    "src/**/*.ts", 
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue", 
    "tests/unit"     // 指定单元测试门路
  ]
}

tests/e2e/tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"]
  }
}

之后再运行 yarn test:unit 的时候就会发现不会报错了,那么通过这次更改 e2e 是否受到影响了呢?运行 yarn test:e2e 显然并没有产生任何谬误,也能够失常运行的。Good Job,真的很不错~~~

当运行 yarn test:e2e 的时候,总会弹出一个窗口,然而当我的项目部署走 CI 的时候,是没有方法进行点击的,这个时候应该怎么办呢?其实 cypress 是有方法在终端执行的,通过 npx cypress run 这个命令去在终端运行 E2E 测试。

批改package.json:

{
  "scripts": {
    "test:unit": "jest",
    "test:e2e": "cypress open",
    "test": "yarn test:unit && npx cypress run"
  }
}

之后运行 yarn test 就能够先运行单元测试,后运行 E2E 测试了。

集成 Git 提交验证

在开发我的项目的时候可能并不是一个人进行开发的,可能会由多集体进行开发,那么作为规范的自动化来讲,对于 Git 提交的时候,要有一些固定显著的格局来标准咱们的我的项目开发人员,这个时候就须要应用某些工具进行束缚。

装置相干依赖:

应用 NPM:

npm install yorkie -D
npm install chalk -D

应用 Yarn:

yarn add yorkie --dev
yarn add chalk --dev

装置完依赖之后,对 yorkie 之后须要对其进行相干的配置,在 package.json 中增加字段:

{
    "gitHooks": {"commit-msg": "node scripts/commitMessage.js"}
}

在下面的配置中,运行了一个 js 文件,那么这个 js 文件中则是对提交内容的校验。

scripts/commitMessage.js

const chalk = require('chalk')
const msgPath = process.env.GIT_PARAMS
const msg = require('fs').readFileSync(msgPath, 'utf-8').trim()

const commitRE = /^(revert:)?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release)(\(.+\))?(.{1,10})?: .{1,50}/
const mergeRe = /^(Merge pull request|Merge branch)/

if (!commitRE.test(msg)) {if (!mergeRe.test(msg)) {console.log(msg)
    console.error(`  ${chalk.bgRed.white('ERROR')} ${chalk.red(`invalid commit message format.`,)}\n\n` +
        chalk.red(`  Proper commit message format is required for automated changelog generation. Examples:\n\n`,) +
        `    ${chalk.green(`feat(compiler): add 'comments' option`)}\n` +
        `    ${chalk.green(`fix(v-model): handle events on blur (close #28)`,
        )}\n\n` +
        chalk.red(`  See https://github.com/vuejs/vue-next/blob/master/.github/commit-convention.md for more details.\n`,),
    )
    process.exit(1)
  }
}

集成 Eslint

Eslint对于团队开发来说是一个很不错的工具,能够依据 Eslint 的配置给束缚开发者代码的格调,以及书写格局。

装置相干依赖:

应用 NPM:

npm install eslint -D
npm install eslint-plugin-vue -D
npm install @vue/eslint-config-typescript -D
npm install @typescript-eslint/parser -D
npm install @typescript-eslint/eslint-plugin -D
npm install typescript -D
npm install prettier -D
npm install eslint-plugin-prettier -D
npm install @vue/eslint-config-prettier -D

应用 Yarn:

yarn add eslint --dev
yarn add eslint-plugin-vue --dev
yarn add @vue/eslint-config-typescript --dev
yarn add @typescript-eslint/parser --dev
yarn add @typescript-eslint/eslint-plugin --dev
yarn add typescript --dev
yarn add prettier --dev
yarn add eslint-plugin-prettier --dev
yarn add @vue/eslint-config-prettier --dev

配置装置实现之后呢,还须要对 eslint 进行配置,在根目录下创立.eslintrc:

.eslintrc

{
  "root": true,
  "env": {
    "browser": true,
    "node": true,
    "es2021": true
  },
  "extends": [
    "plugin:vue/vue3-recommended",
    "eslint:recommended",
    "@vue/typescript/recommended"
  ],
  "parserOptions": {"ecmaVersion": 2021}
}

配置项曾经增加好了,如何去运行曾经配置好的 eslint 呢?接下来就须要在 package.json 中增加命令:

{"lint": "eslint --ext src/**/*.{ts,vue} --no-error-on-unmatched-pattern"
}

接下来运行一下 yarn lint 就能够了,能够通过 eslint 实现格局的校验了,当初的问题是什么,在执行 yarn lint 的时候把所有的文件全副都校验了一次,这个可不是咱们所心愿的,如果有很多文件的话,那么速度将会很慢,那么有没有方法,只在 git 提交的时候对批改的文件进行 eslint 校验呢?

装置相干依赖:

应用 NPM:

npm install lint-staged -D

应用 Yarn:

yarn add lint-staged --dev

批改package.json

{
  "gitHooks": {
    "commit-msg": "node scripts/commitMessage.js",
    "pre-commit": "lint-staged"
  },
  "lint-staged": {"*.{ts,vue}": "eslint --fix"
  },
  "scripts": {
    "test:unit": "jest",
    "test:e2e": "cypress open",
    "test": "yarn test:unit && npx cypress run",
    "lint": "npx prettier -w -u . && eslint --ext .ts,.vue src/** --no-error-on-unmatched-pattern",
    "bea": "npx prettier -w -u ."   //  丑化代码
  },
}

配置 alias

在应用 cli 的时候总是应用 @ 去引入某些文件,因为 Vite 没有提供相似的配置,所以咱们须要手动的对其进行一些相干的配置,能力持续应用 @ 符号去快捷的引入文件。

批改vite.config.ts:

import {defineConfig} from 'vite';
import vue from '@vitejs/plugin-vue';
import {join} from "path";

// https://vitejs.dev/config/
export default defineConfig({plugins: [vue()],
  resolve: {
    alias: [
      {
        find: '@',
        replacement: '/src',
      },
      {find: 'views', replacement: '/src/views'},
      {find: 'components', replacement: '/src/components'},
    ]
  }
});

批改tsconfig.json:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "types": ["vite/client", "jest"],
    "baseUrl": ".",
    "paths": {"@/*": ["src/*"]
    } 
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/unit"
  ]
}

为了保障在单元测试中也能够应用 @ 引入 src 上面的文件须要对 jest.config.js 配置进行批改:

批改jest.config.js

module.exports = {
  transform: {
    '^.+\\.vue$': 'vue-jest',
    '^.+\\.jsx?$': 'babel-jest',
    '^.+\\.tsx?$': 'ts-jest',
  },
  testMatch: ['**/?(*.)+(test).[jt]s?(x)'],
  moduleNameMapper: {"@/(.*)$": "<rootDir>/src/$1" 
  }
};

结尾

应用 Vite 对我的项目初始化还是存在很多坑的,比方在配置单元测试的时候的版本兼容,还有配置别名的时候须要留神多个文件之间的协调。

咱们做了这么多的对立配置无非是为了可能让我的项目在开发过程中更加的标准,可能达成对立的成果,也能让咱们的程序更加的强壮。反动尚未胜利,同志仍需致力。

可能文章中一些见解存在一些问题,欢送大家在评论区指出,大家一起学习,一起提高。如果文章对你有帮忙的话,请点击赞吧~

正文完
 0