Подтвердить что ты не робот

Клиентская сторона HTML MVC Rendering vs Server Side Rending через NodeJS

Мы ищем варианты в нашей команде, чтобы решить между подходом на основе MVC на основе Angular и подход рендеринга на стороне сервера NodeJS/ExpressJS на стороне сервера.

Наше приложение Angular загружается как один index.html и заставляет XHR-запросы заполнять страницу. Поскольку нам нужна предварительная визуализация страницы, мы использовали PhantomJS для сохранения копии каждой страницы, когда содержимое изменяется на местоположение на сервере. Это позволяет поддерживать SEO.

Есть ли примеры полнофункциональных приложений с главной страницей или приложений Angular, которые люди могут указать нам, чтобы узнать, делают ли другие это.

В качестве альтернативы можно привести примеры приложений, обработанных на стороне сервера NodeJS, которые мы можем видеть в дикой природе.

Наконец, есть ли у кого-нибудь мнения о подобной архитектуре?

4b9b3361

Ответ 1

Я работал как с приложениями, так и с большинством клиентов. Каждый тип имеет свои преимущества и недостатки. Однако мысль о том, что вам нужно выбирать между тем или иным, является ложной дихотомией. Если у вас есть ресурсы, вы можете объединить оба, чтобы получить лучшее из обоих миров.

Я вижу 4 основные проблемы с чисто клиентскими платформами:

  • SEO и аналитика
  • Кэширование
  • Память
  • Задержка

SEO

Поскольку вы используете Node.JS, проблему SEO можно смягчить, просто используя клиентскую структуру на сервере для вывода статических страниц для googlebot и компании. Недавно Google сделал хороший API Google Analytics для одностраничных приложений, но это будет немного больше, чем просто добавить пару строк в конец вашего основного шаблона.

Кэширование

Кэширование - действительно важный способ ускорить работу любого веб-приложения. Для небольших объемов данных можно быстрее кэшировать данные на клиенте в памяти или в localStorage, но пространство на диске очень ограничено (в настоящее время около 5 МБ). Плюс кэширование недействительности довольно сложно сделать в localStorage.

Память

Память - это то, что я дорого заплатил за просмотр. Прежде чем я это узнал, я случайно сделал приложение, которое занимает более 200 МБ ОЗУ. Я мог бы довести это до половины с оптимизацией, но я сомневаюсь, что это заняло бы более 20 МБ, если бы я отобразил все это на сервере.

Задержка

Задержка также легко пропустить. Например, Drupal запускает от 50 до 100 SQL-запросов для каждой страницы. Когда сервер базы данных находится рядом с сервером приложений, вам не нужно беспокоиться о задержке, и все эти запросы могут быть выполнены менее чем за пару сотен миллисекунд. Ваше клиентское приложение обычно занимает сто миллисекунд, чтобы сделать один запрос AJAX. Это означает, что вам нужно потратить много времени на разработку API-интерфейсов на стороне сервера, чтобы свести к минимуму эти круглые поездки, но в этот момент сервер уже имеет все необходимые ему данные, чтобы просто генерировать HTML-код. Наличие клиентского приложения, которое говорит о правильном интерфейсе RESTful, может оказаться медленным, если вы не будете осторожны.

37 Сигналы, недавно опубликованные в блоге о гибридной архитектуре клиент/сервер, они реализованы для новой версии Basecamp. Этот гибридный подход использует сервер для рендеринга HTML, но использует на клиенте что-то вроде PJAX, чтобы избавиться от полного обновления страницы. Эффект очень быстрый и я рекомендую.

Ответ 2

С node.js на сервере в принципе вы можете использовать тот же код для рендеринга как на клиенте, так и на сервере. Рамки, реализующие этот подход, Meteor и Derby, также выполняют прозрачную синхронизацию моделей данных между клиентом и сервером. Оба по-прежнему считаются в альфе, но, похоже, работают уже достаточно хорошо.

Между тем, как рендеринг на стороне клиента, так и на стороне сервера имеет плюсы и минусы:

  • На стороне клиента рендеринг имеет тот недостаток, что загрузка начальной страницы занимает много времени, но как только все ресурсы загружаются, пользователь может без проблем перемещаться по сайту без страницы. Возможно, вы захотите минимизировать количество вызовов Ajax и/или использовать кеш-клиент на стороне клиента (например, данные кэша в контроллере Angular.js).
  • На стороне сервера рендеринг обеспечивает быструю загрузку начальной страницы и подходит для SEO, но каждый раз, когда пользователь перемещается, вся страница становится пустой, а загружает новый URL.

Итак, все зависит от того, хотите ли вы быструю загрузку начальной страницы, но не ожидайте, что пользователи останутся такими длинными (тогда используйте рендеринг на стороне сервера), или это не так важно, что страница загружается быстро (как в Gmail) но пользователи будут перемещаться в течение длительного времени (затем использовать рендеринг на стороне клиента).

Ответ 3

В настоящее время мы тестируем этот сумасшедший aproach: у нас есть приложение angularJS, которое работает на клиенте. Когда мы обнаруживаем робота Googlebot как агента, мы запускаем PhantomJS экземпляр и отвечаем на сканер с результатами из этого. Трудная часть - это знать, когда ваше клиентское приложение закончило загрузку, чтобы вы могли ее выбрать и вернуть. Если вы сделаете это раньше, чем приложение JS на стороне клиента загрузится, искатель не получит много данных назад, в основном просто index.html.

Простую реализацию можно найти здесь: http://pastebin.com/N3w2iyr8

UPDATE: В то время, когда я написал исходный ответ, ничего подобного prerendr.io не существовало, но я могу указать на него сейчас.

Ответ 4

Мое решение сделать приложение на Angular Crawlable от Google. Используется в aisel.co

  1. Снимки обрабатываются https://github.com/localnerve/html-snapshots
  2. Добавьте правило в ваш .htaccess

    RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
    RewriteCond %{REQUEST_URI} !^/snapshots/views/ [NC]
    RewriteRule ^(.*)/?$ /snapshots/views/%1 [L]
    
  3. Создайте скрипт node.js для моментальных снимков и запустите его в терминале: node snapshots.js

    var htmlSnapshots = require('html-snapshots');
        var result = htmlSnapshots.run({
        input: "array",
        source: [
                "http://aisel.dev/#!/",
                "http://aisel.dev/#!/contact/",
                "http://aisel.dev/#!/page/about-aisel"
        ],
        outputDir: "web/snapshots",
        outputDirClean: true,
        selector: ".navbar-header",
        timeout: 10000
    }, function(err, snapshotsCompleted) {
        var fs = require('fs');
        fs.rename('web/snapshots/#!', 'web/snapshots/views', function(err) {
            if ( err ) console.log('ERROR: ' + err);
        });
    });
    
  4. Убедитесь, что все работает с curl, введите в терминал

    curl http://aisel.dev/ \? _ escaped_fragment _\=/page/about-aisel/это должно показать содержимое снимка .../www/aisel.dev/public/web/snapshots/views/page/about-aisel/index.html

Не о директиве для Google и других сканеров. Ваше приложение должно содержать мета-правило в голове:

    <meta name="fragment" content="!">

Полные условия от Google здесь: https://developers.google.com/webmasters/ajax-crawling/docs/specification