Farm项目这个项目关注很久了,最近几个月Farm 1.0也推出了,对vite的适配也完善了很多,那么直接来尝试一下,我比较喜欢的Vue后台项目是SoybeanAdmin,所以我们就拿他来做个对比吧。
效果对比
项目使用:https://github.com/soybeanjs/soybean-admin 项目的main分支。
先不说别的,先直接看看效果:
![image.png]()
vite打包用时15.2s
![image.png]()
farm评价用时3.7s左右
![image.png]()
vite启动本地服务时间大概2s,但是因为是bundleless,打开页面还要进行一些编译,可能打开页面时间会慢一点
![image.png]()
farm的话就得久一点了,但是farm使用的是Partial Bundling
的策略,从控制台打印的来看好像就是把很多依赖包都先打包构建好,自然启动时间就长一点了,但是带来的好处就是打开页面之后请求的js数量就少很多了,而且因为已经打包好了,所以请求之后基本可以立刻返回打包好的js,不会出现vite这种可能启动几百ms,但是打开页面等几十个js请求,等好几秒页面才出来的情况。
官方benchmark:
|
Startup |
HMR (Root) |
HMR (Leaf) |
Production Build |
Webpack |
8035ms |
345ms |
265ms |
11321ms |
Vite |
3078ms |
35ms |
18ms |
2266ms |
Rspack |
831ms |
104ms |
96ms |
724ms |
Farm |
403ms |
11ms |
10ms |
288ms |
不过感觉和Farm官方的benchmark有一点点出入,特别是启动时间,可能如果产物越大差别就没那么明显了。
迁移过程
简单讲一下main分支的代码需要怎么迁移吧:
首先是打包配置定义部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import { URL, fileURLToPath } from 'node:url'; import process from 'node:process'; import { defineConfig, loadEnv } from '@farmfe/core'; import { setupVitePlugins } from './build/plugins'; import { createViteProxy, getBuildTime } from './build/config'; import postcss from '@farmfe/js-plugin-postcss'
export default defineConfig(configEnv => { const viteEnv = loadEnv(configEnv.mode, process.cwd()) as Env.ImportMeta;
const buildTime = getBuildTime();
const enableProxy = true;
const proxy = createViteProxy(viteEnv, enableProxy);
process.env.viteEnv = JSON.stringify(viteEnv);
return { compilation: { define: { BUILD_TIME: JSON.stringify(buildTime) }, output: { publicPath: viteEnv.VITE_BASE_URL }, resolve: { alias: { '~': fileURLToPath(new URL('./', import.meta.url)), '@': fileURLToPath(new URL('./src', import.meta.url)) } } }, server: { port: 9527, open: true, proxy }, plugins: [ postcss(), [ '@farmfe/plugin-sass', { additionalData: `@use "@/styles/scss/global.scss" as *;` } ] ], vitePlugins: setupVitePlugins(viteEnv, buildTime) as object[] }; });
|
./build/plugins
部分代码也需要修改一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import type { PluginOption } from 'vite'; import vue from '@vitejs/plugin-vue'; import vueJsx from '@vitejs/plugin-vue-jsx';
import progress from 'vite-plugin-progress'; import { setupElegantRouter } from './router';
import { setupUnplugin } from './unplugin'; import { setupHtmlPlugin } from './html';
export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) { const plugins: PluginOption = [ vue({ script: { defineModel: true } }), vueJsx(), setupElegantRouter(), ...setupUnplugin(viteEnv), progress(), setupHtmlPlugin(buildTime) ];
return plugins; }
|
unocss的vite插件使用到了一些比较特别的vite hook,farm还不支持,所以这里咱们换成postcss插件,安装:@farmfe/js-plugin-postcss
和 @unocss/postcss
创建postcss的配置文件:
1 2 3 4 5 6 7 8
| import UnoCSS from '@unocss/postcss'
export default { plugins: [ UnoCSS(), ], }
|
uno.config.ts文件修改一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| import path from 'node:path'; import process from 'node:process'; import { defineConfig } from '@unocss/vite'; import transformerDirectives from '@unocss/transformer-directives'; import transformerVariantGroup from '@unocss/transformer-variant-group'; import presetUno from '@unocss/preset-uno'; import type { Theme } from '@unocss/preset-uno'; import { presetSoybeanAdmin } from '@sa/uno-preset'; import presetIcons from '@unocss/preset-icons'; import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders'; import { themeVars } from './src/theme/vars';
const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = JSON.parse(process.env.viteEnv as string);
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon'); const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
export default defineConfig<Theme>({ theme: { ...themeVars, fontSize: { 'icon-xs': '0.875rem', 'icon-small': '1rem', icon: '1.125rem', 'icon-large': '1.5rem', 'icon-xl': '2rem' } }, shortcuts: { 'card-wrapper': 'rd-8px shadow-sm' }, transformers: [transformerDirectives(), transformerVariantGroup()], presets: [ presetUno({ dark: 'class' }), presetSoybeanAdmin(), presetIcons({ prefix: `${VITE_ICON_PREFIX}-`, scale: 1, extraProperties: { display: 'inline-block' }, collections: { [collectionName]: FileSystemIconLoader(localIconPath, svg => svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ') ) }, warn: true }) ] });
|
最后注释掉src/plugins/assets.ts
里的import 'uno.css';
换成在src/styles/css/global.css
里使用unocss:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @import './reset.css'; @import './nprogress.css'; @import './transition.css'; @unocss;
html, body, #app { height: 100%; }
html { overflow-x: hidden; }
|
到此为止,咱们就成功将vite切换到farm了,最后结果可以看这个仓库:https://github.com/Wyatex/farm-soybean-admin
再额外补个example分支打包时间对比
因为主分支被精简过了,咱们把main分支合并到example分支然后打包试试:
![image.png]()
vite打包时间是21s左右
![image.png]()
farm的时间就去到6.1s,已经缩短到不到4倍了,看来打包的内容越多打包时间倍数差就没那么大了(手动滑稽),这也可能是这个项目打包时间和benchmark差别大的原因吧。