umi миддл и закулисная проектная практика

React.js

задний план

Промежуточные и внутренние проекты обычно имеют сильную структуру страниц или логическую согласованность, например такие страницы, как поиск, формы, меню навигации, макеты и логические аспекты, такие как поток данных и разрешения. Инкапсуляция этих функций на основе Webpack требует относительно большого объема предварительной работы.Umi основан на маршрутизации и использует ее для расширения функций, включая микроинтерфейсы, упаковку компонентов, библиотеки запросов, библиотеки ловушек, потоки данных и многое другое. Исходя из этого, посадка в компаниюumiупражняться.

Структура каталогов

на основеumiОбъясняется общая структура каталогов проекта, и вы можете получить общее представление о проекте.

├── package.json
├── config
		└── config.js
├── dist
├── mock
├── public
└── src
    ├── .umi
    ├── layouts/index.js
    ├── locales
    ├── models
    ├── pages
        ├── index.less
        └── index.js
    ├── services
    ├── wrappers
    ├── global.js
    └── app.js
  • config.js— В основном конфигурация маршрутизации, конфигурация плагинов,webpackнастроить
  • layouts- связанные с макетом
  • locales- глобализация
  • modelsdvaсхема потока данных илиplugin-model
  • wrappers— Высокоуровневая инкапсуляция компонентов для настройки маршрутизации, например проверка разрешений на уровне маршрутизации.
  • app.js— Конфигурация во время выполнения, например, необходимость динамического изменения маршрутизации, переопределение рендерингаrender, прослушивать изменения маршрутизации
  • global.js— Глобальная запись выполнения, например, может быть размещенаsentryЖдать

маршрутизация

Можно сказать, что маршрутизация является краеугольным камнем интерфейсных проектов.Давайте поговорим о конфигурации, связанной с маршрутизацией.

// config/route.js
export default [{
  path: '/merchant',
  name: '商户管理',
  routes: [
    {
      path: '/merchant/list',
      name: '商户列表'
      component: './list'
    },
    {
      path: '/merchant/detail',
      name: '商户详情',
      hideInMenu: true,
      component: './detail'
    }
  ]
}]

Настройка маршрутизации в дополнение к обычнойname,path,componentТакже может поддерживать конфигурациюumiПараметры конфигурации плагина, такие какpro-layouthideInMenu, чтобы скрыть маршрут, соответствующий пункту меню навигации

Компоненты маршрутизации могут быть загружены по требованию вconfig.jsВключена средняя конфигурация

// config/config.js
export default {
  dynamicImport: {}
}

Маршрутизация также поддерживает операции с ловушками, такие как вход в систему, последующий доступ к странице входа и перенаправление на домашнюю страницу.

// config/route.js
{
  path: '/login',
	wrappers: [
    '@/wrappers/checkLogin',
  ],
  component: './Login'
}

Маршрутизация некоторых проектов может быть настроена базой данных.В настоящее время динамическая маршрутизация требуется для получения данных от интерфейса для создания маршрутизации.

// src/app.js
let extraRoutes;

export function patchRoutes({ routes }) {
  merge(routes, extraRoutes);
}

export function render() {
  fetch('/api/routes').then((res) => { extraRoutes = res.routes })
}

Выбор схемы потока данных

  1. использовать@umijs/plugin-dva, метод разработки аналогиченredux
// config/config.js
export default {
  dva: {
    immer: true,
    hmr: false,
  }
}
  • Соглашение состоит в том, чтобы моделировать способ организации, без ручной регистрацииmodel
  • Имя файла является пространством имен,modelвнутри, если не объявленоnamespace, будет использовать имя файла какnamespace
  • Встроенная двойная загрузка, подключить напрямуюloadingполе можно использовать
  1. использовать@umijs/plugin-model

на основеhooksПростое решение Paradigm для управления данными (некоторые сценарии можно заменитьdva), который обычно используется для глобальных общих данных проектов мидл-офиса.

// src/models/useAuthModel.js
import { useState, useCallback } from 'react'

export default function useAuthModel() {
  const [user, setUser] = useState(null)
  const signin = useCallback((account, password) => {
    // signin implementation
    // setUser(user from signin API)
  }, [])
  const signout = useCallback(() => {
    // signout implementation
    // setUser(null)
  }, [])
  return {
    user,
    signin,
    signout
  }
}

Использовать модель

import { useModel } from 'umi';

export default () => {
  const { user, fetchUser } = useModel('user', model => ({ user: model.user, fetchUser: model.fetchUser }));
  return <>hello</>
};

С точки зрения взаимодействия с пользователем, мидл-офисные проекты в основном представляют собой формы и таблицы, и существует не так много сценариев для обмена данными между страницами.dvaНемного тяжеловат, поэтому рекомендуется 2-йplugin-modelэтот легкий

макет

布局图片

@umijs/plugin-layoutПлагины обеспечивают более удобную верстку

  • По умолчанию используется макет Ant Design@ant-design/pro-layout, который поддерживает все его элементы конфигурации.
  • Данные меню боковой панели автоматически генерируются на основе конфигурации маршрута.
  • Обработка 403/404 и Error Boundary для маршрутов поддерживаются по умолчанию.
  • Используется с плагином @umijs/plugin-access для управления разрешениями маршрутизации.
// src/app.js
export const layout = {
  logout: () => {}, // do something
  rightRender:(initInfo)=> { return 'hahah'; },// return string || ReactNode;
};

разрешение

Общие проекты неотделимы от управления разрешениями, umi использует@umijs/plugin-accessпредоставить настройки разрешений

// src/access.js
export default function(initialState) {
  const { permissions } = initialState; // getInitialState方法执行后

  return {
    canAccessMerchant: true,
    ...permissions
  }
}
  1. Контроль разрешений на странице маршрутизации, добавленный в конфигурацию маршрутизацииaccessАтрибуты
// config/route.js
export default [{
  path: '/merchant',
  name: '商户管理',
  routes: [
    {
      path: '/merchant/list',
      name: '商户列表'
      component: './list',
      access: 'canAccessMerchant'
    }
  ]
}]
  1. Конечно, его также можно использовать на странице или в компоненте.useAccessПолучить информацию, связанную с разрешениями
import React from 'react'
import { useAccess } from 'umi'

const PageA = props => {
  const { foo } = props;
  const access = useAccess();

  if (access.canReadFoo) {
    // 如果可以读取 Foo,则...
  }

  return <>TODO</>
}

export default PageA
  1. В реальном развитии бизнеса разрешения должны быть динамически получены из интерфейса, поэтому вам нужно использовать@umijs/plugin-initial-stateа также@umijs/plugin-model
// src/app.js
/**
getInitialState会在整个应用最开始执行,返回值会作为全局共享的数据。Layout 插件、Access 插件以及用户都可以通过 useModel('@@initialState') 直接获取到这份数据
*/
export async function getInitialState() {
  const permissions = await fetchUserPermissions()
  return { permissions }
}

глобализация

@umijs/plugin-localeПлагин интернационализации для решенияi18nвопрос

использоватьantdДля разработки по умолчанию используется английский язык, для отображения китайского языка необходимо открыть конфигурацию интернационализации.

// config/config.js
export default {
  locale: {
    default: 'zh-CN',
    antd: true,
    baseNavigator: true,
  }
}

в маршрутизацииtitleилиnameИнтернационализацию можно использовать напрямуюkey, который автоматически преобразуется в соответствующую языковую копию

// src/locales/zh-CN.js
export default {
  'about.title': '关于 - 标题',
}
// src/locales/en-US.js
export default {
  'about.title': 'About - Title',
}

Конфигурация проекта следующая

export default {
  routes: [
    {
      path: '/about',
      component: 'About',
      title: 'about.title',
    }
  ]
}

Интегрировать плагин Redux

Если включенdva, то есть использоватьreduxдля централизованного управления потоком данных, затем используйтеredux-persistПостоянство плагинаreduxданные дляlocalStorage, примерно так

// src/app.js
import { getDvaApp } from 'umi'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2'
import createFilter from 'redux-persist-transform-filter'

export const dva = {
  config: {
    onError(e) {
      e.preventDefault()
    },
    onReducer(reducer) {
      const globalCollapsedFilter = createFilter('global', ['collapsed'])
      const persistConfig = {
        key: 'root',
        storage,
        whitelist: ['global'],
        transforms: [globalCollapsedFilter],
        stateReconciler: autoMergeLevel2
      }
      return persistReducer(persistConfig, reducer)
    }
  }
}

window.addEventListener('DOMContentLoaded', () => {
  const app = getDvaApp()
  persistStore(app._store)
})

Разработка плагина

umiОн реализует полный жизненный цикл и делает его подключаемым, тем самым предоставляя пользователям запись расширения. Например, установка плагина конфигурации по умолчанию

export default api => {
  api.modifyDefaultConfig(config => {
    return Object.assign({}, config, {
      title: false,
      history: {
        type: 'hash'
      },
      hash: true,
      antd: {},
      dva: {
        hmr: true
      },
      dynamicImport: {
        loading: '@/components/PageLoading'
      },
      targets: {
        ie: 10
      },
      runtimePublicPath: true,
      terserOptions: {
        compress: {
          drop_console: true
        }
      }
    });
  });
}

Преимущества перехода с Umi2 на Umi3

Проект электронной коммерции в группе, используемый до обновленияumi2изantd-design-pro4, Хотя он может соответствовать развитию бизнеса, многие части шаблона все еще не соответствуют бизнесу, например проверка разрешений.

Выпуск Umi3 также приносит лучшую архитектуру и опыт разработки.

  • Уровень конфигурации сильно упрощен
  • Последний плагин Umi3 предоставляет макет, поток данных, разрешения и другие новые решения.
  • Наконец-то встроил в шаблон код, связанный с разрешениями.

Создание шаблонов строительных лесов на основе Umi

На основе Umi для создания внутреннего шаблона строительных лесов средней платформы, как показано на рисунке ниже.

布局图片

Этот шаблон строительных лесов на основе Umi расширяет следующие возможности

  • Скомпилируйте и упакуйте каталог dist в соответствии со спецификацией развертывания компании beetle (внутренняя платформа CI/CD).
  • Настройте подключаемый модуль конфигурации по умолчанию, чтобы уменьшить конфигурацию элемента конфигурации.
  • eslintчек об оплате
  • prettierкод формата
  • спецификация коммита git
  • комбинироватьpro-layoutДля более удобной планировки
  • Используйте конфигурацию времени выполненияapp.jsДинамически создавать комбинацию локальных и удаленных навигационных меню конфигурации
  • комбинироватьplugin-accessПлагины и внутренняя система разрешений для контроля разрешений на уровне страниц или кнопок

Для нового проекта выбор промежуточного шаблона на основе инструментов создания шаблонов в компании может быстро создать первоначальный проект с такими функциями, как разрешения, макет, спецификация кода и общие страницы, что позволяет значительно избежать дублирования работы.

Суммировать

Umi предоставляет готовые возможности, вам не нужно настраивать webpack, babel и встроенные конфигурации с лучшими практиками. Конечно, вы также можете настроить разработку плагинов-расширений. Umi приложил много усилий для повышения производительности, невидимой для разработчиков.

Чуть меньше, чем правильно Умиwebpack-dev-serverКонфигурация менее открыта, если есть правоwebpack-dev-serverЕсли у вас есть большие требования к конфигурации, вам нужно это учитывать~~

Раздел благосостояния

В соответствии с уведомлением мы опубликуем практику и мышление Zhuanzhuan в микро-интерфейсе, автономном пакете iOS и другой инфраструктуре и технологиях среднего уровня.Приглашаем всех обратить внимание и надеемся на дальнейшее общение с вами. Статья также будет отправлена ​​на публичный аккаунт "Да Чжуань Чжуань ФЭ", а в паблик аккаунте будет проведена лотерея. Призом в этой статье будет памятная футболка Чжуань Чжуаня. Просим всех обратить внимание ✿✿ヽ(°▽°)ノ✿