Рендеринг Vue на стороне сервера с ASP.NET Core 2 - PullRequest
0 голосов
/ 07 июня 2018

Я пытаюсь понять использование и ограничения рендеринга на стороне сервера с помощью vuejs при использовании ядра aspnet.

Я использовал этот стартовый комплект для ядра aspnet и vuejs для настройки простогоvue site, который работает на основе приведенного здесь кода: https://github.com/selaromdotnet/aspnet-vue-ssr-test/tree/master

Затем я изменил проект, обновив aspnet-prerendering, и добавил vue-server-renderer, скомпилировав сборку исходных кодов для объединения этого обновления.: https://github.com/selaromdotnet/aspnet-vue-ssr-test/tree/ssr

Если я запускаю этот проект, кажется, что сайт загружается нормально, и если я отключаю JavaScript в браузере, я вижу, что кажется, что рендеринг на стороне сервера выполнен и заполненрезультат html:

enter image description here

однако, поскольку JavaScript отключен, содержимое не перемещается в DOM, как это выглядит, как будто пытается...

Мое понимание рендеринга на стороне сервера состоит в том, что он полностью заполнит html и предоставит пользователю заполненную страницу, так что даже если бы JS был отключен, они быВосток сможет увидеть страницу (специально для целей SEO).Я ошибаюсь?

Теперь я считаю, что современные поисковые системы будут выполнять простые скрипты, подобные этой, чтобы получить контент, но я все еще не хочу, чтобы пустая страница отображалась, если js отключен ...

Это ограничение рендеринга на стороне сервера, или, возможно, конкретно ssr с ядром vue и / или aspnet?

или я просто пропускаю шаг куда-то?

Редактировать: дополнительная информация

Я посмотрел на исходный код, так как я полагаю, что этот метод преобразует раздел здесь: https://github.com/aspnet/JavaScriptServices/blob/dev/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs

Строка

output.Content.SetHtmlContent(result.Html); 

имеет нулевое значениедля результата. HTML.Однако, когда я вручную редактирую это значение, чтобы поместить тестовое значение, оно также не отображается в выходном html, а тег app div остается пустым ...

Если я что-то не так делаю,Заполните значение result.Html ожидаемым выводом, это одно, и я был бы признателен за помощь в этом, тем более что выходной html, кажется, найден, поскольку он находится в сценарии, который следует сразу за ...

Однако, даже если бы я заполнил его, похоже, что он пропускается, о чем я вручную изменил значение.это ошибка в коде, или я неправильно что-то делаю, или, возможно, оба?

1 Ответ

0 голосов
/ 11 июня 2018

Как вы правильно заметили, для вашего проекта result.Html внутри тега helper равно нулю.Так что эта строка не может быть местом, где генерируется вывод.Поскольку вывод HTML из сценария предварительной визуализации также не содержит тега script, ясно, что что-то должно сгенерировать это.Единственная другая строка, которая могла бы сделать это, это следующее из PrerenderTagHelper:

output.PostElement.SetHtmlContent($"<script>{globalsScript}</script>");

, которое бы соответствовало наблюдаемому результату, поэтому мы должны выяснить, где globalsScriptисходит от.

Если вы посмотрите на реализацию PrerenderTagHelper, вы увидите, что он вызовет Prerenderer.RenderToString, который возвращает RenderToStringResult.Этот результирующий объект десериализуется из JSON после вызова скрипта Node.

Таким образом, здесь есть два интересующих свойства: Html и Globals.Первый отвечает за содержание вывода HTML, который, в конечном итоге, отображается внутри помощника тега.Последний представляет собой объект JSON, содержащий дополнительные глобальные переменные, которые должны быть установлены на стороне клиента.Это то, что будет отображаться внутри этого тега script.

Если вы посмотрите на визуализированный HTML из вашего проекта, вы увидите, что есть две глобальные переменные: window.html и window.__INITIAL_STATE__.Таким образом, эти два значения установлены где-то в вашем коде, хотя html не должно быть глобальным.

Виновником является файл renderOnServer.js:

vue_renderer.renderToString(context, (err, _html) => {
    if (err) { reject(err.message) }
    resolve({
        globals: {
            html: _html,
            __INITIAL_STATE__: context.state
        }
    })
})

Как видите,это разрешит результат, содержащий только объект globals со свойствами html и __INITIAL_STATE__.Это то, что визуализируется внутри тега script.

Но вместо этого вы хотите, чтобы html был не частью globals, а на уровне выше, чтобы его десериализовали вRenderToStringResult.Html свойство:

resolve({
    html: _html,
    globals: {
        __INITIAL_STATE__: context.state
    }
})

Если вы сделаете это так, ваш проект будет правильно выполнять рендеринг на стороне сервера, не требуя JavaScript для начального представления.

...