Для поддержки нескольких доменов с Next.js вы можете использовать custom server, например с express.js.
Сначала установите express.js, если у вас его еще нет:
```bash
npm install express
```
Затем создайте файл server.js в корневом каталоге проекта:
```javascript
const express = require('express')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
const server = express()
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
```
В этом файле создается экспресс-сервер, который фактически обрабатывает все запросы.
Разумеется, для поддержки нескольких доменов вам потребуется соответствующий код. Вы можете использовать, например, middleware, которое по hostname запроса будет раздавать нужные страницы:
```javascript
const express = require('express')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
const server = express()
server.use((req, res, next) => {
switch (req.headers.host) {
case 'www.domain1.com':
req.url = '/domain1' + req.url;
break;
case 'www.domain2.com':
req.url = '/domain2' + req.url;
break;
}
next();
});
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
```
И последнее что вам нужно сделать - это изменить скрипт "start" в файле package.json на следующий:
```json
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js"
}
```
Теперь сервер запускается не стандартным образом next start, а через ваш server.js, где и происходит разделение на домены.
Обратите внимание, что рассмотренный метод требует тщательного тестирования и не всегда может быть оптимальным для больших приложений, особенно если приложение активно развивается и постоянно обновляется.
- Создайте функцию-обертку `withHost`, которая принимает функцию `getStaticPropsData` в качестве аргумента.
- Внутри `withHost`, создайте функцию `getStaticProps`, которая принимает параметр `ctx`.
- Внутри `getStaticProps`, вызовите функцию `getHost` с параметром `ctx.params.host` и сохраните результат в переменной `response`.
- Вызовите функцию `getStaticPropsData` с параметром `ctx` и сохраните результат в переменной `gspData`.
- Верните объект со свойствами `props`, где значениями будут `response.data` и распыленный объект `gspData.props`.
- Создайте функцию `getStaticPaths`, которая не принимает аргументов.
- Внутри `getStaticPaths`, вызовите функцию `ServerCache.get("hosts")` и сохраните результат в переменной `response`.
- Верните объект со свойствами `paths`, где значениями будут результаты применения функции `.map(...)` к `response.data`, и `fallback`, равный "blocking".
- Верните объект с функциями `getStaticPaths` и `getStaticProps` из функции `withHost`.
В файле `index.tsx`, импортируйте функции `getStaticPaths` и `getStaticProps` из `withHost`, и используйте их при экспорте:
```
export const { getStaticPaths, getStaticProps } = withHost(() => ({
props: {}
}));
```
Вынесите функцию `getStaticProps` в отдельную функцию и используйте ее для каждого роута:
```
export const getStaticProps = withHost(() => ({
props: {}
}));
export const getStaticPaths = getHostsPaths();
```
Описание проблемы:
Я потратил 6 часов времени на разработку, и столкнулся с проблемой в следующей функции-обертке:
async function withHost(getStaticPropsData) {
const getStaticProps = async (ctx) => {
const response = await getHost(ctx.params.host);
const gspData = await getStaticPropsData(ctx);
return {
props: { host: response.data, ...gpsData.props }
}
};
const getStaticPaths = async () => {
const response = await ServerCache.get("hosts");
return {
paths: response.data.map(...),
fallback: "blocking"
};
}
return { getStaticPaths, getStaticProps };
};
Решение проблемы:
Я вынес функцию gsp (getStaticProps) в отдельную функцию и использовал ее для каждого роута:
export const getStaticProps = withHost(() => ({
props: {}
}))
export const getStaticPaths = getHostsPaths();
```