Vue is a progressive framework for building user interfaces. Unlike other large-scale JS frameworks, Vue is designed to be applied layer by layer from the bottom to the top, making it easier to use, and easy to integrate with third-party libraries or existing projects. Therefore, Vue It is fully capable of providing drivers for complex single-page applications.
On September 18, 2020, Vue.js 3.0 was officially released. The author You Yuxi described it as: faster, smaller, and easier to maintain.
What new features have been added to Vue 3?
In this release, the Vue framework itself has ushered in a number of updates. For example, Vue's previous response system used Object.defineProperty's getter and setter. However, in Vue 3, ES2015 Proxy will be used as its observer mechanism. The advantage of this is that it eliminates the warnings that existed before, doubles the speed, and saves half of the memory overhead.
In addition to the Proxy-based observer mechanism, other new features of Vue 3 include:
1. Performance (performance improvement)
In Vue 2, when a DOM needs to be updated, it is necessary to traverse the entire virtual DOM tree to determine the update point. In Vue 3, there is no need for this operation. You only need to compare the nodes with patch flags on the virtual nodes through static tags to locate and update the location.
Comparing the performance difference between Vue 2 and Vue 3, specific data descriptions are given in the official documents:
· SSR speed increased by 2~3 times
· Update performance improved by 1.3~2 times
2. Composition API (Composition API)
There are data, methods, mounted and other objects that store data and methods in Vue 2, which should be familiar to us. For example, to implement the function of a carousel diagram, you first need to define the data related to this function in data, define the method of this function in methods, and define the code to automatically turn on the carousel when entering the page in mounted... There is an obvious one The problem is that the code of the same function has to be scattered in different places on the page, which will be quite troublesome to maintain.
In order to solve the above problems, Vue 3 introduced the Composition API with a clear code structure and can eliminate duplicate logic, as well as two brand-new functions setup and ref.
The Setup function can return properties and methods to the template and execute them when the component is initialized. Its effect is similar to beforeCreate and created in Vue 2. If you want to use the data in the setup, you need to return the value. The content that is not returned from the setup function is not available in the template.
The role of the Ref function is to create a reference value, mainly to reference the data response of String, Number, and Boolean.
Compared with Vue 2, the life cycle function of Vue 3 has also changed, as shown below:
· BeforeCreate -> please use setup()
· Created -> please use setup()
· beforeMount -> onBeforeMount
· mounted -> onMounted
· beforeUpdate -> onBeforeUpdate
· updated -> onUpdated
· beforeDestroy -> onBeforeUnmount
· destroyed -> onUnmounted
· errorCaptured -> onErrorCaptured
It should be noted that when Vue 2 uses the life cycle function, the life cycle function is directly written in the page, while in Vue 3, it can be directly referenced:
import {reactive, ref, onMounted} from 'vue'
3. Tree shaking support (packaged modules on demand)
Some people refer to "Tree shaking" as "tree shaking optimization", which is actually "pruning" useless modules to remove unused APIs. Therefore, after "Tree shaking", the packaged volume will be greatly reduced.
The official comparison between Vue 2 and Vue 3, if Vue 2 only writes Hello World, and does not use any module API, the packaged size is about 32kb, while Vue 3 is only 13.5kb after packaging.
4. Brand new scaffolding tool: Vite
Vite is a web development and build tool driven by native ESM. Developed based on the browser's native ES imports in the development environment, and packaged based on Rollup in the production environment.
Compared with Webpack, it has the following characteristics:
· Fast cold start, no need to wait for packaging
· Instant hot module update
· Real on-demand compilation, without waiting for the compilation of the entire project
Since the concept of packaging is completely skipped, the emergence of Vite has greatly shaken the position of Webpack, and it has truly made the server ready to use. It seems that even You Dashen can't escape the "true fragrance" theory.
What is the magic of Vite? Let us experience it by actually building a form editing system based on Vue 3 components.
One, environment construction
Use Vite to initialize a Vue 3 project
1. Execute the code:
$ npm init vite-app <project-name>
$ cd <project-name> //进入项目目录
$ npm install //安装项目所需依赖
$ npm run dev //启动项目
Let's take a look at the generated code, because vite will mirror the default configuration in vue-cli as much as possible, so this code does not look much different from the code generated by vue-cli.
├── index.html
├── package.json
├── public
│ └── favicon.ico
└── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ └── HelloWorld.vue
├── index.css
└── main.js
2. Execute the following commands:
If you do not start the project through npm run dev, but open index.html directly through the browser, you will see the following error:
The reason for the error: The ES module of the browser gets the modules through http requests, so one of the tasks of vite is to start a web server to proxy these modules. In vite, koa is used to start the service.
export function createServer(config: ServerConfig): Server {
// ...
const app = new Koa<State, Context>()
const server = resolveServer(config, app.callback())
// ...
const listen = server.listen.bind(server)
server.listen = (async (...args: any[]) => {
if (optimizeDeps.auto !== false) {
await require('../optimizer').optimizeDeps(config)
}
return listen(...args)
}) as any
return server
}
Because the ESM in the browser cannot obtain the content of the imported module, we need to use tools such as Webpack. If we do not refer to the relative path of the module, but refer to node_modules, and directly import xxx from'xxx', the browser will not be able to get it. Knowing that there are node_modules in your project, you can only find modules through relative or absolute paths.
This is the core of vite's implementation: intercept the browser's request to the module and return the processed result (the implementation mechanism of vite will be explained in depth at the end of the article).
3. Generate project structure:
The code structure of entry index.html and main.js is:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
// main.js
// 只是引用的是最新的 vue3 语法,其余相同
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
createApp(App).mount('#app')
4. Enter the project directory: cd myVue3
5. Install related modules: npm install
6. Download the module:
7. Start the project: npm run dev
8. Enter the address, when we see this page, it means that the project has been successfully started.
Vite's implementation mechanism
1. /@module/ prefix
Comparing the main.js under the project with the main.js actually loaded under the development environment, you can find that the code has changed.
Main.js under the project:
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
createApp(App).mount('#app')
Actually loaded main.js:
import { createApp } from '/@modules/vue.js'
import App from '/src/App.vue'
import '/src/index.css?import'
createApp(App).mount('#app')
In order to solve the problem of import xxx from'xxx' error report, vite has made a unified treatment for this kind of resource path, that is, add a /@module/ prefix.
In the koa middleware of the src/node/server/serverPluginModuleRewrite.ts source code, you can see that vite has done a layer of processing on import, and the process is as follows:
· Get request body in koa middleware
· es-module-lexer to get the content of import
· Determine whether the imported resource is an absolute path, which is absolutely regarded as an npm module
· Return the processed resource path: "vue" => "/@modules/vue"
2. Support /@module/
You can see the general processing logic in /src/node/server/serverPluginModuleResolve.ts:
· Get request body in koa middleware
· Judge whether the path starts with /@module/, if it is the package name
· Go to node_module to find this library, and return the corresponding content based on package.json
3. File compilation
Through the previous article, we know the processing process of js module, how to deal with vue, css, ts and other files?
Take the vue file as an example. Use vue-loader in webpack to compile single-file components, where vite also intercepts the request to the module and executes a real-time compilation.
Through the App.vue under the project and the actual loaded App.vue, the changes are found.
App.vue under the project:
<template>
![](./assets/logo.png)
<HelloWorld msg="Hello Vue 3.0 + Vite" />
</template>
<script>
import HelloWorld from './components/HelloWorld.vue';
export default {
name: 'App',
components: {
HelloWorld,
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
App.vue actually loaded:
import HelloWorld from '/src/components/HelloWorld.vue';
const __script = {
name: 'App',
components: {
HelloWorld,
},
};
import "/src/App.vue?type=style&index=0&t=1592811240845"
import {render as __render} from "/src/App.vue?type=template&t=1592811240845"
__script.render = __render
__script.__hmrId = "/src/App.vue"
__script.__file = "/Users/wang/qdcares/test/vite-demo/src/App.vue"
export default __script
It can be seen that a .vue file is split into three requests (corresponding to script, style, and template respectively). The browser will first receive the response from App.vue containing script logic, and then parse the path to template and style, and then again Initiate an HTTP request to request the corresponding resource. At this time, Vite intercepts it and processes it again and returns the corresponding content.
// App.vue?type=style
import { updateStyle } from "/vite/hmr"
const css = "\n#app {\n font-family: Avenir, Helvetica, Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-align: center;\n color: #2c3e50;\n margin-top: 60px;\n}\n"
updateStyle("7ac74a55-0", css)
export default css
// App.vue?type=template
import {createVNode as _createVNode, resolveComponent as _resolveComponent, Fragment as _Fragment, openBlock as _openBlock, createBlock as _createBlock} from "/@modules/vue.js"
const _hoisted_1 = /*#__PURE__*/
_createVNode("img", {
alt: "Vue logo",
src: "/src/assets/logo.png"
}, null, -1 /* HOISTED */
)
export function render(_ctx, _cache) {
const _component_HelloWorld = _resolveComponent("HelloWorld")
return (_openBlock(),
_createBlock(_Fragment, null, [_hoisted_1, _createVNode(_component_HelloWorld, {
msg: "Hello Vue 3.0 + Vite"
})], 64 /* STABLE_FRAGMENT */
))
}
Vite's processing of other types of files is almost all similar logic, that is, according to the different file types requested, different compilation processing results are made.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。