This article will show you what Vite does to the browser's request

This article will show you what Vite does to the browser's request

Working principle:

  • type="module" ES Module native support in browsers. If the browser supports type="module", we can write it in es6 modular way. The browser will send another http request for the file we need to import and then send it to the server. No packaging is required during the development phase
  • Pre-packaged third-party dependencies
  • Start a development server to handle resource requests

A picture explains the principle of Vite:

What does the browser do?

Host file index.html

<script type="module" src="/src/main.js"></script>

After the browser obtains the resources in the host file, it finds that it needs to request the main.js file again. A resource request for main.js will be sent to the server again.

main.js

In main, it can be found that the browser once again initiates resource requests for the two files vue.js?v=d253a66c and App.vue?t=1637479953836.

The server compiles the content in App.vue and returns it to the browser. As shown in the figure below, the logo image and text are compiled into a static node of _hoisted_.

From the request header, we can also see that the sfc file has become a js file that can be recognized by the browser (the app.vue file must have script content to be compiled into js). For the browser, what is executed is a piece of js code.

Other bare modules

If there are other dependencies in the vue dependency, the browser will still initiate a resource request again to obtain the corresponding resources.

Learn about pre-packaging

For the loading of third-party dependencies (bare modules), vite packages them in advance and puts them under node_modules/.vite. When starting the project, download the file directly from this path.

From the above figure, we can see that the path changes when the bare module is introduced.

What does the server do?

To sum up: the server processes the files with special suffixes and returns them to the front end for display.

We can simulate vite's devServe and start a local service using koa middleware.

//Introduce dependencies const Koa = require('koa')
const app = new Koa()
const fs = require('fs')
const path = require('path')
const compilerSfc = require('@vue/compiler-sfc')
const compilerDom = require('@vue/compiler-dom')

app.use(async (ctx) => {
 const { url, query } = ctx.request
 //Write all the code for processing request resources here})
app.listen(3001, () => {
  console.log('dyVite start!!')
})

Request home page index.html

 if (url === '/') {
    const p = path.join(__dirname, './index.html') // absolute path // Home page ctx.type = 'text/html'
    ctx.body = fs.readFileSync(p, 'utf8')
  }

Looking at the picture above, you know that our host file has been requested successfully. It's just that the browser sends another request for the main.js file to the server. At this time, we also need to judge and process the main.js file.

Request files ending with .js

After we deal with the above situation, emmmm. . . It was found that there were still many other resource requests in main.

Basic js file

main file:

console.log(1)

Processing main:

else if (url.endsWith('.js')) {
   // Respond to js request const p = path.join(__dirname, url)
   ctx.type = 'text/javascript'
   ctx.body = rewriteImport(fs.readFileSync(p, 'utf8')) // Processing dependent functions}

Handle the dependencies in main

Do you think there is only one output in main? Too naive. Can this be handled?

main file:

import { createApp, h } from 'vue'
createApp({ render: () => h('div', 'helllo dyVite!') }).mount('#app')

emmm. . . It should be possible!

We can turn the address imported in main into a relative address.

Add /@modules/ to the bare module path. Then identify the files in /@modules/ (bare module files).

// Convert the readable file address into a relative address // Regular replacement rewrites the import into a relative address // import { createApp } from 'vue' => import { createApp } from '/@modules/vue'
function rewriteImport(content) {
  return content.replace(/ from ['|"](.*)['|"]/g, function (s0, s1) {
    // s0 matches the string, s1 groups the content // Is it a relative path if (s1.startsWith('./') || s1.startsWith('/') || s1.startsWith('../')) {
      // Return directly to return s0
    } else {
      return `from '/@modules/${s1}'`
    }
  })
}

For third-party dependencies, vite uses pre-packaged requests to request internal resources under its own server/node_modules/.vite/.

We can simplify it a bit and get the corresponding resources from node_modules on the client using the dependency name.

  else if (url.startsWith('/@modules/')) {
    // Loading of bare modules const moduleName = url.replace('/@modules/', '')
    const pre![1637477009328](imgs/1637477009328.png)![1637477009368](imgs/1637477009368.png)'s address const module = require(prefix + '/package.json').module
    const filePath = path.join(prefix, module) // Get the address of the file to be loaded // Read related dependencies const ret = fs.readFileSync(filePath, 'utf8')
    ctx.type = 'text/javascript'
    ctx.body = rewriteImport(ret) //There may be dependencies inside the dependency, so recursion is required}

When rendering in main, the following error will be reported:

The files we load are all libraries executed by the server. Code for the node environment may be generated inside, so we need to judge the environment variables. If you are developing, some warning messages will be output, but there will be no warning messages on the front end. So we need to mock it and tell the browser our current environment.

Add process environment variables to html.

  <script>
   window.process = { env: { NODE_ENV: 'dev' } }
  </script>

At this point the main file is loaded.

But this is far from achieving our goal!

What we need is a server that can compile vue files!

Processing .vue files

main.js file:

import { createApp, h } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')

In the vue file, it is loaded modularly.

When processing vue files, we need to process the parameters carried after .vue.

Here, we simplify and only consider the template and sfc cases.

else if (url.indexOf('.vue') > -1) {
    // Process vue file App.vue?vue&type=style&index=0&lang.css
    // Read vue content const p = path.join(__dirname, url.split('?')[0])
    // compilerSfc parses sfc to obtain ast
    const ret = compilerSfc.parse(fs.readFileSync(p, 'utf8'))
    // App.vue?type=template
    // If the request does not have query.type, it means it is sfc
    if (!query.type) {
      // Process internal script
      const scriptContent = ret.descriptor.script.content
      // Convert the default export configuration object to a constant const script = scriptContent.replace(
        'export default ',
        'const __script = ',
      )
      ctx.type = 'text/javascript'
      ctx.body = `
  ${rewriteImport(script)}
  // Template parsing is converted to a separate request for a resource import {render as __render} from '${url}?type=template'
  __script.render = __render
  export default __script
`
    } else if (query.type === 'template') {
      const tpl = ret.descriptor.template.content
      // Compile including render module const render = compilerDom.compile(tpl, { mode: 'module' }).code
      ctx.type = 'text/javascript'
      ctx.body = rewriteImport(render)
    }
  }

Processing image paths

Read directly from the client.

 else if (url.endsWith('.png')) {
   ctx.body = fs.readFileSync('src' + url)
  }

Summarize

This is the end of this article about what Vite does to browser requests. For more information about Vite browser requests, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Vite builds projects and supports micro frontends
  • Vite+Electron to quickly build VUE3 desktop applications
  • How to add Vite support to old Vue projects
  • Vite2.0 Pitfalls
  • Vue3.0+vite2 implements dynamic asynchronous component lazy loading
  • Implementation of vite+vue3.0+ts+element-plus to quickly build a project
  • Steps to build the vite+vue3+element-plus project
  • Learn the principles of Vite

<<:  MySQL database Load Data multiple uses

>>:  The problem of two requests when the src attribute value of the img tag is empty (non-IE browser)

Recommend

Introduction to Linux File Compression and Packaging

1. Introduction to compression and packaging Comm...

The phenomenon of margin-top collapse and the specific solution

What is margin-top collapse Margin-top collapse i...

12 Useful Array Tricks in JavaScript

Table of contents Array deduplication 1. from() s...

Summary of some common writing methods that cause MySQL index failure

Preface Recently, I have been busy dealing with s...

How to implement a single file component in JS

Table of contents Overview Single file components...

CentOS7 64-bit installation mysql graphic tutorial

Prerequisites for installing MySQL: Install CentO...

Div css naming standards css class naming rules (in line with SEO standards)

There are many tasks to be done in search engine o...

MYSQL's 10 classic optimization cases and scenarios

Table of contents 1. General steps for SQL optimi...

Detailed explanation of binary and varbinary data types in MySQL

Preface BINARY and VARBINARY are somewhat similar...