next.jsотличный легкий весreactИзоморфная структура, которую можно использовать для быстрой разработки рендеринга на стороне сервера на основеreactзаявление. существуетnext.jsОфициальный сайт рекомендует использоватьnowДля развертывания приложений, но для домашних пользователей или пользователей с особыми потребностями, развертывание на настраиваемых серверах может быть тем, чего хочет большинство людей. В связи с недавней ревизией официального сайта компании я хотел бы поделиться своим опытом от разработки до развертывания.
Я до сих пор смутно помню, как впервые использовал егоnext.jsбыл в прошлом году (2017), в то время с использованиемnext.js2.x версия,reactЕще версия 15, год спустя, сейчасreactбыл разработан до версии 16, в то время какnext.jsОн разработан до версии 6.0, скорость итерации поражает, и в процессе использования новой версии есть много ям.
используемая технология
Поговорим о том, какие технологии используются на этот раз Ниже перечислены основные технологии или библиотеки инструментов, используемые в проекте.
Веб-фреймворк следующего поколения, разработанный оригинальной командой Express, используется для предоставления веб-сервисов.
Это высокопроизводительный HTTP и обратный прокси-сервер, а также сервер IMAP/POP3/SMTP (из энциклопедии Baidu), разработанный россиянами. Используется для предоставления статических файловых служб, сертификатов https и прокси-служб.
- react 16.3
библиотека пользовательского интерфейса javascript
- next.js 6.0.1
легкийreactИзоморфная структура приложения
Разработано Ant Financial
react的Набор библиотек компонентов среднего и внутреннего продукта.
на основе
reactанимационные решения
Определить, находится ли компонент в текущей области просмотра
reactкомпоненты
Менеджер процессов для приложений Node с балансировкой нагрузки
Изоморфный API-интерфейс WHATWG Fetch
стадия развития
Сказав так много, давайте перейдем к этапу разработки, и первым шагом будет построение структуры проекта.Здесь мы делимся нашей структурой проекта:
📁.vscode
vscodeконфигурационный файл
📁component
reactкомпоненты
📁common
В общедоступную часть я помещаю информацию панели навигации, глобальные переменные и глобальные стили и т. д.
📁pages
Все страницы проекта, а такжеnext.js входной файл для каждой страницы
📁static
статические файлы
📁styles
таблица стилей для каждой страницы
🗄index.js
файл запуска узла
🗄.babelrc
babelконфигурационный файл
🗄.gitignore
конфигурационный файл git
🗄ecosystem.config.js
pm2конфигурационный файл
🗄next.config.js
next.js конфигурационный файл
🗄postcss.config.js
postcss конфигурационный файл
🗄nginx.conf
nginxконфигурационный файл
🗄package.json
конфигурационный файл нпм
После завершения настройки структуры проекта предполагается, что вы уже находитесь вpackage.jsonВсе нужные нам зависимости сохранены в, попробуем набратьyarnдля установки зависимостей. Предполагая, что установка прошла успешно, давайте продолжим наш путь разработки.
Первый вpagesСоздайте новый под файломindex.js, здесь я просто случайным образом извлекаю какой-то код из своего реального проекта в качестве учителя.
export default class HomePage extends React.Component {
static async getInitialProps({ req, pathname }) {
const data = await fetch(`${ctx}/api/projects/common/list`).then(res => res.json())
.then(dt => dt)
.catch(err => {
return {
success: false,
message: err.message
}
})
return { pathname,data };
}
render() {
const { pathname, data } = this.props;
return (
<div>
<Head>
<title>首页-易科捷(武汉)生态科技有限公司</title>
</Head>
<div>Welcome to next.js!</div>
{/*这里省略代码*/}
</div>
);
}
}
если вашpackage.jsonне настроен вnextЗапустите скрипт, пожалуйста, посетитеsetupДля настройки ниже запускаем в консолиnpm run dev, если все в порядке, откройте браузер, и вы увидитеWelcome to next.js!
существуетnext.jsопыт разработки иreactпочти никакой разницы, но вwebpackНастройка этой части может занять немного работы. Некоторые часто используемые плагины, такие какsass,cssЖдать,next.jsВсе это предусмотрено для вас, и вы также можете использовать плагины сообщества с открытым исходным кодом, чтобы завершить свой путь разработки. Для получения подробной информации, пожалуйста, проверьтеофициальный сайт next.js.
развертывать
После прохождения ряда процессов, таких как этап разработки, тестирование и т. д., теперь, наконец, настал этап развертывания. существуетnext.jsНа стадии производства упаковка должна запускаться толькоnpm run buildВот и все, официальная рекомендация - не менять имя запакованной папки (оригинальное имя.next), вот я лично рекомендую модифицировать егоbuildилиdistэти имена. После того, как упаковка будет завершена, вам нужно написатьnodejsЗапустите файл записи и вставьте приведенный ниже пример кода:
const Koa = require('koa')
const next = require('next')
const Router = require('koa-router')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
const server = new Koa()
const router = new Router()
// 首页
router.get('/', async ctx => {
await app.render(ctx.req, ctx.res, '/', ctx.query)
ctx.respond = false
})
// 关于
router.get('/about', async ctx => {
await app.render(ctx.req, ctx.res, '/about', ctx.query)
ctx.respond = false
})
// 产品
router.get('/products/:id', async ctx => {
const {id} = ctx.params
await app.render(ctx.req, ctx.res, `/products/${id}`, ctx.query)
ctx.respond = false
})
// 案例
router.get('/case', async ctx => {
await app.render(ctx.req, ctx.res, '/case', ctx.query)
ctx.respond = false
})
// 联系我们
router.get('/contact', async ctx => {
await app.render(ctx.req, ctx.res, '/contact', ctx.query)
ctx.respond = false
})
// 详情
router.get('/view/:type/:id', async ctx => {
const {id, type} = ctx.params
await app.render(ctx.req, ctx.res, `/view`, {id, type})
ctx.respond = false
})
// 如果没有配置nginx做静态文件服务,下面代码请务必开启
/* router.get('*', async ctx => {
await handle(ctx.req, ctx.res)
ctx.respond = false
})*/
// 防止出现控制台报404错误
server.use(async (ctx, next) => {
ctx.res.statusCode = 200
await next()
})
server.use(router.routes())
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`)
})
})
Общие статические файлы, сжатие gzip не нужно передаватьnodejsЧтобы сделать это, я всегда думал, что профессиональные вещи оставляются профессиональным людям. Здесь задача передаетсяnginx, обратите особое внимание на часть кода, которую я прокомментировал в примере кода выше, если вы не используетеnginxЧтобы использовать статическую файловую службу, обязательно откройте ее, в противном случаеnext.jsупакованныйjs,css, файлы изображений и т. д., будут сообщены404.
существуетnext.jsУпаковано на стадии производственной упаковкиjsПуть запроса файла имеет номер версии, но фактическая упакованная папка не имеет фактического соответствующего каталога, то есть здесь используется упакованный виртуальный каталог.nginxнуждаются в особом внимании. к счастьюnext.jsУкажите элементы конфигурации для измененияbuild id, вот мой реальный код:
// next.config.js
module.exports = {
generateBuildId: async () => {
// For example get the latest git commit hash here
return 'v1'
}
}
Упакованный таким образом виртуальный путь, вероятно,_next/v1/page/xxx.js, если вы используетеcdnпрефикс, здесь есть небольшая разница, но номер версии все же есть.
Еще одно отверстиеnext.jsВ комплекте три папки:bundles,dist,static, для тех, кто не знает исходный код, они не знают, в какой папке находится фактический файл запроса. Так что я вижуnext.jsИсходный код, я обнаружил, что на самом деле я искалbundleпод файломpage, расположение исходного кода:L214
Итак, в конфигурацииnginxВам нужно использовать псевдоним. Ниже мой фрагментnginxРеальный код конфигурации:
# 网站根目录文件
location ~ ^/(robots.txt|humans.txt|favicon.ico|sw.js|baidu_verify_7Kj6tQjI3v.html) {
root /home/website/eco_website_pc/static/;
if ($request_filename ~* sw.js){
expires -1s;
}
expires 10m;
}
# static下的文件
location ^~ /static/ {
alias /home/website/eco_website_pc/static/;
if ($request_filename ~* sw.js){
expires -1s;
}
expires 10m;
}
# next pages页面下的脚本
location ~ ^/(/_next/v1/) {
alias /home/website/eco_website_pc/build/bundles/;
if ($request_filename ~* sw.js){
expires -1s;
}
expires 10m;
}
# next static下的静态文件
location ~ ^/(/_next/static/) {
root /home/website/eco_website_pc/build;
if ($request_filename ~* sw.js){
expires -1s;
}
expires 10m;
}
После того, как статический файл настроен, его необходимо настроитьhttpsСертификат в наличии, т.к. наш проект официальный сайт компании, сертификат получу бесплатно, вот пользуюсьfreesslСертификат целостности в Азии, представленный выше. После примененияsslПосле сертификата нужно перейти к провайдеру доменного имени для настройкиTXTДля справки, здесь я использую Alibaba Cloud.После завершения проверкиfreesslСертификат будет скачан, после получения сертификата необходимо его настроить.nginx sslСертификат, моя полная конфигурация размещена ниже:
server {
listen 80;
listen 443 ssl;
server_name wh-eco.com;
charset utf-8;
ssl_certificate /home/website/ssl/www/full_chain.pem;
ssl_certificate_key /home/website/ssl/www/private.key;
fastcgi_param HTTPS on;
fastcgi_param HTTP_SCHEME https;
if ($scheme = http ) {
return 301 https://$host$request_uri;
}
access_log /var/log/nginx/www.wh-eco.com.access.log;
error_log /var/log/nginx/www.wh-eco.com.error.log;
location / {
proxy_pass http://127.0.0.1:xxxx; #保密 0.0
proxy_set_header Host $host;
#proxy_redirect off;
proxy_set_header REMOTE-HOST $remote_addr;
# 网站可能后期会使用websocket 特次升级请求协议
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_read_timeout 600;
proxy_send_timeout 600;
}
# 网站根目录文件
location ~ ^/(robots.txt|humans.txt|favicon.ico|sw.js|baidu_verify_7Kj6tQjI3v.html) {
root /home/website/eco_website_pc/static/;
if ($request_filename ~* sw.js){
expires -1s;
}
expires 10m;
}
# static下的文件
location ^~ /static/ {
alias /home/website/eco_website_pc/static/;
if ($request_filename ~* sw.js){
expires -1s;
}
expires 10m;
}
# next pages页面下的脚本
location ~ ^/(/_next/v1/) {
alias /home/website/eco_website_pc/build/bundles/;
if ($request_filename ~* sw.js){
expires -1s;
}
expires 10m;
}
# next static下的静态文件
location ~ ^/(/_next/static/) {
root /home/website/eco_website_pc/build;
if ($request_filename ~* sw.js){
expires -1s;
}
expires 10m;
}
error_page 500 502 503 504 = /error.html;
error_page 404 = /notfound.html;
location = /error.html {
root /home;
}
location = /notfound.html{
root /home;
}
}
Что касаетсяgzipВы можете настроить его в соответствии с вашими требованиями, вставьте пример моей конфигурации:
gzip on;
gzip_comp_level 6;
gzip_vary on;
gzip_types
application/atom+xml
application/javascript
application/json
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/svg+xml
image/x-icon
image/jpeg
image/gif
image/png
text/css
text/plain
text/x-component;
по окончанииnginxЧто нужно сделать после настройкиpm2способ запуска всего приложения
pm2 start ecosystem.config.js
После выполнения вышеуказанной команды, если все пойдет хорошо, вы можете ввести доменное имя для доступа к вашему приложению (при условии, что вы завершили работу по разрешению доменного имени).
Суммировать
Как только вы входите в переднюю часть, она такая же глубокая, как море