likes
comments
collection
share

关于我写了一个vite插件那些事

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

关于我写了一个vite插件那些事

为什么要写这个插件 解决了什么问题

在我们开发的过程中有开发模式生产模式,那有些测试代码会在开发模式的时候使用,在生产环境要删掉,一般是手动删除,另一种就是判断环境变量,但是环境变量不好处理template代码以及css代码,为此我写了一个插件将解决以上问题。

插件文档 插件下载地址 开源地址

npm 地址 www.npmjs.com/package/vit…

插件下载地址

npm i vite-plugin-isdev

开源地址 github.com/message163/…

插件用法

安装插件 npm i vite-plugin-isdev

vite.config.ts 引入

import comments from 'vite-plugin-isdev'
//plugins注册插件
plugins: [vue(),comments({
    prefix:"xm",
    debugger:false
})],
接受两个配置项
1.prefix 自定义前缀 默认dev
2.debugger 调试该插件是否生效 生效可以看到<!--条件注释-->这一段代码 false则看不到默认false

使用条件注释语法

在template 里面使用 <!--if-dev--> 被包裹的代码将会在生产环境删除 <!--#end-dev-->

在script tsx ts less 使用 //#if-dev //#end-dev

tips 注意如果你设置了自定义前缀例如我上面设置了xm 那代码就应该是这样子 <!--if-xm--> <!--#end-xm--> 不设置默认为 dev

案例演示

开发环境dev

<template>
    <div>
        <div>扰乱</div>
        <!--#if-xm-->
        <div>dev1</div>
        <div>dev2</div>
        <!--#end-xm-->
    </div>
    <h2>
        <!--#if-xm-->
        <div>dev</div>
        <!--#end-xm-->
    </h2>
   <xxxx></xxxx>
</template>

<script lang="ts" setup>
import random from "random-words"
import xxxx from './App'
console.log(123)
const a = random(5)
//#if-xm
var b = "__dev__"
//#end-xm
console.log('动次打次')
//#if-xm
console.log(a)
//#end-xm
</script>

<style lang="less">
//#if-xm
body{
   background: red;
}
//#end-xm
</style>

<style scoped>
div{
    color:white
}
</style>

编译之后的代码 生产环境

<template>
    <div>
        <div>扰乱</div>
        
    </div>
    <h2>
        
    </h2>
   <xxxx></xxxx>
</template>
<script setup lang='ts' >
import random from "random-words"
import xxxx from './App'
console.log(123)
const a = random(5)

console.log('动次打次')

</script>
<style  lang='less'>

</style>
<style scoped >
div{
    color:white
}
</style>

源码演示

import type { Plugin } from 'vite'
import { parse } from '@vue/compiler-sfc'//vue 处理sfc 的专用库
import type { SFCStyleBlock, SFCScriptBlock } from '@vue/compiler-sfc' //sfc 类型
import { Options, ScriptCode, StyleBlocks } from './type' //类型
let nodeEnv; //当前环境
export default function comments(options: Options = { prefix: "dev", debugger: false}): Plugin {

    //处理template
    const tempReg = new RegExp(`<!--#if-${options.prefix}-->(.*?)<!--#end-${options.prefix}-->`, 'igs');
    const replaceTemplate = (code: string): string => {
        return code.replace(tempReg, options.debugger ? '<!--条件注释template-->' : '');
    }


    const scriptOrStyleOrTsReg = new RegExp(`//#if-${options.prefix}(.*?)//#end-${options.prefix}`, 'igs');
    //处理script
    const replaceScript = (code: SFCScriptBlock): ScriptCode => {
        return {
            content: code.content.replace(scriptOrStyleOrTsReg, options.debugger ? '//条件注释js' : ''),
            setup: code.setup,
            lang: code.lang
        }
    }

    //style 可以有多个
    const replaceStyle = (codes: SFCStyleBlock[]): StyleBlocks[] => {
        return codes.map(style => ({
            content: style.content.replace(scriptOrStyleOrTsReg, options.debugger ? '//条件注释css' : ''),
            scoped: style.scoped,
            lang: style.lang,
            attr: style.attrs
        }))
    }
    //最后重新生成template
    const AssemblyCode = (temp, script: ScriptCode, style: StyleBlocks[]) => {
        let str = ``;
        str += `<template>${temp}</template>\n`;
        str += `<script ${script?.setup ? 'setup' : ''} ${script?.lang ? 'lang=' + `'${script.lang}'` : ''} >${script.content}</script>\n`;
        style.forEach(style => {
            str += `<style ${style?.scoped ? 'scoped' : ''} ${style?.lang ? 'lang=' + `'${style.lang}'` : ''}>${style.content}</style>\n`
        })
        console.log(str)
        return str;
    }

    //处理ts
    const replaceTsOrTsx = (code: string) => {
        return code.replace(scriptOrStyleOrTsReg, options.debugger ? '//条件注释ts' : '')
    }

    return {
        name: "vite-plugin-vue-comments",
        enforce: "pre",
        config(this, config, env) {
            nodeEnv = env //获取环境
        },
        transform(code, id) {
            //code 就是代码  id就是文件路径
            if (/.vue$/.test(id)) {
                const { descriptor } = parse(code)
                const temp = descriptor.template?.content
                const script = descriptor?.scriptSetup;
                const styles = descriptor?.styles
               
                if(temp && script && styles){
                    const tempCode = replaceTemplate(temp)
                    const scriptCode = replaceScript(script)
                    const styleCode = replaceStyle(styles)
                    const template = AssemblyCode(tempCode, scriptCode, styleCode)
                    return nodeEnv.mode == 'development' ? code :  template
                }else{
                    return code
                }
               
            }
            //处理ts文件
            if (/.ts$/.test(id)) {
                return nodeEnv.mode == 'development' ? code : replaceTsOrTsx(code)
            }
            //处理tsx文件
            if(/.tsx$/.test(id)){
               return nodeEnv.mode == 'development' ? code : replaceTsOrTsx(code)
            }

            return code
        }
    }
}
转载自:https://juejin.cn/post/7177204134125240380
评论
请登录