Vite 插件

本章节介绍如何将 Vite 插件迁移到 Rsbuild 插件。

现有插件

在迁移一个 Vite 插件之前,建议先检查 Rsbuild 生态中是否存在对应的插件,你可以通过以下页面来查找:

定义一个插件

Rsbuild 插件的定义方式与 Vite 相似,通常都是一个接收插件选项作为参数的函数,并返回插件的描述对象。

两者的主要区别在于:Vite 的 hooks 直接定义在插件描述对象上,而 Rsbuild 的 hooks 是通过 api 对象 来访问和调用,这允许你更灵活地控制插件 API 的调用时机。

  • Vite 插件:
vitePlugin.ts
const vitePlugin = (options) => ({
  name: 'vite-plugin',
  transform() {
    // ...
  },
});
  • Rsbuild 插件:
rsbuildPlugin.ts
const rsbuildPlugin = (options) => ({
  name: 'rsbuild-plugin',
  setup(api) {
    api.transform(() => {
      // ...
    });
  },
});

插件 hooks

Rsbuild 的插件 API 覆盖了大部分的 Vite 和 Rollup 插件 hooks,例如:

Vite 插件 hooksRsbuild 插件 API
resolveIdresolve
transformtransform
configmodifyRsbuildConfig
configResolvedgetNormalizedConfig
configEnvironmentmodifyEnvironmentConfig
configureServeronBeforeStartDevServer
buildStartonBeforeBuild, onBeforeStartDevServer
buildEndonAfterBuild, onCloseDevServer
closeBundleonCloseBuild, onCloseDevServer
transformIndexHtmlmodifyHTML, modifyHTMLTags

请参考 插件系统 文档来了解更多。

config 钩子

Rsbuild 提供了 modifyRsbuildConfig 钩子来修改 Rsbuild 配置。由于 Rsbuild 与 Vite 的配置结构存在差异,在迁移 Vite 插件时,需要对配置进行调整。

例如,需要将 Vite 的 define 选项替换为 Rsbuild 的 source.define 选项。

  • Vite 插件:
vitePlugin.ts
const vitePlugin = {
  name: 'my-plugin',
  config: (config) => {
    config.define = {
      ...config.define,
      FOO: '"foo"',
    };
  },
};
  • Rsbuild 插件:
rsbuildPlugin.ts
const rsbuildPlugin = {
  name: 'my-plugin',
  setup(api) {
    api.modifyRsbuildConfig((config) => {
      config.source ||= {};
      config.source.define = {
        ...config.source.define,
        FOO: '"foo"',
      };
    });
  },
};
TIP

查看 配置迁移 了解如何将 Vite 的配置迁移到 Rsbuild。

configEnvironment 钩子

Rsbuild 提供了 modifyEnvironmentConfig 钩子来修改特定 environment 的配置。

  • Vite 插件:
const vitePlugin = {
  name: 'config-environment',
  configEnvironment(name, config) {
    if (name === 'web') {
      config.resolve.alias = {
        // ...
      };
    }
  },
};
  • Rsbuild 插件:
const rsbuildPlugin = {
  name: 'config-environment',
  setup(api) {
    api.modifyEnvironmentConfig((config, { name }) => {
      if (name === 'web') {
        config.resolve.alias = {
          // ...
        };
      }
    });
  },
};

configResolved 钩子

Rsbuild 提供了 api.getNormalizedConfig 方法来获取已解析的配置。这个方法与 Vite 的 configResolved 钩子的使用场景类似。

  • Vite 插件:
vitePlugin.ts
const vitePlugin = () => {
  let config;
  return {
    name: 'read-config',
    configResolved(resolvedConfig) {
      config = resolvedConfig;
    },
    transform() {
      console.log(config);
      // ...
    },
  };
};
  • Rsbuild 插件:
rsbuildPlugin.ts
const rsbuildPlugin = () => ({
  name: 'read-config',
  setup(api) {
    api.transform(() => {
      const config = api.getNormalizedConfig();
      console.log(config);
      // ...
    });
  },
});

transformIndexHtml 钩子

Vite 的 transformIndexHtml 钩子对应了 Rsbuild 的两个钩子:

下面一个是替换 HTML 标题的示例。

  • Vite 插件:
vitePlugin.ts
const htmlPlugin = () => {
  return {
    name: 'html-plugin',
    transformIndexHtml(html) {
      return html.replace(
        /<title>(.*?)<\/title>/,
        `<title>Title replaced!</title>`,
      );
    },
  };
};
  • Rsbuild 插件:
rsbuildPlugin.ts
const rsbuildPlugin = {
  name: 'html-plugin',
  setup(api) {
    api.modifyHTML((html) => {
      return html.replace(
        /<title>(.*?)<\/title>/,
        `<title>Title replaced!</title>`,
      );
    });
  },
};

configureServer 钩子

Rsbuild 提供了 onBeforeStartDevServer 钩子来替代 Vite 的 configureServer 钩子,它允许你获取 dev server 实例和添加自定义的中间件。

  • Vite 插件:
vitePlugin.ts
const vitePlugin = () => ({
  name: 'setup-middleware',
  configureServer(server) {
    server.middlewares.use((req, res, next) => {
      // custom handle request...
    });
  },
});
  • Rsbuild 插件:
rsbuildPlugin.ts
const rsbuildPlugin = {
  name: 'setup-middleware',
  setup(api) {
    api.onBeforeStartDevServer(({ server }) => {
      server.middlewares.use((req, res, next) => {
        // custom handle request...
      });
    });
  },
};

apply 属性

Rsbuild 插件提供了与 Vite 插件一致的 apply 属性

  • Vite 插件:
vitePlugin.ts
const vitePlugin = {
  name: 'vite-plugin',
  apply: 'build',
};
  • Rsbuild 插件:
rsbuildPlugin.ts
const rsbuildPlugin = {
  name: 'rsbuild-plugin',
  apply: 'build',
};