使用 Rsbuild 构建 Arco Design Pro Vue

1,683 阅读4分钟

Acro design Pro 是字节旗下的一款中后台模板,使用 Vite 构建 ,样式简约而漂亮。 (下文使用 arco pro 指代)

image.png

而 Rsbuild 同样是字节团队基于 Rspack 底层上集成的开箱即用的 web 构建工具,速度极快。提供了 React / Vue2 / Vue3 / Preact 等多款 Web 框架开箱即用功能。

image.png

安装 Rsbuild 依赖

pnpm add @rsbuild/core -D

从 config 配置文件入手

config 文件内包含了三个文件。

一个是 base / dev / prod ,分别对应的是基础配置,开发配置,生产配置。

主要的配置集中在 base.config.ts 中,用作主要的的基础的配置,而 dev 和 prod 则作为各自环境的补充。

plugin 文件内主要有两个插件。分别是

  • ArcoResolverPlugin(解决Acro的全局引用)
  • ArcoStyleImportPlugin(按需引用 Theme文件)

提供基本支持

在 config 目录先新增一个 rsbuild.config.ts 文件

写入以下基础的 Rsbuild 配置,使其支持 vue3 / vue-jsx / less

import { defineConfig } from '@rsbuild/core';
import { pluginBabel } from '@rsbuild/plugin-babel';
import { pluginVue } from '@rsbuild/plugin-vue';
import { pluginVueJsx } from '@rsbuild/plugin-vue-jsx';
import { pluginLess } from '@rsbuild/plugin-less';
import { pluginSvgr } from '@rsbuild/plugin-svgr';
import { resolve } from 'path';

export default defineConfig({
  html: {
    // 模板文件
    template: './index.html',
  },
  source: {
    // 入口文件
    entry: {
      index: './src/main.ts',
    },
    // 别名
    alias: {
      '@': resolve(__dirname, '../src'),
      'assets': resolve(__dirname, '../src/assets'),
      'vue': 'vue/dist/vue.esm-bundler.js', // compile template
      'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js', // Resolve the i18n warning issue
    },
  },
  plugins: [
    pluginSvgr(),
    // 处理 Vue jsx
    pluginBabel({
      include: /.(?:jsx|tsx)$/,
    }),
    pluginVueJsx(),
    pluginVue(),
    pluginLess({
      lessLoaderOptions: {
        lessOptions: {
          modifyVars: {
            hack: `true; @import (reference) "${resolve(
              'src/assets/style/breakpoint.less'
            )}";`,
          },
        },
      },
    }),
  ]
});

接着修改一下 index.html 文件。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="shortcut icon" type="image/x-icon" href="https://unpkg.byted-static.com/latest/byted/arco-config/assets/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Arco Design Pro - 开箱即用的中台前端/设计解决方案</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

configArcoResolverPlugin 是一个 unplugin 插件, Rsbuild 已经对 unplugin类的插件 做了支持,但 acro pro 开发依赖中为 'unplugin-vue-components:^0.24.1', 故没有 rspack 的选项,我们升级一下到最新的 0.27.4 即可。

知道原理后,我们稍微改动一下,即可支持 unplugin 插件了

/**
 * If you use the template method for development, you can use the unplugin-vue-components plugin to enable on-demand loading support.
 * 按需引入
 * https://github.com/antfu/unplugin-vue-components
 * https://arco.design/vue/docs/start
 * Although the Pro project is full of imported components, this plugin will be used by default.
 * 虽然Pro项目中是全量引入组件,但此插件会默认使用。
 */
import Components from 'unplugin-vue-components/rspack'; // 这里由 vite 改为 rspack 即可
import { ArcoResolver } from 'unplugin-vue-components/resolvers';

export default function configArcoResolverPlugin() {
  return Components({
    dirs: [], // Avoid parsing src/components.  避免解析到src/components
    deep: false,
    resolvers: [ArcoResolver()],
  });
}

现在的 rsbuild.config.ts 文件如下

import { defineConfig } from '@rsbuild/core';
import { pluginBabel } from '@rsbuild/plugin-babel';
import { pluginVue } from '@rsbuild/plugin-vue';
import { pluginVueJsx } from '@rsbuild/plugin-vue-jsx';
import { pluginLess } from '@rsbuild/plugin-less';
import { pluginSvgr } from '@rsbuild/plugin-svgr';
import { resolve } from 'path';
// 这里引用已经修改好的 ArcoResolverPlugin unplugin 插件
import configArcoResolverPlugin from './plugin/arcoResolver';

export default defineConfig({
 ...,
 // 加入一下配置即可
 tools: {
    rspack: {
      plugins: [configArcoResolverPlugin()],
    },
  },
});

而样式按需引用可以直接使用 Rsbuild 中的 transformImport

source: {
  ...
  // 样式按需引入
  transformImport: [
    {
      libraryName: '@arco-design/web-vue',
      libraryDirectory: 'es',
      style: 'css',
    },
  ],

修改完后 ArcoStyleImportPlugin 则可以废弃了。

修改一下 router 内文件

由于 vite 中的 import.meta.glob 在 rsbuild 也有对应的方式。

image.png

所以稍微改动一下,使其支持路由

import type { RouteRecordNormalized } from 'vue-router';

const modules = import.meta.webpackContext('./modules', {
  // 是否搜索子目录
  recursive: false,
  regExp: /.ts$/,
});

const externalModules = import.meta.webpackContext('./externalModules', {
  recursive: false,
  regExp: /.ts$/,
});

function formatModules(
  context: any,
  result: RouteRecordNormalized[]
): RouteRecordNormalized[] {
  context.keys().forEach((path) => {
    const mod = context(path);
    const defaultModule = mod.default;
    if (!defaultModule) return;
    const moduleList = Array.isArray(defaultModule)
      ? [...defaultModule]
      : [defaultModule];
    result.push(...moduleList);
  });
  return result;
}

export const appRoutes: RouteRecordNormalized[] = formatModules(modules, []);
export const appExternalRoutes: RouteRecordNormalized[] = formatModules(
  externalModules,
  []
);

该如何使用 .env 环境变量文件呢?

在 rsbuild 的文档中已经说明了,开箱支持 .env 文件

image.png

这里需要注意一下的是 client 端的 PUBLIC 前缀才是可以在 ts 代码中使用的,所以要加入前缀。否则只能在 rsbuild.config.ts 中使用。

image.png

最终的 Rsbuild 配置如下

import { defineConfig } from '@rsbuild/core';
import { pluginBabel } from '@rsbuild/plugin-babel';
import { pluginVue } from '@rsbuild/plugin-vue';
import { pluginVueJsx } from '@rsbuild/plugin-vue-jsx';
import { pluginLess } from '@rsbuild/plugin-less';
import { pluginSvgr } from '@rsbuild/plugin-svgr';
import { resolve } from 'path';
import { pluginImageCompress } from '@rsbuild/plugin-image-compress';
import configArcoResolverPlugin from './plugin/arcoResolver';

export default defineConfig({
  html: {
    template: './index.html',
  },
  source: {
    entry: {
      index: './src/main.ts',
    },
    // 别名
    alias: {
      '@': resolve(__dirname, '../src'),
      'assets': resolve(__dirname, '../src/assets'),
      'vue': 'vue/dist/vue.esm-bundler.js', // compile template
      'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js', // Resolve the i18n warning issue
    },
    // 样式按需引入
    transformImport: [
      {
        libraryName: 'arco-design-vue',
        libraryDirectory: 'es',
        style: 'css',
      },
    ],
  },
  // 生产优化
  performance: {
    removeConsole: true, // 生产环境的 console 移除
    chunkSplit: {
      strategy: 'split-by-experience',
    },
  },
  tools: {
    rspack: {
      plugins: [configArcoResolverPlugin()],
    },
  },
  plugins: [
    pluginSvgr(),
    // 处理 Vue jsx
    pluginBabel({
      include: /.(?:jsx|tsx)$/,
    }),
    pluginVueJsx(),
    pluginVue(),
    pluginImageCompress(), // 图像压缩
    pluginLess({
      lessLoaderOptions: {
        lessOptions: {
          modifyVars: {
            hack: `true; @import (reference) "${resolve(
              'src/assets/style/breakpoint.less'
            )}";`,
          },
        },
      },
    }),
  ]
});

最后移除掉 Vite / Rollup 的开发依赖

pnpm remove vite rollup

大功告成,现在的 Arco Design Pro Vue 跑在 Rsbuild 上了。

image.png

最后代码已开源到 github 上,如果感兴趣的 jym 话,不妨 clone 下来跑一下,撒花!!!

watsonhaw5566/arco-design-pro-vue-template

下回见。