Реагировать и Vue позвоните друг другу дистанционно демонстративно
Что такое микрофронтенд
Нелегко хорошо выполнять фронтенд-разработку, но еще сложнее масштабировать фронтенд-разработку, чтобы несколько команд могли разрабатывать и поддерживать большой и сложный продукт одновременно. Чтобы решить эту проблему, в области фронтенда постепенно наметилась тенденция: крупномасштабные фронтенд-проекты можно разбить на множество небольших и простых в управлении независимо развертываемых приложений, а также ресурсы уровня приложения (компоненты пользовательского интерфейса). /функции инструментов/бизнес-модули) могут быть общими, как и микросервисы в области бэкенда. В соответствии с этой тенденцией официальный сайт Micro Frontends запустил концепцию микро-интерфейсов: (от:микро-интерфейс — .org/)
Что такое ЭМИ
- EMPЭто новый фрейм микрофронта, основанный на WebPack5 и Module Federation (отличие от DOM Isolation и IFRAME в качестве технического стека), а также новый метод разработки.
- EMPЭто микроинтерфейсная структура, которая может вызывать любые ресурсы в проекте (включая, помимо прочего, сторонние зависимости, компоненты, функции, ресурсы изображений и т. д.) между проектами и платформами.
- EMPЭто новейшая интерфейсная структура с открытым исходным кодом группы веб-технологий YY (Joyful Times) для мидл-офиса. До EMP с открытым исходным кодом группа веб-технологий бизнес-центра YY использовала открытый исходный код.Flutter-uiВ ожидании проекта Starburst.
- EMPОн широко использовался в YY и применялся ко многим средним и тайваньским проектам, а также к проектам To C и To B.
- EMPЯдром фреймворка являетсяemp-cliДля более конкретной реализации можно увидетьemp-cliисходный код.
Обнаружение службы микрофронтенда для EMP
Обнаружение службы микроинтерфейса EMP позволяет локальному проекту знать функции, компоненты, конкретные параметры функций, параметры компонентов и т. д., содержащиеся в удаленном проекте, когда он вызывает удаленный проект. Аналогично обнаружению сервисов для серверных микросервисов.
Общая структура выглядит следующим образом:
Для более конкретной реализации см. Плагин Webpack.emp-tune-dts-plugin.
Обнаружение услуг Micro-Front-End Service также решает проблему, которую типы федераций модуля не могут быть переданы удаленными проектами в случае TypeScript (How typesafe can a remote be with Typescript?), что можно назвать ведущим в отрасли решением этой проблемы.
Как быстро начать работу с проектом EMP
Используйте команду инициализации emp-cli:npx @efox/emp-cli init
Запустите команду инициализации cli и выберите шаблон emp нужного вам стека технологий.В настоящее время emp-cli поддерживает следующие шаблоны:
- react
- vue2
- vue3
- react-base
- react-project
- vue3-base
- vue3-project
(будет поддерживать все основные технологические стеки один за другим)
Удаленные компоненты React и Vue вызывают друг друга на практике
упражняться
Создайте новые проекты React и Vue для emp соответственно.
React
используя emp-cli,npx @efox/emp-cli init
, выберите шаблон React
Напишите простой компонент React
новый/src/components/Hello.tsx
import React from 'react'
import './common.scss'
import './common.less'
import './common.css'
const Hello = ({title}: {title: string}) => (
<>
<h1>{title}</h1>
</>
)
export default Hello
изменить проектemp.config.js
(emp.config.js — файл конфигурации для проекта EMP):
- Предоставьте этот компонент React для удаленного вызова
- Представьте удаленные компоненты Vue (ниже будет написано Vue)
const path = require('path')
const packagePath = path.join(path.resolve('./'), 'package.json')
const {dependencies} = require(packagePath)
console.log(packagePath)
module.exports = ({config, env}) => {
const port = 8001
const projectName = 'ReactComponents'
const publicPath = `http://localhost:${port}/`
config.plugin('mf').tap(args => {
args[0] = {
...args[0],
...{
// 项目名称
name: projectName,
// 暴露项目的全局变量名
library: {type: 'var', name: projectName},
// 被远程引入的文件名
filename: 'emp.js',
// 远程项目别名:远程引入的项目名
remotes: {
'@emp/vueComponents': 'vueComponents',
},
// 需要暴露的东西
exposes: {
// 别名:组件的路径
'./configs/index': 'src/configs/index',
'./components/Hello': 'src/components/Hello',
},
// shared: ['react', 'react-dom'],
shared: {...dependencies},
},
}
return args
})
config.output.publicPath(publicPath)
config.devServer.port(port)
config.plugin('html').tap(args => {
args[0] = {
...args[0],
...{
files: {
js: ['http://localhost:8006/emp.js'],
},
},
}
return args
})
}
существует/src/bootstrap.tsx
Ввести удаленныйVue
Компоненты, представленныеvuera
,использоватьVueInReact
пакет удаленныйVue
компоненты для использования
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import Hello from 'src/components/Hello'
import Content from '@emp/vueComponents/Content.vue'
import {VueInReact} from 'vuera'
const VueComponent = VueInReact(Content)
ReactDOM.render(
<>
<Hello title="I am React Project" />
<div style={{backgroundColor: '#eee', padding: '20px'}}>
<VueComponent title="React use Remote Vue Component" />
</div>
</>,
document.getElementById('emp-root'),
)
Стартовый проектyarn dev
, Вы можете увидеть компоненты этого элемента и удаленные ссылки на компоненты VUE
Vue (в настоящее время не поддерживает Vue3)
используя emp-cli,npx @efox/emp-cli init
, выберите шаблон Vue2
Напишите простой компонент Vue/src/components/Content.vue
<template>
<div style="color: red">{{ title }}</div>
</template>
<script>
export default {
name:'Content',
props:['title'],
data() {
return {
};
},
};
</script>
изменить проектemp.config.js
(emp.config.js — файл конфигурации для проекта EMP):
- Предоставьте этот компонент Vue для удаленного вызова
- Импорт удаленных компонентов React
const path = require('path')
const {VueLoaderPlugin} = require('vue-loader')
//
const ProjectRootPath = path.resolve('./')
// const packagePath = path.join(ProjectRootPath, 'package.json')
// const {dependencies} = require(packagePath)
//
const {getConfig} = require(path.join(ProjectRootPath, './src/config'))
//
module.exports = ({config, env, empEnv}) => {
const confEnv = env === 'production' ? 'prod' : 'dev'
const conf = getConfig(empEnv || confEnv)
console.log('config', conf)
//
const srcPath = path.resolve('./src')
config.entry('index').clear().add(path.join(srcPath, 'main.js'))
//
config.resolve.alias.set('vue', '@vue/runtime-dom')
config.plugin('vue').use(VueLoaderPlugin, [])
config.module
.rule('vue')
.test(/\.vue$/)
.use('vue-loader')
.loader('vue-loader')
//
const host = conf.host
const port = conf.port
const projectName = 'vueComponents'
const publicPath = conf.publicPath
config.output.publicPath(publicPath)
config.devServer.port(port)
//
config.plugin('mf').tap(args => {
args[0] = {
...args[0],
...{
name: projectName,
library: {type: 'var', name: projectName},
filename: 'emp.js',
remotes: {
ReactComponents: 'ReactComponents',
},
exposes: {
'./Content.vue': './src/components/Content',
},
/* shared: {
...dependencies,
}, */
},
}
return args
})
config.resolve.alias
.set('vue$', 'vue/dist/vue.esm.js')
.clear()
//
config.plugin('html').tap(args => {
args[0] = {
...args[0],
...{
title: 'EMP Vue Components',
files: {
js: ['http://localhost:8001/emp.js'],
},
},
}
return args
})
}
существует/src/App.vue
Ввести удаленныйReact
комплектующие, импортvuera
,использоватьReactInVue
пакет удаленныйReact
компоненты для использования
<template>
<div>
<Content title="I am Vue Project" />
<hello-react title="Vue use Remote React Component" />
</div>
</template>
<script>
import { ReactInVue } from "vuera";
import Content from "./components/Content";
import Vue from "vue";
const HelloReact = () => ({
// 需要加载的组件 (应该是一个 `Promise` 对象)
component: import('ReactComponents/components/Hello').then(res=>{
return ReactInVue(res.default)
}),
// 展示加载时组件的延时时间。默认值是 200 (毫秒)
delay: 0,
// 如果提供了超时时间且组件加载也超时了,
// 则使用加载失败时使用的组件。默认值是:`Infinity`
timeout: 3000
})
export default {
name: "APP",
components: {
Content,
"hello-react":HelloReact
},
data() {
return {};
},
created() {
},
};
</script>
<style scoped>
img {
width: 200px;
}
h1 {
font-family: Arial, Helvetica, sans-serif;
}
</style>
Стартовый проектyarn dev
, вы можете увидеть компоненты этого проекта и компоненты React, на которые ссылаются удаленно
Принципиальный анализ
Компиляция и распространение удаленных компонентов
EMPСкомпилируйте компонент в отдельное замыкание в соответствии с конфигурацией поля exposes в emp.config.js, затем отдельно упакуйте компонент в js и, наконец, используйте форму emp.js в качестве справочного индекса для загрузки по требованию.
Скомпилированный код компонента React Hello из предыдущего раздела выглядит следующим образом:
(self["webpackChunk_empreactvue_react"] = self["webpackChunk_empreactvue_react"] || []).push([["src_components_Hello_tsx"],{
/***/ "./src/components/Hello.tsx":
/*!**********************************!*\
!*** ./src/components/Hello.tsx ***!
\**********************************/
/*! namespace exports */
/*! export default [provided] [maybe used in ReactComponents (runtime-defined); used in index] [usage prevents renaming] */
/*! other exports [not provided] [maybe used in ReactComponents (runtime-defined)] */
/*! runtime requirements: __webpack_require__, __webpack_require__.n, __webpack_exports__, __webpack_require__.r, __webpack_require__.* */
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "webpack/sharing/consume/default/react/react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _common_scss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./common.scss */ "./src/components/common.scss");
/* harmony import */ var _common_scss__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_common_scss__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _common_less__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./common.less */ "./src/components/common.less");
/* harmony import */ var _common_less__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_common_less__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _common_css__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./common.css */ "./src/components/common.css");
/* harmony import */ var _common_css__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_common_css__WEBPACK_IMPORTED_MODULE_3__);
var Hello = function Hello(_ref) {
var title = _ref.title;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("h1", null, title));
};
/* harmony default export */ __webpack_exports__["default"] = (Hello);
/***/ })
}]);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9AZW1wcmVhY3R2dWUvcmVhY3QvLi9zcmMvY29tcG9uZW50cy9IZWxsby50c3giXSwibmFtZXMiOlsiSGVsbG8iLCJ0aXRsZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBOztBQUNBLElBQU1BLEtBQUssR0FBRyxTQUFSQSxLQUFRO0FBQUEsTUFBRUMsS0FBRixRQUFFQSxLQUFGO0FBQUEsc0JBQ1osdUlBQ0UsdUVBQUtBLEtBQUwsQ0FERixDQURZO0FBQUEsQ0FBZDs7QUFNQSwrREFBZUQsS0FBZixFIiwiZmlsZSI6ImpzL3NyY19jb21wb25lbnRzX0hlbGxvX3RzeC5lMzAzYzRjNC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCAnLi9jb21tb24uc2NzcydcbmltcG9ydCAnLi9jb21tb24ubGVzcydcbmltcG9ydCAnLi9jb21tb24uY3NzJ1xuY29uc3QgSGVsbG8gPSAoe3RpdGxlfToge3RpdGxlOiBzdHJpbmd9KSA9PiAoXG4gIDw+XG4gICAgPGgxPnt0aXRsZX08L2gxPlxuICA8Lz5cbilcblxuZXhwb3J0IGRlZmF1bHQgSGVsbG9cbiJdLCJzb3VyY2VSb290IjoiIn0=
Удаленный вызов других компонентов фреймворка компилируется в текущий фреймворк
При компиляции компонентов других структур необходимо использовать библиотеку Vuera, чтобы помочь нам составить компоненты других структур в используемые в настоящее время.
Сравнение с другими технологиями микро-интерфейса
По сравнению с фреймворком микро-интерфейса, основанным на изоляции домена, на примере qiankun.
- положение дел. Микроинтерфейс, созданный qiankun, не может чрезмерно изолировать проект базовой станции и подпроекты, что приводит к несогласованному контексту, общему состоянию и т. д., которые необходимо передавать через шину, что очень проблематично. А EMP делает совместное использование состояния очень удобным, вызывая удаленное управление состоянием.
- Вызовите реализации между платформами. qiankun упрощает реализацию кросс-фреймворка через изоляцию DOM, но не может вызывать друг друга, а гранулярность может отображаться только в указанной области DOM. Гранулярность межкадровых вызовов, реализованная в EMP, представляет собой функцию, и ею очень удобно пользоваться.
- Объемный аспект. QianKun реализован с помощью изоляции DOM, поэтому полагаться на совместное использование не идеально, оно должно зависеть от systemjs, а совместное использование неудобно, в результате чего приходится полагаться на зависимость, так что объем становится большим. EMP полагается на совместное использование через федерацию модулей, поэтому зависимость не будет повторяться повторно (в зависимости от глобальной переменной одна и та же зависимость оставит только одну), поэтому объем меньше, чем у QianKun.
По сравнению с микрофронтендами на основе iframe
- положение дел. Микроинтерфейс iframe без управления реальным состоянием общается через postMessage.
- Аспекты вызываются через фреймворки. Микрофронтенды для iframe нельзя вызывать между фреймами.
- объем. Микрофронтенды для iframe не имеют общих зависимостей.
Суммировать
- EMPЭто новейшая микроинтерфейсная среда с открытым исходным кодом группы веб-технологий среднего офиса YY. В настоящее время он широко используется в компании и значительно улучшил управление статусами, взаимные звонки и оптимизацию объема нескольких проектов.
- Это удобно для удаленных вызовов между фреймворками. Так удобно звонить друг другу через фреймворки, и не проблема звонить друг другу с одним и тем же стеком технологий.
- Это совершенно новый метод разработки, направленный на улучшение совместной работы над несколькими проектами.