likes
comments
collection
share

【vite】plugin介绍与手写压缩HTML-plugin

作者站长头像
站长
· 阅读数 20

Vite

在介绍vite plugin之前,先介绍一下vite:

  • Vite,一个基于浏览器原生ES模块的开发服务器。利用浏览器去解析模块,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用。同时另有有Vue文件支持,还搞定了热更新,而且热更新的速度不会随着模块增加而变慢。
  • Vite要求项目完全由ES模块模块组成,common.js模块不能直接在Vite上使用。因此不能直接在生产环境中使用。在打包上依旧还是使用rollup等传统打包工具。
  • Vite的基本实现原理,就是启动一个koa服务器拦截浏览器请求ES模块的请求。通过路径查找目录下对应文件的文件做一定的处理最终以ES模块格式返回给客户端。

相对于传统的webpack它的优势主要为以下两点:

  1. 无需打包:只有浏览器请求某个模块时,再根据需要对模块内容进行编译,webpack则需要全部模块编译完成之后再启动开发服务器;
  2. 热更新(HMR):当改动了一个模块后,vite仅需让浏览器重新请求该模块即可,不像webpack那样需要把该模块的相关依赖模块全部编译一次;

Plugin

webpack插件插件由一个构造函数实例化出来,与webpack插件申明方式不同,vite的插件通常以function来定义:

webpack

注册插件

// plugin.js
class WaylonWebpackPlugin {
    // 参数
    constructor(options) {
        this.options = options;
    }
    // 构造函数定义 apply 方法,在安装插件时,apply 方法会被 Webpack compiler 调用一次
    apply(compiler) {
        // 准备开始构建
        compiler.hooks.beforeRun.tap('begin', () => {
            console.log('开始编译🚀');
        });
        // 编译完成
        compiler.hooks.done.tap('end', () => {
            console.log('恭喜你,没有bug,编译完成~ 🚀');
        });
    }
}

module.exports = WaylonWebpackPlugin;

使用插件

// webpack.config.js
const WaylonWebpackPlugin = require('./plugin.js');
plugins: [new WaylonWebpackPlugin()]

vite

注册插件

// plugin.js
const WaylonVitePlugin = () => {
    return {
        name: 'WaylonVitePlugin', // 必须的,将会在 warning 和 error 中显示
        buildStart() {
            console.log('开始编译🚀');
        },
        buildEnd() {
            console.log('恭喜你,没有bug,编译完成~ 🚀');
        },
    };
};
export default WaylonVitePlugin;

使用插件

// vite.config.js
import WaylonVitePlugin from './plugin.js';
plugins: [WaylonVitePlugin()];

vite钩子介绍

Vite的插件可以有两种形式,一种是vite插件,仅供vite使用;另一种则是rollup通用插件,它不使用 Vite 特有的钩子,让我们简单介绍一下关于这两种插件的生命周期:

通用钩子

以下钩子在服务器启动时被调用:

以下钩子会在每个传入模块请求时被调用:

以下钩子在服务器关闭时被调用:

vite专属钩子

详细介绍可以直接点击进入官网查阅,这里我们简单介绍几个常用的钩子:

下面的钩子会在服务启动时调用一次(文件更新也不会调用)

  • options:替换或操纵rollup选项
  • buildStart:开始创建

vite特有的钩子

  • config: 修改Vite配置
  • configResolved:Vite配置确认
  • configureServer:用于配置dev server,可以进行中间件操作
  • transformIndexHtml:用于转换宿主页
  • handleHotUpdate:自定义HMR更新时调用

下面钩子每次有模块请求时都会被调用:(核心hook)

  • resolveId:创建自定义确认函数,常用语定位第三方依赖(找到对应的文件)
  • load:创建自定义加载函数,可用于返回自定义的内容(加载文件源码)
  • transform:可用于转换已加载的模块内容(转变源码为需要的代码)

开发一个压缩HTML的vite plugin

插件功能: 由于vite编译出来的HTML存在换行符、注释、空格等,这里我们简单做一个插件将HTML中的换行符、注释、空格去掉以压缩HTML文件;

首先我们所要使用到的是vite插件中transformIndexHtml这个钩子,具体实现方式如下:

// utils.ts
// 清除类 采用构建者模式进行开发 每次执行方法后将this返回 链式调用
export class Clear {
    htmlStr: string;
    constructorrting) {
        this.htmlStr = str;
    };
    clear(reg:RegExp) {
        if (!reg) {
            return this;
        }
        this.htmlStr = this.htmlStr.replace(reg, '');
        // 每次清除完毕后将this放回, 供下一次清除其他目标
        return this;
    };
    replace(reg:RegExp, text:string) {
        if (!reg) {
            return this;
        }
        this.htmlStr = this.htmlStr.replace(reg, text);
        // 每次清除完毕后将this放回, 供下一次清除其他目标
        return this;
    }
}
// plugin.ts
import { Clear } from "./utils";
const uglifyHtmlPlugin = () => {
    return {
        name: 'uglifyHtmlPlugin', // 必须的,将会在 warning 和 error 中显示
        transformIndexHtml(html: string) {
            const replaceObj = new Clear(html);
            // 构建者模式: 先去除空格与换行符 再去除注释
            replaceObj.clear(/[\r\n]*/g).clear(/<!--[\w\W\r\n]*?-->/gmi);
            // 放回处理完毕以后的html字符串
            return replaceObj.htmlStr;
        },
    };
};
export default uglifyHtmlPlugin;

// vite.config.js
import uglifyHtmlPlugin from '@waylonzheng/vite-uglify-html-plugin'; // 这里我已经发npm包了,直接引
plugins: [uglifyHtmlPlugin()];

效果对比:

【vite】plugin介绍与手写压缩HTML-plugin

最后

这个插件已经发布在npm上了,目前还有一点待优化的地方,比如说如何将没用的双标签修改为单标签等等,后续会优化;

GitHub: github.com/waylonzheng… npm: www.npmjs.com/package/@wa…