предисловие
В Интернете очень мало руководств по umi.Многие люди написали только немного и много по гидрологии, поэтому я планирую написать один, собрать umi самостоятельно, инкапсулировать часто используемые функции и использовать их в реальные проекты компании.
Знакомство с уми
Что такое Уми?
Уми, по-китайски можно произносить какУми, представляет собой расширяемую среду интерфейсных приложений корпоративного уровня. Umi основан на маршрутизации и поддерживает как маршрутизацию конфигурации, так и маршрутизацию соглашений, чтобы обеспечить полные функции маршрутизации и соответственно расширить функции. Затем он оснащен системой подключаемых модулей с полным жизненным циклом, охватывающим каждый жизненный цикл от исходного кода до создания продуктов, поддерживающих различные функциональные расширения и потребности бизнеса.
Umi 是蚂蚁金服的底层前端框架,已直接或间接地服务了 3000+ 应用,包括 java、node、H5 无线、离线(Hybrid)应用、纯前端 assets 应用、CMS 应用等。 Он хорошо обслуживал наших внутренних пользователей и, надеюсь, сможет обслуживать и внешних пользователей.
В основном он выполняет следующие функции:
- 🎉 Масштабируемость, Umi реализует полный жизненный цикл и делает его подключаемым, а внутренние функции Umi также дополняются подключаемыми модулями. Кроме того, поддерживаются подключаемые модули и наборы подключаемых модулей для удовлетворения потребностей в многоуровневости функциональных и вертикальных доменов.
- 📦из коробки, Umi имеет встроенную маршрутизацию, сборку, развертывание, тестирование и т. д., и вы можете начать разработку только с одной зависимостью. Он также предоставляет интегрированный набор плагинов для React с богатыми функциями, которые могут удовлетворить 80% ежедневных потребностей в разработке.
- 🐠 Предприятие, подтвержденный более чем 3000 внутренними проектами Ant, а также проектами Ali, Youku, Netease, Fliggy, Koubei и другими компаниями, он заслуживает доверия.
- 🚀 Много самоисследования, включая микроинтерфейсы, упаковку компонентов, инструменты документирования, библиотеки запросов, библиотеки ловушек, потоки данных и т. д., чтобы удовлетворить периферийные потребности повседневных проектов.
- 🌴Полная маршрутизация, поддерживает как маршрутизацию конфигурации, так и маршрутизацию по соглашению, сохраняя при этом полноту функций, таких как динамическая маршрутизация, вложенная маршрутизация, маршрутизация разрешений и т. д.
- 🚄лицом к будущему, удовлетворяя потребности, мы не перестанем изучать новые технологии. Например, ускорение dll, современный режим, webpack @ 5, автоматический внешний, без сборщика и т. Д.
Когда не использовать уми?
Если ты,
- Требуется браузер, поддерживающий IE 8 или ниже.
- Необходимо поддерживать React ниже React 16.8.0
- Необходимо запустить в среде ниже Node 10
- Иметь строгие требования к настройке веб-пакета и субъективную готовность
- Необходимо выбрать другую схему маршрутизации
Уми не может быть для вас.
Почему бы нет?
create-react-app
create-реагировать-приложение — это схема уровня упаковки, основанная на веб-пакете, включая сборку, разработку, lint и т. д. Она обеспечивает максимальное удобство работы на уровне упаковки, но не включает маршрутизацию, не является фреймворком и не поддерживает настройку. . Поэтому, если вы захотите модифицировать какие-то конфигурации на его основе или хотите провести техническую конвергенцию вне уровня упаковки, вы столкнетесь с трудностями.
next.js
Next.js - хороший выбор, УМИ Многие функции - это ссылка Next.js do. Сказать, что есть районы не так хороши, как УМИ, я думаю, что может быть достаточно, чтобы закрыть бизнес, а не наземный газ. Например, проблема ANND, DVA Deep Integration, такая как интернационализация, привилегии, поток данных, конфигурация маршрутизации, программа патча, автоматизированные внешние аспекты и т. Д. На передние разработчики.
инициализация проекта umi3
Подготовка окружающей среды
сначала надо иметьnode, и убедитесь, что версия узла 10.13 или выше.
Рекомендуемое использованиеyarnУправление зависимостями npm
В этом проекте используется версия nodev14.17.5 yarn 1.22.15
строительные леса
Создайте новую папку umi3 на рабочем столе, откройте ее с помощью vscode, откройте терминал vscode,
воплощать в жизньyarn create @umijs/umi-appСоздать проект
Установить зависимостиyarn
Стартовый проектyarn start
Настроить красивее, eslint, stylelint
umi поддерживает набор файлов конфигурации для prettier, eslint и stylelint.umi-fabric
yarn add @umijs/fabric -D
Создайте следующие три файла в корневом каталоге и удалите файл .prettierrc.
.eslintrc.js,.prettierrc.js,.stylelintrc.js
Конфигурация выглядит следующим образом
//.eslintrc.js 配置
module.exports = {
extends: [require.resolve('@umijs/fabric/dist/eslint')],
// in antd-design-pro
globals: {
ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: true,
page: true,
},
rules: {
// your rules
'prefer-const': 0,
},
};
//.prettierrc.js 配置
const fabric = require('@umijs/fabric')
module.exports = {
...fabric.prettier,
semi: false,
}
//.stylelintrc.js 配置
const fabric = require('@umijs/fabric')
module.exports = {
...fabric.stylelint,
}
Создайте новый файл игнорирования eslint в корневом каталоге .eslintignore.
.eslintrc.js
node_modules
Добавлен lint-staged в package.json."eslint --fix"
Наконец, ваш vscode должен установить эти три расширения с одинаковым именем.В это время измените файлы js и less соответственно, и вы обнаружите, что проверка стиля уже есть.
验证
Исправлятьsrc/paegsв папкеindex.tsxфайл, добавьте переменную a, появится сообщение об ошибке eslint, указывающее, что eslint действует
Затем отправьте файл index.tsx отдельно.
Он подскажет, что есть ошибка и не может отправить, объяснитеpre-commmitхук вступает в силу
Автоматически форматировать код при сохранении
В настройках vscode в форматировании текстового редактора поставьте галочку Формат при сохранении
Мой эслинт или красивше не действует?
Перейдите к выводу в терминале, найдите eslint или prettier, чтобы посмотреть, нормальный ли у них журнал вывода. Если есть ошибка, устраните проблему в соответствии с сообщением об ошибке.
检查步骤:
- Обязательно установите umi-fabric
- Проверьте, существует ли файл конфигурации
- Загружены ли плагины vscode eslint и prettier?
- Подтвердите выходной журнал, есть ли ошибка
lint-staged во время предварительной фиксации не вступает в силу
В package.json настраиваем следующий код
Это означает выполнение более красивого кода форматирования и исправления eslint перед фиксацией кода.Если вы не вступаете в силу при отправке кода, пожалуйста, выполните
yarn install --force
Выполните эту команду, чтобы повторно вытащить зависимости
Причина, по которой это не работает?
В начале гуглил, проверял документы, причину не нашел, в итоге нашел ответ в вопросе umi2.
Причина в том порядке, в котором мы инициализируем git-репозиторий, если мы сначала инициализируем git-репозиторий, затем создаем проект, а затем подтягиваем зависимости. Нет проблем.
Если мы сначала создадим проект umi, вытащим зависимости и, наконец, инициализируем git и отправим код в репозиторий git, когда мы вытащим зависимости, соответствующая предварительная фиксация не будет сгенерирована без .git, поэтому она не вступит в силу. . Итак, на данный момент нам нужно только повторно вытащить зависимости.
Настроить код инициализации css
为什么要初始化css
Опытные создатели веб-сайтов знают, что это необходимо для учета совместимости браузеров.На самом деле, разные браузеры имеют разные значения по умолчанию для некоторых тегов.Если CSS не инициализирован, страницы между браузерами часто будут отличаться. Конечно, инициализация стиля окажет определенное влияние на SEO, но вы не можете иметь и то, и другое, но постарайтесь инициализировать с наименьшим влиянием.
Самый простой способ инициализации:* {padding: 0; margin: 0;}. Есть много людей, которые написали это так. Это действительно просто, но у некоторых людей это может вызвать подозрения: общий символ, такой как *, быстр при написании кода, но если веб-сайт большой и файл таблицы стилей CSS большой, он будет создавать все теги таким образом.Инициализируйте его один раз. , что сильно увеличивает нагрузку на сайт, и сайт загружается долго.
Инициализация CSS относится к сбросу стиля браузера. Разные браузеры могут иметь разные стили по умолчанию, поэтому первое, что нужно сделать при разработке, — это унифицировать их. Различия страниц между браузерами часто возникают, если CSS не инициализирован. Каждый раз, когда разрабатывается новый веб-сайт или новая веб-страница, инициализация свойств стиля CSS делает его более удобным и точным для тегов CSS или html, которые мы будем использовать, что делает его более удобным и кратким при разработке веб-контента, сокращая при этом объем кода CSS и экономя время загрузки веб-страницы.
Конгресс в Умиsrc/global.cssЭто глобальный стиль. Если этот файл существует, он будет автоматически импортирован в начало файла записи.
Создайте новый в srcglobal.css, код показывает, как показано ниже
body,
ol,
ul,
h1,
h2,
h3,
h4,
h5,
h6,
p,
th,
td,
dl,
dd,
form,
fieldset,
legend,
input,
textarea,
select,
figure,
figcaption {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
img {
border: none;
}
input {
outline: none;
}
конфигурационный файл
Уми ин.umirc.ts или config/config.tsНастраивайте проекты и плагины в , поддерживайте es6.
Если конфигурация проекта не сложная, рекомендуется.umirc.tsНапишите конфигурацию в , если конфигурация проекта более сложная, вы можете написать конфигурацию вconfig/config.tsи разделить часть конфигурации, например, конфигурацию маршрутизации можно разделить на отдельныеroutes.ts
Рекомендуется выбрать один из двух способов настройки..umirc.tsболее высокий приоритет.
Мы используем метод config для удаления .umirc.ts и создания нового корневого каталога.configпапка,
Создайте новый config.ts внутри
Содержимое по умолчанию выглядит следующим образом
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
routes: [
{ path: '/', component: '@/pages/index' },
],
fastRefresh: {},
});
Несколько сред и несколько файлов конфигурации
через переменные окруженияUMI_ENVРазличайте разные среды, чтобы указать конфигурацию.
Для совместимости можно использовать сторонние инструментыcross-envустановить переменные окружения
yarn add cross-env --dev
в пакете.jsonscriptсередина
"start": "cross-env UMI_ENV=dev umi dev",
"start:test": "cross-env UMI_ENV=test umi dev",
"start:prd": "cross-env UMI_ENV=prd umi dev",
"build": "cross-env UMI_ENV=dev umi build",
"build:test": "cross-env UMI_ENV=test umi build",
"build:prd": "cross-env UMI_ENV=prd umi build",
Затем создайте новый в папке config
config.dev.ts,config.test.ts,config.prd.ts
Файлы конфигурации, представляющие среду разработки, тестовую среду и производственную среду.
config.dev.ts
import { defineConfig } from 'umi';
export default defineConfig({
define: {
CurrentEnvironment: 'dev',
},
});
config.test.ts
import { defineConfig } from 'umi';
export default defineConfig({
define: {
CurrentEnvironment: 'test',
},
});
config.prd.ts
import { defineConfig } from 'umi';
export default defineConfig({
define: {
CurrentEnvironment: 'prd',
},
});
CurrentEnvironmentПеременная представляет текущую среду, которая будет использоваться позже для настройки различных адресов запросов в соответствии с различными средами.
defineИспользуется для предоставления переменных, доступных в коде, определенные переменные могут быть получены глобально
В это время выполнитьyarn start:prd, затем перейдите к index.tsx страниц для печатиCurrentEnvironment.
Затем вам нужно перейти в корневой каталогtypings.d.tsДобавить к
// 声明当前的环境
declare const CurrentEnvironment: 'dev' | 'test' | 'prd';
Затем ошибка исчезает, и консоль печатает следующее
В это время повторно выполнитьyanr start:testКонсоль печатает следующим образом
Переменные среды и многоконструктивный успех
**注意点**:
config.tsКак файл конфигурации, не забудьте удалить.umirc.tsВ противном случае config.ts не вступит в силу.
пользовательские переменные среды
Если мы хотим настроить переменную окружения, REACT_APP_ENV.package.jsonвнутренние настройки
Так как же нам получить такую переменную?
Сначала мы будемconfig.tsизdefineнастроить
define: {
REACT_APP_ENV: process.env.REACT_APP_ENV,
},
затем в корневой каталогtypings.d.tsопределение
declare const REACT_APP_ENV: string;
Это можно получить и использовать по всему мируREACT_APP_ENVэта переменная окружения.
Может печатать непосредственно на любом компоненте
console.log('自定义环境变量', REACT_APP_ENV);
системные переменные окружения
Официально предоставленные переменные среды
как использовать?
Новое в корневом каталоге.envфайл конфигурации переменной среды
затем написать
PORT=3000 // 表示启动的端口号为3000
COMPRESS = none // 不压缩 CSS 和 JS
Есть также некоторые переменные среды, которые нельзя настроить в.env, можно добавить только в командной строке
НапримерFORK_TS_CHECKERПроверка типа TypeScript не включена по умолчанию, значение равно1включен.
"start": "cross-env FORK_TS_CHECKER=1 UMI_ENV=dev umi dev",
инкапсуляция запроса
Создайте новый в папке srcrequestпапка новаяrequest.ts
request.ts
/**
* 网络请求工具 封装umi-request
* 更详细的 api 文档: https://github.com/umijs/umi-request
*/
import { extend } from 'umi-request';
import type { RequestOptionsInit } from 'umi-request';
import { notification } from 'antd';
// codeMessage仅供参考 具体根据和后端协商,在详细定义.
const codeMessage = {
200: '服务器成功返回请求的数据。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
500: '服务器发生错误,请检查服务器。',
};
type mapCode = 200 | 400 | 500;
/**
* 错误异常处理程序
*/
const errorHandler = (error: { response: Response }): Response => {
const { response } = error;
if (response && response.status) {
let errorText = codeMessage[response.status as mapCode] || response.statusText;
const { status, url } = response;
response
?.clone()
?.json()
?.then((res) => {
// 后端返回错误信息,就用后端传回的
errorText = res.msg ? res.msg : errorText;
notification.error({
message: `请求错误 ${status}: ${url}`,
description: errorText,
});
});
} else if (!response) {
notification.error({
description: '您的网络发生异常,无法连接服务器',
message: '网络异常',
});
}
return response;
};
/**
* 配置request请求时的默认参数
*/
const request = extend({
errorHandler, // 默认错误处理
credentials: 'include', // 默认请求是否带上cookie
});
// 根据不同的开发环境,配置请求前缀
interface ApiPrefix {
dev: string;
test: string;
prd: string;
}
const apiPreFix: ApiPrefix = {
dev: 'http://120.55.193.14:3030/',
test: 'http://120.55.193.14:3030/',
prd: 'http://120.55.193.14:3030/',
};
// request拦截器, 携带token,以及根据环境,配置不同的请求前缀
request.interceptors.request.use((url: string, options: RequestOptionsInit) => {
// 不携带token的请求数组
let notCarryTokenArr: string[] = [];
if (notCarryTokenArr.includes(url)) {
return {
url: `${apiPreFix[CurrentEnvironment]}${url}`,
options,
};
}
// 给每个请求带上token
let token = localStorage.getItem('tokens') || '';
let headers = {
Authorization: `Bearer ${token}`,
};
return {
url: `${apiPreFix[CurrentEnvironment]}${url}`,
options: { ...options, interceptors: true, headers },
};
});
/**
* @url 请求的url
* @parameter 上传的参数
*/
// 封装的get,post.put,delete请求
const get = async (url: string, parameter?: Record<string, unknown>): Promise<any> => {
try {
const res = await request(url, { method: 'get', params: parameter });
return res;
} catch (error) {
console.error(error);
}
};
const deletes = async (url: string, parameter?: Record<string, unknown>): Promise<any> => {
try {
const res = await request(url, { method: 'delete', params: parameter });
return res;
} catch (error) {
console.error(error);
}
};
const post = async (url: string, parameter?: Record<string, unknown>): Promise<any> => {
try {
const res = await request(url, { method: 'post', data: parameter });
return res;
} catch (error) {
console.error(error);
}
};
const put = async (url: string, parameter?: Record<string, unknown>): Promise<any> => {
try {
const res = await request(url, { method: 'put', data: parameter });
return res;
} catch (error) {
console.error(error);
}
};
export default {
get,
post,
put,
deletes,
};
Здесь инкапсулируется umi-запрос, ошибки интерфейса обрабатываются единообразно, перехватчик запроса переносит токен и т. д. Наконец, его очень легко использовать с useRequest.
Использование два в уми
представлять
Содержит следующие функции,
-
встроенный два, версия по умолчанию
^2.6.0-beta.20, если в проекте есть зависимости, сначала будет использоваться версия зависимостей в проекте. - Традиционная модель организации, нет необходимости вручную регистрировать модель
- Имя файла является пространством имен, если в модели не объявлено пространство имен, в качестве пространства имен будет использоваться имя файла
-
Встроенная двойная загрузка, подключить напрямую
loadingПоле можно использовать -
поддержка погружена, настроив
immerоткрытым
Традиционная модель организации
Файлы, соответствующие следующим правилам, считаются файлами моделей.
-
src/modelsфайлы под -
src/pages, файлы в каталоге моделей в подкаталоге -
src/pages, все файлы model.ts (без учета регистра любых букв)
фактическое использование
Например, создайте новую папку моделей в src и создайте новую папку внутриtest.ts
test.ts
import type { Effect, Reducer, Subscription } from 'umi'; // 映入umi 定义好的ts类型
import axios from '../request/request'; // 引入封装好的网络请求
// state 接口
export interface TextModelState {
name?: string;
testData?: string;
}
// test model接口
export interface TextModelType {
namespace: 'testModel';
state: TextModelState;
effects: {
query: Effect;
};
reducers: {
save: Reducer<TextModelState>;
msg: Reducer<TextModelState>;
};
subscriptions?: { setup: Subscription };
}
const IndexModel: TextModelType = {
namespace: 'testModel',
state: {
name: '初始名字',
testData: '初始testData',
},
effects: {
*query(action, { call, put }) {
const getDataTest = async () => {
const data = await axios.get('test');
return data;
};
let testData = yield call(getDataTest);
yield put({
type: 'msg',
data: { testData: testData?.msg },
});
},
},
reducers: {
save(state) {
return {
...state,
name: 'jimmy',
};
},
msg(state, action) {
return {
...state,
testData: action?.data?.testData,
testData2: action?.data?.testData2,
};
},
},
};
export default IndexModel;
под источник/страницыindex.tsxиспользуется в
index.tsx
import type { Effect, Reducer, Subscription } from 'umi'; // 引入umi 定义好的ts类型
import axios from '../request/request'; // 引入封装好的网络请求
// state 接口
export interface TextModelState {
name?: string;
testData?: string;
}
// test model接口
export interface TextModelType {
namespace: 'testModel';
state: TextModelState;
effects: {
query: Effect;
};
reducers: {
save: Reducer<TextModelState>;
msg: Reducer<TextModelState>;
};
subscriptions?: { setup: Subscription };
}
const IndexModel: TextModelType = {
namespace: 'testModel',
state: {
name: '初始名字',
testData: '初始testData',
},
effects: {
*query(action, { call, put }) {
const getDataTest = async () => {
const data = await axios.get('test');
return data;
};
let testData = yield call(getDataTest);
yield put({
type: 'msg',
data: { testData: testData?.msg },
});
},
},
reducers: {
save(state) {
return {
...state,
name: 'jimmy',
};
},
msg(state, action) {
return {
...state,
testData: action?.data?.testData,
testData2: action?.data?.testData2,
};
},
},
};
export default IndexModel;
mfsu
启用 mfsu 后,热启动得到 **10 倍** 提升;热更新提升 **50%** 以上!
Как включить
Добавьте в config/config.tsmfsu:{}
Исходный код проекта
Вместе с двумя небольшими партнерами мы будем продолжать обновлять и повторять в соответствии с проблемами в реальном использовании или областями, которые не были рассмотрены для улучшения.Если у вас есть какие-либо вопросы, пожалуйста, поднимите проблему или оставьте сообщение в области комментариев.
FAQ
umiНе внутренняя или внешняя команда
Решение
воплощать в жизнь yarn global binПолучите путь к корзине. Затем добавьте этот путь к пути системной переменной в переменной окружения
Если это все еще не работает, выполните
yarn global add umi
Для получения дополнительных вопросов, пожалуйста, проверьте
Выпуск в официальном репозитории
大家还是要把官方文档看两遍哦,一些基础,简单的知识本文章没有涉及.
наконец
Если вы наступите на яму в продолжении, вы продолжите обновлять.Если у вас есть какие-либо ошибки или предложения, пожалуйста, оставьте сообщение в области комментариев.Если вы считаете, что статья полезна для вас, пожалуйста, поддержите ее .