Как перейти с многостраничного приложения на Piral - PullRequest
0 голосов
/ 09 апреля 2020

Мы запускаем несколько ASP. NET основных приложений, которые поставляются с некоторыми страницами. Это все «классовые c» многостраничные приложения.

Для нашего нового портала мы решили go с помощью piral. Хотя мы добавляем пару новых модулей, мы также хотим использовать существующие приложения.

Как мы можем интегрировать многостраничное приложение в piral или в клиентский (SPA) микро-интерфейс?

One Пример многостраничного приложения выглядит так (размещен на некотором адресе, например 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">
            &copy; 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>

Нам не нужно иметь все сценарии - большинство из них просто есть из-за шаблон На самом деле мы также можем работать без них.

1 Ответ

2 голосов
/ 09 апреля 2020

Миграция MPA в Piral может быть выполнена несколькими способами.

  1. Создание оболочки обертки, которая предоставляет доступ к разным SSR-частям с помощью iframes
  2. Создание оболочки обертки, которая предоставляет доступ различные части SSR через фрагменты, которые динамически получаются
  3. Преобразование ваших видов 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 (или отправьте специальный заголовок) и только return фрагмент вместо полного ответа
  • Если нужны таблицы стилей, либо «fi sh» их из ответа, либо интегрируйте их заранее (см. следующий пункт)
  • Код выше не имеет специальной обработки SPA-ссылок. Таким образом, все ссылки относятся к заданному URL-адресу страницы, и они выполняют полный переход ...
  • JavaScript не будет загружен / не работает в данном решении

Теперь относительно таблицу стилей, которую вы могли бы сделать (среди прочего):

import './my-style.css';
import * as React from 'react';

export function setup(app) {
  // ...
}

, где my-style.css выглядит так:

@import url(https://myexample.com/css/site.css);

У нас могло бы быть больше URL и т. д. c. здесь, но я оставляю это нарочно. Имейте в виду, что ранее показанный способ может привести к столкновениям. Так что либо «загрузите» лист заранее и добавьте к нему префикс («область действия»), либо используйте все это в теневом решении DOM (теневой DOM всегда «свободен» от стиля родительского DOM и должен импортировать свои собственные таблицы стилей).

Для обработки ссылок, что вы можете сделать: использовать эффект макета, получить все элементы 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} />;
    }));
}
...