这是为什么呢?原来啊对付vite而言,它会先读取到该项目的代码,然后将唯一的html文件输出给浏览器,让浏览器加载,然后加载引入JavaScript文件,此时浏览器就会向vite要JavaScript文件,vite也就会去项目中找JavaScript文件.利用vite构建工具,那么该项目的文件会被浏览器当做资源要求,将全体vue文件都做成接口要求.
手搓实现vite的事情流程这是该项目的目录构造,我们利用npm init -y初始化该项目,并将vue的源码下载过来了方便利用. 我们现在目的是打造一个能实现vite事情流程一样的项目出来.创建了一个叫作simple-vite.js文件.
这里我们利用的Node.js原生所具有的模块.

ini
代码解读
复制代码
const http = require('http') const fs = require('fs') const path = require('path')
http用于创建一个做事,fs和path则是用于读取文件内容或者写文件内容以及获取文件相对应的路由.
javascript
代码解读
复制代码
const server = http.createServer((req, res) => { }) server.listen(5173, () => { console.log('项目运行在 5173'); })
第一步我们在req中解构出我们发生要求的url地址,我们拿到这url,去判断是要求一个什么文件,假设要求的是根目录文件,也便是说url === '/'我们就返回唯一的html文件给浏览器.如果要求的是一个js文件,那么我们就通过path.resolve(__dirname, url.slice(1))拿到该文件的路径,然后返回给浏览器,这里我们打造了一个函数用于重构一下import引入的写法.
javascript
代码解读
复制代码
function rewriteImport(content) { return content.replace(/ from ['|"]([^'"]+)['|"]/g, function(s0, s1) { if (s1[0] !== '.' && s1[1] !== '/') { return ` from '/@modules/${s1}'` } else { return s0 } }) }
变成了这样,而不是import {createApp} from "vue",这样子方便我们后续去找vue的源码利用.
如果url读取到的是url.startsWith('/@modules/')这样我们就须要在node_modules文件夹下找.假设这个路径是/@modules/vue为了方便我们在node_modules中查找我们就须要将/@modules/vue利用replace方法变成/vue这样我们就能准确找到该文件夹了,那么源码会在哪里呢?会在vue文件夹下的package.json中的module,将其返回给浏览器即可.
如果读取到的是一份vue文件的话,首先我们先获取到该文件的完全路径.我们都是找一个Vue文件是包括template,script,style三部分的,以是我们就要借助Vue.js 生态系统中的两个主要模块@vue/compiler-sfc 和 @vue/compiler-dom,通过const { descriptor } = compilerSfc.parse(fs.readFileSync(p, 'utf8'))解析出vue文件的各个部分。然后动态天生一个JavaScript文件.并且将<template>部分的编译结果作为渲染函数导入进来。
dart
代码解读
复制代码
const content = ` ${rewriteImport(descriptor.script.content.replace('export default', 'const __script = '))} import { render as __render } from "${url}?type=template" __script.render = __render export default __script `
当客户端要求带有 type=template 查询参数的 .vue 文件时,做事器会返回该文件的模板部分经由编译后的 JavaScript 代码
arduino
代码解读
复制代码
else if (query.get('type') === 'template') { // 问我要 App.vue 的 template 部分 const template = descriptor.template const render = compilerDom.compile(template.content, {mode: 'module'}).code res.writeHead(200, {'Content-Type': 'application/javascript'}) res.end(rewriteImport(render)) }
当url.endsWith('.css')判断为一个css文件,我们须要处理css文件的要求,并将css文件的转化成为一个JavaScript文件,该文件会帮助我们再客户端动态天生一份style.
然后我们运行一下该项目看看是否和vite一样发送接口要求获取资源文件
该项目的紧张功能的完全代码:
php
代码解读
复制代码
const http = require('http') const fs = require('fs') const path = require('path') const compilerSfc = require('@vue/compiler-sfc') const compilerDom = require('@vue/compiler-dom') function rewriteImport(content) { return content.replace( if (s1[0] !== '.' && s1[1] !== '/') { return ` from '/@modules/${s1}'` } else { return s0 } }) } const server = http.createServer((req, res) => { const { url } = req const query = new URL(req.url, `http://${req.headers.host}`).searchParams; if (url === '/') { res.writeHead(200, { 'content-type': 'text/html' }) let content = fs.readFileSync('./index.html', 'utf-8') res.end(content) } else if (url.endsWith('.js')) { // '/src/main.js' const p = path.resolve(__dirname, url.slice(1)) res.writeHead(200, { 'content-type': 'application/javascript' }) let content = fs.readFileSync(p, 'utf-8') res.end(rewriteImport(content)) } else if (url.startsWith('/@modules/')) { // '/@modules/vue' const prefix = path.resolve(__dirname, 'node_modules', url.replace('/@modules/', '')) const module = require(prefix + '/package.json').module const p = path.resolve(prefix, module) const content = fs.readFileSync(p, 'utf-8') res.writeHead(200, { 'content-type': 'application/javascript' }) res.end(rewriteImport(content)) } else if (url.indexOf('.vue') !== -1) { const p = path.resolve(__dirname, url.split('?')[0].slice(1)) const { descriptor } = compilerSfc.parse(fs.readFileSync(p, 'utf8')) if (!query.get('type')) { res.writeHead(200, {'Content-Type': 'application/javascript'}) const content = ` ${rewriteImport(descriptor.script.content.replace('export default', 'const __script = '))} import { render as __render } from "${url}?type=template" __script.render = __render export default __script ` res.end(content) } else if (query.get('type') === 'template') { const template = descriptor.template const render = compilerDom.compile(template.content, {mode: 'module'}).code res.writeHead(200, {'Content-Type': 'application/javascript'}) res.end(rewriteImport(render)) } } else if (url.endsWith('.css')) { const p = path.resolve(__dirname, url.slice(1)) const file = fs.readFileSync(p, 'utf8') const content = ` const css = "${file.replace(/\n/g,'')}" let link = document.createElement('style') link.setAttribute('type','text/css') document.head.appendChild(link) link.innerHTML = css export default css ` res.writeHead(200, {'Content-Type': 'application/javascript'}) res.end(content) } }) server.listen(5173, () => { console.log('项目运行在 5173'); })
本文到此就结束了,希望对大家有所帮助,如有不敷,恳请各位大侠指示一二,让我功力精进一二!
!
!
原文链接:https://juejin.cn/post/7418797990304858175