preface
Due to the release of vue3.2, the
In my opinion, the core work of front-end architecture is to customize a set of solutions suitable for the current business requirements, so as to reduce the complexity of technical implementation brought by the increase of requirements. Below, I will gradually lead you to build your own scaffold from 16 directions, formulate a reasonable solution, lay a good foundation for the project, and form appropriate development habits with your partners.
Due to the length of the problem, to explain the realization of the train of thought, I hope you speak friendly, common progress!
directory
- 1. Build scaffolding
- 1.1 What functions should front-end scaffolding have?
- 1.2 How to develop your own scaffold?
- 1.3 How Can I Generate files based on Options?
- 2. Create a basic template based on Vite
- 2.1 Creating a Basic template project
- 2.2 Common Plug-in Recommendations
- 3. Use the Typescript
- 4. Configure environment variables
- 4.1 Configuration Mode
- 4.2 Common Environment Variables
- 4.3 Encapsulating A Static Resource File
- 4.4 packaging
SVG
Icon component of
- 5. Automatically import components as required
- 5.1 Installation and Configuration
- 5.2 Changing the Registration Mode of Global Components
- 5.3 Importing component Libraries Automatically
- Style of 6.
- 6.1 Preset base Styles
- 6.2 CSS preprocessor
- 6.3 open the scoped
- 6.4 Depth selector
- Layout of 7.
- 7.1 General Layout
- 7.2 Special Layout
- 8. Integrated Tailwind. CSS
- 8.1 Efficiency Improvement
- 8.2 JIT mode
- 8.3 About packing volume
- 9. Vuex alternative pinia
- 9.1 Why Pinia?
- 9.2 create the Store
- 9.3 the State
- 9.4 Getters
- 9.5 the Actions
- 9.6 Devtools
- 10. Handle event linkage between components based on mitt
- 10.1 Why Mitt was Chosen?
- 10.2 Major Warning
- 10.3 How to Use Mitt?
- 11. Asynchronous request
- 11.1 Axios-based encapsulation
- 11.2 Added generics support for AXIos
- 11.3 More convenient encapsulation of useRequest
- 11.4 Unified API Management
- 11.5 the mock
- 12. The routing
- 12.1 Creating a Route Trilogy
- 12.2 Enrich your Routing with Meta
- 13. Optimized project performance and details
- 13.1 open the gzip
- 13.2 Page loading progress bar
- 13.3 the Title
- 13.4 Troubleshooting vH Usage on mobile Devices
- 13.5 JavaScript libraries that can be resident
- 14. Code style and process specification
- 14.1 ESLint
- 14.2 StyleLint
- 14.3 Code submission specifications
- 15. Write usage documentation
- 15.1 Building Documents using VitePress
- 15.2 Document Deployment
- 16. The plugin
- 16.1 VSCode plug-in
- 16.2 the Chrome plug-ins
- The source code
- reference
1. Build scaffolding
Using VUE-CLI or Vite to initialize a development template through a series of configurations, without building a development environment from scratch, can effectively improve the development efficiency, and I believe it is also a way most developers take over a new project. Although the scaffolding provided by the government is excellent enough, it may not really meet the usage habits of our team. Therefore, developing our own scaffold based on the official basis can improve the development efficiency more.
1.1 What functions should front-end scaffolding have?
- Reduce repeated initialization efforts, eliminating the need to copy other similar projects to remove irrelevant code, or build a project from scratch.
- Directory structures and files can be generated based on team requirements using simple interactive operations.
- Unify the team’s development habits and code styles to ensure the consistency of build results.
- Complete use of documentation, reduce the novice, development and later maintenance costs.
1.2 How to develop your own scaffold?
Referred to build in the front-end engineering scaffold, I believe you have seen many articles, a few years ago I wrote an article about scaffolding building, literally search keywords can see a lot of related articles, here don’t do too much introduction, mainly about some how these rarely mentioned in the article according to the options generated file.
1.3 How Can I Generate files based on Options?
To tell the truth, I also don’t know how the big guys are compiled into corresponding files according to various configurations, this piece of hope everyone to speak up, seeking a more efficient and concise way. Here is my plan to share with you:
On the interactive side, those of you who have scaffolding will know that Inquirer is a library that makes it easy to interactively retrieve some of the custom configuration parameters we’ve selected. So the question is, how do you create the corresponding files from these configurations?
Here I recommend using EJS + Prettier to generate code and fs-extra to write the final file.
- EJS
EJS is a JavaScript template engine. We can pass in parameters and generate corresponding code strings, for example, create a package. EJS to generate package.json. If we choose to use SCSS as CSS preprocessor, Then use SASS and Stylelint-SCSS as installation dependencies for the project:
= = = '< % if (precss SCSS') {- % > "sass" : "1.26.5", "stylelint - SCSS" : "^ 3.20.1", < % %} - >Copy the code
The template engine can help you generate code from parameters, it does not restrict you to generate any type of code file, because we generate pure code, and finally by reading.ejs file to generate the corresponding type file.
- Prettier
Prettier, a code formatting tool, is no stranger to Prettier. The purpose of EJS generation is still for developers to read and edit, so the generated code should conform to the final formatting requirements, since we’ll be adding tools like ESLint and StyleLint to the scaffolding later, and a bunch of red line errors in the project we just created can be very unfriendly.
import prettier = require("prettier");
prettier.format(code, { parser: 'json' }))
Copy the code
Parser is the parser for Prettier. Common typescript, CSS, less, JSON files can be formatted.
2. Create a basic template based on Vite
When I first built vue3 scaffolding, I chose to build it with VUE/CLI. Due to the unsound ecology, some webpack-based functions could not be used. But now vite ecology has been relatively perfect, so I rebuilt the scaffolding from Webpack to Vite. This step greatly improves the development experience.
2.1 Creating a Basic template project
npm init vite@latest
yarn create vite
pnpm create vite
Copy the code
Vite offers few options, just vue or Vue + TS, not as many configuration options as Vue/CLI, so the rest needs to be configured manually.
Of course Vite offers a lot of templates, but I think it’s easier to add than subtract, and it’s hard to find one that works for us.
2.2 Common Plug-in Recommendations
Here’s a quick look at some useful Vite plugins:
- Unplugin-vue-components: Automatic import of components on demand.
- Vite-plugin-svg-icons: used to generate SVG Sprite images.
- Viet-plugin-compression: Use gzip or brotli to compress resources.
Why are only a few plug-ins recommended? This is because Vite has built-in support for many of the loaders and plugins that WebPack needs to install, such as less, sass, and typescript, which will be explained in the following sections.
3. Use the Typescript
The vue2. X version is a major blow to TypeScript support, and TypeScript’s ability to secure large projects is widely recognized. This is very nicely supported in vue3. X.
Vite naturally supports the introduction of.ts files.
Here are some changes to tsconfig.json:
{
"compilerOptions": {
"types": ["vite/client"]."baseUrl": "src"."paths": {
"@ / *": [". / *"]}},"exclude": ["node_modules"]}Copy the code
In the early days of typeScript, many people preferred to use the any type. Instead of writing typeScript as anyScript, it was easy to use, but it lost the value of typeScript type checking. Of course, the habit of writing type is the need to develop slowly, not in a hurry.
4. Configure environment variables
Vite provides two modes: Development with a development server and Production.
Here we can create 4.env files, a common configuration, and three environments: development, test, and production.
4.1 Configuration Mode
NODE_ENV=production NODE_ENV=productionCopy the code
- Env general configuration. I personally like to think of it as a configuration file for the project, such as the title of the project, which does not correspond to any schema.
- .env.development Development environment, using development mode.
- Env.staging test environment. Production mode is used because you are deploying to a test server or previewing it locally using the serve command.
- .env.production Production environment, use production mode because you are deploying to a test server or using the serve command to preview locally.
Script in package.json requires the staging command
"script": {
"build": "vue-tsc --noEmit && vite build"."staging": "vue-tsc --noEmit && vite build --mode staging"."serve": "vite preview --host"
}
Copy the code
4.2 Common Environment Variables
Three common variables are recommended:
- VITE_APP_BASE_URL
The interface requests the address.
Typically, the backend differentiates between three environments and is deployed at different addresses.
- VITE_APP_STATIC_URL
Static resource address.
Static resources I do not recommend putting them directly into your project, as this will cause the project repository to become huge.
For the local development and testing environment, I will choose the static resource server built locally. You can ask the backend operation and maintenance students to help you build it, or you can use HTTP-server to start a server locally. In the production environment, you are advised to upload it to the OSS.
- VITE_PUBLIC_PATH
Build a common path for resources.
Similar to publicPath in vue/ CLI, sometimes you build projects that are not stored in the same path, such as http://ip:port/{project name}.
4.3 Encapsulating A Static Resource File
If you have configured the VITE_APP_STATIC_URL static resource environment variable, then you need to encapsulate two things:
- Returns the actual resource address function based on the environment.
- Easy to use static resource components.
baseStaticUrl.ts
// Handle static resource links
export default function baseStaticUrl(src = ' ') {
const { VITE_APP_STATIC_URL } = import.meta.env;
if (src) {
return `${VITE_APP_STATIC_URL}${src}`;
}
return VITE_APP_STATIC_URL as string;
}
Copy the code
Static resource component
Static resources mainly include pictures, audio and video in three common forms.
- Write relative paths via SRC, and use the above function to complete the complete path. You can use static resources at different addresses in different environments.
- Pass type the type of image, audio, and video.
- Autoplay is a solution to the problem of video not playing automatically when the video is in the background.
<script lang="ts" setup> import { computed, ref, Ref, withDefaults, onMounted, watch } from 'vue'; import { baseStaticUrl } from '@/libs/utils'; import useDevice from '@/hooks/useDevice'; interface Props { src? : string; type? : string; autoplay? : boolean; } const props = withDefaults(defineProps<Props>(), { src: '', type: 'img', autoplay: true, }); const envSrc = computed(() => baseStaticUrl(props.src)); Const {deviceType} = useDevice(); const {deviceType} = useDevice(); const poster = computed(() => deviceType.value === 'desktop' ? '' : baseStaticUrl(props.src), ); const videoRef: Ref<HTMLVideoElement | null> = ref(null); Function videoAutoPlay() {if (props. Type === 'video' && videoref.value! == null) { videoRef.value.src = baseStaticUrl(props.src); } if (props.autoplay && videoRef.value) { videoRef.value.oncanplay = () => { if (videoRef.value) videoRef.value.play(); }; OnMounted (() => {videoAutoPlay(); }); Watch (envSrc, () => {if (videoref.value) videoref.value.play (); }); </script> <script lang="ts"> export default { name: 'StaticFile' }; </script> <template> <img v-if="type === 'img'" :src="envSrc" /> <video ref="videoRef" v-else-if="type === 'video'" muted :poster="poster" /> <audio v-else :src="envSrc" /> </template>Copy the code
4.4 packagingSVG
Icon component of
SVG ICONS are small and are readable XML text, so we can put them directly in the project. Using the vite-plugin-SVG-icons plug-in, WE can automatically import SVG ICONS.
Configuration vite. Config. Ts:
plugins: [
viteSvgIcons({
iconDirs: [resolve(process.cwd(), 'src/assets/icons')].symbolId: 'icon-[dir]-[name]',}),]Copy the code
Encapsulate a VUE component:
<script setup lang="ts"> import { computed, withDefaults } from 'vue'; interface Props { prefix? : string; name? : string; color? : string; } const props = withDefaults(defineProps<Props>(), { prefix: 'icon', name: '', color: '#000', }); const symbolId = computed(() => `#${props.prefix}-${props.name}`); </script> <template> <svg aria-hidden="true"> <use :xlink:href="symbolId" :fill="color" /> </svg> </template>Copy the code
First place the downloaded.svg ICONS in the @/ Assets/ICONS folder
<svg-icon name="" color="" />
Copy the code
- Name Specifies the name of the file placed in the @/assets/ ICONS folder.
- Color Color fill. Using this option overrides the icon color by default.
5. Automatically import components as required
Unplugin-vue-components is a powerful plugin (highly recommended) that automatically imports components on demand, tree-shakable, and registers only the components you use. Here are its two core usage and configuration methods.
This plugin supports not only VUe3, but also VUe2, Vite, Webpack, Vue CLI, and Rollup.
5.1 Installation and Configuration
Installation:
npm i unplugin-vue-components -D
Copy the code
Configuration:
// vite.config.ts
import Components from 'unplugin-vue-components/vite'
export default defineConfig({
plugins: [
Components({ /* options */})],})Copy the code
Options here allows you to configure some of the options that will be used by the component library registry mentioned later.
5.2 Changing the Registration Mode of Global Components
We usually will be global components encapsulation in @ / SRC/components, and then through app.com ponent registered global components (). After using this plug-in, you can use components directly in the template without having to manually register them:
Here’s an official example:
<template> <div> <HelloWorld MSG ="Hello Vue 3.0 + Vite" /> </div> 'App' } </script>Copy the code
Automatically compiles to:
<template> <div> <HelloWorld MSG ="Hello Vue 3.0 + Vite" /> </div> </template> <script> import HelloWorld from './src/components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld } } </script>Copy the code
5.3 Importing component Libraries Automatically
When using component libraries, we also register regular components globally, but using local registrations is great because it can be cumbersome to use multiple components on a page, such as the Ant-Design-Vue component library.
It can be used directly in the template without manual registration or local reference:
<template> <a-button> </a-button> </template>Copy the code
Of course, you also need to include its parser in Vite:
import Components from 'unplugin-vue-components/vite'
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
Components({
resolvers: [
AntDesignVueResolver(),
]
})
],
})
Copy the code
Currently supported parsers, choose according to your preference:
- Ant Design Vue
- Element Plus
- Element UI
- Headless UI
- IDux
- Naive UI
- Prime Vue
- Vant
- VEUI
- Varlet UI
- View UI
- Vuetify
- VueUse Components
- Quasar
Style of 6.
Use generic styles in your project. Create a SRC /styles directory to store them.
Styles ├ ─ ─ antdComponent library style overwrite, name yourself, here using Ant Design as an example├ ─ ─ color. Less# color├ ─ ─ index. Less# entry├ ─ ─ global. LessPublic class #├ ─ ─ the transition. Less# Animation related└ ─ ─ variable. Less# variable
Copy the code
6.1 Preset base Styles
Normalize, which many of you have used, can reset CSS styles to make them look the same across browsers. Tailwind. CSS has a built-in function for resetting preset styles, which is different from normalize if you are interested.
6.2 CSS preprocessor
Although Vite natively supports less/ Sass/SCSS/Stylus, you must manually install their preprocessor dependencies, for example:
npm install -D less
Copy the code
How do I choose a preprocessor?
It is recommended to use the style language of the component library you are using, because once the CSS preprocessor learns one, it costs almost nothing to learn the others.
6.3 open the scoped
The absence of the scoped attribute compiles to a global style, causing global contamination.
<style scoped></style>
Copy the code
6.4 Depth selector
Sometimes we might want to explicitly specify a rule for child components.
If you want one of the selectors in the Scoped style to go “deeper”, such as affecting child components, you can use the >>> operator. Some preprocessors like Sass don’t parse >>> correctly. In this case you can use the /deep/ or ::v-deep operators instead — both are aliases for >>> and work just as well.
Layout of 7.
The overall layout of a page is the outermost framework structure of a product, often containing navigation, footers, sidebars, and so on. Within the page, there is also a lot of block layout. In real projects, the layout of the page is usually the main interface of the application, so it is necessary to break it out separately.
In scaffolding, all general layout components should be placed in SRC /layouts. This is easy to use, but you won’t need to post code here.
7.1 General Layout
BasicLayout
Basic page layout, including header navigation, sidebar, etc.
BlankLayout
Blank layout.
7.2 Special Layout
RouteLayout
If your project needs to cache some secondary pages during route switching, it is recommended that you create a RouteLayout that returns either a router-view or a router-view wrapped with keep-Alive via the configuration in route Meta.
UserLayout
Used for user login, registration and so on page out.
PageLayout
The basic layout, containing breadcrumbs and other information, contains slots.
8. Integrated Tailwind. CSS
Tailwind. CSS was repellent to me when I first saw it, but it really smells good when I get to play it. From the VUe2 project, I have introduced tailwind, and the overall result is that the
Overall, it’s not expensive to learn, and two hours is enough time to learn the class names without memorizing them by rote.
8.1 Efficiency Improvement
A lot of people talk about styles being separate from HTML, so why tailwind now? This is because the use of frameworks like VUE is now highly componentized, style separation is for ease of reuse and maintenance, but in the face of componentization style separation can only reduce development efficiency.
Here’s what Tailwind offers to improve efficiency:
- Provides a large number of functional classes, greatly improving maintainability.
- Responsive design, a shuttle for all kinds of equipment.
- Hover, focus, and other states.
- Dark mode.
- Support configurations, such as colors, are difficult to align with your designer.
- Don’t bother with a name??
8.2 JIT mode
If your environment supports PostCSS8 (the VUE/CLI built VUe2 project is PostCSS7) then JIT mode takes you straight off the ground.
- Super fast build speed.
- Support variants, you could even write this
sm:hover:active:disabled:opacity-75
. - Support for arbitrary styles, for example
md:top-[-113px]
. - The development and production environment results are consistent (I encountered inconsistent component library builds on the VUe2 project).
If you are using vscode you must install the Tailwind CSS IntelliSense plugin, which automatically completes class names, significantly reducing learning costs.
8.3 About packing volume
Using the default configuration, uncompressed is 3739.4kB, Gzip is 293.9kB, and Brotli is 73.2kB. This may seem like a lot, because Tailwind offers thousands of feature classes, most of which you won’t use.
When building production, you should use the Purge option to optimize unused styles with tree-shake and optimize your final build size. When using Tailwind to remove unused styles, it’s hard to end up with more than 10KB of compressed CSS.
Also, Atom CSS greatly improves style reuse, which directly reduces build volume.
9. Vuex alternative pinia
Vuex 4’s support for typescript was disappointing, so state management abandoned Vuex in favor of Pinia.
I don’t know where I saw it, but Utah seems to say that Pinia may replace vuex, so please feel free to use it.
9.1 Why Pinia?
- PiniaAPI design is very close
Vuex 5
的The proposal. (The writer is a member of Vue core team) - Don’t need to like
Vuex 4
Customizing complex types to support typescript is inherently perfect for type inference. - Modular design, every store you introduce can be split automatically when packaged.
- There is no nesting structure, but you can cross and combine them between any store.
- Pinia is linked to Vue DevTools and will not affect the Vue 3 development experience.
Here is a brief introduction to how to use Pinia and compare the differences and precautions of VUEX. Please refer to the official documentation for details.
9.2 create the Store
Pinia is already built into scaffolding and associated with vue, so you can create a store anywhere:
import { defineStore } from 'pinia'
export const useUserStore = defineStore({
id: 'user'.state: () = >({}),
getters: {},
actions: {}})Copy the code
This is very different from Vuex in that it is a standard Javascript module export, which also makes it clear to developers and your IDE where the Store is coming from.
Differences between Pinia and Vuex:
- The ID is required to connect the store being used to DevTools.
- Creation method:
new Vuex.Store(...)
(vuex3),createStore(...)
(vuex4). - In contrast to Vex3, state is now a function return object.
- There is no mutations, don’t worry, the change of state is still recorded in DevTools.
9.3 the State
Now that the store is created, you can create some properties in state:
state: () = > ({ name: 'codexu'.age: 18 })
Copy the code
Setting the state property in the store to a function that returns an object with different state values is very similar to how we define data in components.
Use store in templates:
Now we want to get the state of name from store, we just need to use the following method:
<h1>{{userStore.name}}</h1>
const userStore = useUserStore()
return { userStore }
Copy the code
Note that userstore.state.name is not required here.
While the above is comfortable, you must not deconstruct it to extract its internal values, as doing so will lose its responsiveness:
const { name, email } = useUserStore()
Copy the code
9.4 Getters
The getters in Pinia have the same functionality as getters in Vuex and computed properties in components. Traditional function declarations use this instead of passing state, but arrow functions still use the first argument of the function to get state. Because the arrow function handles the scope of this:
getters: {
nameLength() {
return this.name.length
},
nameLength: state= > state.name.length,
nameLength: () = > this.name.length ❌
}
Copy the code
9.5 the Actions
Unlike Vuex, Pinia only provides a way to define how to change the rules of the state, abandoning mutations and relying solely on Actions, which is a major change.
Pinia makes Actions more flexible:
- It can be called from a component or other action
- Can be called from an action in another store
- Called directly on the store instance
- Support synchronous or asynchronous
- There are any number of parameters
- Can include logic on how to change the state (which is what Vuex’s mutations do)
- can
$patch
Method directly changes the status properties
actions: {
async insertPost(data){
await doAjaxRequest(data);
this.name = '... '; }}Copy the code
9.6 Devtools
Scaffolding has the following code built in, which adds DevTools support:
import { createPinia, PiniaPlugin } from 'pinia'
Vue.use(PiniaPlugin)
const pinia = createPinia()
Copy the code
Time travel seems to be working now. I will pay attention to this later.
10. Handle event linkage between components based on mitt
If you’ve ever been a developer of vue2.x, please read this quote from the official documentation below:
We completely removed the $ON, $OFF, and $once methods from the instance. $EMIT is still included in the existing API because it is used to trigger event handlers added declaratively by the parent component.
In Vue 3, it is no longer possible to use these apis to listen for events emitted by the component itself from within the component, and there is no way to migrate the use case. However, the eventHub pattern can be replaced with an external library that implements the event trigger interface, such as Mitt or Tiny-Emitter.
10.1 Why Mitt was Chosen?
- Small enough, only 200bytes.
- All events can be monitored and removed in batches.
- No dependency, no matter what framework can be used directly.
10.2 Major Warning
We are no longer able to use eventBus in the project. We only recommend you to use Mitt for special occasions. It is not normal for development, so make sure you know what you are doing. Otherwise your project will be difficult to maintain!!
10.3 How to Use Mitt?
Please read the official documentation before using MITT:
Scaffolding provides an object that can be used directly by default:
import emitter from '@/libs/emitter';
Copy the code
Of course, you can also introduce mitt already installed:
import mitt from 'mitt'
const emitter = mitt()
Copy the code
Mitt provides a very simple API, and the following code is the official demo:
// listen to an event
emitter.on('foo'.e= > console.log('foo', e) )
// listen to all events
emitter.on(The '*'.(type, e) = > console.log(type, e) )
// fire an event
emitter.emit('foo', { a: 'b' })
// clearing all events
emitter.all.clear()
// working with handler references:
function onFoo() {}
emitter.on('foo', onFoo) // listen
emitter.off('foo', onFoo) // unlisten
Copy the code
11. Asynchronous request
Most projects are bound by interfaces. If your project has a lot of interfaces, I recommend the following:
- Encapsulate the request.
- Unified API interface management.
- Mock data functionality (use as required).
The main purpose of the above is to help simplify the code and facilitate the later maintenance of the update.
11.1 Axios-based encapsulation
For those of you who have developed vue2 projects and are already familiar with Axios, here are some ideas for encapsulation:
- through
import.meta.env.VITE_APP_BASE_URL
Get environment variables and configure thembaseURL
If the interface has multiple domain names, it can be controlled by js variables. - Set up the
timeout
Handle request timeout or disconnection. - Set up theRequest headerCarry,
token
. - Exception interceptionThe back end passes through what you carry
token
Determine if you are out of date if returned401
You may need to jump to the login page and be prompted to log in again. - Response interception, usually the back end returns code, data, MSG, if the request is normal, we can directly return data data, if it is abnormal code, we can also directly pop up an error message here.
- Refresh the token without feeling. If your token expires, you can call the refresh interface through the refreshToken returned by the backend to obtain a new token. Of course, there are many details involved, such as terminal requests, resending requests, and reordering requests.
- Interrupt a request, such as a page switch, where we interrupt a request in progress.
Related codes (for reference only)
11.2 Added generics support for AXIos
So far, the axios request has returned type any, and we’re not getting the type hint from TS when we’re working on the requested data, which is obviously not what we expected.
All we need to do is redeclare the AXIos module: create a new shims.d.ts and add generics to the call.
import { AxiosRequestConfig } from 'axios';
declare module 'axios' {
export interface AxiosInstance {
<T = any>(config: AxiosRequestConfig): Promise<T>;
request<T = any>(config: AxiosRequestConfig): Promise<T>;
get<T = any>(url: string, config? : AxiosRequestConfig):Promise<T>;
delete<T = any>(url: string, config? : AxiosRequestConfig):Promise<T>;
head<T = any>(url: string, config? : AxiosRequestConfig):Promise<T>;
post<T = any>(url: string, data? :any, config? : AxiosRequestConfig):Promise<T>;
put<T = any>(url: string, data? :any, config? : AxiosRequestConfig):Promise<T>;
patch<T = any>(url: string, data? :any, config? : AxiosRequestConfig):Promise<T>; }}Copy the code
Once you have done this, you must declare the type of data requested when you create the interface.
11.3 More convenient encapsulation of useRequest
When writing request code, we usually define several variables:
- Data: Stores requested data
- Loading: Request loading status
In particular, loading needs to be set to True before the request and false after the request.
The above encapsulation method is the basic function encapsulation. Since we are using VUe3, we can encapsulate it again to become hook, which will be more convenient for us to use.
For example:
Define an interface using useRequest:
export default getUserInfo(id) {
return useRequest({
method: 'get'.url: '/api/user'.params: { id }
})
}
Copy the code
Using this interface:
const { data, loading } = getUserInfo();
Copy the code
Notice that data here is reactive.
This is an idea THAT I came up with, but it has not been well packaged yet, and relevant codes are only for reference. You can also learn from some mature schemes, such as useFetch in Vueuse, but it is designed based on Fetch API, which does not meet my expected requirements. If you have a better scheme, please leave a comment below.
11.4 Unified API Management
Since the separation of front end and back end, front and back end interface docking has become the normal, and the process of interface docking is inseparable from the interface document, the mainstream is Swagger, but how to better manage the interface docking with the back end in the front end project?
Create the API directory in the SRC directory, and the internal directory should be created according to the module specified on the back end.
Create multiple TS files for each module, one TS file for each interface, which contains the following contents:
- Type declarations for request parameters.
- The type declaration of the response data.
- Returns the defined request functions (URL, method, Params, data, and so on).
As long as you name the backend specification and write the type declarations carefully, typescript is the best interface documentation for the front end.
11.5 the mock
Using mock data with Vite is very easy. You can use the viet-plugin-mock plugin. If you know MockJS, you can get started quickly.
12. The routing
Routing and menus are the key skeleton for organizing an application.
12.1 Creating a Route Trilogy
Usually a project needs to do these steps:
- Use createRouter to create a route, and select a Hash route or a History route as required.
- Configure the routing according to the business requirements, noting that it is likely to use the layout components mentioned earlier.
- If there is a permission-related business, you need to create permission-ts to do something when the route hook fires.
If you have many pages, you are advised to create a routes directory and declare routes in modules.
Reference code
12.2 Enrich your Routing with Meta
Vue-router4. x supports typescript and configures the route type as RouteRecordRaw.
- title: string; Page title, usually mandatory.
- icon? : string; Icon, usually used with the menu.
- auth? : boolean; Whether login permission is required.
- ignoreAuth? : boolean; Whether to ignore permissions.
- roles? : RoleEnum[]; Accessible role
- keepAlive? : boolean; Whether to enable page caching
- hideMenu? : boolean; There are some routes that we don’t want to show in menus, such as some edit pages.
- order? : number; Menu sorting.
- frameUrl? : string; Nested outer chain.
Here only provide some ideas, each project will be more or less involved in these problems, please refer to the specific information to solve.
13. Optimized project performance and details
13.1 open the gzip
Enabling gzip can greatly compress static resources, which has a significant effect on the speed of page loading.
The use of Vite-plugin-compression allows you to compress resources in gzip or brotli mode. This step requires the cooperation of the server side. Vite can only help you package.gz files. This plugin is easy to use, you don’t even need to configure parameters, just import.
13.2 Page loading progress bar
A loading progress bar is very friendly when switching routes to a page, preventing the user from thinking that the page is dead.
In this case, we can use nProgress, which is turned on and off during route switching:
import NProgress from 'nprogress';
router.beforeEach(async (to, from, next) => {
NProgress.start();
});
router.afterEach((to) = > {
NProgress.done();
});
Copy the code
13.3 the Title
It is normal to display different titles under different routes. We can change the title on the TAB page by getting the title property in the meta from the route hook.
You can use the useTitle provided by Vueuse, or window.document.title itself.
You can also concatenate your main heading after the route heading with environment variables:
const { VITE_APP_TITLE } = import.meta.env;
Copy the code
13.4 Troubleshooting vH Usage on mobile Devices
If you are interested, you can try 100Vh on Chrome Mobile, which is 100% of the height of the real viewport.
To solve this problem, we can use the postCss plug-in.
Install the postCSs-viewport-height-correction plugin:
npm install -D postcss-viewport-height-correction
Copy the code
Add plugin to postcss.config.js:
module.exports = {
plugins: {
'postcss-viewport-height-correction': {},}},Copy the code
To add this js code globally, you can add it directly to index.html:
const customViewportCorrectionVariable = 'vh';
function setViewportProperty(doc) {
let prevClientHeight;
const customVar = `--${customViewportCorrectionVariable || 'vh'}`;
function handleResize() {
const { clientHeight } = doc;
if (clientHeight === prevClientHeight) return;
requestAnimationFrame(function updateViewportHeight() {
doc.style.setProperty(customVar, `${clientHeight * 0.01}px`);
prevClientHeight = clientHeight;
});
}
handleResize();
return handleResize;
}
window.addEventListener('resize', setViewportProperty(document.documentElement));
Copy the code
13.5 JavaScript libraries that can be resident
- Vueuse, mentioned above, is very powerful and highly recommended.
- Lodash, we agreed to stay early and leave early.
14. Code style and process specification
14.1 ESLint
Whether it’s a multi-person collaboration or a personal project, code specification is important. Doing so not only largely avoids basic syntax errors, but also keeps the code readable.
The Airbnb specification is recommended.
Configure the reference
14.2 StyleLint
Although tailwind, as mentioned earlier, allows you to write almost no CSS, it has to be careful when it comes to teamwork.
StyleLint is a powerful, modern CSS detection tool. Similar to ESLint, StyleLint helps you avoid errors in your style sheets by defining a set of coding style rules that, along with the editor’s automatic repair, can be used to align your team project’s CSS style.
Configure the reference
14.3 Code submission specifications
Git repositories and Workflow are important in the context of multi-person collaboration. Git commit -m “” commitLint + husky git commit -m” As we all know, when using Git commit, Git prompts us to fill in the commit information. Don’t underestimate these commits. The team has a standard COMMIT that allows you to see each code commit record more clearly and automatically generate changeLog files based on custom rules.
Submission format (note space after colon) :
<type>[optional scope]: <description>
Copy the code
- Type: Indicates the type of change we are committing this time.
- Optional Scope: Identifies which module in the code is primarily involved in this commit.
- Description: Describe the main content of the submission in one sentence. Make it brief and comprehensive.
Type Type
- Build: Compile-related changes, such as releases, changes to project builds, or dependencies
- Chore: Other modifications, such as changing the build process, or adding dependency libraries, tools, etc
- Ci: Continuous integration modification
- Docs: Document modification
- Feat: New features, new functions
- Fix: Fixes bugs
- Perf: Optimization related, such as improved performance, experience
- Refactor: Code refactoring
- Revert: Rollback to a previous version
- Style: Code format modification, note not CSS modification
- Test: Test case modification
There are many articles on the configuration of Commitlint + Husky. Please configure it according to your actual situation.
15. Write usage documentation
At this point, you’re nearing the end of your entire scaffolding development, but you’ve done so much that your colleagues won’t know how to use it, and even you’ll forget it after a while, so you must develop good documentation habits.
15.1 Building Documents using VitePress
Here I recommend using Vuepress or VitePress, to be honest if you just write documentation vitePress is much more comfortable because it’s fast.
Vitepress is great for building blog sites and technical documents because it can be written directly in MarkDown. Anyone who has ever blogged should be familiar with vitePress. A.md file, can generate a page, very convenient.
Creating a VitePress document is too easy, you can refer to the official documentation, or refer to my documentation.
15.2 Document Deployment
It’s great if your team can help you set up CI/CD auto-deployment, but if not, you can also use github’s Actions feature for auto-deployment.
Reference code
16. The plugin
If you want to use the above functions more quickly, I suggest you install the following plug-ins.
16.1 VSCode plug-in
- Vue Language Features (Volar), you may not find Volar now, you need this.
- Vue 3 Snippets, vue3 quick input.
- Tailwind CSS IntelliSense, Tailwind code prompt.
- Stylelint
- Prettier – Code formatter
- ESLint
16.2 the Chrome plug-ins
- Vue. Js devTools, of course you need to install a Vue 3 supported version, which is also very pinia friendly.
The source code
The above content can be found in my open source project X-build. If it can help you, please give me a star or a thumbs-up to encourage me to contribute more open source projects or articles.
reference
- Vue based Front-end Architecture, I made these 15 points
- Build your Own Scaffolding – “Elegant” Generation Front-end Engineering
- Vex4 isn’t TypeScript friendly, so I’ll go with Pinia
- “Front End Scaffolding Webpack migration Vite2 Trampling practice”