乐趣区

关于javascript:Vite-太快了烦死了是时候该小睡一会了

本文首发公众号「前端从进阶到入院」,欢送关注!

在知乎看参加 Vue Conf 2021 是怎么的体验?这个问题的时候,偶尔发现 Anthony Fu 的答复里提到了一个好玩的凡尔赛插件:vite-plugin-sleep。

先看看答复中 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 —— 钩子 章节浏览文档,留神有一部分钩子是继承自 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 钩子是 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 插件的基础知识,美滋滋!

感激大家

欢送关注 ssh,前端潮流趋势、原创面试热点文章包罗万象。

记得关注后加我好友,我会不定期分享前端常识,行业信息。2021 陪你一起度过。

退出移动版