useViteInitialize the project

Why use Vite

  • Vite is a lighter, faster Web development application for modern browsers
  • Implement Vite project dependencies based on the ECMAScript standard Native Module System (ESM)
  • Vite only compiles the corresponding module when the file is requested
  • .

NPM is used here to initialize the project

 npm init vite@latest
Copy the code

Then follow the prompts to select templates, ESLint standards, etc

configurationeslint

npm install eslint --save-dev
# Set esLint rules and produce configuration files
./node_modules/.bin/eslint --init
Copy the code

By default, the generated vUE configuration file is vue 2.x rule. You need to manually change the configuration file to Vue3 rule

module.exports = {
    ...
    extends: [
        'plugin:vue/vue3-strongly-recommended'.'standard'],}Copy the code

If there is an ESLint error, such as defineProps, you need to add it to the ESLint configuration file

{
  globals: {
    defineProps: 'readonly'.defineEmits: 'readonly'.defineExpose: 'readonly'.withDefaults: 'readonly'}}Copy the code

Vscode editor configuration

  • The installationVolarThis plugin
  • If you have installed Vue2 beforeVeturYou need to disable the plugin and restart the editor
  • Install ESLint and set ESLint to the default way to format code

Configure git commit hook

Install the lint – staged

npx mrm@2 lint-staged
Copy the code

Configuration lint – staged

{
  "lint-staged": {
    "*.{js,jsx,ts,tsx,vue}": [
      "npm run lint"."git add"]}}Copy the code

Code submission specification

Using commitlint

# Install commitlint cli and conventional config
npm install --save-dev @commitlint/{config-conventional,cli}
# For Windows:
npm install --save-dev @commitlint/config-conventional @commitlint/cli

# generate commitlint. Config. Js
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
Copy the code

Use the commit-msg hook

npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
Copy the code

Generate the change log

If the following error occurs, set the encoding of commitlint.config.js to UTF-8

Commitlint.config. js:1 � SyntaxError: Invalid or unexpected TokenCopy the code

Relevant information reference www.ruanyifeng.com/blog/2016/0…

TS support in Vue3

The document address v3.cn.vuejs.org/guide/types…

Script setup in Vue3

Script Setup can make our development code even better. With this feature, it is much easier to develop Vue projects with less boilerplate code

The document address

  • V3.cn.vuejs.org/api/sfc-scr…
  • Github.com/vuejs/rfcs/…

Props and Emmit declare

Both props and emits can be declared using a pure type syntax that passes literal types to defineProps and defineEmits:

const props = defineProps<{
  foo: string bar? : number }>()const emit = defineEmits<{
  (e: 'change'.id: number): void
  (e: 'update'.value: string): void} > ()Copy the code

Declare the default value for props

interface Props { msg? : string labels? : string[] }const props = withDefaults(defineProps<Props>(), {
  msg: 'hello'.labels: () = > ['one'.'two']})Copy the code

Configuration JSX

Why was JSX used

Vue recommends using templates to create your HTML in most cases. However, in some scenarios, you really need the full programming power of JavaScript. In this case you can use render functions, which are closer to the compiler than templates.

When we create the following components

const { createApp, h } = Vue

const app = createApp({})

app.component('anchored-heading', {
  render() {
    return h(
      'h' + this.level, / / tag name
      {}, / / prop or attribute
      this.$slots.default() // An array containing its children)},props: {
    level: {
      type: Number.required: true}}})Copy the code

But when we use render functions, it can be painful

h(
  'anchored-heading',
  {
    level: 1
  },
  {
    default: () = > [h('span'.'Hello'), ' world! ']})Copy the code

Using templates is very simple

<anchored-heading :level="1"> <span>Hello</span> world! </anchored-heading>
Copy the code

That’s why we use JSX, and why React developers would prefer to use JSX

Vue3 provides a Babel plug-in for using JSX syntax in Vue3

import AnchoredHeading from './AnchoredHeading.vue'

const app = createApp({
  render() {
    return (
      <AnchoredHeading level={1}>
        <span>Hello</span> world!
      </AnchoredHeading>
    )
  }
})

app.mount('#demo')
Copy the code

Configure JSX in Vite

Vue users should use the official @Vitejs/plugin-VUE-jsx plug-in, which provides support for Vue 3 features, including HMR, global component resolution, directives and slots.

import vueJsx from '@vitejs/plugin-vue-jsx'

export default {
  plugins: [
    vueJsx({
      // options are passed on to @vue/babel-plugin-jsx}})]Copy the code

Address of relevant documents

  • The JSX Vue3 v3.cn.vuejs.org/guide/rende…
  • Babel-plugin-jsx 中文 版 github.com/vuejs/jsx-n…
  • Configuration in vite JSX cn. Vitejs. Dev/guide/featu…

Vue Router

Install the Vue Router

npm install vue-router@4
Copy the code

Router-link and router-view are the same as with Vue2. X

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'

const routes:RouteRecordRaw[] = [
  {
    path: '/'.name: 'Home'.// When using ts, do not omit the filename and suffix, because if omitted, TS will not be able to recognize its type
    component: () = > import('.. /views/Home/index.vue')}, {path: '/login'.name: 'Login'.component: () = > import('.. /views/Login/Login.vue')}]const router = createRouter({
  history: createWebHashHistory(),
  routes
})
export default router

Copy the code

Use vue-router in the entry file

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

createApp(App)
  .use(router)
  .mount('#app')
Copy the code

Vuex

Install Vuex

npm install vuex@next --save
Copy the code

use

// store/index.js
import {
  createStore
} from 'vuex'

export interface State {
    count: number
}

const store = createStore<State>({
  state () {
    return {
      count: 0}},mutations: {
    increment (state) {
      state.count++
      state.a = 1}}})export default store
Copy the code

Import file in the entry

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
+ import store from './store'

createApp(App)
+ .use(store)
  .use(router)
  .mount('#app')
Copy the code

Use in pages

<script setup lang="ts">
import { useStore } from 'vuex'
const store = useStore()
</script>

<template>
  <div>store {{ $store.state.count }}| {{ store.state.count }}</div>
</template>
Copy the code

Ts cannot infer $store.state.count and store.state.count in the page, we can refer to ts support documentation in VUex

Create the vuex.d.ts file in your project

// eslint-disable-next-line no-unused-vars
import { ComponentCustomProperties } from 'vue'
import { Store } from 'vuex'

declare module '@vue/runtime-core' {
  // Declare your store state
  interface State {
    count: number
  }

  // Provide a type declaration for 'this.$store'
  // eslint-disable-next-line no-unused-vars
  interface ComponentCustomProperties {
    $store: Store<State>
  }
}

Copy the code

When using useStore, TS cannot infer store.state

// store/index.js
import { InjectionKey } from 'vue'
import {
  createStore,
  Store,
  useStore as baseUseStore
} from 'vuex'

export interface State {
    count: number
}

export const key: InjectionKey<Store<State>> = Symbol('store')

export const store = createStore<State>({
  state () {
    return {
      count: 0}},mutations: {
    increment (state) {
      state.count++
    }
  }
})

export function useStore () {
  return baseUseStore(key)
}
Copy the code

Entrance to the file

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { store, key } from './store'

createApp(App)
  .use(store, key)
  .use(router)
  .mount('#app')
Copy the code

Use in pages

<script setup lang="ts">
import { useStore } from 'vuex'
import { key } from './store'
const store = useStore(key)
...
</script>
...
Copy the code

Simplify useStore usage

import { InjectionKey } from 'vue'
import {
  createStore,
  Store,
  useStore as baseUseStore
} from 'vuex'

export interface State {
    count: number
}

export const key: InjectionKey<Store<State>> = Symbol('store')

export const store = createStore<State>({
  state () {
    return {
      count: 0}},mutations: {
    increment (state) {
      state.count++
    }
  }
})

export function useStore () {
  return baseUseStore(key)
}
Copy the code

Used in vUE components

<script setup lang="ts">
import { useStore } from './store'
const store = useStore()
...
</script>
...
Copy the code

Processing file paths

Configuration vite alias

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

export default defineConfig({
  resolve: {
    alias: {
      The '@': path.join(__dirname, 'src')}},plugins: [
    vue(),
    eslintPlugin(),
    vueJsx({
      // options are passed on to @vue/babel-plugin-jsx})]})Copy the code

After configuration, there is no problem with the code running in the project, and an error will be reported in TS. You need to configure the path in the TS configuration file. The related documents

{
  "compilerOptions": {..."baseUrl": ". /"."paths": {
      "@ / *": [
        "src/*"]}},... }Copy the code

After a path alias is configured, it can be used not only in JS, but also in HTML and CSS

CSS

For details about how to handle CSS in Vite, refer to the Vite CSS documentation

PostCSS

If the project contains a valid PostCSS configuration (any format supported by PostCSs-load-config, such as postcss.config.js), it will automatically be applied to all imported CSS.

CSS Modules

Any CSS file with the.module. CSS suffix is considered a CSS modules file. Importing such a file returns a corresponding module object:

CSS preprocessor

You do not need to configure the CSS preprocessor in Vite. You only need to install the preprocessor dependency

npm i sass -D
npm i stylus -D
npm i less -D
Copy the code

Vite has improved @import resolution for Sass and Less to ensure that Vite aliases can also be used. In addition, Sass/Less files in a different directory than the root file referenced by the relative path in URL () are automatically rebased to ensure correctness.

Stylus is not supported by @import aliases and URL base changes due to Stylus API limitations.

Cross domain processing

During development, there are two main types of cross-domain solutions

  • Server-side Resolution (CORS)
  • Configure the agent
    • Here we can use viet-server.proxy
  • Other schemes, such as JSONP, are not considered for their limited use conditions

In the Vite project, we can use viet-server. proxy, refer to the documentation

Caches in Vite

In the process of development, we may encounter some problems, for example, after modifying the file, we can manually delete node_modules/. Vite file, and then rebuild

Vite caches pre-built dependencies to node_modules/.vite. It determines whether the pre-build step needs to be rerun based on several sources:

  • List of Dependencies in package.json
  • The lockfile of the package manager, such as package-lock.json, yarn.lock, or pnpm-lock.yaml
  • It may have been configured in the relevant fields of viet.config.js

If for some reason you want to force Vite to rebuild dependencies, you can either start the development server with the –force command-line option, or manually delete the node_modules/.vite directory.

Related documents refer to cn.vitejs.dev/guide/dep-p…