current position:Home>[let's implement a simple vite!] Chapter 4 - compiling single file components

[let's implement a simple vite!] Chapter 4 - compiling single file components

2022-04-29 11:41:43It's a foreign persimmon

Form writing habits together ! This is my participation 「 Nuggets day new plan · 4 Yuegengwen challenge 」 Of the 14 God , Click to see the event details .

Chapter four - Compile a single file component

Take the book back  【 To achieve a simple Vite Well 】! The third chapter - Load third party module , Let's deal with   Compile a single file component The problem of .

The browser can't handle what we're doing main.js Single file module and style module referenced in , Browsers can only handle js modular , So single file module , It needs to be converted into... In our server js file

Reference resources

Next , We open the browser reference vite How to deal with single file components in , Other modules are not listed in the following table .

image.png

image.png

From here we can see , When we request a single file component , The server compiles single file components , And return the compiled file to the browser , Then we'll ask again The module marked in the figure

image.png This request is for , Let the server convert a single file to render function . And then again App.vue Use this function again in

Compile a single file component

Vue3 Provides us with a compilation tool compiler-sfc, Especially great !

1. Install the plug-in

```js
npm i @vue/compiler-sfc
```
 Copy code 

2. Create middleware

```js
const compilerSFC = require('@vue/compiler-sfc')
...
// 4. Process single file components 
app.use(async (ctx, next) => {

  await next()
})

```
 Copy code 

3. Determine whether it is a single file component

To determine whether it is a single file component , That is, whether the requested road strength is .vue ending

if(ctx.path.endsWith('.vue')) {}
 Copy code 

A small line of code can handle , Hey

4. Get file content

Next we need to get ctx.body The content in , And then call compiler-sfc Of parse Method

 //  Need to convert stream 
const contents = await stremToString(ctx.body)
const { descriptor } = compilerSFC.parse(contents)
 Copy code 

there parse and Vue2 There are some differences , Vue2 in parse The return is AST object , Here is also an object , There are two members in this object , Namely : Description object and of single file component Error object generated during compilation

5. Our processing request does not contain type Request

A single file is processed twice , This time our request does not contain type At the request of

let code
//  without type request , That was the first request 
if(!ctx.query.type) {
  code = descriptor.script.content
  console.log(code)
}
 Copy code 

Here we are , A print code Take a look at the code

image.png then , We're opening up vite The code in , We need to change the content of this output to and Vite Same , To put it bluntly, it's plagiarism !

image.png

image.png After copying the above code , You have the following output

code = code.replace(/export\s+default\s+/g, 'const __script = ')
code += ` import { render as __render } from "${ctx.path}?type=template" __script.render = __render export default __script `
 Copy code 

6. Text to stream file


const { Readable } = require('stream')
...
const stringToStream = text => {
  const stream = new Readable()
  stream.push(text)
  stream.push(null) //  Mark the end 
  return stream
}
...
// 4. Process single file components 
app.use(async (ctx, next) => {
  if(ctx.path.endsWith('.vue')) {
    //  Need to convert stream 
    const contents = await stremToString(ctx.body)
    const { descriptor } = compilerSFC.parse(contents)
    let code
    //  without type request , That was the first request 
    if(!ctx.query.type) {
      code = descriptor.script.content
      code = code.replace(/export\s+default\s+/g, 'const __script = ')
      code += ` import { render as __render } from "${ctx.path}?type=template" __script.render = __render export default __script `
    }
    ctx.type = 'application/javascript'
    ctx.body = stringToStream(code)
  }
  await next()
})
 Copy code 

7. compile

 if (ctx.query.type === 'template') {
      const templateRender = compilerSFC.compileTemplate({ source: descriptor.template.content })
      code = templateRender.code
    }
 Copy code 

And then modify middleware 2 Of Part content

// 2.  Before returning the static file to the browser, determine whether it is **js modular **, If so, modify the module path to `/@/modules/${ Module name }`
app.use(async (ctx, next) => {
  if(ctx.type === 'application/javascript') {
    ...
    ctx.body = contents
      .replace(/(from\s+['"])(?![\.\/])/g, '$1/@modules/')
      .replace(/process\.env\.NODE_ENV/g, '"development"')
  }
})
 Copy code 

Come here , Our code is finished

image.png here , We haven't dealt with , Style and picture module , After that , We'll do some processing At present, the complete code : gitee.com/liuyinghao1…

copyright notice
author[It's a foreign persimmon],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/04/202204291141382936.html

Random recommended