Уми3 Учебник

внешний интерфейс JavaScript

предисловие

В Интернете очень мало руководств по 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"

1634719305(1).png

Наконец, ваш vscode должен установить эти три расширения с одинаковым именем.В это время измените файлы js и less соответственно, и вы обнаружите, что проверка стиля уже есть.

验证

7d684cab2e5ef8d167c81653582af15.jpg

Исправлятьsrc/paegsв папкеindex.tsxфайл, добавьте переменную a, появится сообщение об ошибке eslint, указывающее, что eslint действует

Затем отправьте файл index.tsx отдельно.

f87c265f5003a8899498b860baa64ce.png

Он подскажет, что есть ошибка и не может отправить, объяснитеpre-commmitхук вступает в силу

Автоматически форматировать код при сохранении

В настройках vscode в форматировании текстового редактора поставьте галочку Формат при сохранении

1.png

Мой эслинт или красивше не действует?

222.png

Перейдите к выводу в терминале, найдите eslint или prettier, чтобы посмотреть, нормальный ли у них журнал вывода. Если есть ошибка, устраните проблему в соответствии с сообщением об ошибке.

检查步骤:

  • Обязательно установите umi-fabric
  • Проверьте, существует ли файл конфигурации
  • Загружены ли плагины vscode eslint и prettier?
  • Подтвердите выходной журнал, есть ли ошибка

lint-staged во время предварительной фиксации не вступает в силу

В package.json настраиваем следующий код

565.png

Это означает выполнение более красивого кода форматирования и исправления 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.

b49bd8611d5c6403479a1547ba4bbc6.png

Затем вам нужно перейти в корневой каталогtypings.d.tsДобавить к

// 声明当前的环境
declare const CurrentEnvironment: 'dev' | 'test' | 'prd';

Затем ошибка исчезает, и консоль печатает следующее

1634721237(1).png

В это время повторно выполнитьyanr start:testКонсоль печатает следующим образом

11.png

Переменные среды и многоконструктивный успех

**注意点**:

config.tsКак файл конфигурации, не забудьте удалить.umirc.tsВ противном случае config.ts не вступит в силу.

пользовательские переменные среды

Если мы хотим настроить переменную окружения, REACT_APP_ENV.package.jsonвнутренние настройки

1634783299(1).png

Так как же нам получить такую ​​переменную?

Сначала мы будем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Не внутренняя или внешняя команда

image.png

Решение

воплощать в жизнь yarn global binПолучите путь к корзине. Затем добавьте этот путь к пути системной переменной в переменной окружения

Если это все еще не работает, выполните

yarn global add umi

Для получения дополнительных вопросов, пожалуйста, проверьте

Официальный FAQ

Выпуск в официальном репозитории

大家还是要把官方文档看两遍哦,一些基础,简单的知识本文章没有涉及.

наконец

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