如何从多页面应用程序迁移到 Piral
How to migrate from a multipage app to Piral
我们 运行 一些 ASP.NET 核心应用程序确实带有一些页面。这些都是 "classic" 多页应用程序。
对于我们的新门户,我们决定使用 piral。在我们添加几个新模块的同时,我们还想使用现有的应用程序。
我们如何在 piral 或客户端 (SPA) 微前端中集成多页面应用程序?
多页面应用程序的一个示例如下所示(托管在 https://myexample.com/home 等地址)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Privacy Policy - DotnetApp</title>
<link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" href="/">DotnetApp</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" href="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" href="/Home/Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
<h1>Privacy Policy</h1>
<p>Use this page to detail your site's privacy policy.</p>
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2020 - DotnetApp - <a href="/Home/Privacy">Privacy</a>
</div>
</footer>
<script src="/lib/jquery/dist/jquery.min.js"></script>
<script src="/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="/js/site.js?v=4q1jwFhaPaZgr8WAUSrux6hAuh0XDg9kPS3xIVq36I0"></script>
</body>
</html>
我们不需要拥有所有脚本 - 由于样板文件,其中大部分脚本就在那里。其实我们也可以 运行 没有他们。
可以通过多种方式将 MPA 迁移到 Piral。
- 创建一个包装器 pilet,通过 iframe 公开不同的 SSRed 部分
- 创建一个包装器 pilet,通过动态获取的片段公开不同的 SSRed 部分
- 将您的 Razor 视图转换为 React 部分并在 FE/BE 之间进行拆分;将 React 部件放在桩中
我不知道您的应用程序有多复杂,但也许 (1) 最容易上手(尤其是如果它只是一个页面)。
让我们看看 (2) 是如何实现的:
import * as React from 'react';
export function setup(app) {
const connect = app.createConnector(() => fetch('https://myexample.com/home').then(res => res.text()));
app.registerPage('/myexample', connect(({ data }) => {
const __html = data;
return <div dangerouslySetInnerHTML={{ __html }} />;
}));
}
在这里,我们从 https://myexample.com/home
延迟加载内容并将其显示在组件(将是一个页面)中。
您应该注意以下几点:
- 在最好的情况下检测
fetch
(或发送一个特殊的 header)并且只 return 一个片段 而不是完整的回应
- 如果需要样式sheet,要么"fish"将它们从响应中移除,要么预先集成它们(见下一点)
- 上面的代码没有特殊的 SPA link 处理。因此,所有 link 都是相对于给定页面 URL 并且它们正在进行完全转换 ...
- JavaScript 不会在给定的解决方案中加载/工作
现在关于样式sheet你可以做的(除其他外):
import './my-style.css';
import * as React from 'react';
export function setup(app) {
// ...
}
其中 my-style.css
看起来像:
@import url(https://myexample.com/css/site.css);
我们可以在这里有更多的 URLs 等等,但我故意把它漏掉了。请记住,之前显示的方式可能会导致冲突。所以要么 "download" 前面的 sheet 和前缀 ("scope") 它,要么在影子 DOM 解决方案中全部使用它(影子 DOM 总是 "free" parent DOM 的样式,需要导入自己的样式 sheets).
对于 link 处理你可以做的事情:使用布局效果,通过选择器获取所有 a
元素,附加事件并取消原始导航。请改用 history
上下文。
在代码中,这类似于:
import * as React from 'react';
import { useHistory } from 'react-router';
export function setup(app) {
const connect = app.createConnector(() => fetch('https://myexample.com/home').then(res => res.text()));
app.registerPage('/myexample', connect(({ data }) => {
const __html = data;
const container = React.useRef();
const history = useHistory();
React.useLayoutEffect(() => {
if (container.current) {
const anchors = container.current.querySelectorAll('a[href]');
Array.prototype.forEach.call(anchors, anchor => {
anchor.addEventListener('click', ev => {
ev.preventDefault();
history.push(anchor.getAttribute('href'));
});
});
}
}, []);
return <div dangerouslySetInnerHTML={{ __html }} ref={container} />;
}));
}
我们 运行 一些 ASP.NET 核心应用程序确实带有一些页面。这些都是 "classic" 多页应用程序。
对于我们的新门户,我们决定使用 piral。在我们添加几个新模块的同时,我们还想使用现有的应用程序。
我们如何在 piral 或客户端 (SPA) 微前端中集成多页面应用程序?
多页面应用程序的一个示例如下所示(托管在 https://myexample.com/home 等地址)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Privacy Policy - DotnetApp</title>
<link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" href="/">DotnetApp</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" href="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" href="/Home/Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
<h1>Privacy Policy</h1>
<p>Use this page to detail your site's privacy policy.</p>
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2020 - DotnetApp - <a href="/Home/Privacy">Privacy</a>
</div>
</footer>
<script src="/lib/jquery/dist/jquery.min.js"></script>
<script src="/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="/js/site.js?v=4q1jwFhaPaZgr8WAUSrux6hAuh0XDg9kPS3xIVq36I0"></script>
</body>
</html>
我们不需要拥有所有脚本 - 由于样板文件,其中大部分脚本就在那里。其实我们也可以 运行 没有他们。
可以通过多种方式将 MPA 迁移到 Piral。
- 创建一个包装器 pilet,通过 iframe 公开不同的 SSRed 部分
- 创建一个包装器 pilet,通过动态获取的片段公开不同的 SSRed 部分
- 将您的 Razor 视图转换为 React 部分并在 FE/BE 之间进行拆分;将 React 部件放在桩中
我不知道您的应用程序有多复杂,但也许 (1) 最容易上手(尤其是如果它只是一个页面)。
让我们看看 (2) 是如何实现的:
import * as React from 'react';
export function setup(app) {
const connect = app.createConnector(() => fetch('https://myexample.com/home').then(res => res.text()));
app.registerPage('/myexample', connect(({ data }) => {
const __html = data;
return <div dangerouslySetInnerHTML={{ __html }} />;
}));
}
在这里,我们从 https://myexample.com/home
延迟加载内容并将其显示在组件(将是一个页面)中。
您应该注意以下几点:
- 在最好的情况下检测
fetch
(或发送一个特殊的 header)并且只 return 一个片段 而不是完整的回应 - 如果需要样式sheet,要么"fish"将它们从响应中移除,要么预先集成它们(见下一点)
- 上面的代码没有特殊的 SPA link 处理。因此,所有 link 都是相对于给定页面 URL 并且它们正在进行完全转换 ...
- JavaScript 不会在给定的解决方案中加载/工作
现在关于样式sheet你可以做的(除其他外):
import './my-style.css';
import * as React from 'react';
export function setup(app) {
// ...
}
其中 my-style.css
看起来像:
@import url(https://myexample.com/css/site.css);
我们可以在这里有更多的 URLs 等等,但我故意把它漏掉了。请记住,之前显示的方式可能会导致冲突。所以要么 "download" 前面的 sheet 和前缀 ("scope") 它,要么在影子 DOM 解决方案中全部使用它(影子 DOM 总是 "free" parent DOM 的样式,需要导入自己的样式 sheets).
对于 link 处理你可以做的事情:使用布局效果,通过选择器获取所有 a
元素,附加事件并取消原始导航。请改用 history
上下文。
在代码中,这类似于:
import * as React from 'react';
import { useHistory } from 'react-router';
export function setup(app) {
const connect = app.createConnector(() => fetch('https://myexample.com/home').then(res => res.text()));
app.registerPage('/myexample', connect(({ data }) => {
const __html = data;
const container = React.useRef();
const history = useHistory();
React.useLayoutEffect(() => {
if (container.current) {
const anchors = container.current.querySelectorAll('a[href]');
Array.prototype.forEach.call(anchors, anchor => {
anchor.addEventListener('click', ev => {
ev.preventDefault();
history.push(anchor.getAttribute('href'));
});
});
}
}, []);
return <div dangerouslySetInnerHTML={{ __html }} ref={container} />;
}));
}