Vite
is very hot now, maybe many friends have not used Vite
, but I believe most of the friends are already using Vite
, because it is too fragrant. There may be many things that Vite
is not configured in the process of use. It is not as Vue-cli
. So today I will talk about how to configure the development environment. The main points involved are as follows:
- TypeScript
- Vuex
- Vue-Router
E2E
- Cypress
Test unit
- Jest
- vtu
- Eslint + Perttite
- verify git commit message
- CI
- alias
Vite initialization project
Before starting, you must first use Vite
create a project. If you Vite
, you can skip it. According to the Vite
official website, you can use npm
or yarn
to create a project.
Use NPM:
npm init vite@latest
Use Yarn:
yarn create vite
Use PNPM:
pnpx create-vite
After entering the command, follow the prompts. Because the project needs to support TypeScript
I chose vue-ts
here. Once you've created Vite
will help us to create a good project can be found Vite
create a good project and actually use Vue-cli
created project directory structure in fact is about the same, not much to go into details here.
Integrated Vue-Router
Vue-Router
is one of the indispensable tools in most projects. Vue-Router
can make it easier to build single-page applications. The functions included are:
- Nested routing/view table
- Modular, component-based routing configuration
- Routing parameters, queries, wildcards
- View transition effect based on Vue.js transition system
- Fine-grained navigation control
- Link with automatically activated CSS class
- HTML5 history mode or hash mode, automatically downgraded in IE9
- Custom scroll bar behavior
The above is intercepted from Vue-router official website
Install Vue-Router:
Use NPM:
npm install vue-router@next --save
Use Yarn:
yarn add vue-router@next --save
After the installation is complete, create a folder router/index.ts
src
directory. After the creation is complete, you need to initialize Vue-Router
in Vue-Router
We temporarily put the initialization work aside, first need to create the pages
folder, and create the page that needs to be displayed.
After the creation is complete, the next step is to complete the initialization of the file in 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;
Next, integrate Vue-Router
in the main.ts
file:
import { createApp } from 'vue';
import App from './App.vue';
import router from "./router";
const app = createApp(App);
app.use(router);
app.mount('#app');
Test it. Here we modify App.vue
to test whether our routing can be used normally.
<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>
After starting the service, you can see the configured page, indicating that the configured route has taken effect. Good Job
, really good~~~
Integrate Vuex
Vuex
is Vue
. It also plays a great role in the actual application process. When the data flow between multiple components becomes very difficult, it is necessary to centrally manage the state. The state storage of Vuex
Responsive. When the Vue
component reads the status store
store
changes, the corresponding component will be updated accordingly.
Install Vuex:
Use NPM:
npm install vuex@next --save
Use Yarn:
yarn add vuex@next --save
After the installation is complete, first add store/index.ts
to initialize Vuex
. It should be noted that the following example uses the Vuex
namespace. It may be relatively common to use namespaces in actual projects to avoid variable pollution during state management.
import { createStore } from "vuex";
const store = createStore({
modules: {
home: {
namespaced: true,
state: {
count: 1
},
mutations: {
add(state){
state.count++;
}
}
}
}
})
export default store;
Integrated into 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');
Now Vuex
has been integrated into Vue
. In order to ensure that the integrated Vuex
is effective, you need to test this:
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>
When you click the button, you can find that the count
also increases with each click, so store
can be used normally. Good Job
, really good~~~
Integrated unit test
In order to ensure the robustness of the program during the development process, the program needs to be unit tested, so when the project is initialized, it is also necessary to configure the unit test. The tool used in the configuration is jest
. If you don't know much about unit testing, please learn from Baidu on your own and get out of the focus of this article, so I won't go into details.
Installation related dependencies:
Use 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
Use 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
After the dependency installation is complete, create a tests
src
directory. This folder is used to store test-related files. Because we not only have unit tests but also E2E
tests, we need to distinguish between the two.
Because the installation and configuration may cause version incompatibility and cause an error, you must pay attention to the version number when you configure it. The version number has been annotated above, so you need to pay attention. After installing the dependencies, the next step is to configure the unit test.
Create the basic configuration of Jest
jest.config.js
in the root directory:
module.exports = {
transform: { // babel预设
"^.+\\.vue$": "vue-jest", // 支持导入Vue文件
"^.+\\.jsx?$": "babel-jest", // 支持import语法
'^.+\\.tsx?$': 'ts-jest' // 支持ts
}
};
Modify 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" // 指定单元测试路径
]
}
Because Node
not run TypeScript
here need to use babel
to TypeScript
compile, to configure babel
related configuration, created in the root directory babel.config.js
:
module.exports = {
transform: {
"^.+\\.vue$": "vue-jest",
"^.+\\.jsx?$": "babel-jest",
'^.+\\.tsx?$': 'ts-jest'
},
testMatch: [ // 匹配单元测试规则
"**/?(*.)+(test).[jt]s?(x)"
]
};
The configuration of the unit test has been basically completed above. The next step is to test whether the unit test can be run normally. Create folders (files) such as 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
};
After that is to run the unit test, add the command package.json
{
"scripts": {
"test:unit": "jest"
}
}
Run it to see the output result, then it means that our unit test can run normally, Good Job
, really good~~~
Integrated E2E testing
Maybe many friends are not particularly familiar with the E2E
E2E
is an end-to-end test, which is a black box test. By writing test cases, it automatically simulates user operations to ensure normal communication between components and program flow data transfer as expected.
Now that E2E
have a certain understanding of 060f53f2198c87, you need to install E2E
test the related modules. The E2E
test uses the cypress
dependency. The first installation may be slow, so be patient:
Use NPM:
yarn add cypress -D # e2e测试工具
Use Yarn:
yarn add cypress --dev # e2e测试工具
After the installation dependencies are completed, cypress
needs to be initialized. At this time, we need to add commands to package.json
{
"scripts": {
"test:e2e": "cypress open"
}
}
After the execution is complete, a cypress
folder will be created in the root directory. This folder contains many directory-related files. tests
. Then add the e2e
folder to the cypress
folder, and cut all the contents of tests/e2e
in.
After completing the above operations? cypress
at run time will default to cypress
file to find its dependencies, but now the cypress
the file has been moved away, then we need to cypress
to configure, modify cypress
base path and point to tests/e2e
file That's it.
cypress.json
file in the root directory:
{
"pluginsFile": "tests/e2e/plugins/index.ts",
"video": false // 关掉视频录制默认行为
}
.ts
may have discovered that the file cited above ends with 060f53f2198e7d, but under the corresponding directory is the .js
file. Why? Because our project is based on TypeScript
based projects, so we E2E
test should also use TypeScript
, this time we should put E2E
folder all .js
file instead .ts
(It should be noted that the integration
into specs
, and delete All test cases inside).
Change plugin
under the index.ts
folder:
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'
});
};
The unit test for cypress
has been completed, but the test case has been deleted just now. Next, write the test case and create it tests/e2e/specs
first.specs.ts
describe("First ", () => {
it("before", () => {
cy.visit("http://localhost:3000/");
cy.get("button").click();
});
});
It should be noted that because cypress
needs to be tested when the project is started, we need to run the local service. After the test case is realized, it can be run. In the pop-up page, you will see the files of all the use cases. Click the corresponding file and it will be opened in the browser. The left side of the browser shows the corresponding test steps.
After the above configuration, the configuration of E2E
has been basically completed, because the two tests are all in tests
, will the two tests affect each other?
episode
Now that both the E2E
test and the unit test have been completed, run the unit test and the E2E
test respectively. After running the unit test, an error will be thrown.
● 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.
Obviously, our unit test E2E
test, and the operation failed. You can find the corresponding location according to the file prompt. Because the expect
expect
under the unit test is no longer the original one. Unit test expect
too.
Time since the problem emerged on the need to solve the problem ing, hives tested in the above, in order to make unit testing support TypeScript
in tsconfig.json
add a path test, if we just point to unit test inside the problem is not solved, but If so, cypress
can no longer support TypeScript
, in fact, we can E2E
then create a tsconfig.json
this document applies only to 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"]
}
}
Later, when you run yarn test:unit
, you will find that no error will be reported. So after this change, is e2e
affected? Obviously no error occurred when running yarn test:e2e
, and it can run normally. Good Job
, really good~~~
When running yarn test:e2e
, a window will always pop up, but when the project is deployed to CI
, there is no way to click. What should I do at this time? In fact, cypress
be executed on the terminal. Use the npx cypress run
command to run the E2E
test on the terminal.
Modify package.json
:
{
"scripts": {
"test:unit": "jest",
"test:e2e": "cypress open",
"test": "yarn test:unit && npx cypress run"
}
}
Then run yarn test
to run the unit test first, and then run the E2E
test.
Integrated Git submission verification
When developing the project, it may not be developed by one person, but by multiple people. As a standard automation, Git
, there must be some fixed and significant formats to standardize our project developers. , This time you need to use certain tools to constrain.
Installation related dependencies:
Use NPM:
npm install yorkie -D
npm install chalk -D
Use Yarn:
yarn add yorkie --dev
yarn add chalk --dev
After installing dependence on yorkie
following configuration needs to be related, in package.json
add field:
{
"gitHooks": {
"commit-msg": "node scripts/commitMessage.js"
}
}
In the above configuration, a js
file is run, then the js
file is a verification of the submitted content.
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)
}
}
Integrated Eslint
Eslint
is a very good tool for team development. It can be configured to constrain the developer's code style and writing format Eslint
Installation related dependencies:
Use 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
Use 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
After the configuration and installation are complete, you need to eslint
.eslintrc
in the root directory:
.eslintrc
{
"root": true,
"env": {
"browser": true,
"node": true,
"es2021": true
},
"extends": [
"plugin:vue/vue3-recommended",
"eslint:recommended",
"@vue/typescript/recommended"
],
"parserOptions": {
"ecmaVersion": 2021
}
}
The configuration items have been added, how to run the configured eslint
? Next, you need to add a command package.json
{
"lint": "eslint --ext src/**/*.{ts,vue} --no-error-on-unmatched-pattern"
}
Then try running yarn lint
on it, you can eslint
complete check of the format, the question now is what, in the implementation of yarn lint
time to check all the documents all the time, this is not what we want, if many of the documents, then the speed will be very slow, so there is no way, only git
be of modified files when submitted eslint
check it?
Installation related dependencies:
Use NPM:
npm install lint-staged -D
Use Yarn:
yarn add lint-staged --dev
Modify 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 ." // 美化代码
},
}
Configure alias
When using cli
, always use @
to import some files. Because Vite
does not provide similar configuration, we need to manually configure some related configurations to continue to use the @
symbol to quickly import files.
Modify 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' },
]
}
});
Modify 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"
]
}
In order to ensure the unit can also be used in the test @
introduced src
following documents for jest.config.js
modification to the configuration:
Modify jest.config.js
:
module.exports = {
transform: {
'^.+\\.vue$': 'vue-jest',
'^.+\\.jsx?$': 'babel-jest',
'^.+\\.tsx?$': 'ts-jest',
},
testMatch: ['**/?(*.)+(test).[jt]s?(x)'],
moduleNameMapper: {
"@/(.*)$": "<rootDir>/src/$1"
}
};
end
Vite
when using 060f53f21b2420 to initialize the project. For example, when configuring unit testing, the version is compatible, and when configuring aliases, you need to pay attention to the coordination between multiple files.
We have done so many unified configurations to make the project more standardized in the development process, to achieve a unified effect, and to make our programs more robust. The revolution has not yet succeeded, comrades still need to work hard.
There may be some problems with some of the insights in the article. You are welcome to point out in the comment area. Let's learn and make progress together. If the article is helpful to you, please click like it~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。