liuweiGL / vite-plugin-demand-import

Demand import for the library that has side effects
MIT License
8 stars 0 forks source link

Support to transform imports into different formats (esm and cjs) #5

Open emosheeep opened 6 months ago

emosheeep commented 6 months ago

Describe the feature

If I use it in a library and want to output two formats (esm and cjs), I can transform an import into only one format.

import { Button } from '@arco-design/mobile-react';
import Button from '@arco-design/mobile-react/esm/Button'; // in esm format
import Button from '@arco-design/mobile-react/cjs/Button'; // in cjs format

Can this plugin support this case?

liuweiGL commented 6 months ago

Unfortunately, the plugin is not supported

emosheeep commented 6 months ago

emmm,we can use regexp to replace it if the provided library is an external

emosheeep commented 6 months ago

Like this, and it works for me, maybe inspire you.

import path from 'path';
import { PluginOption } from 'vite';

interface LibItem {
  libName: string;
  esmDirectory: string;
  cjsDirectory: string;
  style: (name: string) => string;
  camel2DashComponentName?: boolean;
}

/**
 * 拓展按需引用插件,根据不同的 format 输出不同的引用路径
 */
export function createDemandImportPlugin(options: LibItem[]): PluginOption {
  const cjsReplacer: [RegExp, string][] = options.map((item) => {
    return [
      new RegExp(`(?<=require\\((['"])${item.libName}\/)(${item.esmDirectory})(?=\/.*?\\1\\))`, 'g'),
      item.cjsDirectory,
    ];
  });

  return [
    // default plugin
    {},
    // our hack
    {
      name: 'import:esm-to-cjs',
      enforce: 'post',
      renderChunk(code, _, { format }) {
        return format === 'cjs'
          ? cjsReplacer.reduce((result, [reg, replacer]) => result.replaceAll(reg, replacer), code)
          : null;
      },
    },
  ];
}