This article only analyzes the basic vite and focuses on the vue Reload principle of HMR for the time being.

We know that vite doesn’t need to be packaged, it relies on the browser’s ESM modularity, for example if we write it in HTML

<script type='module' src="/src/main.js"></script>
Copy the code

The browser then issues an http://…. / SRC /main.js is a request to vite’s service, which koa wrote, so we give it fs.read HTML from our project, but Vite also has client-side code that accepts notification of hot updates. So we also need to inject this thing in, so that we have client.js on the browser side,

Then the browser will continue to request.js through these two inserted script tags, and after our KOA receives it, it will return to the fs.read file. I still put vue2 here for the time being, because the company still uses VUe2, but the analysis process will still talk about vue3.

This is the original main.js file

import Vue from 'vue'

import App from './components/App.vue'

let app = new Vue({

Render: h => h(App) // createComponent when h accepts obj

}).$mount('#app')

Main.js will request a vue third-party library. For third-party libraries, we know that we need to change the prefix to /@module/vue, otherwise the browser will report an error. We’ll also go to reWriteImport for third-party library dependencies,

If we had our own app.vue, we would read it under SRC, which is fine because the browser will automatically concatenate./components/ app.vue based on the current path

const vue = fs.readFileSync(p, 'utf-8')

cacheEntry.set(url, vue)

const ast = compilerSFC.parse(vue)

Of course, vue can’t be passed directly after FS, we need to use compilerSFC to parse an AST object, spell things out and fetch them back, this is mainly template processing, you need to send a separate request URL, ok? The template suffix

res = ` import {render as _render} from '${url}? type=template' ${rewriteImport(aa)} let compVm _script.render = _render .... `

In this case, _script.render is also a js return value, which of course needs to be handled separately

HMR :(with vue3)

When we change a file, we need to use the third-party library Chokidar to listen for changes in the file. There are several cases. If it is a vue file or a style file, we will look at vue for the moment.

A cacheEntry is a cache that we do when we first read a file

  chokidar.watch('./src').on('change', (fpath) => {    if (fpath.endsWith('vue')) {      let vueFile = fpath.replace(path.dirname(fpath), "")      let cache = cacheEntry.get(vueFile)      if (isTemplateBlocksEqual(vueFile, cache)) {           //todo      } else {      }      ws.send(vueFile.slice(1));    } else {      //todo    }  });
Copy the code

We take it out of the cache and compare it to the new file to figure out exactly what’s changed in the file,

If the template has changed, just issue a vue-rerender, meaning to rerender the tempalte once again. If not, then the script in the file has changed, issue vue-reload. Let’s see what happens when the client receives it

Call _vue_hmr_runtime_.reaload and re-import the new M.fault. If you go into this function you can see that we sent the new newComp to extend to the old record.com.

{Component :{}, Instances :[]},instances:[]},instances:[]},instances:[]},instances:[]

Component changes affect instance.type on all instances because they are referenced, and update each component ** from its parent. But I’m not sure… QueueJob is used to prevent the parent from repeating upate multiple times.

Then look inside the update,

instance.update = effect(function componentEffect() {

if (! instance.isMounted) { // ... }

else { //... const nextTree = renderComponentRoot(instance);

const prevTree = instance.subTree;

instance.subTree = nextTree;

if ((process.env.NODE_ENV ! == 'production')) {

startMeasure(instance, `patch`);

}

patch(prevTree, nextTree, // parent may have changed if it's in a teleport

next.el = nextTree.el; / /...

}

This is wrapped in effect, presumably to collect dependencies,

RenderComponentRoot: normalizeVnode (render. Call ())

Then you get into the pacTCH process

I’ll write it here for now, and I’ll attach the Github code address