Vite 太快了,烦死了,是时候该小睡一会了。

简介: 在知乎看参与 Vue Conf 2021 是怎样的体验?[1]这个问题的时候,偶然发现 Anthony Fu 的回答里提到了一个好玩的凡尔赛插件:vite-plugin-sleep[2]。

在知乎看参与 Vue Conf 2021 是怎样的体验?[1]这个问题的时候,偶然发现 Anthony Fu 的回答里提到了一个好玩的凡尔赛插件:vite-plugin-sleep[2]

先看看回答中 Anthony Fu 是怎么引出这个插件的:

关于 QA 环节中对于 Vite 快的意义的提问似乎引发了大家的一些讨论,借此机会说说自己的浅见。我们有两个词,UX 和 DX,分别对应用户体验(User Experience)和开发者体验(Developer Experience)。

的确某种程度上,作为开发者我们应该优先满足于终端用户的体验,但是随着开发者数量的增加,以及软件需求的越发复杂,开发者同样作为人的体验也十分重要。

如果开发者不能获得很好的 DX,便很难有足够好的效率去进行 UX 的改善。而性能的提升可以更好的让机器接受人的命令而不是浪费时间在等待机器完成工作。

当然,如果你是觉得工具太快影响休息的话,这里安利一下 @小炫 的插件,让你的 Vite 也休息一下 vite-plugin-sleep(被你发现了,其实抖这个机灵才是我的目的)

这充满凡尔赛气息的话语属实逗笑我了,Webpack 的构建之慢确实带给了我们一些美好的摸鱼时间,Vite 是夺走它们的罪魁祸首,这才是属于打工人的插件


介绍


先看看 vite-plugin-sleep 的「动机」章节:

In the old days with webpack, we had many times when we could compile with pay, and with vite it was so fast that we couldn't rest. Time to take a nap in the vite.

在 Webpack 陪伴的那些日子里,我们在编译的时候有很多的时间可以用来休息,但 Vite 太快了,夺走了这一切

是时候小睡一会了……


用法


yarn add vite-plugin-sleep
// vite.config.ts
import sleep from "vite-plugin-sleep";
/** @see {@link https://vitejs.dev/config/} */
export default defineConfig({
  plugins: [
    // ...other plugins
    sleep(/* options */),
  ],
});

就这么简单,安装然后引入,属于你的摸鱼时间又回来了。


原理


看看这个插件的源码是什么样的,顺便学习一下 Vite 插件的编写方式。

Vite 插件的通用形式一般是个函数,接受用户传入的一个 options 配置选项,返回 Vite 标准的插件格式,一个形如这样的对象:

{
  name: 'vite-plugin-sleep',
  config() { // 自定义 config 逻辑 }
  load() { // 自定义 load 逻辑 },
}

Vite 暴露了很多钩子函数给用户,让用户在适当的时机对源码内部的行为进行一些介入和更改。

在官网的 插件 API —— 钩子[3] 章节阅读文档,注意有一部分钩子是继承自 Rollup 的,所以需要去 Rollup 的官网来查看使用说明。

以官网中提到的例子来解释:

export default function myPlugin() {
  const virtualFileId = "@my-virtual-file";
  return {
    name: "my-plugin", // 必须的,将会显示在 warning 和 error 中
    resolveId(id) {
      if (id === virtualFileId) {
        return virtualFileId;
      }
    },
    load(id) {
      if (id === virtualFileId) {
        return `export const msg = "from virtual file"`;
      }
    },
  };
}

这个插件允许用户引入一个虚拟文件(在实际文件中不存在),通过 load 钩子来自定义读取文件的内容,用户就可以这样引入 "from virtual file" 这个字符串了。

import { msg } from "@my-virtual-file";
console.log(msg);

有了这些前置知识,我们来看下这个插件是怎么写的:

import type { Plugin } from "vite";
import type { UserOptions } from "./lib/options";
import { sleep } from "./lib/utils";
import { name } from "../package.json";
export default function sleepPlugin(userOptions: UserOptions = {}): Plugin {
  const options = {
    ...userOptions,
  };
  let firstStart = true;
  return {
    name,
    enforce: "pre",
    configureServer(server) {
      server.middlewares.use(async (req, __, next) => {
        // if not html, next it.
        // @ts-expect-error
        if (!req.url.endsWith(".html") && req.url !== "/") {
          return next();
        }
        if (firstStart) {
          await sleep(options.devServerStartDelay || 20000);
          firstStart = false;
        }
        next();
      });
    },
    async load() {
      await sleep(options.hmrDelay || 2000);
      return null;
    },
  };
}

其实很简单,configureServer[4] 钩子是 Vite 官方提供的独有钩子(也就是 Rollup 中不存在的钩子),是用于配置开发服务器的钩子,最常见的用例是添加一些自定义服务中间件。

load 钩子则是 Rollup 内置的,根据官网的说法,return null 代表这个文件交给其他插件或者由默认解析行为处理,也就是延迟两秒后啥都不干。

再回到插件的内容,先定义一个睡觉的函数:

export function sleep(delay: number) {
  return new Promise((resolve) => setTimeout(resolve, delay));
}

配合 await 语法,可以实现非常优雅的睡眠。

通过 enforce: 'pre' 来强制这个插件的钩子在最前面执行(其他插件别想阻止我摸鱼)。

configureServer 这个钩子里的代码也很简单,初次启动 Vite 开发服务器的时候,访问入口 HTML 文件时,sleep 沉睡用户传入的时间,默认 20 秒。(20 秒够干嘛?XD,请设置成 120 秒。)

官方给出的例子就是添加中间件,但尤老板万万没想到中间这段注释代码被摸鱼小能手填充之后,竟是用来做这种事!

之后是 load 钩子,读取每个文件的时候,默认沉睡 2 秒。

就这么简单,一个 Vite 摸鱼插件完成了。


总结


周末了,通过这个凡尔赛的插件图个乐子,顺便学习一下 Vite 插件的基础知识,美滋滋!


参考资料


[1]

参与 Vue Conf 2021 是怎样的体验?: https://www.zhihu.com/question/460852226

[2]

vite-plugin-sleep: https://github.com/IndexXuan/vite-plugin-sleep

[3]

插件 API —— 钩子: https://cn.vitejs.dev/guide/api-plugin.html#universal-hooks

[4]

configureServer: https://cn.vitejs.dev/guide/api-plugin.html#configresolved


相关文章
|
5天前
|
存储 缓存 前端开发
从此告别网速慢,轻松掌握浏览器缓存知识点!(一)
从此告别网速慢,轻松掌握浏览器缓存知识点!
|
5天前
|
存储 缓存 前端开发
从此告别网速慢,轻松掌握浏览器缓存知识点!(二)
从此告别网速慢,轻松掌握浏览器缓存知识点!
|
6月前
|
缓存 前端开发 JavaScript
前端Vue小项目的一个非常诡异离谱的"眼神不好"Bug
公司放假, 现在来提升自己的前端的技术, 想着使用饿了么UI搭建一个简单的页面, 并完成mock数据的获取, 一个小项目就好了....
54 0
|
8月前
|
JavaScript 算法 前端开发
阿秀思考了很久,最后还是决定啦!
五月份离职后,我给自己放了半个月的假才去入职的新公司,emm,截止目前为止暂时还没后悔,如果以后真的发生北京hulu那样被一锅端的事就算我倒霉好了。
48 1
|
10月前
|
Web App开发 数据采集 存储
我给项目加了性能守卫插件,同事叫我晚上别睡的太死-1
由于我组主要是负责的是H5移动端项目,老板比较关注性能方面的指标,比如首页打开速度,所以一般会关注FP,FCP等等指标,所以一般项目写完以后都会用lighthouse查看,或者接入性能监控系统采集指标.
96 0
|
9月前
|
存储 JavaScript
下班前几分钟,我学会了如何使用 Vuex
下班前几分钟,我学会了如何使用 Vuex
33 0
|
10月前
|
前端开发 程序员
写了那么久的文章,现在才改回来!
大家好,我是即兴小索奇,最近在阅读文章时发现了自己文章的一个缺陷,就记录下来并分享给大家,大家写文章时也可以借鉴。
|
存储 JavaScript 前端开发
测试脚本把页面搞崩了
测试脚本把页面搞崩了
119 0
测试脚本把页面搞崩了
|
存储 JavaScript
用了那么久this了,还不了解它?
this想必大家都很不陌生了,在例如`Vue.js`中,各种this,唰唰唰的写,但是有没有遇到this指向出错的问题呢? 我有,我猜应该也会有人跟我一样。 所以,我总结了一些this的基础概念和基本使用在这里,供大家参考。