Next.js - Бессерверный рендеринг с помощью Clouflare Workers?

Я использую Next.js v9 и хотел бы воспользоваться опцией бессерверного развертывания Next, используя свое приложение с Cloudflare Workers.

Из документации Next.js я знаю, что каждая бессерверная функция, созданная Next, имеет следующую подпись:

export function render(req: http.IncomingMessage, res: http.ServerResponse) => void

При использовании класса http.Server узла (например, с использованием express) передача объектов req и res становится тривиальной, и в документации показан пример этого.

Однако проблема в том, что Cloudflare Workers используют другой объект Request и Response, чем ожидает Next. Документы для их Request объекта можно найти здесь, а документы для их Response объект можно найти здесь.

Итак, пока простое приложение "hello world", работающее на Cloudflare Workers, выглядит так:

// 1. Register a FetchEvent listener that sends a custom
//    response for the given request.
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

// 2. Return a custom request object
async function handleRequest(request) {
  return new Response('hello world')
}

а рендеринг простой функции Next.js может выглядеть примерно так:

const page = require('./.next/serverless/pages/some_page.js');

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  return page.render(request, new Response());
}

существует внутреннее несоответствие между типами resuest и response, поэтому я подозреваю, что будут возникать ошибки.

Я знаю, что мне нужно изменить их, чтобы они передавались так, как ожидает Next.js. Я знаю, что объект Request Worker'а можно изменить, как показано здесь. Но я не уверен, как именно согласовать его с объектом http.IncomingMessage. И я не уверен, как отформатировать объект Response. Есть предположения?

Спасибо


person mrstack999    schedule 02.12.2019    source источник
comment
Это будет сложно. ReadableStreams и NodeJS Readables совершенно разные внутри. Список можно продолжить с другими реализациями. Так что восполнить этот пробел здесь потребует много работы. Думаю, так проще роутинг переделать ...   -  person Jonas Wilms    schedule 02.12.2019
comment
Да, похоже, именно так. Но не могли бы уточнить, что вы подразумеваете под переработкой маршрутизации?   -  person mrstack999    schedule 02.12.2019
comment
Что ж, не используйте NextJS.   -  person Jonas Wilms    schedule 02.12.2019


Ответы (2)


Вы стремитесь реплицировать API для модуля Node.js http, который предоставляет _ 2_ и _ 3_. Это кажется грандиозным мероприятием, которое в некотором смысле сводит на нет цель работы с Cloudflare Workers, моделируемыми на основе Service Worker API. Вместо этого рассмотрите возможность отказа от Next.js для специфичного для Cloudflare Workers подхода к SSR для React, как Cloudflare демонстрирует здесь.

person selfagency    schedule 02.12.2019
comment
Понятно, спасибо за голову и ссылку. Как вы думаете, можно ли использовать Next традиционным способом - то есть без указания цели сборки как бессерверной - с Cloudflare? Необходимость писать приложение, используя простой renderToString подход, в конце концов, лишает смысла использование Next.js - person mrstack999; 02.12.2019
comment
Нет, не знаю. Я думаю, что если вы привержены Next.js, вам лучше использовать Netlify или Zeit, которые больше ориентированы на запуск приложений Node.js, а Cloudflare Workers просто нет. - person selfagency; 02.12.2019
comment
Гоча, очень ценим - person mrstack999; 02.12.2019

Вы можете попытаться имитировать объект ответа вот так.

        const page = require('./.next/serverless/pages/some_page.js');

        addEventListener('fetch', event => {
            event.respondWith(handleRequest(event.request))
        })

        async function handleRequest(request) {
            return new Promise((resolve) => {
                const response = {
                    setHeader: () => {},
                    getHeader: () => {},
                    end: (htmlString) => {
                        resolve(htmlString);
                    },
                };
                page.render(request, response);
            });
        }
person Gustavo Edinger    schedule 10.12.2019
comment
Спасибо, я попробую - person mrstack999; 11.12.2019
comment
@ mrstack999 как дела? - person balupton; 08.01.2021