The overview

Recently completed an in-house website to develop vitesse, a new Web framework using VUE3 and Vite, written by ANTfu, a core developer of VUE.

Vitesse, in addition to the benefits of quick vite startup, quick hot update, and no need to reboot to modify configuration files, also adds a series of easy-to-develop plug-ins, including automatic import on demand, automatic routing generation, Layout system layout, and multi-language I18N and MarkDown support.

In addition to TypeScript, vue3 uses the more concise

In terms of style, the use of utility first WindicSS, through the class name to use the built-in CSS style, you can solve most of the style problems through the class name, including CSS pseudo-class, dark mode variant, etc., The units of measurement in the style are all rem after reactive processing.

The overall development experience is better with these features in mind.

For development tools, the chrome plugin market has a new beta version of vue. js devtools, need to uninstall the original reinstall, the new plug-in support vue2 and vue3, vscode plug-in from the original Vetur switch to Volar.

GitHub provides a demo of the overall framework. If you want to get your hands on Vue3 and Vite, or build your own website, clone the demo. Address: Vitesse-with-ANTd, welcome star~

Below is an analysis of the overall framework used and an introduction to the function points implemented.

Framework for analysis

According to the need to introduce

Components are imported on demand

On-demand references to components use viet-plugin-Components, which allows files in the specified directory to be loaded on demand. The default path is SRC/Components. Components can be used directly in a project, eliminating the need for separate imports in each Vue file.

<template>
  <div>
    <HelloWorld msg=Vue 3.0 + Vite />
  </div>
</template><script setup lang="ts">
</script>
Copy the code

It automatically converts to something like this

<template>
  <div>
    <HelloWorld msg=Vue 3.0 + Vite />
  </div>
</template><script setup lang="ts">
import HelloWorld from './src/components/HelloWorld.vue'
</script>
Copy the code

ICONS are introduced on demand

The vite-plugin-icons plugin supports importing all ICONS from Iconify, using them together in vite-plugin-components or using ICONS provided by Iconify without importing them separately. Supported ICONS can be found by accessing icones.

On-demand introduction of UI libraries

Taking ant-Design-Vue as an example, it also supports the import of UI component libraries on demand. UI components can be used directly, where matching components starting with A are imported from Ant-design-vue in Node-modules.

All of the aforementioned on-demand features are configured in Vite as follows:

import ViteComponents from "vite-plugin-components";
import ViteIcons, { ViteIconsResolver } from "vite-plugin-icons";
export default defineConfig({
  plugins: [
    // https://github.com/antfu/vite-plugin-components
    ViteComponents({
      // auto import icons
      customComponentResolvers: [
        // https://github.com/antfu/vite-plugin-icons
        ViteIconsResolver({
          componentPrefix: "",}).(name: string) = > {
          if (name.startsWith('A'))
            return { importName: name.slice(1), path: 'ant-design-vue'}},]}),// https://github.com/antfu/vite-plugin-icons
    ViteIcons(),
  ]
})
Copy the code

Routing and layout

Routing and layout are distributed to two plugins, viet-plugin-vue-Pages and Viet-plugin-Pages

Viet-plugin-pages automatically routes vue files in the Pages directory to layouts defined in the vue file in each Pages directory. For example, the following definition makes the current route load a SRC /layouts/ Empty file.

<route lang="yaml">
  meta:
    layout: empty
</route>
Copy the code

For route creation, in previous vue-Router 3.x, we used mode to control whether to use history or hash mode route, in 4.x, we used createWebHistory, CreateWebHashHistory to distinguish

import { createRouter, createWebHistory } from "vue-router";
import { setupLayouts } from "layouts-generated";
import generatedRoutes from "pages-generated";
​
const routes = setupLayouts(generatedRoutes);
const router = createRouter({
  history: createWebHistory(),
  routes,
});
app.use(router);
Copy the code

TypeScript related

TypeScript is used globally in Web-dev. Locally used type definitions can be defined separately in a single vue file or in a d.ts file. Some globally common type definitions are placed under the types folder in the root path.

The TypeScript configuration file tsconfig.json supports path configurations that define global types

"typeRoots": ["./node_modules/@types/"."./types"]
Copy the code

The types defined in the d.ts file under typeRoots are global and can be used globally without additional introductions.

If d.ts contains import and export, the global type definition will be invalid. For details, see this issue.

For the props type definition in VUe3, you cannot use the props type definition at creation. Instead, you need to use the PropType provided by VUe3 to specify the constructor. By the way, vue3 uses defineProps to defineProps.

import type { PropType } from 'vue'
const props = defineProps({
  list: {
    type: Array as PropType<MaterialConfig[]>,
    default: []}})const { list } = toRefs(props)
Copy the code

The use of hooks

Currently, hooks are mainly used to extract some reusable methods, which are consistent with the design idea of composition-API, focusing on the logic of implementing the same function module in a single hooks, from which we can export multiple variables or methods.

Following vue’s diagram, it can be understood that logic implemented by hooks represents a color block on the right

A common structure for hooks is as follows

import { ref } from 'vue'export const useMyHooks = (params) = > {
  const data = ref([])
  const functionData = () = > {
    // Do Sth
  }
  return {
    data,
    functionData
  }
}
​
Copy the code

Which is easier to get when writing hooks

(1) The logic in hooks should be decoupled from the external logic as far as possible, and the methods provided by hooks should be easy to use and reduce the repeated implementation of the same logic

(2) Each time you use useMyHooks, a separate memory is created for the variables. If you have any shared variables, declare them outside of useMyHooks.

Based on what we’ve seen so far, mixins should do what hooks do in terms of logic reuse.

For example, if I need to use constant A, method B provided by hooks, THEN I need to consciously and manually import the things THAT I want to reuse so that the source of the methods and variables is clear.

Mixins have more freedom, and as long as they are used, all methods are implicitly introduced by default, resulting in version iterations and multiplayer development that may not be easy to maintain.

Function point implementation

UI library theme color modification

The default skin color of Ant-Design-Vue is blue, and we needed to change the default skin color to purple to better match the style we wanted.

Antd’s official website only provides the method to modify the theme color less variable in Webpack, and the CSS preprocessor is also provided in Vite. We can modify the theme color through the following configuration:

// vite.config.js
export default defineConfig({
    css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true.modifyVars: {
          'primary-color': '#7546c9'},},},},})Copy the code

The dark mode is switched online

To change the theme color in ANTD, you only need to change a primary-color variable. To change the night mode, you need to change a series of variable values, and you need to support online switching. We used the antdDarkThemePlugin provided by the viet-plugin-theme.

Less variables in ANTD -> antdDarkThemePlugin generate a dark mode CSS file based on these variable values -> style file and insert it into the HTML.

The user switches to Dark mode and modifies [data-theme=dark] in the body to use the dark mode style.

import { viteThemePlugin, antdDarkThemePlugin } from 'vite-plugin-theme';
import { getLessVars } from 'antd-theme-generator';
const antdDarkVars = getLessVars('./node_modules/ant-design-vue/lib/style/themes/dark.less')
​
export default defineConfig({
  plugins:[
    viteThemePlugin({
      colorVariables: [' '].// You need to give an initial value to use the function properly
    }),
    antdDarkThemePlugin({
      darkModifyVars: {
        'primary-color': '#7546c9'.// Dark mode also supports purple skin. antdDarkVars } }) ] })Copy the code

The mode switching method is extracted from hooks, and useDark and useToggle provided by @vueuse/core are used to modify the dark mode variable in storage, so that the mode switching of user switching operation can be cached. The dark mode variant of tailwindcss should also be taken from here.

You also need to reload the CSS file to make the switchover take effect in production mode.

import { useDark, useToggle } from '@vueuse/core';
import { loadDarkThemeCss } from 'vite-plugin-theme/es/client';
​
export function useToggleDark() {
  const isDark = useDark()
  const toggleDarkDefault = useToggle(isDark);
  
  const toggleAntd = async() = > {if(isDark.value) {
      await loadDarkThemeCss();
      document.body.setAttribute('data-theme'.'dark')}else {
      document.body.setAttribute('data-theme'.'light')
    }
  }
  
  toggleAntd()             // Execute once initially
  
  const toggleDark = async () => {
    toggleDarkDefault();
    // Change antD to Dark mode
    toggleAntd()
  };
​
  
  return { isDark, toggleDark }
}
Copy the code

Global entry animation effect

Windicss supports custom class names. In web-dev we use the implementation in vue-vben-admin to define some progressive animation effects, such as Enter -x, enter-y, -enter-x,-enter-y. Animates a child element using the class name.

Windicss offers @Windicss /animations, which also have defined animations that can be used to enhance the user experience.

The introduction of the Emoji

In order to increase the interactivity of the platform, we simulated Github to implement comments and emoticon reply functions

To choose which emoji you want to use, check out listemoji