Next.js: Бессерверное Next: сделать `next` зависимостью только для разработчиков, ввести` next-server` для небольших сборок и более быстрой загрузки

Созданный на 29 мая 2018  ·  52Комментарии  ·  Источник: vercel/next.js

Проблема: при оптимизации для производственной сборки вызов next start или использование require('next') в настраиваемом server.js включает перенос всего набора зависимостей next , включая относящиеся исключительно к разработке, например webpack .

Это не только проблематично с точки зрения образа сборки и производительности времени загрузки при создании производственных сборок, но также, вероятно, ухудшает время загрузки. _Примечание: это смягчается тем фактом, что мы осторожно лениво загружаем тяжелые зависимости, такие как webpack в режиме разработки. _

Для тех, кто заботится о производительности и чувствителен к _ холодному времени запуска_ (см., Например: https://twitter.com/rauchg/status/990667331205447680), мы можем ввести пакет next-server .

Он будет иметь те же возможности, что и require('next') за вычетом всех настроек времени разработки , плюс очень маленький next-server CLI, который может открыть порт и выполнить плавное завершение работы.

Для чего мы хотим оптимизировать:

  • Общий набор зависимостей next-server должен быть как можно меньше.
  • Мы должны сильно оптимизировать время загрузки, чтобы начать как можно быстрее

Кроме того, мы должны предоставить пример в examples/ того, как использовать next-server в сочетании с pkg для экспорта вашего приложения Next.js как автономного двоичного файла

p1 feature request

Самый полезный комментарий

Время холодного запуска, которое мы видим в Now 2.0 для нашего интерфейса, составляет 1,5 секунды для размера изображения 80 МБ IIRC.

2018-05-29 16 50 37

Должна быть возможность сделать его намного ближе к 1 без каких-либо изменений в Node или V8 или любых зависимостях, холодная оценка которых занимает много времени (например, react и react-dom )

Все 52 Комментарий

Время холодного запуска, которое мы видим в Now 2.0 для нашего интерфейса, составляет 1,5 секунды для размера изображения 80 МБ IIRC.

2018-05-29 16 50 37

Должна быть возможность сделать его намного ближе к 1 без каких-либо изменений в Node или V8 или любых зависимостях, холодная оценка которых занимает много времени (например, react и react-dom )

ты, это круто !! : o

Ух ты, здорово.

несколько вопросов для next-server .

  1. это будет легкий экспресс-сервер?
  2. да, можно ли его настроить с помощью экспресс-маршрутов и next-routes ?

@ Nishchit14 Вы бы не добавили express если бы пытались уменьшить размер сборки.

Я уверен, что next-routes прежнему будет работать нормально.

Итак, мы говорим здесь о извлечении существующего сервера в его собственный пакет. Таким образом, он будет работать так же, как и раньше, но вместо следующего импорта вы импортируете следующий сервер.

Это круто! Я и другие люди, которых я знаю, запускали Next.js поверх AWS Lambda с использованием скандия ( используя это руководство ), и некоторые из основных проблем заключались в следующем:

1) Размер упаковки. Lambda дает жесткое ограничение в 50 МБ, к которому можно легко приблизиться со всеми включенными инструментами разработки.

2) Холодный старт. Быстрая загрузка очень важна, так как Lambda может решить запустить больше серверов в любой момент. Существующие серверы также живут максимум ~ 4 часа, поэтому холодный запуск будет важен на протяжении всего жизненного цикла приложения.

Очень рад этой инициативе и рад помочь!

Это отличная идея, у нас то же самое с Nuxt.js, мы назвали его nuxt-start так как это команда, которая вам нужна для запуска nuxt start -> nuxt-start

Слежу за этим внимательно. В качестве точки данных о том, что возможно, www.bustle.com представляет собой предварительное приложение SSR на AWS Lambda с холодным запуском <1 с. Размер развернутого производственного zip-файла составляет 166 КБ. Это весь код приложения и библиотеки. Webpack используется для комплектации.

Спасибо, что поделились @southpolesteve. Это супер впечатляет. #цели

Случай пользователя очень похож на micro и micro-dev .

Почему бы не использовать ту же номенклатуру? next и next-dev

Я возился с next.js и serverless, используя этот пример, и мне любопытно, есть ли какой-либо способ выполнить сборки меньшего размера сейчас. Есть ли список node_modules, которые нам абсолютно не нужны в производстве и которые могут быть исключены с помощью файлов конфигурации в упаковщике, например serverless или repack-zip ?

@Enalmada Я использую next.js с несколькими deps, и одним из них является material-ui , у меня довольно большое приложение с точки зрения масштаба, но встроенный zip-архив, который я загружаю в Lambda, составляет ~ 45 МБ. Какие размеры вы ищете?

@albinekb Я вдохновлен ответом southpolesteve bustle.com выше 166 КБ и задаюсь вопросом, какая часть моих «45 МБ» бесполезна и легко удаляется, если бы я просто знал, что добавить в файл dist exclude в качестве хака, пока этот отличный билет не будет готов .

@albinekb Настоятельно рекомендуем вам изучить использование webpack, parcel или rollup для объединения вашего JS для лямбда-выражения. Вы сэкономите не только на размере, но и на времени загрузки, так как обращение к файловой системе через обычный узел требует довольно много времени.

Если вы развертываете ZEIT Now и хотите, чтобы ваш образ был небольшим для быстрой холодной загрузки, вы можете использовать такой инструмент, как Package Phobia, чтобы проверить размер зависимости npm перед его установкой (или просто проверьте размер текущих зависимостей. чтобы вырезать заворот).

В файле readme также есть много похожих инструментов, которые помогут вам бороться с вздутием живота. Посмотрите здесь: https://github.com/styfle/packagephobia

Разве это не должно было быть решено в выпуске Next 7? :(

Если вы сейчас развертываете zeit и хотите, чтобы ваш образ был небольшим для быстрой холодной загрузки, вы можете использовать такой инструмент, как Package Phobia.

Черт побери, antd: https://packagephobia.now.sh/result?p=antd

@Enalmada , вероятно, это зависит от зависимостей antd, а не от самой библиотеки. Я искал это для https://packagephobia.now.sh/result?p=%40material-ui%2Fcore. Большая часть веса исходит от одной или двух зависимостей.

Разве это не должно было быть решено в выпуске Next 7? :(

Чтобы прояснить это, Next.js 7 закладывает основу для Serverless Next.js, мы удалили около 5 маршрутов, оставив только 2, действительно необходимых для производства.

Кто-нибудь когда-нибудь получал next.js для работы с rollup? Я чувствую, что подошел очень близко ... бегущий сверток на моем 60-метровом файле dist уменьшил размер до 6 метров. К сожалению, файл dist на самом деле не запускается, и я думаю, что это связано с одной циклической зависимостью в коде next.js, которая является предупреждением во время объединения. Если бы кто-то мог взвесить возможность удаления циклической зависимости в коде next.js, мы все могли бы быть очень близки к гораздо меньшим сборкам и более быстрой загрузке:
https://github.com/zeit/next.js/issues/5392

Слежу за этим внимательно. В качестве точки данных о том, что возможно, www.bustle.com представляет собой предварительное приложение SSR на AWS Lambda с холодным запуском <1 с. Размер развернутого производственного zip-файла составляет 166 КБ. Это весь код приложения и библиотеки. Webpack используется для комплектации.

@southpolesteve Не могли бы вы поделиться чем-нибудь из конфигурации вашего пакета webpack?

@shauns К сожалению, я больше не в Bustle, и мне больше не нужно смотреть код: /

@southpolesteve не беспокойтесь! Хорошо хотя бы знать его возможности в веб-пакете.

Можно новости о следующем сервере? Я видел несколько коммитов в этом месяце назад.

Проверьте канарейку.

Когда вы планируете его выпустить?

Я не могу поделиться графиком на данный момент.

Похоже, это может помочь исправить эту ошибку:
https://spectrum.chat/zeit/general/unable-to-import-module-now-launcher-error~2662f0ba-4186-402f-b1db-2e3c43d8689a

Только что приземлился # 5927

@timneutkens Должен ли я переместить next в devDependencies и добавить next-server в мои зависимости или вы делаете это автоматически через babel?
https://github.com/zeit/next.js/blob/canary/packages/next/build/babel/plugins/next-to-next-server.ts

@Skaronator, если вы используете # 5927, это ни то, ни другое, в соответствии со спецификацией он будет выводить один пакет на страницу, никаких зависимостей не требуется. Это означает, что вы можете взять .next/serverless/index.js require ( require('./.next/serverless/index.js') ), а затем вызвать его метод render :

const page = require('./.next/serverless/index.js')

page.render(req, res)

Это отобразит страницу и завершит ответ

Это потрясающе!
Я пробую это сделать, но у меня проблемы с его работой на aws lambda. Есть ли у кого-нибудь советы?

Думаю, нам больше не нужен пользовательский экспресс-сервер, мы могли бы просто потребовать бессерверный файл на основе пути 🤔

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

const serverless = require("serverless-http");
const http = require('http');
const app = require('./.next/serverless/index.js');
const server = new http.Server((req, res) => app.render(req, res))
app.prepare().then(() => {
    const handler = serverless(server, {
        binary: binaryMimeTypes
    });
    return handler(event, context, callback);
});

Похоже, вы путаете «настраиваемый сервер» с «бессерверным», их API-интерфейсы полностью разделены, в бессерверном режиме нет метода .prepare как нечего готовить, мы немедленно визуализируем страницу в html и завершаем ответ при вызове render .

const serverless = require("serverless-http");
const http = require('http');
const page = require('./.next/serverless/index.js');
const server = new http.Server((req, res) => page.render(req, res))
const handler = serverless(server, {
  binary: binaryMimeTypes
});
handler(event, context, callback);

В самом деле, и я понятия не имею, почему приведенный выше код работал (возможно, это был просто кеш), но ни мой, ни ваш фрагмент кода не работали, потому что serverless-http , похоже, не поддерживает http.Server и Я не могу просто вернуть page.render(req, res) потому что лямбда-объект event не может заменить необходимый параметр render req .

Кроме того, я не хочу использовать express / koa / something, поскольку это нарушит всю цель этой следующей новой функции .. ( serverless-http не зависит от зависимостей, поэтому его можно было использовать)

У меня нет идей: /

Возможно, это поможет вам @guillaumebreux https://github.com/zeit/now-builders/blob/master/packages/now-node-bridge/bridge.js

Спасибо @timneutkens , ценю вашу помощь.
Но пока тоже не работает, у меня все еще такая ошибка: typeError: Parameter "url" must be a string, not undefined

Я перестану загрязнять эту тему и продолжу копать, и я напишу пример, если найду решение 😄

Я немного не понимаю. Этот поток выглядит так, как будто он применяется к двум сценариям: безсерверным приложениям и предварительно скомпилированным серверам, которые включают все необходимые серверные npm-пакеты, объединенные вместе.

Гифка в первом комментарии к этой теме, похоже, относится ко второму сценарию, который и интересует меня. Похоже, он использует next-server который может быть, а может и не быть этим пакетом npm - это не к нему не прикреплен репозиторий, и я не смог найти его через поиск в Google или GitHub, хотя один из тегов версии - 8.0.0-canary.7 - тег версии next - так что я подозреваю, что это правильный пакет.

Верно ли то, что я написал до сих пор? Если да, то даже если он на канарейке, могу ли я получить к нему ранний доступ?

Мое текущее решение (которое по очевидным причинам я не использую в продукте ) состоит в том, чтобы удалить функцию из config.externals в моем next.config.js .

Я хотел бы быть в состоянии произвести предварительный встроенный сервер , так что мне не нужно , чтобы установить 200 Мб node_modules , а затем потратить 2 минуты компиляции на моих бедных, маленьких производствах VM каждый раз , когда я нажимаю обновление.


* "prod" используется нечетко, поскольку этот проект не является критически важным или профессиональным.

Слежу за этим внимательно. В качестве точки данных о том, что возможно, www.bustle.com представляет собой предварительное приложение SSR на AWS Lambda с холодным запуском <1 с. Размер развернутого производственного zip-файла составляет 166 КБ. Это весь код приложения и библиотеки. Webpack используется для комплектации.

Бессерверная цель Next.js 8 по умолчанию имеет размер архива 42 КБ 😌

Это потрясающе! Жду этого с нетерпением!

У меня точно такой же вопрос, что и у @dfoverdx. Я хочу создать серверную сборку, которая также включает в себя все необходимые для запуска node_modules. Я использую собственный сервер с экспрессом, поэтому я не ожидаю, что эти зависимости будут включены в пакет, но теперь вам нужно установить _все_ зависимости и на свой сервер (response, next, axios, ...).

Не понимаю, как это не по умолчанию?
Упаковка всех зависимостей и возможность их минимизировать должны привести к значительному повышению производительности сервера, или я здесь совершенно не прав?

Перезапись раздела externals конфигурации webpack следующим образом включает большинство зависимостей

module.exports = {
  webpack: (config, { dev }) => {
    config.externals = [];
    return config;
  })
};

Но на сервере по-прежнему требуются react и react-dom. Я не могу понять, как их включить ...

К сожалению, в текущем бессерверном режиме создать собственный сервер невозможно. И если вы используете нормальный режим, вам нужно включить next и все его зависимости, потому что сгенерированный _app.js в .next зависит, например, от next / router

Почему бы не добавить в пакет еще и несерверный режим?

К сожалению, в текущем бессерверном режиме создать собственный сервер невозможно. И если вы используете нормальный режим, вам нужно включить next и все его зависимости, потому что сгенерированный _app.js в .next зависит, например, от next / router

Обратите внимание: начиная со следующих 8, вы можете требовать «следующий сервер» вместо «следующий» в своем server.js, и вы теряете горячую перезагрузку только во время локальной разработки, делая это. Теоретически это дает вам возможность выполнять CI-сборку на промежуточном сервере, а не копировать зависимости, связанные с Webpack, в производственные экземпляры. Но мы еще не пробовали это в нашем проекте.

@ElvenMonky ждал чего-то подобного с года, но не смог найти ничего об этом в документации или примерах.

@timneutkens, не могли бы вы это проверить?

Если это так, я мог бы поэкспериментировать с такой настройкой и отправить PR за документы / примеры.

Обратите внимание, что начиная со следующих 8 вы можете требовать 'next-server' вместо 'next' в вашем server.js, и вы теряете горячую перезагрузку только во время локальной разработки, делая это.

К сожалению, это не работает.

Во-первых, запуск бессерверной сборки с целевым сервером активно блокируется следующим сообщением: «Невозможно запустить сервер, если целью не является сервер. Https://err.sh/zeit/next.js/next-start-serverless »

Затем, если вы решите выполнить обычную сборку, тогда файлы сборки будут ссылаться на вещи из пакета next напрямую (например, next/router в скомпилированном файле _app.js для серверной части). Это означает, что next и webpack все равно должны быть в производственной сборке.

@ElvenMonky

Обратите внимание: начиная со следующих 8, вы можете требовать «следующий сервер» вместо «следующий» в своем server.js, и вы теряете горячую перезагрузку только во время локальной разработки, делая это.

Next делает это внутри как плагин Babel, как вы можете видеть здесь:
https://github.com/zeit/next.js/blob/709850154754278d2fc86b987eebe1b3f0565255/packages/next/build/babel/plugins/commonjs.ts#L5 -L32

@sheerun, как я уже упоминал, в # 7011, вы можете устранить неразрешенную зависимость next/router , перенеся модуль next с помощью плагина next-transpile-modules .

Я разработал и скорректировал пример для пользовательского экспресс-сервера, чтобы проиллюстрировать решение: https://github.com/ElvenMonky/next.js/tree/custom-next-server-express/examples/custom-server-express

PS: Меня все еще очень волнует # 5927, несмотря на то, что моему приложению требуется все, что указано в TODO, не говоря уже о динамических маршрутах и ​​обслуживании статического контента.
Хорошая новость заключается в том, что вышеуказанное решение, похоже, хорошо сочетается с

Обратите внимание: начиная со следующих 8, вы можете требовать «следующий сервер» вместо «следующий» в своем server.js, и вы теряете горячую перезагрузку только во время локальной разработки, делая это.

Я использовал этот совет, но, к сожалению, не могу использовать конфигурацию времени выполнения, так как для этого требуется next/config а для этого требуется next .

Я не знаю почему, но require('next/config') раньше работал в продакшене без next установленного в node_modules в следующей версии 8.0.3, но не работает в следующей версии 8.1.0

Можно ли переместить следующий / config в другой пакет, например next-runtime-config ?
Или next-runtime-vars (избегая термина config, чтобы не путать с next.config.js).

Дайте знать, если приемлемо, я создам пиар.

Привет всем! Эта проблема реализована, начиная с Next.js 8, и все еще присутствует в Next.js 9. Я собираюсь закрыть это как завершенное. 😌

Извините, я запутался в этой проблеме: https://github.com/zeit/next.js/issues/7011
Я не проверял цель: "без сервера"


См. Удаленный комментарий

Некоторые "next/*" можно заменить на "next-server/*" , например:

  • следующий / конфигурация -> следующий-сервер / конфигурация
  • следующий / amp -> следующий-сервер / amp
  • следующий / динамический -> следующий-сервер / динамический
  • следующий / константы -> следующий-сервер / константы
  • следующий / голова -> следующий-сервер / голова

Но есть несколько, для которых нет поддержки такой оптимизации, упомянутой OP этой проблемы.

  • следующий / маршрутизатор -> следующий-сервер / dist / lib / router / router (возможно)? (Должен быть пустым или должен выдавать ошибку, если используется на сервере)
  • следующая / ссылка?

Не нужны, поскольку они встроены даже на сервере (AKAIK)

  • следующий / приложение
  • следующий / документ

Привет всем! Эта проблема реализована, начиная с Next.js 8, и все еще присутствует в Next.js 9. Я собираюсь закрыть это как завершенное.

Привет, @Timer - Вы имеете в виду цель без сервизов или замену «следующего» на «следующий-сервер»?

Если мы заменим next на следующий сервер, это не изменит размер папки node_modules, если также не обновятся зависимости packages.json.

Есть ли пример любого из подходов? в бессерверном варианте мой вариант использования - развертывание на AWS Lambda.

Подход, описанный в первоначальной задаче, превратился в цель serverless , мы рекомендуем вам ее использовать.

@timneutkens serverless target не может и не может решить проблемы с настраиваемым сервером, который использует динамические маршруты. # 5927 Это не решение для многих реальных бизнес-приложений, как в моем случае, где мы должны использовать динамически генерируемые страницы, префикс ресурсов, настраиваемые _app, _document и _err: в основном все, что указано в списке TODO.
next-server дает нам частичное решение для развертывания в продакшене без странных зависимостей только от разработки, таких как webpack и babel. Однако это можно сделать с помощью некоторых хаков и танцев вуду, которые мы здесь обсуждаем.

У меня создалось впечатление, что вы понимаете эту разницу, и я надеялся когда-нибудь увидеть более надежное решение первоначальной проблемы, как это описано @rauchg.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги