V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
zhangfg
V2EX  ›  分享创造

腿夹腿,带你用 react 撸后台,系列一(Vite 篇)

  •  
  •   zhangfg · 30 天前 · 3580 次点击

    Github 地址 | 文档地址 | 预览地址

    react-antd-console 是一个后台管理系统的前端解决方案,封装了后台管理系统必要功能(如登录、鉴权、菜单、面包屑、标签页等),帮助开发人员专注于业务快速开发。项目基于 React 18Ant design 5ViteTypeScript 等新版本。对于使用到的各项技术,会被持续更新至最新版本。可放心用于生产环境。

    为了方便大家更好的掌握和使用本项目,推出系列文章:

    • 腿夹腿,带你用 react 撸后台,系列一( Vite 篇)

    如果你喜欢这个项目或认为对你有用,欢迎使用体验和 Star

    1. 概述

    首先我们需要搞定构建工具问题,我们使用了 Vite 作为构建工具

    Vite 是一个超快速的前端构建工具,推动着下一代网络应用的发展

    Vite 最大的特点是启动极速(通常 1s 内)、轻量快速的热更新、对 TypeScript 、JSX 、CSS 等支持开箱即用。相较于 Webpack 传统构建工具,其配置极简,并同样可以实现我们想要的诸多功能,维护心智负担极低

    1.1 Vite 的问题

    如果一个构建工具存在瓶颈,那么哪怕其他有再好的方面,最终也无法选用。所以我们不能忽视 Vite 的缺点。那就是:

    1.1.1 刷新页面慢?

    Vite 因为减少了源文件( JS/TS/CSS )的工作量,导致并发请求多而拖慢刷新页面的速度。但结合启动和热更新,在速度上,相比 Webpack ,本文档认为仍然具有明显的优势

    本项目在开发启动后,刷新首页,共有 168 项请求,耗时 150 至 200 毫秒。作为参考

    1.1.2 开发和打包不一致?

    理论上是有可能的,因为 Vite 开发使用 esbuild, 打包使用 rollup 。但实际情况中,作者从没有碰到过不一致的情况。而且 Vite 即将使用 Rolldown 作为底层打包工具。Rolldown 将保证开发和打包结果完全一致,并提供更快的打包速度。届时可平滑升级

    2. Vite 内置

    Vite 内置了很多开箱即用的功能,本项目用到的内置功能有:

    2.1 样式

    样式预处理器我们使用的是 Less。在 Vite 中,只需要安装 less 模块即可直接使用

    npm i -D less
    

    本项目没有额外配置 less 选项,若需要进一步配置,可参考 Vite 配置 css.preprocessorOptions

    2.1.1 打包后,样式名自动加前缀

    对于样式名,不同浏览器可能有不同的前缀,例如 -webkit--ms--moz- 等。但我们写代码时并不想写这些前缀,但打包时可以自动生成。Vite 中如果项目包含有效的 PostCSS 配置 (任何受 postcss-load-config 支持的格式,例如 postcss.config.cjs),它将会自动应用于所有已导入的 CSS 。

    安装 PostCSS 插件 autoprefixer

    npm i -D autoprefixer
    

    <root>/postcss.config.cjs 中配置自动前缀插件即可生效:

    // postcss.config.cjs
    module.exports = {
      plugins: [
        require('autoprefixer'),
      ],
    };
    

    参考文档:

    2.2 入口

    • html 入口为根目录的 <root>/index.html,可在该 html 中引入入口 ts/tsx 文件
    • 入口 ts/tsx 文件 位于 src/main.tsx,在该文件中,初始化了 react 等

    说明:

    • 在开发时,访问本地服务根路径,会返回上述 html 文件
    • 在打包后,根目录的 <root>/dist 文件夹中也会包含打包后的 html 文件,其源码被引入的 ts/tsx 文件和路径,会被自动转换成打包后的文件和路径

    打包前:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <link rel="shortcut icon" type="image/x-icon" href="/images/favicon.ico" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>react-antd-console</title>
      </head>
      <body>
        <div id="root"></div>
        <script type="module" src="/src/main.tsx"></script>
      </body>
    </html>
    

    打包后:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <link rel="shortcut icon" type="image/x-icon" href="/images/favicon.ico" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>react-antd-console</title>
        <script type="module" crossorigin src="/assets/index-B68Xj7Fq.js"></script>
        <link rel="stylesheet" crossorigin href="/assets/index-CHnsXl1V.css">
      </head>
      <body>
        <div id="root"></div>
      </body>
    </html>
    

    2.3 打包

    当我们通过 package.json 中的 npm run build:prod 命令打包时,其实是调用了 vite build --mode prod命令。默认情况下,它使用 <root>/index.html 作为其构建入口点,并生成能够静态部署的应用程序包 <root>/dist/。若要部署,我们将打完的包放到 nginx 等服务上即可

    我们还可以指定打包后的文件所支持的浏览器目标,例如指定为支持 es2015 浏览器

    // vite.config.js
    export default defineConfig({
      build: {
        target: 'es2015',
      },
    })
    

    参考文档:

    2.4 public 目录

    public 目录 位于根目录的 <root>/public 文件夹。该目录中的资源在开发时能直接通过 / 根路径访问到,并且打包时会被完整复制到目标目录的根目录下

    3. Vite 配置

    另外有些功能是需要配置的,Vite 配置极其简洁。配置文件位于根目录的 <root>/vite.config.ts 如下:

    // vite.config.ts
    export default defineConfig({
      plugins: [
        react(),
        createSvgIconsPlugin({
          iconDirs: [path.resolve(process.cwd(), 'src/assets/svg')],
          symbolId: 'icon-[dir]-[name]',
        }),
      ],
      resolve: {
        alias: {
          '@': path.resolve(__dirname, './src'),
          '@@': path.resolve(__dirname, './examples'),
        },
      },
      server: {
        host: true,
        port: 9527,
        proxy: {
          '/api': {
            target: 'http://localhost:3000',
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/api/, ''),
          },
        },
      },
      esbuild: {
        target: 'chrome65',
      },
      build: {
        target: 'es2015',
      },
    });
    

    以下功能为配置后生效的功能:

    3.1 开发服务

    // vite.config.js
    export default defineConfig({
      server: {
        host: true,
        port: 9527,
        proxy: {
          '/api': {
            target: 'http://localhost:3000',
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/api/, ''),
          },
        },
      },
    })
    
    • server.host 指定服务器应该监听哪个 IP 地址。 如果将此设置为 0.0.0.0 或者 true 将监听所有地址,包括局域网和公网地址
    • server.port 指定开发服务器端口
    • server.proxy 为开发服务器配置自定义代理规则。具体配置继承自 http-proxy
      • 解释: 当请求 /api 开头的 url 时,该请求会被代理到 http://localhost:3000 ,并且请求路径会自动去除 /api

    启动服务后,Vite 会使用 esbuild 作为编译工具,我们指定下编译的文件所支持的浏览器版本为 chrome65 以上:

    // vite.config.js
    export default defineConfig({
      esbuild: {
        target: 'chrome65',
      },
    })
    

    3.2 react 支持

    使用官方的 react 插件 @vitejs/plugin-react,支持:

    • 在开发中启用热更新 (需要 react >= 16.9)
    • 使用自动 JSX 运行时
    • 使用安装体积小的自定义 Babel 插件/预设
    // vite.config.js
    import react from '@vitejs/plugin-react'
    
    export default defineConfig({
      plugins: [react()],
    })
    

    3.3 路径别名

    import 文件时,我们常常会把 <root>/src 别名为 @,这样编写代码就比较方便

    // vite.config.js
    export default defineConfig({
      resolve: {
        alias: {
          '@': path.resolve(__dirname, './src'),
        },
      },
    })
    

    3.4 多环境

    多环境采用 vite 内置的方案。

    • 当使用 vite --mode localhost 启动项目时,环境的配置文件,对应的是根目录的 <root>/.env.localhost 文件。
    • .env.localhost 文件中定义的环境变量,可通过 const { VITE_API_HOST } = import.meta.env 在代码中引入。

    如何新增环境,并新增环境变量?

    1. 在根目录新建 .env.newEnv 文件
    2. .env.newEnv 文件中定义环境变量: VITE_SOME_KEY = someValue
    3. src/vite-env.d.ts 定义 VITE_SOME_KEY 的类型
    4. 在项目的 ts/tsx 文件中引入环境变量 const { VITE_SOME_KEY } = import.meta.env;

    3.4.1 指定环境构建

    添加构建命令:

    // package.json
    {
      "scripts": {
        "build:newEnv": "vite build --mode newEnv",
      }
    }
    

    执行构建:

    npm run build:newEnv
    

    4. 其他 Vite 不相关的工程化配置

    4.1 编码规范

    项目总体按最小约束原则约束编码规范,只使用了 eslint。你可以根据自己的需求自行添加各规范,如 stylelintprettier

    [!TIP] 我们认为在编码规范方面,应当在工程统一性灵活性之间找到一个平衡,而不是一味地使用各种 lint 类工具作强制约束。你可以找到自己团队的平衡点,定制适合自己团队的编码规范

    4.1.1 eslint 规则

    本项目采用官方建议的通用 eslint 规则,如下:

    • @typescript-eslint/recommendedeslint 官方赞助的社区 typescript 规则)
    • eslint:recommendedeslint 官方推荐规则)
    • eslint-plugin-react (社区流行的 react 规则)

    详见 <root>/.eslintrc.cjs

    eslint 可配合 huskylint-staged 实现 git commit 时自动校验 eslint,其他文档和教程很多,在此不再赘述

    5. 完整版预览

    5.1 深/浅色主题

    Light Dark

    5.2 任意主色切换

    5.3 任意背景色切换

    Background Light Background Dark

    5.4 4 种布局

    侧分栏 侧单栏
    头分栏 头单栏

    5.5 丰富的主题配置

    6. 系列文章

    • 腿夹腿,带你用 react 撸后台,系列一( Vite 篇)

    如果你喜欢这个项目或认为对你有用,欢迎使用体验和 Star

    Github 地址 | 文档地址 | 预览地址

    62 条回复    2024-10-31 15:47:58 +08:00
    russ44
        1
    russ44  
       30 天前 via Android
    cool
    cbythe434
        2
    cbythe434  
       30 天前
    腿夹腿撸和手把手撸体验上有差吗
    ZGame
        3
    ZGame  
       30 天前
    挺好看的 学习一下
    michaelluang
        4
    michaelluang  
       30 天前
    写得很棒,期待下一篇。
    zhangfg
        5
    zhangfg  
    OP
       30 天前   ❤️ 1
    @cbythe434 手摸手,已经有用 vue 撸的了。腿夹腿用 react 撸,是一种新的体验😊
    zhangfg
        6
    zhangfg  
    OP
       30 天前
    @russ44 谢谢
    zhangfg
        7
    zhangfg  
    OP
       30 天前
    @ZGame 感谢,欢迎体验使用
    zhangfg
        8
    zhangfg  
    OP
       30 天前
    @michaelluang 感谢,后面会继续编写
    ZGame
        9
    ZGame  
       30 天前
    @zhangfg #7 功能挺全 但是为啥感觉丑丑的 ,可以参考下 vben 那个
    zclzone
        10
    zclzone  
       30 天前
    写得很好,已 star ,顺便推荐一下 vue-naive-admin ,使用 vue3 + vite ,https://github.com/zclzone/vue-naive-admin
    zhangfg
        11
    zhangfg  
    OP
       30 天前
    @ZGame 基本上用的 antd 原来样式,没做很多修改,没有专业 UI 设计,组合起来确实不太好看
    starcoming
        12
    starcoming  
       30 天前
    支持一下
    zhangfg
        13
    zhangfg  
    OP
       30 天前
    @zclzone 感谢,这个项目 https://github.com/zclzone/vue-naive-admin ,看了也很棒,已 star
    zhangfg
        14
    zhangfg  
    OP
       30 天前
    @starcoming 感谢,欢迎体验使用
    ZGame
        15
    ZGame  
       30 天前
    @zhangfg #11 是,我感觉建议参考一下别的修改下样式, 还有希望可以支持一下 monorepo 那种模式。
    zhangfg
        16
    zhangfg  
    OP
       30 天前
    @ZGame 这块我再参考和学习一下,后续继续更新
    shintendo
        17
    shintendo  
       30 天前
    但实际情况中,作者从没有碰到过不一致的情况
    ------
    有一个挺常见的坑,开发和打包后的 CSS 顺序不一致,相关 issue 开了 4 年了至今未解决
    Ma4cus
        18
    Ma4cus  
       30 天前
    厉害了,有 vue 的吗
    ColdBird
        19
    ColdBird  
       30 天前
    还好不是手把腿
    zhangfg
        20
    zhangfg  
    OP
       30 天前
    @shintendo 是在什么特定 case 下产生的吗,我去瞅瞅
    zhangfg
        21
    zhangfg  
    OP
       30 天前
    @Ma4cus 有,评论区就有一个 vue 的
    zhangfg
        22
    zhangfg  
    OP
       30 天前
    @ColdBird 要用心
    HHAO2019
        23
    HHAO2019  
       30 天前
    好奇问一下, 多标签页怎么实现的 antd 好像默认不支持
    zclzone
        24
    zclzone  
       30 天前
    代码运行跟你预览地址的不一样,是有代码还没提交吗
    randomstream
        25
    randomstream  
       30 天前
    端口编号 9527
    344457769
        26
    344457769  
       30 天前


    使用 Firefox 会有很大概率出现页面空白,闪一下页面内容然后就消失了。
    zhangfg
        27
    zhangfg  
    OP
       30 天前   ❤️ 1
    @HHAO2019 antd 有 Tabs 组件。传 items 就会展示多标签,传 activeKey 会高亮指定的 tab 。所以只需要管理好 items 数据即可。items 相关数据存到 localstorage,刷新页面就还会继续展示。另外封装好拖拽和右键逻辑以复用,我们就可以只写样式,便可产出多个不同样式的标签页。
    zhangfg
        28
    zhangfg  
    OP
       30 天前
    @zclzone 是的。目前是一个相对比较干净的模板,只包含必要的功能,在这个基础上做二开,是比较方便的。功能越多,二开就越麻烦,尤其是主题那块。后续我再写写后面的系列文章,根据大家使用的情况补功能进来(如果大家还感兴趣的话)
    zhangfg
        29
    zhangfg  
    OP
       30 天前
    @randomstream 都没用 8964
    randomstream
        30
    randomstream  
       30 天前
    @zhangfg #29 好家伙,搜了才知道,🐮
    1622346252
        31
    1622346252  
       30 天前
    先 start 后看
    bao3
        32
    bao3  
       30 天前
    广大女性心头一紧。
    yaroga
        33
    yaroga  
       30 天前
    学习下,不用 monorepo 么
    zhangfg
        34
    zhangfg  
    OP
       30 天前
    @1622346252 老哥,谢谢你,你是好人
    zhangfg
        35
    zhangfg  
    OP
       30 天前
    @bao3 其实男性也可以的
    zhangfg
        36
    zhangfg  
    OP
       30 天前
    @yaroga 没有呢,目前没有什么地方有需要用到
    Vitumoc
        37
    Vitumoc  
       30 天前
    还是你们前端圈子奔放,上一个还是手摸手呢=。=
    到这就腿夹腿了
    以后的我都不敢想
    Vitumoc
        38
    Vitumoc  
       30 天前
    看了一下,爽,打算把我之前 vue2 + element 的老后台改过来了
    zhangfg
        39
    zhangfg  
    OP
       30 天前
    @Vitumoc 只要东西里面过硬,什么姿势都无所谓
    zhangfg
        40
    zhangfg  
    OP
       30 天前
    @Vitumoc react 感觉后端用起来更顺手,写法更贴近语言本身
    godymho
        41
    godymho  
       30 天前
    你这个动态多标签是基于什么的呀
    SimonWoo
        42
    SimonWoo  
       29 天前
    @zhangfg 兄弟你这端口...我怀疑你意识形态有问题啊
    zclzone
        43
    zclzone  
       29 天前
    @zhangfg 预览版本的很多功能都没有,如果是想保持干净的模板可以提供多个版本的,让用户去选择使用哪个,很多这类开源项目都是这样做的。预览是完整版,开源的是阉割版,多少有点挂羊头卖狗肉的嫌疑,当然,你可能有别的想法或者顾虑,开源的东西不能要求太多,我仅仅只是建议
    yurenfeijing
        44
    yurenfeijing  
       29 天前
    挺好的,已经 star 了,另外 github 代码是不是最新的啊,怎么找不到主题和 debugger.html 那块的代码?
    zhangfg
        45
    zhangfg  
    OP
       29 天前
    @zclzone 谢谢你的建议。所谓的阉割版是一个干净的模板,它是通用的。所谓的完整版,是在模板的基础上丰富的,它还未完全准备好,还没准备完全开源。如果哪些功能有必要并且是通用的,会根据大家使用的情况按需加到模板里。所谓的“完整版”,是我个人的完整版,不是所有人的完整版。我会把这个情况在 github 里说明下,或许会再开一个链接,两个预览链接都放着。(无论如何,我不太喜欢阉割版这个说法,我们可以多讨论技术问题本身)
    zhangfg
        46
    zhangfg  
    OP
       29 天前
    @yurenfeijing 那您可千万别 star 啊
    zhangfg
        47
    zhangfg  
    OP
       29 天前
    @SimonWoo 那只是一个端口...
    zclzone
        48
    zclzone  
       29 天前
    @zhangfg 期待你的完全开源
    zhangfg
        49
    zhangfg  
    OP
       29 天前
    @godymho 上面有回复类似问题:antd 有 Tabs 组件。传 items 就会展示多标签,传 activeKey 会高亮指定的 tab 。所以只需要管理好 items 数据即可。items 相关数据存到 localstorage,刷新页面就还会继续展示。另外封装好拖拽和右键逻辑以复用,我们就可以只写样式,便可产出多个不同样式的标签页。
    再补充一些,如何管理 items 数据:当点击标签,需要跳转路由;当路由切换,需要新增 item ;当点击关闭标签,需要删除当前 item 并需要跳转到下一个 item ;右键菜单还有一些关闭其他,关闭右侧,关闭左侧的逻辑,和上述关闭逻辑是类似的。把这些逻辑封装封装。
    zhangfg
        50
    zhangfg  
    OP
       29 天前
    @zclzone 感谢你给这个小项目的一些生存空间
    yurenfeijing
        51
    yurenfeijing  
       29 天前
    @zhangfg 这有啥,那就取消呗😅谁能想到放的截图是完整的,代码是阉割的,也只有一个分支,我有疑问不是很正常吗?
    zhangfg
        52
    zhangfg  
    OP
       29 天前
    @yurenfeijing 好嘞
    zhangfg
        53
    zhangfg  
    OP
       29 天前
    更新:
    [在线预览]( https://template.react-antd-console.site) | [个人 pro 版在线预览]( https://react-antd-console.site) | [文档]( https://doc.react-antd-console.site)
    jones2000
        54
    jones2000  
       29 天前
    Vite 很不好用, 每次改 node_modules 里面插件得源码, 都不会自动编译, 还要删 vite 得缓存, 然后在重新编译, 麻烦得要死。
    zhangfg
        55
    zhangfg  
    OP
       29 天前 via Android
    @jones2000 一般不会改 node_modules 里的源码吧...或许应该提 issue 或 fork 或 monorepo 或私仓
    zhangfg
        56
    zhangfg  
    OP
       29 天前 via Android
    @jones2000 而且 node_modules 里一般多是打包后的代码
    jones2000
        57
    jones2000  
       29 天前
    @zhangfg 发”issue“要等到什么时候。 公司都是内网,不能访问外网。 一次性把包下完,移到内网。不满足需求得, 直接手动 node_modules 里面改。
    zhangfg
        58
    zhangfg  
    OP
       29 天前 via Android
    @jones2000 感觉这是包的问题,不是 vite 需要覆盖解决的问题呢
    hutoer
        59
    hutoer  
       29 天前
    OP ,开源版,内容会不少了些?你看看 https://www.v2ex.com/t/1039863 这位和你用的技术栈很像
    zhangfg
        60
    zhangfg  
    OP
       29 天前
    @hutoer 我看看,我再加点东西进来
    jones2000
        61
    jones2000  
       28 天前
    @zhangfg 编译出来的东西, 跟 node_modules 里面的源码对不上。 编译的时候根本就不会去检测 node_modules 源码里面哪些插件源码否变动了,就简单的判断了下插件的版本号。这个就是所谓的“更快的打包速度”。
    zhangfg
        62
    zhangfg  
    OP
       23 天前
    大家好,收到一些反馈后,react-antd-console 升级了以下功能:

    新增功能:

    - 动态路由示例
    - 动态 meta 示例
    - 外链示例
    - 单 sider 示例
    - 无 layout 示例
    - 路由权限示例
    - 局部权限示例
    - 全屏

    优化:

    - 整体布局样式
    - 首页样式

    修复:

    - 非动态参数路由使用 router.setSiblings 无效的问题

    另外说明下,有个别评论认为 react-antd-console 是一个阉割版,其实这是一个误解。它是一个模板,另外的 pro 版是本项目的一个拓展。它们的核心代码全都是一模一样的,只是少了示例代码,少了主题功能。这些功能,我认为对于真正要使用 react-antd-console 开发的人来说,示例代码是冗余的,而主题是因人而异的。为了消除可能的误解,现在增加了一些示例代码,如果不需要,可以删除掉。最后,react-antd-console 是一个诚意满满的开源项目,再次欢迎大家使用体验,希望对你能有用。如果喜欢,请 star 一下,谢谢大家!

    在线预览: https://template.react-antd-console.site
    github 地址: https://github.com/diandian18/react-antd-console
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2736 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 14:56 · PVG 22:56 · LAX 06:56 · JFK 09:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.