vite插件之条件编译

434 阅读1分钟

需求

多平台、多版本策略的不同内容、资源,打包可以shaking掉。传统的if else属于“硬”引用,无法满足。

源码

实现

定义一个宏变量:德玛,只支持单一的条件判断,对于'.ts', '.tsx', '.vue','.css','.scss'分别加入不同的宏标签。如下:

//#if 德玛 
console.log('德玛 mode') 
//#endif

{#if 德玛} 
<div>德玛</div>
{#endif}


<!-- #if 德玛 --> 
<div>德玛</div> 
<!-- #endif -->

实现vite插件:

/* eslint-disable @typescript-eslint/no-explicit-any */
import * as fs from 'fs';
export default function macroUse(def: {
  德玛: boolean
}) {
  console.log('macroUse', def);
  console.log('macroUse', def.德玛);
  return {
    name: 'macro-use',
    load(id: string) {
      console.log('load', id);
      // 处理的数组文件
      const filesTypes = ['.ts', '.tsx', '.vue','.css','.scss'];
      // 获取文件后缀
      const fileType = id.slice(id.lastIndexOf('.'));
      if (filesTypes.includes(fileType)) {
        let code = fs.readFileSync(id, 'utf-8');
        /**
          * //#if 德玛
          * console.log('德玛 mode')
          * //#endif 
         */
        code = code.replace(/\/\/#if 德玛\n([\s\S]*?)\n\/\/#endif/g, function (match, p1) {
          return def.德玛 ? p1 : '';
        });
        /**
          * {#if 德玛}
          * console.log('德玛 mode')
          * {#endif}
         */
        code = code.replace(/\{\/\* #if 德玛 \*\/\}\n([\s\S]*) \{\/\* #endif \*\/\}/g, function (match, p1) {
          return def.德玛 ? p1 : '';
        });
        /**
         * <!-- #if 德玛 -->
         * <div>德玛 mode</div>
         * <!-- #endif -->
         */
        code = code.replace(/<!-- #if 德玛 -->\n([\s\S]*)<!-- #endif -->/g, function (match, p1) {
          return def.德玛 ? p1 : '';
        });
        return code;
      }


    }
  }
}

vite.config.ts中使用

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import macroUse from './plugins/vite-plugin-macro-use'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(), macroUse({ 德玛: true })],
})

效果

macroUse({ 德玛: false })

开发时

image.png

image.png

打包后

image.png

引用的svg logo被去掉

结语

本案例仅供参考,基本可用。