什么是Vite?

  • 法语:轻量化,快速
  • 基于VUE3 非 打包开发服务器,请注意,它是个开发服务器哇!!
  • 快速开发,按需编译,不再等待整个应用编译完成
  • 基于原生模块系统ESModule实现
  • 说白了,就是一个node.js服务器,帮你运行起来代码,让你可以调试
  • 它和我们部署的webserver不同的是,里面内置了websoket,当监听到代码改变 通过websoket更新代码,实现热更新

实现原理

  • 使用export import 方式导入导出模块,同时实现按需加载
  • 高度依赖module script 特性

下面开始搞事情吧~~

  • 兼容性注意
  • Vite 需要 Node.js 版本 >= 12.0.0。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。

新建一个文件夹,执行命令,构建一个 Vite + Vue 项目

# npm 6.x
npm create vite@latest my-vue-app --template vue # npm 7+, extra double-dash is needed:
npm create vite@latest my-vue-app -- --template vue

进入项目,执行

 cd my-vue-app
npm install
npm run dev

恭喜哇,项目跑起来啦~

  • 复制地址用浏览器访问

打开项目看一下我们的目录

看个厉害的e

是不是很好奇,为什么会可以直接加载.vue文件呢???接下来我们就开始探索一下吧

  • 新建一个文件夹 vite,然后进去执行下面命令
npm init -y
  • 然后生成了一个package.json文件



  • 安装依赖 koa 用来实现node服务器,它帮我们封装了node-http哦
npm install koa

  • 接下来我们看一下,当我们执行 npm run dev 的时候,实际是执行了下面的命令,如果我们想要实现这个命令,我们又该怎么做呢?

新建命令执行入口 vite\bin\www.js

配置package.json

"bin":"./bin/www.js",

配置执行环境(这个是必须写的哇)

#! /usr/bin/env node

// 这个就是我们的入口文件啦~~

console.log('xiaojin love code!')

配置环境映射?怎么说,这个就是把这个环境临时搞到全局,让cmd也可以用

npm link

当然,还有更好玩的东西

  • 我把命令改了一下,好玩多了
{
"name": "vite",
"version": "1.0.0",
"description": "",
"main": "index.js",
"bin":{
"xiaojin": "./bin/www.js"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"koa": "^2.13.4"
}
}

新建一个文件编写服务代码,先跑一把玩一下 vite\src\server.js

const Koa = require('koa')
const { Static } = require('vue')
function createServer() {
let app = new Koa()
// 实现静态服务功能,访问我们的服务器可以返回对应的文件koa-Static
return app
}
createServer().listen(8088,()=>{
console.log('xiaojin server is start at 8088')
})

使用nodemon来监控代码变化,然后来自动重新执行,我们要执行下面的命令,其实我之前用过另一个叫做 surpervisor,也是可以的

npm i nodemon

在外层新建一个配置文件,监控这个目录的代码变化 nodemon.json

{
"watch":["vite"],
"exec":"xiaojin"
}



记得配置这个

重新执行nodemon命令试一把,记得,是在外层哦

nodemon

下个步骤,等我今天晚上熬夜写完继续补充

来啦~~

接下来我们来实现,通过服务访问静态资源

  • 就直接用我们外层的那个文件 index.html,添加几句测试代码
<!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>
  • 安装 koa-static
PS C:\jin_files\code\testDemo\vite-demo\my-vue-app> cd vite
PS C:\jin_files\code\testDemo\vite-demo\my-vue-app\vite> npm install koa-static

  • 新增vite\src\serverPluginServerStatic.js,编写静态插件调用的逻辑代码
const static = require('koa-static')

function staticPlugin({app,root}) {
app.use(static(root)) // 这个root指的是根目录哦~~当我访问我的服务localhost:8088的时候,它会去找根目录下面的index.html
}
module.exports = staticPlugin
  • 在server.js里,编辑代码,搞一下插件,先来实现静态服务功能
const Koa = require('koa')
const staticPlugin = require('./serverPluginServerStatic')
function createServer() {
let app = new Koa()
// 实现静态服务功能,访问我们的服务器可以返回对应的文件koa-Static
const context = { // 创建一个上下文,给不同插件共享功能
app,
root:process.cwd() // 这个目录就在vite-vue
}
const resolvePlugin = [staticPlugin]
resolvePlugin.forEach(plugin => plugin(context))
return app
}
createServer().listen(8088,()=>{
console.log('xiaojin server is start at 8088')
console.log('修改代码跑一把')
})
  • 关键代码标记给大家:



  • 然后,去浏览器里输入http://localhost:8088/,看一下效果吧~~

  • 很成功哇,我们的服务调用了静态资源,运行起来啦

配置一下,访问public目录试一把

  • 根路径下,创建测试文件public\test.txt
I am xiaojin ,I love code~

  • 进入vite\src\serverPluginServerStatic.js添加代码
const static = require('koa-static')
const path = require('path')
function staticPlugin({app,root}) {
app.use(static(root)) // 这个root指的是根目录哦~~当我访问我的服务localhost:8088的时候,它会去找根目录下面的index.html
app.use(static(path.resolve(root,'public')))
}
module.exports = staticPlugin

  • 访问http://localhost:8088/test.txt,试一把~
  • 成功啦~~

打开F12看一下

  • 啊哦~ 报错了
  • Uncaught TypeError: Failed to resolve module specifier "vue". Relative references must start with either "/", "./", or "../".



怎么才能正常显示我们的资源不报错呢???就是说,如何让这句话 import { createApp } from 'vue' 正常执行?

冷静分析

  • es6模块会自动发送请求,查找相应文件
  • vite所做的事情就是: 根据你需要的文件,进行改写
  • 我们发请求,请求了main.js文件
  • 我们可以在后端将main.js里的内容进行改写操作,将所有不带./ ../ / 的全部加一个/@modules去寻找相应资源,不就不会报错了吗??

添加模块重写代码逻辑,重写我们的请求路径哇~~

  • 新建文件 vite\src\serverPluginModuleRewrite.js

function reWritePlugin({app,root}) {
app.use(async (ctx, next) =>{
// todu:
await next() // 先走静态服务,因为默认会先执行 静态服务中间件,将结果放到ctx.body
// 需要将流转换为字符串,而且我们只需要处理其中JS的引用问题
console.log('reWritePlugin:')
if(ctx.body && ctx.response.is('js')){
console.log(ctx.body)
console.log('ctx.body已打印完毕')
} })
}
module.exports = reWritePlugin
  • 添加插件引用代码到vite\src\server.js
const reWritePlugin = require('./serverPluginModuleRewrite')
function createServer() {
...
const resolvePlugin = [
reWritePlugin, // 重写请求路径插件 ,为什么这么写这个顺序呢,原因解释放到插件里吧~~
staticPlugin, // 静态服务插件
]
...
}

  • 访问http://localhost:8088/,然后查看你的命令行

好了,我要睡觉了,明天继续写

睡觉中......

继续开工啦~~

接下来开始读取文件流,

  • 解决 vite\src\serverPluginModuleRewrite.js 中需要将流转换为字符串,而且我们只需要处理其中JS的引用问题
  • 创建vite\src\utils.js
const {Readable} = require('stream')
async function readBody(stream) {
if(stream instanceof Readable) {
return new Promise((resolve,reject)=>{
let res = ''
stream.on('data',function(chunk){
res += chunk
})
stream.on('end',function() {
resolve(res)
})
})
}else{
return stream
}
}
exports.readBody = readBody
  • 修改代码vite\src\serverPluginModuleRewrite.js
const { readBody } = require("./utils")

function reWritePlugin({app,root}) {
app.use(async (ctx, next) =>{
// todu:
await next() // 先走静态服务,因为默认会先执行 静态服务中间件,将结果放到ctx.body
// 需要将流转换为字符串,而且我们只需要处理其中JS的引用问题
console.log('reWritePlugin:')
if(ctx.body && ctx.response.is('js')){
// console.log(ctx.body) // 这个打出来是main.js的文件流
let res = await readBody(ctx.body)
console.log(res)
console.log('ctx.body已打印完毕')
} })
}
module.exports = reWritePlugin



访问http://localhost:8088/,试一把

打印完成啦~~开心(),接下来我们开始解析并改写文件内容(就是把VUE文件解析处理为 @/modules)

  • 我们需要安装插件,处理字符串
  • es-module-lexer 可以解析所有的import语法
  • magic-string 处理字符串,把字符串变成对象类型,引用类型
  • 外层执行:

npm install es-module-lexer magic-string

  • 给 vite\src\serverPluginModuleRewrite.js 添加解析代码
const {parse} = require('es-module-lexer')
function reWriteImports(source) {
let imports = parse(source)
console.log(imports)
}

  • 刷新一下页面,看打印结果
修改代码跑一把
reWritePlugin:
reWritePlugin:
[
[
{ n: 'vue', s: 27, e: 30, ss: 0, se: 31, d: -1, a: -1 },
{ n: './App.vue', s: 49, e: 58, ss: 32, se: 59, d: -1, a: -1 }
],
[],
false
]
reWriteRes已打印完毕
  • 解释一下这个是什么哦

开始编写重写文件逻辑啦

const { readBody } = require("./utils")
const { parse } = require('es-module-lexer')
const MagicString = require('magic-string')
function reWriteImports(source) {
let imports = parse(source)[0]
// console.log(imports)
// 路径处理逻辑开始咯
let ms = new MagicString(source)
if (imports.length > 0) {
imports.forEach(_ => {
let { s, e, n } = _
let id = n
console.log('old id :', id)
if (/^[^\/\.]/.test(id)) {
id = `/@modules/${id}`
console.log('new id :', id)
ms.overwrite(s, e, id)
}
})
}
return ms.toString()
} function reWritePlugin({ app, root }) {
app.use(async (ctx, next) => {
// todu:
await next() // 先走静态服务,因为默认会先执行 静态服务中间件,将结果放到ctx.body
// 需要将流转换为字符串,而且我们只需要处理其中JS的引用问题
console.log('reWritePlugin:')
if (ctx.body && ctx.response.is('js')) {
// console.log(ctx.body) // 这个打出来是main.js的文件流
let res = await readBody(ctx.body)
const reWriteRes = reWriteImports(res)
ctx.body = reWriteRes
// console.log(reWriteRes)
console.log('reWriteRes已打印完毕')
} })
}
module.exports = reWritePlugin
  • 重点改了这里哦



  • 给大家看一下打印出来的内容

old id : vue
new id : /@modules/vue
old id : ./App.vue

跑一把试一下,main.js已经被改写成功了呢~~~~

继续睡觉啦,明天接着写~~

从0到1手把手实现vite的更多相关文章

  1. 从0开始,手把手教你用Vue开发一个答题App01之项目创建及答题设置页面开发

    项目演示 项目演示 项目源码 项目源码 教程说明 本教程适合对Vue基础知识有一点了解,但不懂得综合运用,还未曾使用Vue从头开发过一个小型App的读者.本教程不对所有的Vue知识点进行讲解,而是手把 ...

  2. 从0开始,手把手教你用Vue开发一个答题App

    项目演示 项目演示 项目源码 项目源码 教程说明 本教程适合对Vue基础知识有一点了解,但不懂得综合运用,还未曾使用Vue从头开发过一个小型App的读者.本教程不对所有的Vue知识点进行讲解,而是手把 ...

  3. 从0开始,手把手教你使用React开发答题App

    项目演示地址 项目演示地址 项目源码 项目源码 其他版本教程 Vue版本 小程序版本 项目代码结构 前言 React 框架的优雅不言而喻,组件化的编程思想使得React框架开发的项目代码简洁,易懂,但 ...

  4. ActionMQ5.8.0 JMS实例 手把手详细图解

    出自:http://blog.csdn.net/tongjie008/article/details/40687087 ActionMQ 是开源的JMS实现 1.下载ActiveMQ 去官方网站下载: ...

  5. 从0开始,手把手教你开发并部署上线一个知识测验微信小程序

    上线项目演示 微信搜索[放马来答]或扫以下二维码体验: 项目源码 项目源码 其他版本 Vue答题App实战教程 Hello小程序 1.注册微信小程序 点击立即注册,选择微信小程序,按照要求填写信息 2 ...

  6. vite 动态 import 引入打包报错解决方案

    关注公众号: 微信搜索 前端工具人 ; 收货更多的干货 原文链接: 自己掘金文章 https://juejin.cn/post/6951557699079569422/ 关注公众号: 微信搜索 前端工 ...

  7. 快速新建并配置一个eslint+prettier+husky+commitlint+vue3+vite+ts+pnpm的项目

    前置准备 一台电脑 vscode pnpm vscode插件:ESLint v2.2.6及以上 vscode插件:Prettier - Code formatter v9.5.0及以上 vscode插 ...

  8. React Native教程

    React Native 中文网  http://reactnative.cn/ 相关资料======================= React-Native学习指南 https://github ...

  9. Vue3发布半年我不学,摸鱼爽歪歪,哎~就是玩儿

    是从 Vue 2 开始学基础还是直接学 Vue 3 ?尤雨溪给出的答案是:"直接学 Vue 3 就行了,基础概念是一模一样的." 以上内容源引自最新一期的<程序员>期刊 ...

  10. ZAM 3D 制作简单的3D字幕 流程(二)

    原地址:http://www.cnblogs.com/yk250/p/5663907.html 文中表述仅为本人理解,若有偏差和错误请指正! 接着 ZAM 3D 制作简单的3D字幕 流程(一) .本篇 ...

随机推荐

  1. import cv2报错

    其实是没错的,不过有的python编译器对这个不太支持,把import cv2 改为import cv2.cv2 as cv2就行了.

  2. 29.渲染器Renderer

    什么是渲染器     渲染器就是将服务器生成的数据格式转为http请求的格式   渲染器触发及参数配置 在DRF配置参数中,可用的渲染器作为一个类的列表进行定义 但与解析器不同的是,渲染器的列表是有顺 ...

  3. 27.路由器Routers

    像一些reils这样的web框架提供自动生成urls的功能,但是Django没有 rest framework为django添加了这一功能,以一种简单.快速.一致的方式 routers必须配合view ...

  4. DQL语句

    DQL语句 DQL(Data QueryLanguage )数据查询语言,基本结构是由SELECT子句,FROM子句,WHERE子句组成的查询块. 一.DQL概述 1.1.什么是DQL DQL:数据查 ...

  5. Python--网络编程学习笔记系列02 附:tcp服务端,tcp客户端

    Python--网络编程学习笔记系列02 TCP和UDP的概述: udp通信模型类似于写信,不需要建立相关链接,只需要发送数据即可(现在几乎不用:不稳定,不安全) tcp通信模型类似于打电话,一定要建 ...

  6. Python基础之模块:7、项目开发流程和项目需求分析及软件开发目录

    一.项目开发流程 1.项目需求分析 明确项目具体功能: 明确到底要写什么东西,实现什么功能,在这个阶段的具体要询问项目经理和客户的需求 参与人员: 产品经理.架构师.开发经理 技术人员主要职责: 引导 ...

  7. OpenFOAM 编程 | 求解捕食者与被捕食者模型(predator-prey model)问题(ODEs)

    0. 写在前面 本文问题参考自文献 \(^{[1]}\) 第一章例 6,并假设了一些条件,基于 OpenFOAM-v2206 编写程序数值上求解该问题.笔者之前也写过基于 OpenFOAM 求解偏分方 ...

  8. 华为开发者大会2022:HMS Core 3D建模服务再升级,万物皆可驱动

    11月4日,HDC2022华为开发者大会在东莞松山湖举办.在本次大会的HMS Core创新图形能力分论坛中,HMS Core重点介绍了其在3D技术领域的创新应用方向,其中3D建模服务展示了创新的自动骨 ...

  9. SpringMVC&Maven进阶

    3. SpringMVC 3.1 了解SpringMVC 概述 SpringMVC技术与Servlet技术功能等同,均属于web层开发技术 学习路线 请求与响应 REST分割 SSM整合 拦截器 目标 ...

  10. Jmeter——请求响应内容乱码解决办法

    前段时间,换过一次设备,重新下载了Jmeter.有一次在编写脚本时,响应内容中的中文一直显示乱码. 遇到乱码不要慌,肯定是有办法来解决的.具体解决办法,可以参考之前的博文,Jmeter--BeanSh ...