详解antd+react项目迁移vite的解决方案

antd+react+webpack往往是以react技术栈为主的前端项目的标准组合,三者都有成熟的生态和稳定的表现,但随着前端圈的技术不断革新,号称下一代构建平台vite2的发布,webpack似乎不那么香了,为什么这么说呢,因为vite太快了。经过一段时间的尝试,决定在项目中把webpack替换成vite试试,遂写成本文分享给大家。

Vite是什么

作为本文的主角,首先简单介绍一下vite这个构建工具,该工具是尤雨溪推出的【下一代前端开发和构建工具】,vite其实也不是一个新的工具,早在一年多以前,就已经推出了很多版本,直到2.x版本的推出,在前端圈引起了足够大的震动,标志着vite的成熟和强大,这里并不打算详细介绍vite,大家可以参考官网https://cn.vitejs.dev/ 了解。

迁移过程

了解了vite这款工具之后,我们就可以着手准备做迁移工作了;

1.安装vite依赖

npm i vite antd-vite-import-plugin @vitejs/plugin-react-refresh vite-plugin-html -D

2.更新项目原有依赖项

这里我们项目使用的是dva+antd3.x作为基础的开发框架,这里我将系统的主要依赖项都升级到了最新的版本,比如dva我用的2.6.0-beta.22版本,其他附带的react、react-dom、react-router-dom及@babel/plugin-transform-runtime等相关依赖项都更新了(antd还是3.x版本,暂未更新到4.x的大版本),这一块取决于自己的实际需求;

3.项目根目录添加vite.config.js配置文件

和webpack的配置文件比起来,vite的简单了许多,而且很多功能都是内置的,比如对静态资源的处理,功能开启也比较简单,具体如下:

import { defineConfig } from 'vite';
import vitePluginHtml from 'vite-plugin-html';
import reactRefresh from '@vitejs/plugin-react-refresh';

export default defineConfig({
    css: {
        preprocessorOptions: {
            less: {
                javascriptEnabled: true,
            },
        }
    },
    publicDir: './src/configs',
    plugins: [
        reactRefresh(),
        antdViteImportPlugin(),
        vitePluginHtml({
            minify: true,
            inject: {
                injectData: {
                    title: 'vite-react-example',
                    injectScript: '<script src="/configs.js"></script>', // publicDir作为根目录
                },
                injectOptions: {
                    filename: './index.html', // 模板页
                }
            },
        }),
    ],
    server: {
        open: true,
        port: 10010,
    }
});

这里我们使用了vite-plugin-html插件作为html-webpack-plugin的替代方案,其中需要注意injectData和injectOptions选项,injectData可以方便的往我们的模板页中插入自定义数据,injectOptions可以指定模板页,还有其他配置项可以参考https://www.npmjs.com/package/vite-plugin-html 。相应的需要改造index.html页面:

<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <title><%- title %></title>
    ......
</head>
<body>
    <div id="app"></div>
    <script>
        var global = globalThis || window; // 防止启动报错
    </script>
    <%- injectScript %>
    <script type="module" src="/src/index.jsx"></script>
</body>
</html>

和webpack有差异的是,这里我们需要手动指定一下入口文件,script的标签type为module。

4.修改文件后缀

这里的文件是以js作为后缀的react组件,在webpack构建平台下,js(x)、ts(x)都是没啥问题的,但如果使用vite的话,那么最好是ts 、 jsx 、 tsx 的后缀文件,关于这个问题,可以看下这个issue:https://github.com/vitejs/vite/issues/1552 ,最后作者发出批量改个后缀有这么难的吐槽,算了,还是改吧,如果觉得手动改麻烦,写个脚本也不是啥难事。

5.添加启动脚本

"scripts": {
 "dev": "vite",
 "build": "vite build",
 ......
}

到这里应该就差不多了吧,但是情况却不是那么顺利,项目居然跑不起来,好吧,没有那么一帆风顺的事情,接下来我们来看下遇到的问题吧。

遇到的问题

1.decorators not support

在业务代码中,我们使用了dva提供的connect来绑定状态,形如:

@connect(state =&gt; state.foo)
class Foo extends React.PureComponent {
 ....
}

但是decorators语法居然不被vite支持,关于这个问题,也有一个issus:https://github.com/vitejs/vite/issues/2349 ,目前没有一个好的解决办法,只好去掉decorators,改用常规的函数绑定了。

2.antd Unknown theme type: undefined, name: undefined

我们项目目前还是使用的antd的3.x版本,在启动时就出现了这个错误,其实主要是antd组件初始化的时候,加载了antd/es/icon/index.js文件:

import * as allIcons from '@ant-design/icons/lib/dist';
......
ReactIcon.add.apply(ReactIcon, _toConsumableArray(Object.keys(allIcons).map(function (key) {
  return allIcons[key];
})));
......

'@ant-design/icons/lib/dist'导出的对象是{ default: {...} },要正确访问的形式是allIcons.default,而不是allIcons,因此导致获取不到icon的正确导出对象,关于这个问题,大家可以看下这个issue:https://github.com/ant-design/ant-design/issues/19002 ,这里要说明的一点是antd4.x版本不会出现,但是对于我们的项目来讲,目前还不会升级到4这个大版本,那么怎么解决呢,其实只要引用antd/lib下的组件,就没有这个问题了,我们可以看下antd/lib/icon/index.js:

......
var allIcons = _interopRequireWildcard(require("@ant-design/icons/lib/dist"));

function _interopRequireWildcard(obj) { if (obj &amp;&amp; obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" &amp;&amp; typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache &amp;&amp; cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty &amp;&amp; Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc &amp;&amp; (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
......

这里_interopRequireWildcard方法帮我们处理了导出的问题,那么修改一下babel-plugin-import的配置不就好了么,好吧,没有那么容易的,vite对babel-plugin-import支持不那么好,首先还是去vite的issues里面找找看,有一个类似的提问:https://github.com/vitejs/vite/issues/1389 ,看了下,并没有解决我的问题,里面提到的几个插件倒是给我了思路,那就自己写个vite插件去实现我们的需求呗。插件的思路很简单,就是将antd组件的引入方式进行统一的修改:

---修改前---
import { Button } from 'antd';
---修改后---
import Button from 'antd/lib/button';
import 'antd/lib/button/style/index.css';

这里需要说明的是css样式的引入,如果引入style/index或者style/css,会出现require is not defined的问题,因为这两个js文件中使用了require,但是vite在预编译时不是node环境,当然就报错了。
关于这个插件的使用,可以参考https://www.npmjs.com/package/antd-vite-import-plugin

3.'default' is not exported

有时候三方依赖项加载会出错,例如'default' is not exported等,这里可以参考https://github.com/vitejs/vite/issues/2679

在实际开发过程中,还是难免遇到一些奇怪的问题,这都是尝鲜的代价。

速度之争

vite的一个优势就是快,那么和webpack相比,到底有多大的差距呢,这里我们用webpack和vite分别启动同一个本地项目:

构建工具 启动时间(ms)
vite 702ms
webpack 7093ms

这里只是一个粗略的对比,从数据上看有十倍之差,单从速度上讲,vite是很快了,根据官网的解释,Vite 将会使用 esbuild 预构建依赖。Esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。

最后

经历过一番折腾后,觉得vite2的成熟度有所欠缺,在一些小项目中可以试试。对我而言还是决定先用webpack吧,毕竟webpack经过这么多年的发展,坑很少,而目前vite对于react来说还是不那么完美。

到此这篇关于详解antd+react项目迁移vite的解决方案的文章就介绍到这了,更多相关antd react迁移vite内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • react实现antd线上主题动态切换功能

    demo 框架选择: create-react-app + mobx + webpack5 + antdesign 说明 由于最近公司有多个主题的共存性,所以需要实现线上主题切换的功能,所以本文主要描述的是基于create-react-app之上的主题切换. CSS切换 有考虑过根据用户选择的主题在切换的时候选择加载页面css文件的区分方案,但是考虑到这种形式需要在页面切换的时候去reload,因为htmlDOM是在css与JS的结合产物,用户体验不是很好. Less切换 单纯引入所有的less

  • React+Antd 实现可增删改表格的示例

    最近写了一个小东西,模仿自己原先用vue写的项目改成react语法.写了一个可编辑的表格,期间磕磕碰碰的,打算把bug记录下.先把效果图和代码贴上去,主要用的是react+antd table表格,点击编辑,打开弹窗,弹窗内是tab切换显示不同的form表单+可编辑表格,表格内操作栏"+",表格内新增一行可编辑的数据,编辑,保存,删除这些操作就不细说也不贴效果图了 Table/index.js import React, { useState }from 'react' import

  • react antd表格中渲染一张或多张图片的实例

    使用antd table中显示一张图片,代码如下: const columns = [ { title: "姓名", dataIndex: "name", width: 100 , // table列定宽 可不设 fixed: "left" // 固定列的位置 }, { title: "联系电话", width: 150, dataIndex: "phone" }, { title:"显示一张图片

  • create-react-app使用antd按需加载的样式无效问题的解决

    官网给出的按需加载解决方案,先安装 babel-plugin-import 因为antd默认引入样式是less,所以需要手动配置为CSS,配置方法如下: 第一种方法:在package.json中配置,这种方法成功的前提是webpack里query下配置babelrc:true, 这样就会使用babelrc文件中的配置 "babel": { "presets": [ "react-app" ], "plugins": [ [ &

  • react+antd 递归实现树状目录操作

    1.写在前面 作为前端小白的我一直对算法和数据结构浅尝辄止,哝,吃亏了.使用多次递归实现数据格式化后将数据进行树状展示的目的,分享一下我这次挠头的经历~ 2.数据 后台传过来的数据大概是这样的 { "data":[ { "id":1, "name":"一级节点", "parentId":0, "isValid":true, "canAddChild":true, &q

  • react配置antd按需加载的使用

    我目前使用的antd版本是2.13.现在最新的是3.0.1. 脚手架工具就是create-react-app.创建完成项目后,需添加配置,执行yarn eject 也就是打开配置的文档. 然后安装第三方依赖yarn add babel-plugin-import --save-dev 找到config文件夹.里面有2个配置文档, webpack.config.dev.js和webpack.config.prod.js 添加配置时一定要保持文档的一致性.我就是犯了错误,值配置了开发的没有配置正式文

  • react使用antd表单赋值,用于修改弹框的操作

    1.使用getFieldDecorator的initialValue 2.在state里定义一个变量存表格的数据 3.给打开弹框的方法传个record 4.把表格里的值存到state 5.把在state里存的值传给弹框 6.获取传过来的值 7.在取消方法和修改成功后中给赋空值,要不然,点击添加的方法表单里面会有值 7.OK 补充知识:react中使用antd的表单重置数据 resetFields 重置一组输入控件的值(为 initialValue)与状态,如不传入参数,则重置所有组件 Funct

  • react配合antd组件实现的管理系统示例代码

    前言:此文需要有一定react,redux基础,具体学习资料请科学上网. 使用create-react-app脚手架 具体基础配置请参考 配合antd组件实现的管理系统demo,线上地址 开发前反思 1. 按需加载 webpack的 import 动态加载的模块的函数,import(参数),参数为模块地址. 注意: import 后会返回一个promise对象. import('/components/chart').then(mud => { dosomething(mod) }); 本dem

  • 解决React在安装antd之后出现的Can't resolve './locale'问题(推荐)

    React在安装antd之后出现的Can't resolve './locale'问题,是因为moment在2.2之后的版本都有问题,而react默认使用了最新的moment,但是在moment@2.18.1中是没有问题的. 解决方案就是配置webpack的alias,将所有的 moment 路径引用导入到 moment@2.18.1 操作步骤 安装moment 依赖 npm install moment@2.18.1 在react项目中使用yarn eject暴露config文件.如果没有安装

  • 详解antd+react项目迁移vite的解决方案

    antd+react+webpack往往是以react技术栈为主的前端项目的标准组合,三者都有成熟的生态和稳定的表现,但随着前端圈的技术不断革新,号称下一代构建平台vite2的发布,webpack似乎不那么香了,为什么这么说呢,因为vite太快了.经过一段时间的尝试,决定在项目中把webpack替换成vite试试,遂写成本文分享给大家. Vite是什么 作为本文的主角,首先简单介绍一下vite这个构建工具,该工具是尤雨溪推出的[下一代前端开发和构建工具],vite其实也不是一个新的工具,早在一年

  • 详解Springboot+React项目跨域访问问题

    一.开发环境 框架:springboot 1.5.10.RELEASE 开发工具:IDEA JDK:1.8 前端框架:React 15.6.1 浏览器:Chrome浏览器 二.跨域问题 本地使用ajax访问localhost:8080端口时报错: Failed to load http://localhost:8080/test/test.do: No 'Access-Control-Allow-Origin' header is present on the requested resourc

  • 详解在React项目中安装并使用Less(用法总结)

    less的安装配置 安装react-app-rewired,react-app-rewire-less,babel-plugin-import插件 执行命令: npm install react-app-rewired --save-dev npm install react-app-rewire-less --save-dev npm install babel-plugin-import --save-dev 配置package.json文件 找到scripts属性,修改start的值为re

  • 详解对于React结合Antd的Form组件实现登录功能

    一.React 结合 Antd 实现登录功能 引入所需的 Antd 组件,代码如下所示: import { Form, Icon, Input, Button, message } from 'antd' 在 Login.jsx 中,创建一个 Login 组件.当对外暴露组件时,需要使用 Form 组件进行包装,包装 Form 组件生成一个新的组件 Form(Login),同时新组件会向 Form 组件传递一个强大的对象属性 form,这样就可以取到 Form 表单的值,这也是高阶组件和高阶函数

  • 详解C 语言项目中.h文件和.c文件的关系

    详解C 语言项目中.h文件和.c文件的关系 在编译器只认识.c(.cpp))文件,而不知道.h是何物的年代,那时的人们写了很多的.c(.cpp)文件,渐渐地,人们发现在很多.c(.cpp)文件中的声明语句就是相同的,但他们却不得不一个字一个字地重复地将这些内容敲入每个.c(.cpp)文件.但更为恐怖的是,当其中一个声明有变更时,就需要检查所有的.c(.cpp)文件. 于是人们将重复的部分提取出来,放在一个新文件里,然后在需要的.c(.cpp)文件中敲入#include XXXX这样的语句.这样即

  • 详解eclipse将项目打包成jar文件的两种方法及问题解决方法

    第一种:利用eclipse中自带的export功能 第一种方法分两种情况先来看第一种情况:没有引用外部jar的项目打包 步骤一:右键点击项目选择导出(export),选择java>jar文件(不是选择可运行jar文件) 步骤二:选择你要导出的项目以及文件,指定文件导出路径.连续点击两个下一步后到第四步. 步骤三:选择主类. 按照以上步骤即可完成对一个不引用外部jar项目的打包. 第二种情况:没有引用外部jar的项目打包 当我们引用了外部jar后,使用eclipse自带的export打包略显繁琐.

  • 详解Angular5/Angular6项目如何添加热更新(HMR)功能

    本文介绍了详解Angular5/Angular6项目如何添加热更新(HMR)功能,分享给大家,具体如下: A:什么是HMR? Q:HMR(热替换)用于在运行的应用程序中更新代码而不需要重建它.这将导致更快的更新和更少的全页重新加载. angular6-hmr 提供angular6以上HMR(热更新)功能 步骤 1.进入angular项目父级目录内 git clone https://github.com/staven630/angular6-hmr angular6-hmr目录与angular项

  • 详解DevEco Studio项目构建讲解、编写页面、布局介绍、页面跳转

    首先要知道鸿蒙的APP是怎么构成的?   HarmonyOS的应用软件包以APP Pack(Application Package)形式发布,它是由一个或多个HAP(HarmonyOS Ability Package)以及描述每个HAP属性的pack.info组成.HAP是Ability的部署包,HarmonyOS应用代码围绕Ability组件展开. 一个HAP是由代码.资源.第三方库及应用配置文件组成的模块包,可分为entry和feature两种模块类型,如下图所示. 一.项目目录 首先来看一

  • 详解本地Vue项目请求本地Node.js服务器的配置方法

    目录 1.使用vue-cli脚手架搭建vue项目 2.使用koa搭建node后端 3.Vue项目中添加后端请求 参考资料: 前言:本文只针对自己需要本地模拟接口于是搭建一个本地node服务器供自己测试使用,仅作自己从头到尾搭建项目的记录 1.使用vue-cli脚手架搭建vue项目 1.在桌面运行 cmd,使用命令vue create demo创建一个vue项目demo,插件依赖等使用默认配置2.项目创建成功之后,使用命令 cd demo,进入 demo 文件夹,然后使用命令 npm run se

  • 详解如何在项目中应用SpringSecurity权限控制

    目录 1.Spring Security环境准备 2.实现认证和授权 3.在控制器上实现注解鉴权 4.请求获取当前登录的用户名信息 5.用户退出 要进行认证和授权需要前面课程中提到的权限模型涉及的7张表支撑,因为用户信息.权限信息.菜单信息.角色信息.关联信息等都保存在这7张表中,也就是这些表中的数据是我们进行认证和授权的依据.所以在真正进行认证和授权之前需要对这些数据进行管理,即我们需要开发如下一些功能: 1.权限数据管理(增删改查) 2.菜单数据管理(增删改查) 3.角色数据管理(增删改查.

随机推荐