likes
comments
collection
share

从 UmiJS 迁移到 Vite 过程

作者站长头像
站长
· 阅读数 71

为什么要替换UmiJS

UmiJS 对于开发者而言,好处有开箱即用、配置少、功能多、文档齐全等等。对于团队来说更容易协作,更多注意力关注于需求的实现,进而提升开发效率。

随着项目日益增长,需求不断迭代的情况下:一次启动一个项目要1分钟以上,修改一次代码热更新半天,极度吃内存。 特别是我们平台是一个微前端项目,总共有40来个子应用,想想同时需要启动多个子应用进行开发...💢💢💢

总结下对于 UmiJS 主要痛点是:

  1. 启动时间过长
  2. 热更新慢
  3. 框架高度封装,扩展功能不方便,自定义插件开发难度较高

尽管我们对全平台进行了一次体积优化、构建速度优化,但是效果还是不显著。

为什么选择 Vite

最主要的几个点是:

  1. 极速的服务启动
  2. 轻量快速的热重载
  3. 优化的构建

极速的服务启动

当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。

从 UmiJS 迁移到 Vite 过程

Vite 通过在一开始将应用中的模块区分为 依赖 和 源码 两类,改进了开发服务器启动时间。

  1. 依赖:使用 go 编写的 esbuild 预构建依赖 , 速度比 js 编写的打包器预构建依赖快 10-100 倍。
  2. 源码:非 js 类文件(tsxjsx)时常会被编辑,但是又不需要所有的源码都被加载。(例如基于路由拆分的代码模块)。Vite原生ESM 方式在浏览器请求源码时按需提供源码,让浏览器接管打包程序的部分工作。

从 UmiJS 迁移到 Vite 过程

迁移

  1. Vite 官方指令生成一个 vite-react 项目模板,并安装 vite-plugin-legacy-qiankun 插件对 qiankun 进行支持。

main.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from "react-router-dom";
import { createLifecyle, getMicroApp } from 'vite-plugin-legacy-qiankun';

const appName = 'vite-react';
const microApp = getMicroApp(appName);

const render = () => {
  ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
    <BrowserRouter>
      <React.StrictMode>
        <App />
      </React.StrictMode>
    </BrowserRouter>,
  );
};

if (microApp.__POWERED_BY_QIANKUN__) {
  createLifecyle(appName, {
    mount() {
      console.log('mount', appName);
      render();
    },
    bootstrap() {
      console.log('bootstrap', appName);
    },
    unmount() {
      console.log('unmount', appName);
    },
  });
} else {
  render();
}
  1. 启动后发现报错 [less] '~@sensoro-design/styles/style/themes/default.less' wasn't found. Tried

原因:vite 无法识别 ~ 符号

解决方案:添加 resolve.alias 配置替换

export default defineConfig({
  // ...
  resolve: {
    alias: [
      // https://github.com/vitejs/vite/issues/2185#issuecomment-784637827
      {
        find: /^~/,
        replacement: '',
      },
    ],
  }
})
  1. 使用 vite-plugin-externals 配置外部扩展
export default defineConfig({
  // ...
  plugins: [
    // ...
    viteExternalsPlugin({
      react: 'React',
      'react-dom': 'ReactDOM',
      lodash: '_',
    }),
  ]
})
  1. 报错 import { bpfrpt\_proptype\_WindowScroller } from "../WindowScroller.js

原因:在 react-virtualized 被打包过程中, vite 未删除对已移除代码的引用

解决方案:先进行了手动移除处理

import type { PluginOption } from 'vite';
import { createRequire } from 'node:module';
import { URL } from 'node:url';
import { join } from 'node:path';
import { readFileSync, writeFileSync } from 'node:fs';

const WRONG_CODE = `import { bpfrpt_proptype_WindowScroller } from "../WindowScroller.js";`
export function virtualized(): PluginOption {
  return {
    name: 'flat:react-virtualized',
    configResolved: async () => {
      // @ts-ignore
      const url = import.meta.url;
      const require = createRequire(url)
      const reactVirtualizedPath = require.resolve('react-virtualized')
      const { pathname: reactVirtualizedFilePath } = new URL(reactVirtualizedPath, url)
      const file = reactVirtualizedFilePath
        .replace(
          join('dist', 'commonjs', 'index.js'),
          join('dist', 'es', 'WindowScroller', 'utils', 'onScroll.js'),
        )
      const code = readFileSync(file, 'utf-8')
      const modified = code.replace(WRONG_CODE, '')
      writeFileSync(file, modified)
    },
  }
}
  1. vite 打包正式环境 require is not defined

原因:vite 不支持 require 引入文件,一些第三方的包会使用这种方式引用。

解决方案:开启打包混合模式转换

export default defineConfig({
  // ...
  build: {
    commonjsOptions: {
      transformMixedEsModules: true,
    },
  },
})

结语

替换 vite 之后,对开发时的启动速度和热更新速度有质的提升,后续有其他新发现会再次更新。

转载自:https://juejin.cn/post/7240998073647136829
评论
请登录