React UmiMax搭建项目

umi官网:快速上手
Umi Max:Umi Max 简介
proComponent官网:https://procomponents.ant.design

一、环境准备(建议)

1. 首先你的电脑上必须有 node 并且版本在 14+

// 检查当前node版本

$ node -v

v16.10.0

 2. 安装 pnpm。

// 查看当前镜像源

$ npm config get registry

// 切换淘宝镜像源

$ npm config set registry https://registry.npm.taobao.org/

// 全局安装pnpm

$ npm install -g pnpm

// 查看pnpm版本

$ pnpm -v

7.3.0

二、创建项目 

1. 找个地方建个空目录。

$ mkdir myapp && cd myapp

2. 通过官方工具创建项目

 $ pnpm dlx create-umi@latest

注意:这里第一个选项Ant Design Pro,我们使用的是 @umijs/max 来创建项目

Umi Max 简介

3. 启动项目

$ pnpm dev 

umi官网会自动帮我们生成框架,我们的项目文件和项目是这样的

4. 目录结构

参考官网:目录结构

.

├── mock //mock接口数据文件

│ └── app.ts|tsx

├── node_modules //存放依赖文件

├── src

│   ├── .umi //dev 时的临时文件目录。

│   ├── .umi-production //build 时的临时文件目录。

│   ├── assets

│   │   └── .gitkeep //无意义,起到占位符的作用

│   ├── components //公共组件

│   │   └── Model

│   ├── constants //定义常量文件

│   │   └── index.ts

│   ├── models //全局状态管理文件

│   │   └──global.ts

│   ├── pages //页面组件

│   │   └── Home

│   ├── services // 接口文件

│   │   └── demo

│   ├── utils // 工具文件

│   │   └── format.ts

│   ├── app.(ts|tsx) //运行时配置 文件。

│   └──access.ts //定义项目中的权限。

├── .eslintrc.js //规则

├── .gitignore //配置git忽略文件或目录

├── .lintstagedrc

├── .npmrc

├── .prettierignore

├── .prettierrc

├── .stylelintrc.js

├── .umirc.ts //配置文件,包含 Umi 所有非运行时配置

├── package.json //Webpack配置和项目包管理文件

├── pnpm-lock.yaml

├── README.md

├── tsconfig.json

└── typings.d.ts

5. 主题 

因为公司要求的主题是偏暗黑风格,所以我们一起来配置一下主题色调吧

点击进入主题编辑器 - Ant Design 定制主题风格,点击保存,点击主题配置并复制。

然后打开.umirc.ts文件,找到antd属性,把我们的代码复制上去,更多属性可以参考 umi/max antd

 6. 布局

因为布局太过大众化,所以我们先打开app.ts文件,稍微修改一下我们的布局。然后再打开.umirc.ts文件,把我们的路由稍微调整一下。

splitMenus属性为我们提供了横向和纵向分离的布局,来看下效果拔(分离之后是不是更加简洁了呢)。

7. 自定义右上角用户

如果你的用户只需要定义一个退出登录的功能,直接在app.ts文件中添加logout函数即可;

 

如果需要定义更多功能,则需要使用rightRender自定义渲染,除此之外我们还能自定义一些结果页面203,404,错误页面等。

三、配置 

1. 路由

// .umirc.ts 文件

export default defineConfig({

        routes: [

                { path: '/', component: 'index' },

                { path: '/user', component: 'user' },

        ],

})

2. 代理

// .umirc.ts 文件

export default defineConfig({ 

        proxy: {

                '/api': {

                    'target': 'http://jsonplaceholder.typicode.com/',

                    'changeOrigin': true,

                    // 'pathRewrite': { '^/api' : '' },

                },

        },

})

3. 配置请求

// app.tsx 文件

import { RequestConfig } from '@umijs/max';
export const request: RequestConfig = {
  // timeout: 3000,
  // other axios options you want
  errorConfig: {
    errorHandler() {},
    errorThrower() {},
  },
  // 请求拦截器
  requestInterceptors: [
    // 直接写一个 function,作为拦截器
    (url, options) => {
      // do something
      return { url, options };
    },
    // 一个二元组,第一个元素是 request 拦截器,第二个元素是错误处理
    [
      (url, options) => {
        return { url, options };
      },
      (error) => {
        return Promise.reject(error);
      },
    ],
    // 数组,省略错误处理
    [
      (url, options) => {
        return { url, options };
      },
    ],
  ],
  // 响应拦截器
  responseInterceptors: [
    // 直接写一个 function,作为拦截器
    (response) => {
      // 不再需要异步处理读取返回体内容,可直接在data中读出,部分字段可在 config 中找到
      // const { data = {} as any, config } = response;
      // do something
      console.log(response);

      return response;
    },
    // 一个二元组,第一个元素是 request 拦截器,第二个元素是错误处理
    [
      (response) => {
        return response;
      },
      (error) => {
        return Promise.reject(error);
      },
    ],
    // 数组,省略错误处理
    [
      (response) => {
        return response;
      },
    ],
  ],
};

 发送请求

import { request } from '@umijs/max';
export const getFindList = (params: {
  // query
  /** keyword */
  key?: string;
  /** current */
  page?: number;
}) =>
  request<API.Result>(
    `/union/shop/discovery/${params.key}/${params.page}`,
  );

4. 公共状态管理

// src/models/global.ts

import { useState } from 'react';

const useUser = () => {

        const [name, setName] = useState<string>("你好! 同学");

        return {

                name,

                setName,

        };

};

export default useUser;

 // src/pages/Home/index.tsx

import { useModel } from '@umijs/max';

const HomePage: React.FC = () => {

        const { name , setName } = useModel('global');//根据文件名获取

        return (

            <div>

                <p>{name}</p>

                <button onClick={()=>setName("你好!UMI")}> 按钮</button>

            </div>

        );

};

export default HomePage;

5. 环境变量

$ pnpm install cross-env -D

package.json修改命令 

"scripts": {

        "build": "cross-env UMI_ENV=release max build", //生产环境打包

        "build:test": "cross-env UMI_ENV=trial max build", //测试环境打包

        "dev": "cross-env UMI_ENV=develop max dev", //开发环境本地运行

        "dev:test": "cross-env UMI_ENV=trial max dev", //测试环境本地运行

},

根目录下创建文件.umirc.develop.ts  

import { defineConfig } from '@umijs/max';

export default defineConfig({

        define: {

           'process.env': {

                BASE_URL: '开发环境地址',

            },

        },

})

根目录下创建文件.umirc.trial.ts

import { defineConfig } from '@umijs/max';

export default defineConfig({

        define: {

           'process.env': {

                BASE_URL: '测试环境地址',

            },

        },

})

根目录下创建文件.umirc.release.ts

import { defineConfig } from '@umijs/max';

export default defineConfig({

        define: {

           'process.env': {

                BASE_URL: '生产环境地址',

            },

        },

})

项目中使用

console.log('UMI_ENV', process.env.BASE_URL); 

 6. 打包(白屏问题)

在.umirc.ts文件中添加

export default defineConfig({

        hash: true, 

        history: {

                type: 'hash', // 可选 browser、hash 和 memory

        },

        base: '/',

        publicPath: process.env.NODE_ENV === 'production' ? './' : '',

});

pnpm build 

7. 登录 

使用umi/max登录的逻辑,是在登录页面拿到token

// 页面

import { LockOutlined, UserOutlined } from '@ant-design/icons';
import { useNavigate } from '@umijs/max';
import { Button, Card, Form, Input, message } from 'antd';
import { Cookies } from 'react-cookie';
import './index.less';
export default () => {
  const navigate = useNavigate();
  const onFinish = (values: any) => {
    const username = values.username === 'admin';
    const password = values.password === '123456';
    if (username && password) {
      const cookies = new Cookies();
      cookies.set('user-token', '5tgb3edc7ytfc8ujhn');
      message.success('登录成功');
      navigate('/home');
    } else {
      message.error('账号或密码错误');
    }
  };
  return (
    <div className="login-pages">
      <Card title="登录" className="login-card">
        <Form wrapperCol={{ offset: 4, span: 16 }} onFinish={onFinish}>
          <Form.Item
            name="username"
            rules={[{ required: true, message: '请输入 账号' }]}
          >
            <Input prefix={<UserOutlined />} placeholder="用户名或手机号" />
          </Form.Item>

          <Form.Item
            name="password"
            rules={[{ required: true, message: '请输入 密码!' }]}
          >
            <Input.Password prefix={<LockOutlined />} placeholder="密码" />
          </Form.Item>

          <Form.Item wrapperCol={{ offset: 8, span: 8 }}>
            <Button type="primary" htmlType="submit" className="login-button">
              登录
            </Button>
          </Form.Item>
        </Form>
      </Card>
    </div>
  );
};
// 样式

.login-pages{
    height: 100vh;
    min-height: 276px;
    width: 100vw;
    min-width: 600px;
    background: #eeeeee;
    padding-top: calc(50vh - 136px);
}
.login-card {
  width: 420px;
  margin: auto;
}
.login-button {
  width: 100%;
}

getInitialState 统一获取、管理用户信息

// app.tsx文件 用户信息数据流

import { Cookies } from 'react-cookie';
export async function getInitialState(): Promise<{ userInfo: API.UserInfo }> {
  // 获取token
  const cookies = new Cookies();
  console.log(cookies.get('user-token'));

  // 根据token获取请求用户数据
  const userInfo = {
    id: 1,
    userName: 'admin',
    nickName: '王布尔',
    isAdmin: false,
    avatar:
      'https://img.alicdn.com/imgextra/i2/O1CN01Jd8bIr1gZUwzJDpdp_!!6000000004156-0-tps-720-540.jpg',
  };

  // 此处return的数据可用useModel获取,也可以用作权限管理
  return {
    userInfo,
  };
}

export const layout = () => {
  return {
    ...,
    pure: location.hash === '#/login' ? true : false, //如果为登录页面就隐藏系统布局
  };
};

8. 路由权限

// access.ts 权限

export default (initialState: { userInfo: API.UserInfo }) => {
  // 此处的initialState是app.tsx文件中getInitialState()函数反回的用户数据
  // 在这里按照初始化数据定义项目中的权限,统一管理
  // 参考文档 https://umijs.org/docs/max/access
  // console.log('--------', initialState);

  return {
    isAdmin: initialState?.isAdmin ?? false,
  };
};
// app.tsx 配置错误跳转的页面

export const layout = () => {
  return {
    ...,
    // 自定义 403 页面
    unAccessible: <UnAccessible />,
    // 自定义 404 页面
    noFound: <NoFound />,
    // Ant Design Pro 的错误页
    errorBoundary: <ErrorBoundary />,
  };
};
// route.ts

      {
        name: '地图',
        path: '/file/map',
        component: './FileManagement/Map',
        access: 'isAdmin', //判断isAdmin是否为true为页面添加权限
      },

最后建议。如果.umirc配置较为复杂,建议采用.config文件夹代替配置项目。

  • 12
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
在使用React Umi进行图片压缩时,可以通过配置webpack.config.js文件来实现。首先,确保已经安装了image-webpack-loader插件。如果安装失败,可以尝试使用cnpm安装,具体步骤如下: 1. 首先,卸载image-webpack-loader插件,可以使用以下命令: yarn remove image-webpack-loader npm uninstall image-webpack-loader 2. 更换镜像源,可以使用以下命令安装cnpm: npm install cnpm -g --registry=https://registry.npm.taobao.org 3. 使用cnpm安装image-webpack-loader插件: cnpm install --save-dev image-webpack-loader 安装完成后,打开webpack.config.js文件,在配置项中添加以下内容: ```javascript { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, use: [ { loader: 'file-loader', options: { name: '[name].[hash:7].[ext]', outputPath: 'mobile/img' } }, { loader: 'image-webpack-loader', options: { mozjpeg: { progressive: true, quality: 50 }, optipng: { enabled: false }, pngquant: { quality: [0.5, 0.65], speed: 4 }, gifsicle: { interlaced: false } } } ] } ``` 在这个配置中,可以根据自己的需求调整图片压缩的质量。通过设置mozjpeg的quality参数,可以控制JPEG图片的压缩质量。同时,设置pngquant的quality参数,可以控制PNG图片的压缩质量。 请确保在配置完成后,运行yarn build进行打包。经过压缩后,图片的大小可能会减小,但也可能会导致图片稍微模糊。根据实际情况,可以自行调整压缩的质量来平衡图片大小和清晰度。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [react打包压缩js\css\img](https://blog.csdn.net/qq_41359066/article/details/107507264)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王布尔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值