使用最快的 Rust web 框架 Farm 迁移最火的 Vue3 后台管理系统

10,301 阅读7分钟

8ebbb198-fc1a-46df-b608-255e42035fa5.gif

Farm 介绍

可能很多同学还不知道 Farm , 先给大家介绍一下, Farm 是一个基于 Rust 的 Web 构建工具, 类似 webpack 和 vite,但更快Farm 用 resolve, load, transform 把所有的 asset (js/jsx/ts/tsx、css/sass/less、html、静态资源、json 等),并将它们打包成一系列可部署文件Farm 作为一个速度极快的构建工具,可帮助您更快的构建出 web / nodejs 应用程序。

Farm 特性以及设计理念

  • 超级快: 使用 Rust 编写, 可以在毫秒级别内启动一个 React 或 Vue 项目。 在大多数情况下, 可以在 10ms 内执行 HMR 的更新, 理论上任何项目热启动在开启增量编译的情况下启动时间不会超过 1 秒

  • 增量构建: 支持持久缓存,以模块粒度进行缓存复用,任何一个模块如果没有改变,始终只会编译一次!

  • 🧰 完全可拔插: Farm 由插件驱动, 兼容 Vite, Rollup, Unplugin 插件,同时支持 Farm 编译插件(RustJavaScript 插件,以及 Swc 插件),Farm Runtime 插件,Farm Dev Server 插件。

  • ⚙️ 丰富的编译能力支持: 开箱即用, Farm 内置了 JS/TS/JSX/TSX、CSS、Css Modules、Sass、Less、Postcss,HTML 和静态资源的编译,支持 ReactVueSolid, Svelte, Preact 等框架。

  • ⏱️ 懒编译: 仅仅在请求时才编译动态导入的资源,极大提速大型项目的编译。通过 dynamic import 即可启用,被 dynamic import 的模块及其依赖仅在使用时才会编译。

  • 📦 局部打包: 自动根据依赖关系、资源大小,将项目打包成若干个资源,提升资源加载性能的同时,保证缓存命中率。参考 RFC-003 Partial Bundling

  • 🔒 一致性: 开发环境和生产环境的表现一致,所见即所得。

  • 🌳 兼容性: 同时支持传统(ES5)和现代浏览器。

从 vite 项目中如何迁移

接下来就进入正题, 那么如何从已有的 vite 项目迁移到 Farm 呢 ?

从 vite 迁移到 farm 其实非常简单, 因为 farm 内置了对 vite 插件的兼容, 所以您只需要做的是将 vite.config.ts 转换成 farm.config.js

  • 参考 Configuring Farm 将 Farm 的配置选项映射到 vite 配置
  • 对于 Vite Plugins,将 vite.config.ts 中的plugins移动到 farm.config.ts 中的 vitePlugins

但是需要注意的是

  • 对于某些 vite 插件例如: unocss 这种与 vite 深度集成的插件, 由于内部设计的差异问题, 会导致某些插件与 Farm 并不兼容,

  • 一些 Vite 配置选项在 Farm 中是不需要的,例如 optimizeDeps,您可以在迁移到 Farm 时忽略这些选项

  • 对于 SSR,您需要将其重构为Farm SSR

迁移基础项目

我们先从基础项目来体会一下从 vite 迁移到 Farm 有多简单

首先还是我们熟悉的创建 vite 项目

pnpm create vite

我们选一个 Vue 项目模版, 创建好项目之后, 我们的 vite.config.ts 应该是这样的

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
})

那么把大象放进冰箱一共需要三步

  1. 第一步: 安装依赖
pnpm install @farmfe/core @farmfe/cli -D
  1. 第二步: 新增 farm.config.ts 文件,Farm 在插件系统 和 hmr 做了一套适配器来兼容 vite 生态, 所以这里我们就可以直接使用 vite 插件啦
import { defineConfig } from '@farmfe/core'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  vitePlugins: [vue()],
})

  1. 第三步: 啊 没有第三步了, 因为我们已经迁移完成啦。

然后我们在控制台执行 npx farm start 控制台就可以看到以下命令

image.png

执行构建命令 npx farm build

image.png

这样就大功告成啦, 是不是非常简单。

迁移 vue-pure-admin

接下来我们来迁移一个比较复杂的项目, vue-pure-admin 是一个全面ESM+Vue3+Vite+Element-Plus+TypeScript 编写的一款后台管理系统, 并且模块数量算是比较大, 那么我们使用 Farm 来迁移这个项目, 来进一步体现出 Farm 的优势. 以及迁移的成本到底有多低

首先我们先克隆一下 pure-admin 的仓库代码, 然后查看一下项目的 vite 配置文件, 并提示出迁移所需要修改的地方

import { getPluginsList } from "./build/plugins";
import { include, exclude } from "./build/optimize";
import { type UserConfigExport, type ConfigEnv, loadEnv } from "vite";
import {
  root,
  alias,
  warpperEnv,
  pathResolve,
  __APP_INFO__
} from "./build/utils";

export default ({ mode }: ConfigEnv): UserConfigExport => {
  const { VITE_CDN, VITE_PORT, VITE_COMPRESSION, VITE_PUBLIC_PATH } =
    warpperEnv(loadEnv(mode, root));
  return {
    base: VITE_PUBLIC_PATH,
    root,
    resolve: {
      alias
    },
    // 服务端渲染
    server: {
      // 端口号
      port: VITE_PORT,
      host: "0.0.0.0",
      // 预热文件以提前转换和缓存结果,降低启动期间的初始页面加载时长并防止转换瀑布
      warmup: {
        clientFiles: ["./index.html", "./src/{views,components}/*"]
      }
    },
    plugins: getPluginsList(VITE_CDN, VITE_COMPRESSION),
    // https://cn.vitejs.dev/config/dep-optimization-options.html#dep-optimization-options
    optimizeDeps: {
      include,
      exclude
    },
    build: {
      // https://cn.vitejs.dev/guide/build.html#browser-compatibility
      target: "es2015",
      sourcemap: false,
      // 消除打包大小超过500kb警告
      chunkSizeWarningLimit: 4000,
      rollupOptions: {
        input: {
          index: pathResolve("./index.html", import.meta.url)
        },
        // 静态资源分类打包
        output: {
          chunkFileNames: "static/js/[name]-[hash].js",
          entryFileNames: "static/js/[name]-[hash].js",
          assetFileNames: "static/[ext]/[name]-[hash].[ext]"
        }
      }
    },
    define: {
      __INTLIFY_PROD_DEVTOOLS__: false,
      __APP_INFO__: JSON.stringify(__APP_INFO__)
    }
  };
};

farm 配置基本平替 vite 配置, 我们再来看一下迁移到 farm 所需要修改的配置文件,由于对 css 的处理 farmvite 的处理方向上的差异,所以我们只需要把一些 css 的插件配置替换成 farm 的插件, 其他的 vite 插件完全可以复用

import { getPluginsList } from "./build/plugins";
import { type UserConfigExport, type ConfigEnv, loadEnv } from "@farmfe/core";
import { root, alias, warpperEnv, __APP_INFO__ } from "./build/utils";
import postcss from "@farmfe/js-plugin-postcss";
import sass from "@farmfe/js-plugin-sass";

export default ({ mode }: ConfigEnv): UserConfigExport => {
  const { VITE_CDN, VITE_PORT, VITE_COMPRESSION, VITE_PUBLIC_PATH } =
    warpperEnv(loadEnv(mode, root)[0]);
  return {
    compilation: {
      output: {
        publicPath: VITE_PUBLIC_PATH,
        targetEnv: "browser-es2015",
        filename: "static/[ext]/[name]-[hash].[ext]",
        assetsFilename: "static/[ext]/[name]-[hash].[ext]"
      },
      resolve: {
        alias
      },
      script: {
        plugins: [
          {
            name: "@swc/plugin-remove-console",
            options: {
              exclude: ["error"]
            },
            filters: {
              moduleTypes: ["js", "ts", "jsx", "tsx"]
            }
          }
        ]
      },
      externalNodeBuiltins: false,
      define: {
        __INTLIFY_PROD_DEVTOOLS__: false,
        __APP_INFO__: process.env.FARM_FE
          ? __APP_INFO__
          : JSON.stringify(__APP_INFO__)
      }
    },
    root,
    // 服务端渲染
    server: {
      // open: true,
      port: VITE_PORT
    },
    plugins: [
      sass({
        legacy: true
      }),
      postcss(),
      {
        name: "remove-css-filter-plugin",
        priority: 0,
        transform: {
          filters: {
            resolvedPaths: ["element-plus/dist/index.css"]
          },
          async executor({ content }) {
            return {
              content: content.replace(/filter:\s*alpha\(opacity=0\);/g, "")
            };
          }
        }
      }
    ],
    vitePlugins: getPluginsList(VITE_CDN, VITE_COMPRESSION)
  };
};

我们可以看到 vite 插件完全复用, 需要修改的地方仅仅是一些编译输出的属性, 整体最大的修改点只有这些,我在 vue-pure-admin 项目提了一个 pr, 还有一些设计差异的小细节大家可以在这里 查看 尽管从 Vite 迁移到 Farm 需要进行一些调整和适配,但是这个过程并不复杂,而且可以通过优化提升项目的性能和开发效率。因为确实迁移很简单, 所以本篇文章只是简单的介绍一下 Farm 目前的可用度,随着 Farm 的不断发展和完善,相信它会成为更多项目的首选构建工具。

那么到了大家最关心的一点, 那么迁移之后的性能到底怎么样呢?

在开启增量构建的情况下的项目启动对比

8ebbb198-fc1a-46df-b608-255e42035fa5.gif

注:因为 vite 对于源代码是请求时编译,所以此处加上了 “项目可访问时间”(即 “热启动时间” + “页面加载时间”),作为另一个指标来综合对比性能。所以 Farm 在热启动比 vite 快 5 倍左右

结语

farm 已经具有了 所有开发调试 发布 也有很大的提升空间

Farm 开源已经一年多了, 也已经正式的发布了 1.0 版本, 已经达到了生产可用的状态, 不仅仅是从 vite 中迁移, 在 webpack 中迁移, 团队中也做了非常多的尝试, 迁移成本都很低, Farm 下一步计划基于 Farm 打造出下一代 SSR 框架, 也希望可以有更多的同学参与进来, 共同学习进步。

未来,我们将继续撰写更多的文章,深入介绍 Farm 的各项功能以及特性和原理解析,帮助大家更好地理解和使用下一代的构建工具,可以对前端工程化以及代码解析与编译的原理理解之后, 可以更加深入地了解现代前端开发的核心概念和技术,并掌握构建高效、稳定的前端项目的关键技能。让我们共同期待未来的探索和发现,共同探讨前端技术的前沿话题,为构建更加美好的 Web 世界贡献一份力量。

下一篇文章我计划带领大家从头开始,使用 Farm 提供的 api 能力来构建一个 cli 项目, 让每个人都可以搭建出属于自己的编译工具,探索其灵活性和扩展性,让每个人都可以发布属于自己的框架, 为项目的定制化需求提供更好的解决方案。

欢迎加入大家加入 Farm 团队来一起共同建设。欢迎大家 Star🌟

Farm 官网:Farm
Farm 代码仓库:Farm Code
Farm 交流群

5f1f6b61fae95d0044f4faf53c64503.jpg