Skip to content

arco design 与 vite + vue3 的使用 ​

1. 按需加载 ​

需要配合unplugin-vue-components 和 unplugin-auto-import 和 vite-plugin-style-import)

1.1 unplugin-vue-components ​

该插件主要是用来解决每新建一个vue文件都需要手动导入一些相同组件(包括外部和内部组件)的问题, 如ui组件库这些(单独的如Message这种组件还是需要配合下面的插件完成), 具体使用如下所示, 按需导入arco组件

javascript
Components({
	// 指定组件位置,默认是src/components
  dirs: ['src/components'],
	resolvers: [
  	ArcoResolver({
  	  sideEffect: true
  	})
  ]
})

插件会生成一个ui库组件以及指令路径components.d.ts文件, 在这个文件里面的就是一些自动导入的组件

1.2 unplugin-auto-import ​

该插件主要是用来自动导入vue3的hooks, 当然在里面也可以添加自己的想要自动导入的组件, 这里以Message为例, 想要自动导入的话需要下面的配置

javascript
 AutoImport({
  // 这里的按需加载和官网上的一样, 和arco-pro默认配置的有出入
  // resolvers: [ArcoResolver()],
  // targets to transform
  include: [
    /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
    /\.vue$/,
    /\.vue\?vue/, // .vue
    /\.md$/, // .md
  ],
  // 配置后会在根目录生成./auto-imports.d.ts文件
  dts: './auto-imports.d.ts', // or a custom path
  imports: [
    // presets
    'vue',
    'vue-router',
    {
      '@arco-design/web-vue': ['Message'],
    }
  ],
  eslintrc: {
    // eslintrc-auto-import.json文件
    enabled: true,
    filepath: './.eslintrc-auto-import.json',
    globalsPropValue: true,
  },
})

同时为了防止eslint报错, 也还会生成一个eslint的自动引入文件, .eslintrc-auto-import.json, 最后在eslint的extends里面配置该文件, 进而使其生效, 不会造成eslint报错

javascript
module.exports = {
  extends: [
    // ...
    './.eslintrc-auto-import.json'
  ],
}

1.3 vite-plugin-style-import ​

该插件主要是用来自动引入相关组件的样式, 如果不使用该组件的话, 如Message这种组件根本不能显示, 当然使用全局导入样式也能展示出来, 但是这样的话打包后的文件就会多出来一些无用的内容 这里需要注意的是: arco里面一些组件的样式是在父组件样式文件里面, 所以还需要进行处理.

具体的插件配置如下所示:

javascript
createStyleImportPlugin({
  libs: [
    {
      libraryName: '@arco-design/web-vue',
      esModule: true,
      resolveStyle: name => {
        // The use of this part of the component must depend on the parent, so it can be ignored directly.
        // 这部分组件的使用必须依赖父级,所以直接忽略即可。
        const ignoreList = [
          'config-provider',
          'anchor-link',
          'sub-menu',
          'menu-item',
          'menu-item-group',
          'breadcrumb-item',
          'form-item',
          'step',
          'card-grid',
          'card-meta',
          'collapse-panel',
          'collapse-item',
          'descriptions-item',
          'list-item',
          'list-item-meta',
          'table-column',
          'table-column-group',
          'tab-pane',
          'tab-content',
          'timeline-item',
          'tree-node',
          'skeleton-line',
          'skeleton-shape',
          'grid-item',
          'carousel-item',
          'doption',
          'option',
          'Optgroup',
          'icon',
        ]
        // List of components that need to map imported styles
        // 需要映射引入样式的组件列表
        const replaceList: any = {
          'typography-text': 'typography',
          'typography-title': 'typography',
          'typography-paragraph': 'typography',
          'typography-link': 'typography',
          'dropdown-button': 'dropdown',
          'input-password': 'input',
          'input-search': 'input',
          'input-group': 'input',
          'radio-group': 'radio',
          'checkbox-group': 'checkbox',
          'layout-sider': 'layout',
          'layout-content': 'layout',
          'layout-footer': 'layout',
          'layout-header': 'layout',
          'month-picker': 'date-picker',
          'range-picker': 'date-picker',
          row: 'grid', // 'grid/row.less'
          col: 'grid', // 'grid/col.less'
          'avatar-group': 'avatar',
          'image-preview': 'image',
          'image-preview-group': 'image',
        }
        if (ignoreList.includes(name)) return ''
        // eslint-disable-next-line no-prototype-builtins
        return replaceList.hasOwnProperty(name)
          ? `@arco-design/web-vue/es/${replaceList[name]}/style/css.js`
          : `@arco-design/web-vue/es/${name}/style/css.js`
        // less
        // return `@arco-design/web-vue/es/${name}/style/index.js`;
      },
    },
  ],
})

1.4 arco icon模板引入问题 ​

WARNING

在项目中使用模板方法创建menu菜单, 出现了arco icon不能自动导入的问题, 目前的处理方案就是全局导入, 还没找到更好的方案

2. 项目vite config配置示例 ​

有待后面再整理一次, 添加一些备注

2.1 prod配置 ​

vite.prod.config.js

javascript
import { resolve } from 'path'
import { mergeConfig } from 'vite'

// 分析打包后文件大小
// import configVisualizerPlugin from '../plugins/visualizer'
import BaseConfig from './vite.base.config'

export default mergeConfig(
  {
    mode: 'production',
    // plugins: [configVisualizerPlugin()],
    build: {
      outDir: './dist',
      rollupOptions: {
        output: {
          // 拆分打包文件目录
          assetFileNames: (assetInfo: { name: string }) => {
            const info = assetInfo.name.split('.')
            let extType = info[info.length - 1]
            if (/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/i.test(assetInfo.name)) {
              extType = 'media'
            } else if (/\.(png|jpe?g|gif|svg)(\?.*)?$/.test(assetInfo.name)) {
              extType = 'img'
            } else if (/\.(woff2?|eot|ttf|otf)(\?.*)?$/i.test(assetInfo.name)) {
              extType = 'fonts'
            }
            return `static/${extType}/[name]-[hash][extname]`
          },
          chunkFileNames: 'static/js/[name]-[hash].js',
          entryFileNames: 'static/js/[name]-[hash].js',
          manualChunks: {
            arco: ['@arco-design/web-vue'],
            vue: ['vue', 'vue-router', 'pinia'],
            store_vendor: [`${resolve(__dirname, '/src/store/index.ts')}`],
          },
        },
      },
      chunkSizeWarningLimit: 1024,
    },
  },
  BaseConfig
)

2.2 base配置 ​

vite.base.config.js

javascript
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import { resolve } from 'path'
import AutoImport from 'unplugin-auto-import/vite'
// import { ArcoResolver } from 'unplugin-vue-components/resolvers'
import { defineConfig } from 'vite'

import { arcoResolver } from '../plugins/arcoResolver'
import configStyleImportPlugin from '../plugins/styleImport'

// https://vitejs.dev/config/
export default defineConfig({
  resolve: {
    alias: [
      {
        find: '@',
        // 这里可以根据自己的根目录进行修改
        replacement: resolve(__dirname, '../../src'),
      },
      // 这里是为了解决menu render的编译问题, 使用运行时编译
      {
        find: 'vue',
        replacement: 'vue/dist/vue.esm-bundler.js', // compile template
      },
    ],
    extensions: ['.js', '.ts', '.jsx', '.tsx', '.json'],
  },
  plugins: [
    vue(),
    vueJsx(),
    AutoImport({
      // 这里的按需加载和官网上的一样, 和arco-pro默认配置的有出入
      // resolvers: [ArcoResolver()],
      // targets to transform
      include: [
        /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
        /\.vue$/,
        /\.vue\?vue/, // .vue
        /\.md$/, // .md
      ],
      dts: './auto-imports.d.ts', // or a custom path
      imports: [
        // presets
        'vue',
        'vue-router',
        {
          '@arco-design/web-vue': ['Message'],
        },
      ],
      eslintrc: {
        // eslintrc-auto-import.json文件
        enabled: true,
        filepath: './.eslintrc-auto-import.json',
        globalsPropValue: true,
      },
    }),
    // 自动引入arco design 这个文件在1.1章节中有, 主要内容一样, 函数包装一下就行
    arcoResolver(),
    // 按需导入arco design样式 这个文件在1.3章节中有, 主要内容一样, 函数包装一下就行
    configStyleImportPlugin(),
  ],
  css: {
    preprocessorOptions: {
      less: {
        modifyVars: {
          hack: `true; @import (reference) "${resolve('src/assets/style/breakpoint.less')}";`,
        },
        javascriptEnabled: true,
      },
    },
  },
})

2.3 dev配置 ​

vite.dev.config.js

javascript
import { mergeConfig } from 'vite'
import eslint from 'vite-plugin-eslint'

import BaseConfig from './vite.base.config'

// https://vitejs.dev/config/
export default mergeConfig(
  {
    mode: 'development',
    server: {
      port: 3001,
      hmr: true,
      proxy: {
        // 选项写法
        '/api/v1': {
          target: 'http://localhost:8001', // 所要代理的目标地址
          ws: true, // 支持websocket
          // rewrite: path => path.replace(/^\/search/, ''), // 重写传过来的path路径,比如 `/api/index/1?id=10&name=zs`(注意:path路径最前面有斜杠(/),因此,正则匹配的时候不要忘了是斜杠(/)开头的;选项的 key 也是斜杠(/)开头的)
          changeOrigin: true, // true/false, Default: false - changes the origin of the host header to the target URL
        },
      },
    },
    plugins: [
      // 用来配置eslint
      eslint({
        cache: false,
        include: ['src/**/*.ts', 'src/**/*.tsx', 'src/**/*.vue'],
        exclude: ['node_modules'],
      }),
    ],
  },
  BaseConfig
)