Оригинальные опубликованные Nuggets:nuggets.capable/post/684490…
0. О
В последнее время, в связи с тем, что в будущей работе задействовано много промышленных приложений, и учитывая, что промышленные приложения необходимо отображать в одной системе в будущем, я надеюсь, что будет прорыв в решении этой проблемы, т.е. для отображения различных промышленных приложений в одном общем проекте каждое промышленное приложение является отдельным проектом.Поскольку промышленные приложения могут разрабатываться разными командами, лучше всего использовать стек технологий разработки приложений без ограничений.Единый интерфейсный фреймворк может уже не соответствовать требованиям Отсюда я узнал о микро-фронтендах и попытался их изучить.Микро-фронтенды могут решить проблему сводного отображения промышленных приложений.
Конечно, существует не так много способов реализации микрофронтендов, включая iframe, single-spa и т. д. В этой статье в основном используется single-spa. Если вы использовали iframe, то знаете, что iframe и single-spa совсем не сложны.Если сравнивать iframe с простым режимом, то single-spa — это адский режим. способ использования микро-фронтенда Это iframe, я полагаю, что есть много людей, которые думают делать микро-фронтенд студенты.Они внезапно умерли на пути к изучению сингл-спа, а также недостаток информации, потому что хоть и есть много статей по микро-фронтенду в интернете, но большинство из них являются просто теоретическим введением и отображение части кода не помогает нам реально реализовать его в проекте.
Основными трудностями одноместного использования спа являются: 1. Для всего проекта, как полностью совместим с каждым подпроектом, чтобы технологический стек не имел ничего общего, и чтобы пользователи чувствовали, что это целый проект. 2. Для каждого подпроекта, как уменьшить вторжение кода и сделать его пригодным для независимой разработки, независимой работы и независимого развертывания.
1. Что такое микрофронтенд
Микрофронтенд основан на концепции внутренних микросервисов.официальный сайт спа-салонаОбъясняется, что микрофронтенд — это микросервис, который существует в браузере, то есть микрофронтенд — это микросервис, который существует в браузере, а микрофронтенд также является частью пользовательского интерфейса, обычно состоящего из десятков компонентов, и эти компоненты может быть React, Vue и Angular. В зависимости от реализации разных фреймворков каждый проект микро-фронтенда может управляться разными командами, и каждая команда также может выбрать свой фреймворк. Хотя при миграции или экспериментировании могут быть добавлены другие фреймворки, лучше всего использовать один фреймворк для всех микрофронтендов, что наиболее практично. Каждый проект микрофронтенда можно поместить в отдельный репозиторий git с собственным package.json и конфигурацией инструмента сборки. Таким образом, каждый проект микроинтерфейса имеет независимый процесс сборки и упаковки и независимое развертывание, что означает, что мы можем быстро завершить упаковку и запустить наш проект микроинтерфейса без необходимости каждый раз выполнять проект монолита. если позже появятся новые требования, вам нужно только изменить соответствующий проект микро-интерфейса.
2. Зачем использовать микрофронтенды
В настоящее время, с непрерывным развитием внешнего интерфейса, инженерные проекты предприятия становятся все больше и больше, со все большим количеством страниц, проект становится очень раздутым, и его очень сложно поддерживать.Иногда нам нужно только изменить простой стиль проекта, и весь проект нужно переупаковывать и запускать. , что доставляет массу хлопот разработчикам и трату времени. Чтобы интегрироваться в новый проект, старый проект также необходимо постоянно рефакторить, а стоимость рабочей силы также очень высока.
Трудности, с которыми приходится сталкиваться при фронтенд-разработке:
- Инженерные проекты предприятий становятся все больше и больше, а скорость создания и развертывания проектов низкая.
- В команде много инженеров, технологический стек трудно унифицировать, стоимость связи между удаленными командами высока, а код разработки подвержен конфликтам, что повлияет на весь проект.
- Старый проект подвергается рефакторингу, изменения в коде слишком велики и отнимают много времени.
Сравнительный анализ:
- Он имеет независимую работу и независимые функции развертывания, а скорость строительства и развертывания высокая.
- Независимо от стека технологий, он имеет независимые функции разработки, чтобы избежать конфликтов при разработке и снизить затраты на совместную работу.
- Старые проекты могут быть частью проекта микрофронтенда, избегая рефакторинга.
3. Реализация микроинтерфейса
Существует два способа реализации микрофронтендов:
1. Встраивание iframe (сложность: ★)
2.Single-spa комбинированное одностраничное приложение (сложность: ★★★★★)
4. iframe
Метод внедрения iframe относительно прост в реализации, поэтому я не буду вдаваться в подробности.
Why Not Iframe
Почему бы не использовать iframe, это первый вопрос, который будет оспорен практически всеми решениями для микро-фронтенда. Но большинство микро-интерфейсных решений неизменно отказывались от решения iframe.Есть причина, а не для «показухи» или намеренного преследования «индивидуализма».Самая большая особенность iframe заключается в том, чтобы обеспечить собственное решение жесткой изоляции браузера, будь то изоляция стиля, изоляция js и другие проблемы, которые могут быть идеально решены. Но его самая большая проблема заключается в том, что его изоляция не может быть нарушена, что приводит к невозможности совместного использования контекста между приложениями и, как следствие, проблемам с опытом разработки и опытом работы с продуктом.
- URL-адрес не синхронизирован. Состояние URL-адреса обновления браузера iframe теряется, кнопки «Назад» и «Вперед» использовать нельзя.
- Пользовательский интерфейс не синхронизирован, структура DOM не используется совместно. Представьте всплывающее окно со слоем маски в iframe в правом нижнем углу экрана, при этом мы требуем, чтобы всплывающее окно отображалось в центре браузера и автоматически центрировалось при открытии браузера. изменен размер.
- Глобальный контекст полностью изолирован, а переменные памяти не используются совместно. Для обеспечения связи и синхронизации данных внутренней и внешней систем iframe файлы cookie основного приложения должны быть прозрачно переданы в подприложения с разными корневыми доменными именами для достижения эффекта отсутствия входа в систему.
- медленный. Каждая запись подприложения представляет собой процесс реконструкции контекста браузера и перезагрузки ресурсов.
Некоторые проблемы решить легко (Задача 1), на некоторые проблемы мы можем закрыть глаза (Задача 4), а некоторые проблемы нам решить сложно (Задача 3) или даже невозможно решить (Задача 2). и эти неразрешимые проблемы принесут очень серьезные проблемы с опытом работы с продуктом, что в конечном итоге привело к тому, что мы отказались от решения iframe.
Справочная статья:Why Not Iframe
5. single-spa
Принцип реализации одного спа:
Во-первых, зарегистрируйте маршрут микро-интерфейса, используйте single-spa в качестве загрузчика микро-интерфейса и используйте его как единую запись для проекта, чтобы разрешить доступ ко всем URL-адресам страниц. -frontend выберите загрузку соответствующего модуля микро-интерфейса, а затем модуль микро-интерфейса выполняет маршрутизацию для ответа на URL-адрес, то есть модуль микро-интерфейса находит соответствующий компонент и отображает содержимое страницы.
Справочная статья:официальный сайт спа-салона
6. Процесс внедрения микрофронтенда
❤️❤️❤️ Адрес исходного кода проекта ❤️❤️️❤️
6.1 Проект пьедестала (модификация основного проекта)
Создание проекта пьедестала:
yarn create react-app portal
yarn add antd
// 创建config-overrides.js支持antd按需加载
// fixBabelImports('import', {
// libraryName: 'antd',
// libraryDirectory: 'es',
// style: true,
// }),
В этой статье используется принцип внешней микрозагрузки следующим образом:
Сначала создайте узел dom в родительском проекте и введите узел, который нужно смонтировать в процессе регистрации проекта, чтобы завершить выполнение подпроекта в родительском проекте.
6.2.1 Создание маршрутов и подпроектов для монтирования узлов dom
код показывает, как показано ниже:
<div className="App" >
<Layout>
<Sider trigger={null} collapsible collapsed={collapsed}>
<div className="logo" />
<ul >
<li key="react" >
<Link to="/react">React</Link>
</li>
<li key="vue" >
<Link to="/vue">Vue</Link>
</li>
<li key="angular" >
<Link to="/angular">Angular</Link>
</li>
</ul>
</Sider>
<Layout className="site-layout">
<Header className="site-layout-background" style={{ padding: 0 }}>
{React.createElement(collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, {
className: 'trigger',
onClick: () => { setCollapse(!collapsed) },
})}
</Header>
<Content
className="site-layout-background"
style={{
margin: '24px 16px',
padding: 24,
minHeight: 280,
}}
<blockquote style=' padding: 10px 10px 10px 1rem; font-size: 0.9em; margin: 1em 0px; color: rgb(0, 0, 0); border-left: 5px solid #9370DB; background: rgb(239, 235, 233);'></blockquote>
<div id="vue" />
<div id="react-app" />
<app-root></app-root>
</Content>
</Layout>
</Layout>
</div>
6.2.2 Регистрация приложения Micro-Front
src создал файл singleSpa.js.
Импортируйте файл в файл index.js файла входа проекта.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { BrowserRouter as Router } from 'react-router-dom'
import "./singleSpa.js"; // 引入微前端配置文件;
// 项目目录结构
├── public
├── src
│ ├── index.js
│ ├── singleSpa.js
│ └── App.jsx
├── config-overrides.js
├── package.json
├── README.md
├── yarn.lock
часть кода singleSpa.js:
import * as singleSpa from 'single-spa';
// 注册应用方式参考文章:
// Single-Spa + Vue Cli 微前端落地指南 (项目隔离远程加载,自动引入)(https://juejin.cn/post/6844904025565954055#heading-2)
/**
* runScript 一个promise同步方法。可以代替创建一个script标签,然后加载服务
* @param {string} url 请求文件地址
*/
const runScript = async (url) => {
// 加载css同理
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.onload = resolve;
script.onerror = reject;
const firstScript = document.getElementsByTagName('script')[0];
firstScript.parentNode.insertBefore(script, firstScript);
});
};
// 注册微前端服务
/*
注册所用函数;
return 一个模块对象(singleSpa),模块对象来自于要加载的js导出(子项目);
如果这个函数不需要在线引入,只需要本地引入一块加载:
() => import('xxx/main.js')
*/
singleSpa.registerApplication(
'vue',
async () => {
await runScript('http://127.0.0.1:8080/js/chunk-vendors.js');
await runScript('http://127.0.0.1:8080/js/app.js');
return window.singleVue;
},
// 配置微前端模块前缀
// 纯函数根据参数查看是否处于活动状态
(location) => location.pathname.startsWith('/vue')
);
singleSpa.start(); // 启动注册,别忘记!
Значение параметра registerApplication:1,
appName: string
Имя приложения2,
applicationOrLoadingFn: () => <Function | Promise>
Возвращает функцию загрузки обещания или разрешенное приложение.// 应用作为参数,该参数由一个带有生命周期的对象组成。 const application = { bootstrap: () => Promise.resolve(), //bootstrap function mount: () => Promise.resolve(), //mount function unmount: () => Promise.resolve(), //unmount function } registerApplication('applicatonName', application, activityFunction)
Функция загрузки должна возвращать обещание или асинхронную функцию в качестве параметра.При первой загрузке приложения функция будет вызываться без каких-либо параметров.Возвращенное обещание должно быть разрешено вместе с приложением. Наиболее распространенный способ импорта функции загрузки:
() => import('/path/to/application.js')
3.
activityFn: (location) => boolean
Функция активности, которая должна быть чистой функцией, предоставляет window.location в качестве первого параметра и возвращает результат оценки, когда приложение активно. Обычно первый параметр динамической функции (функция активности) используется для определения того, активно ли субприложение.
6.2 Внешний интерфейс микропроекта (трансформация подпроекта)
6.2.1 Преобразование подпроекта Vue
Подготовка среды:
npm install -g @vue/cli //全局安装vue-cli
vue create vue-project // 创建子项目
// 项目目录结构
├── public
├── src
│ ├── main.js
│ ├── assets
│ ├── components
│ └── App.vue
├── vue.config.js
├── package.json
├── README.md
└── yarn.lock
Измените файл main.js для регистрации
import Vue from 'vue'
import App from './App.vue'
import singleSpaVue from "single-spa-vue";
Vue.config.productionTip = false
// el 为子项目待挂载到父项目的DOM节点!!!
const vueOptions = {
el: "#vue",
render: h => h(App)
};
// 主应用注册成功后会在window下挂载singleSpaNavigate方法
// 为了独立运行,避免子项目页面为空,
// 判断如果不在微前端环境下进行独立渲染html
if (!window.singleSpaNavigate) {
new Vue({
render: h => h(App),
}).$mount('#app')
}
const vueLifecycles = singleSpaVue({
Vue,
appOptions: vueOptions,
});
export const bootstrap = vueLifecycles.bootstrap; // 启动时
export const mount = vueLifecycles.mount; // 挂载时
export const unmount = vueLifecycles.unmount; // 卸载时
export default vueLifecycles;
Создайте vue.config.js в корневом каталоге, чтобы изменить конфигурацию веб-пакета.
module.exports = {
/*
重点:
设置publicPath,避免父项目加载子项目时,部分资源文件路径为父项目地址,导致请求文件失败。
*/
publicPath: "//localhost:8080/",
configureWebpack: {
devtool: 'none', // 不打包sourcemap
output: {
library: "singleVue", // 导出名称
libraryTarget: "window", //挂载目标,可以在浏览器打印window.singleVue查看
}
},
devServer: {
contentBase: './',
compress: true,
}
};
В целом трансформацию подпроектов можно разделить на два этапа:
1. Изменить входной файл подпроекта, зарегистрировать микро-интерфейс и определить узел монтирования подпроекта;
2. Файл экспорта веб-пакета подпроекта трансформируется, а метод singleVue создается под окном после упаковки.
6.2.1 Преобразование подпроекта React
Подготовка среды:
yarn create react-app react // 创建子项目
yarn add single-spa-react // 安装single-spa-react
// 项目目录结构
├── public
├── src
│ ├── App.js
│ ├── index.js
│ └── serviceWorker.js
├── config
│ ├── jest
│ ├── webpack.config.js
│ └── webpackDevServer.config.js
├── scripts
│ ├── build.js
│ ├── start.js
│ └── test.js
├── package.json
├── README.md
└── yarn.lock
Index.js Изменение файлового регистра
import Vue from 'vue'
import App from './App.vue'
import singleSpaVue from "single-spa-vue";
Vue.config.productionTip = false
// el 为子项目待挂载到父项目的DOM节点!!!
const vueOptions = {
el: "#vue",
render: h => h(App)
};
// 主应用注册成功后会在window下挂载singleSpaNavigate方法
// 为了独立运行,避免子项目页面为空,
// 判断如果不在微前端环境下进行独立渲染html
if (!window.singleSpaNavigate) {
new Vue({
render: h => h(App),
}).$mount('#app')
}
const vueLifecycles = singleSpaVue({
Vue,
appOptions: vueOptions,
});
export const bootstrap = vueLifecycles.bootstrap; // 启动时
export const mount = vueLifecycles.mount; // 挂载时
export const unmount = vueLifecycles.unmount; // 卸载时
export default vueLifecycles;
Измените номер порта запуска проекта:
// scripts文件夹内start.js文件
- const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000
+ const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 5000;
Измените конфигурацию веб-пакета, измените файл webpack.config.js в папке конфигурации.
- publicPath:paths.publicUrlOrPath
+ publicPath: 'http://localhost:5000/',
+ library: "singleReact", // 导出名称
+ libraryTarget: "window", //挂载目标
Родительский проект сначала загружает решение ошибки изображения логотипа статического файла подпроекта:
- После сбоя загрузки в ходе проверки обнаруживается, что адрес изображения загруженного подпроекта в родительском проекте:http://localhost:3000/static/media/logo.5d5d9eef.svg.
- В настоящее время адрес родительского проекта:http://localhost:3000/, адрес подпроекта: http://localhost:5000/
- Нетрудно найти, что адрес запроса изображения логотипа должен быть адресом подпроекта.http://localhost:5000/static/media/logo.5d5d9eef.svg
- Конечный путь доступа к статическим ресурсам = output.publicPath + путь конфигурации, такой как загрузчик ресурсов или плагин.Путь publicPath по умолчанию — это расположение корневого каталога веб-сайта, и когда родительский проект загружает подпроект, текущий корневой каталог веб-сайтаhttp://localhost:3000/
- Это можно сделать, установив output.publicPath для подпроекта и каталога.http://localhost:5000/ решает проблему.
6.2.1 Преобразование подпроекта Angular
Подготовка среды:
npm install -g @angular/cli //全局安装angular/cli,直接安装报错
// 报错信息 TypeError: Cannot read property 'flags' of undefined
npm install @angular/cli@9.0.0 -g // 指定版本安装
ng new angular-project // 创建项目
// 项目目录结构
├── e2e
├── src
│ ├── + `main.single-spa.ts`
│ ├── + `single-spa`
│ │ ├── + `single-spa-props.ts`
│ │ └── + `asset-url.ts`
│ ├── app
│ │ ├── + `empty-route`
│ │ │ └── + `empty-route.component.ts`
│ │ ├── empty-route.component.ts
│ │ ├── app.component.ts
│ │ └── `app.module.ts` //use src/app/empty-route/ EmptyRouteComponent
│ ├── assets
│ ├── environments
│ ├── index.html
│ ├── polyfills.ts
│ └── test.ts
├── node_modules
├── + `extra-webpack.config.js`
├── package.json
├── README.md
├── angular.json
└── yarn.lock
[Ошибка: TypeError: не удается прочитать «флаги» свойства неопределенного] (https://stackoverflow.com/questions/49544854/typeerror-cannot-read-property-flags-of-undefined)
- Install single-spa-angular.
- Generate
single-spa-props.ts
insrc/single-spa/
- Generate
asset-url.ts
insrc/single-spa/
- Generate an EmptyRouteComponent in
src/app/empty-route/
, to be used in app-routing.module.ts.
Зарегистрируйте приложение
// src/app/empty-route/empty-route.component.ts 文件内代码
import { Component } from '@angular/core';
@Component({
selector: 'app2-empty-route',
template: '',
})
export class EmptyRouteComponent {
}
// src/app/app.module.ts 文件内代码
+ import { EmptyRouteComponent } from './empty-route/empty-route.component';
@NgModule({
declarations: [
AppComponent,
+ EmptyRouteComponent
],
// src/single-spa/asset-url.ts 文件内代码
export function assetUrl(url: string): string {
// @ts-ignore
const publicPath = __webpack_public_path__;
const publicPathSuffix = publicPath.endsWith('/') ? '' : '/';
const urlPrefix = url.startsWith('/') ? '' : '/'
return `${publicPath}${publicPathSuffix}assets${urlPrefix}${url}`;
}
// src/single-spa/single-spa-props.ts 文件内代码
import { ReplaySubject } from 'rxjs';
import { AppProps } from 'single-spa';
export const singleSpaPropsSubject = new ReplaySubject<SingleSpaProps>(1)
export type SingleSpaProps = AppProps & {
}
// src/main.singleSpa.ts 文件内代码
import { enableProdMode, NgZone } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { Router } from '@angular/router';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { singleSpaAngular } from 'single-spa-angular';
import { singleSpaPropsSubject } from './single-spa/single-spa-props';
if (environment.production) {
enableProdMode();
}
// if (!window.singleSpaNavigate) {
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
// }
const lifecycles = singleSpaAngular({
bootstrapFunction: singleSpaProps => {
singleSpaPropsSubject.next(singleSpaProps);
return platformBrowserDynamic().bootstrapModule(AppModule);
},
template: '<app2-root />',
Router,
NgZone: NgZone,
});
export const bootstrap = lifecycles.bootstrap;
export const mount = lifecycles.mount;
export const unmount = lifecycles.unmount;
Измените angular.json, чтобы подготовиться к изменению файла экспорта.
npm i -D @angular-builders/custom-webpack //用于修改webpack 配置
npm i -D @angular-builders/dev-server
"build": {
- "builder": "@angular-devkit/build-angular:browser",
+ "builder": "@angular-builders/custom-webpack:browser",
"options": {
+ "customWebpackConfig": {
+ "path": "./extra-webpack.config.js" // 读取文件,修改webpack配置
+ },
+ "deployUrl": "http://localhost:4000/", // 修改publicPath
"outputPath": "dist/Delete",
"index": "src/index.html",
————————————————
"serve": {
- "builder": "@angular-devkit/build-angular:dev-server",
+ "builder": "@angular-builders/custom-webpack:dev-server"
"options": {
"browserTarget": "Delete:build"
},
————————————————
Настройте экспортный файл:
Создайте extra-webpack.config.js и настройте его
module.exports = {
output: {
library: "singleAngular", // 导出名称
libraryTarget: "window", // 挂载目标
},
}
Справочная статья:
single-spa-angular
пример кода single-spa-angular
версия angular/cli | односпа-угловое исполнение | |
---|---|---|
Официальный пример | 8.1.0 | 3.0.1 |
Пример этой статьи | 9.0.0 | 4 |
7. Разверните конфигурацию Nginx онлайн
В процессе загрузки родительского проекта все запросы:
После завершения онлайн-развертывания в «первом запросе vue» возникает «ошибка nginx 404 Not Found». В ходе расследования было обнаружено, что путь поиска nginx неверен:Формат адреса доступа к развертыванию: xx.xx:0000/vue/#/app1.
vue:微前端应用名称;
app1:子项目路由
Анализ ошибок Nginx:
Когда запрос делается в первый раз, поскольку запись здесь аналогична browserRouter, папка /vue будет искаться в файле корневого каталога nginx в соответствии с запросом и наличием возвращаемого файла index.html.
xx.xx:0000/XX => папка XX в файле nginx => папка не существует и возвращает 404
Поскольку /vue предназначен только для регистрации приложений, на самом деле нет необходимости заходить в /vue в nginx для поиска index.html, потому что поиск по этому пути не может быть успешным, и мы все еще надеемся искать по исходному корневому адресу.Когда nginx встретит адрес типа /XXX, он будет использоваться как прокси для поиска соответствующей папки, если папки нет, то будет выдано сообщение об ошибке 404, но на самом деле, я надеюсь войти в свой проект, и я сделаю мое собственное суждение.
решение:
При доступе с помощью /vue сначала оцените, а затем используйте nginx для перенаправления в исходный корневой каталог.
Меры предосторожности:В это время выполняется перенаправление, но мы не хотим, чтобы URL-адрес менялся, поэтому нам нужно использовать форму перехода перезаписи «/xxx» /abc last;, но это перенаправление может только переписать URL-адрес на сайте, если Второй параметр перезаписи начинается с http или https или использование постоянного приведет к изменению адресной строки URL. (302, 301 и т. д. изменят адрес адресной строки)
location /vue/ {
root /home/nginx/static/html/refining/;
rewrite ^/vue(.*) /;
index index.html index.htm;
}
// 注意重定向保持url不变,
Первоначально думал, что это может объявить успех! ! ! Но реальность всегда жестока. Мы обновили браузер, чтобы родительский проект перезагрузил дочерний проект, и обнаружили, что загрузка файла дочернего проекта в родительском проекте по-прежнему сообщает об ошибке или возвращает html, вызывая ошибку типа.
Посмотрев на запрос, можно обнаружить, что фактический запрос: xx.xx:0000/vue/#/static/css/main.d6XXXXXXXXXX
Продолжим перенаправлять статические ресурсы:
location ~.*(gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ {
root /home/nginx/static/html/refining/;
rewrite ^/vue(.*) /$1 break;//$1 为匹配到的第一个参数,即去掉vue后的请求地址
index index.html index.htm;
}
Другие эталонные конфигурации:
server {
listen 8080;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
ssi on;
# 将 / 重定向到 /browse
rewrite ^/$ http://localhost:8080/browse redirect;
# 根据路径访问 html
location /browse {
set $PAGE 'browse';
}
location /order {
set $PAGE 'order';
}
location /profile {
set $PAGE 'profile'
}
# 所有其他路径都渲染 /index.html
error_page 404 /index.html;
}
8. Перспективы
8.1 Оптимизация модернизации
8.1.1 Автоматическая загрузка файлов JS
stats-webpack-plugin генерирует manifest.json для автоматической загрузки.
8.1.2 CSS-песочница
Обработка CSS использует postcss-loader, postcss-loader использует postcss, мы добавляем подключаемые модули обработки postcss, добавляем корневой селектор с именем `.namespace-kaoqin` для каждого селектора CSS, и окончательный упакованный CSS выглядит следующим образом:
8.1.3 Песочница JS
8.1.4 Загрузка подприложений в HTML
Адрес доступа необходимо настроить только один раз, а динамическая загрузка манифеста опущена, поскольку html сам по себе является полным манифестом.
Справочная статья
- Single-Spa + Vue Cli Micro Frontend Landing Guide (удаленная загрузка изоляции проекта, автоматическое введение)
- Практика микрофронтенда
- Микрофронтенд - портальный проект
- Специалист по развитию полного стека(Как приземляется микропередок? Подробный принцип)
- Сервер командной строки (http-сервер) и кросс-доменный
- Вероятно, самое полное решение для микроинтерфейса, которое вы когда-либо видели.
- Сессия по обмену интерфейсом — предварительное исследование трансформации микроинтерфейса
- Возьмем рукописный микроинтерфейсный фреймворк
- Углубленный анализ исходного кода Vue — полный процесс монтирования и компиляция шаблона
- Как ant design pro использует qiankun в качестве микроинтерфейса (часть 1)
- Micro Front-End _single-Spa Новая идея