Привет. Меня зовут Андрей, я студент-магистрант в одном из технических ВУЗов Москвы и по совместительству очень скромный начинающий предприниматель и разработчик. В этой статье я решил поделиться своим опытом перехода от PHP (который когда-то мне нравился из-за своей простоты, но со временем стал ненавидим мною — под катом объясняю почему) к NodeJS. Здесь могут приводиться очень банальные и кажущиеся элементарными задачи, которые, тем не менее, лично мне было любопытно решать в ходе моего знакомства с NodeJS и особенностями серверной разработки на JavaScript. Я попытаюсь объяснить и наглядно доказать, что PHP уже окончательно ушёл в закат и уступил своё место NodeJS. Возможно, кому-то даже будет полезно узнать некоторые особенности рендеринга HTML-страниц в Node, который изначально не приспособлен к этому от слова совсем.


Введение


Во время написания движка я использовал простейшие техники. Никаких менеджеров пакетов, никакого роутинга. Только хардкор — папки, чьё название соответствовало запрашиваемому маршруту, да index.php в каждой из них, настроенный PHP-FPM для поддержания пула процессов. Позднее возникла необходимость использовать Composer и Laravel, что и стало последней каплей для меня. Перед тем, как перейти к рассказу о том, зачем же я вообще взялся переписывать всё с PHP на NodeJS, расскажу немного о предыстории.


Менеджер пакетов


В конце 2018 года довелось работать с одним проектом, написанным на Laravel. Нужно было исправить несколько багов, внести правки в существующий функционал, добавить несколько новых кнопок в интерфейсе. Начался процесс с установки менеджера пакетов и зависимостей. В PHP для этого используется Composer. Тогда заказчик предоставил сервер с 1 ядром и 512 мегабайтами оперативной памяти и это был мой первый опыт работы с Composer. При установке зависимостей на виртуальном приватном сервере с 512 мегабайтами памяти процесс аварийно завершился из-за нехватки памяти.


Wut?


Для меня, как человека знакомого с Linux и имеющего опыт работы с Debian и Ubuntu решение такой проблемы было очевидно — установка SWAP-файла (файл подкачки — для тех, кто не знаком с администрированием в Linux). Начинающий неопытный разработчик, установивший свой первый Laravel-дистрибутив на Digital Ocean, например, просто пойдёт в панель управления и будет поднимать тариф до тех пор, пока установка зависимостей не перестанет завершаться с ошибкой сегментации памяти. А как там обстоят дела с NodeJS?
А в NodeJS есть свой собственный менеджер пакетов — npm. Он значительно проще в использовании, компактнее, может работать даже в среде с минимальным количеством оперативной памяти. В целом, ругать Composer на фоне NPM особо не за что, однако в случае возникновения каких-то ошибок при установке пакетов Composer вылетит с ошибкой как обычное PHP-приложение и вы никогда не узнаете, какая часть пакета успела установиться и установилась ли она в конце-концов. И вообще, для администратора Linux вылетевшая установка = флэшбеки в Rescue Mode и dpkg --configure -a. К тому времени, как меня настигли такие "сюрпризы", я уже недолюбливал PHP, но это уже были последние гвозди в крышку гроба моей некогда великой любви к PHP.


Long-term support и проблема версионирования


Помните, какой ажиотаж и изумление вызвал PHP7, когда разработчики впервые презентовали его? Увеличение производительности более чем в 2 раза, а в некоторых компонентах до 5 раз! А помните, когда появился на свет PHP седьмой версии? А как быстро-то заработал WordPress! Это был декабрь 2015 года. А знали ли вы, что PHP 7.0 уже сейчас считается устаревшей версией PHP и крайне рекомендуется обновить его… Нет, не до версии 7.1, а до версии 7.2. По утверждениям разработчиков, версия 7.1 уже лишена активной поддержки и получает лишь обновления безопасности. А через 8 месяцев прекратится и это. Прекратится, вместе с активной поддержкой и версии 7.2. Выходит, что к концу текущего года у PHP останется лишь одна актуальная версия — 7.3.


Используемые в текущее время версии PHP


На самом деле, это не было бы придиркой и я бы не отнёс это к причинам моего ухода от PHP, если бы написанные мной проекты на PHP 7.0.* уже сейчас не вызывали deprecation warning при открытии. Вернёмся к тому проекту, где вылетала установка зависимостей. Это был проект, написанный в 2015 году на Laravel 4 с PHP 5.6. Казалось, прошло же всего 4 года, ан-нет — куча deprecation-предупреждений, устаревшие модули, невозможность нормально обновиться до Laravel 5 из-за кучи корневых обновлений движка.


И это касается не только самого Laravel. Попробуйте взять любое приложение на PHP, написанное во времена активной поддержки первых версий PHP 7.0 и будьте готовы потратить свой вечер на поиск решений проблем, возникших в устаревших модулях PHP. Напоследок интересный факт: поддержка PHP 7.0 была прекращена раньше, чем поддержка PHP 5.6. На секундочку.


А как дела с этим обстоят у NodeJS? Я бы не сказал, что здесь всё значительно лучше и что сроки поддержки у NodeJS кардинально отличаются от PHP. Нет, здесь всё примерно так же — каждая LTS-версия поддерживается в течение 3 лет. Вот только у NodeJS немного больше этих самых актуальных версий.


Используемые в текущее время версии NodeJS


Если у вас возникнет необходимость развернуть приложение, написанное в 2016 году, то будьте уверены, что у вас не будет с этим совершенно никаких проблем. Кстати говоря, версия 6.* перестанет поддерживаться только в апреле этого года. А впереди ещё 8, 10, 11 и готовящаяся 12.


О трудностях и сюрпризах при переходе на NodeJS


Начну, пожалуй, с самого волнующего меня вопроса о том, как же всё-таки рендерить HTML-страницы в NodeJS. Но давайте для начала вспомним, как это делается в PHP:


  1. Встраивать HTML напрямую в PHP-код. Так делают все новички, кто ещё не добрался до MVC. И так сделано в WordPress, что категорически ужасающе.
  2. Использовать MVC, что как бы должно упростить взаимодействие разработчика и обеспечить какое-то разбиение проекта на части, но на деле этот подход лишь усложняет всё в разы.
  3. Использовать шаблонизатор. Наиболее удобный вариант, но не в PHP. Просто посмотрите синтаксис, предлагаемый в Twig или Blade с фигурными скобками и процентами.

Я являюсь ярым противником совмещения или слияния нескольких технологий воедино. HTML должен существовать отдельно, стили для него — отдельно, JavaScript-отдельно (в React это вообще выглядит чудовищно — HTML и JavaScript вперемешку). Именно поэтому идеальный вариант для разработчиков с предпочтениями как у меня — шаблонизатор. Искать его для веб-приложения на NodeJS долго не пришлось и я сделал выбор в пользу Jade (PugJS). Просто оцените простоту его синтаксиса:


    div.row.links
        div.col-lg-3.col-md-3.col-sm-4
            h4.footer-heading Флот.ру
            div.copyright
                div.copy-text 2017 - #{current_year}  Флот.ру
                div.contact-link
                    span Контакты:
                        a(href='mailto:hello@flaut.ru') hello@flaut.ru

Здесь всё достаточно просто: написал шаблон, загрузил его в приложение, скомпилировал один раз и далее используешь в любом удобном месте в любое удобное время. По моим ощущениям, производительность PugJS примерно в 2 раза лучше, чем рендеринг с помощью внедрения HTML в PHP-код. Если раньше в PHP статическая страница генерировалась сервером примерно за 200-250 миллисекунд, то теперь это время составляет примерно 90-120 миллисекунд (речь идёт не о самом рендеринге в PugJS, а о времени, затраченном от запроса страницы до ответа сервера клиенту с готовым HTML). Так выглядит загрузка и компиляция шаблонов и их компонентов на стадии запуска приложения:


const pugs = {}

fs.readdirSync(__dirname + '/templates/').forEach(file => {
    if(file.endsWith('.pug')) {
        try {
            var filepath = __dirname + '/templates/' + file
            pugs[file.split('.pug')[0]] = pug.compile(fs.readFileSync(filepath, 'utf-8'), { filename: filepath })
        } catch(e) {
            console.error(e)
        }
    }
})

// и далее рендеринг уже скомпилированного шаблона
return pugs.tickets({  ...config })

Выглядит невероятно просто, но с Jade возникла небольшая сложность на этапе работы с уже скомпилированным HTML. Дело в том, что для внедрения скриптов на странице используется асинхронная функция, которая забирает все .js файлы из директории и добавляет к каждому из них дату их последнего изменения. Функция имеет следующий вид:


for(let i = 0; i < files.length; i++) {
    let period = files[i].lastIndexOf('.') // get last dot in filename
    let filename = files[i].substring(0, period)
    let extension = files[i].substring(period + 1)

    if(extension === 'js') {
        let fullFilename = filename + '.' + extension
        if(env === 'production') {
            scripts.push({ path: paths.production.web + fullFilename, mtime: await getMtime(paths.production.code + fullFilename)})
        } else {
            if(files[i].startsWith('common') || files[i].startsWith('search')) {
                scripts.push({ path: paths.developer.scripts.web + fullFilename, mtime: await getMtime(paths.developer.scripts.code + fullFilename)})
            } else {
                scripts.push({ path: paths.developer.vendor.web + fullFilename, mtime: await getMtime(paths.developer.vendor.code + fullFilename)})
            }
        }
    }
}

На выходе получаем массив объектов с двумя свойствами — путь к файлу и время его последнего редактирования в timestamp (для обновления клиентского кэша). Проблема в том, что ещё на этапе сбора файлов скриптов из директории они все загружаются в память строго по алфавиту (так они расположены в самой директории, а сбор файлов в ней осуществляется сверху вниз — от первого до последнего). Это приводило к тому, что сначала загружался файл app.js, а уже после него шёл файл core.min.js с полифиллами, и в самом конце — vendor.min.js. Решилась эта проблема достаточно просто — очень банальной сортировкой:


scripts.sort((a, b) => {
    if(a.path.includes('core.min.js')) {
        return -1
    } else if(a.path.includes('vendor.min.js')) {
        return 0
    }
    return 1
})

В PHP же это всё имело монструозный вид в виде заранее записанных в строку путей к JS-файлам. Просто, но непрактично.


NodeJS держит своё приложение в оперативной памяти


Это огромный плюс. У меня всё устроено так, что на сервере параллельно и независимо друг от друга существуют два отдельных сайта — версия для разработчика и production-версия. Представим, что я сделал какие-то изменения в PHP-файлы на сайте для разработки и мне нужно выкатить эти изменения на production. Для этого нужно останавливать сервер или ставить заглушку "извините, тех. работы" и в это время копировать файлы по отдельности из папки developer в папку production. Это вызывает какой-никакой простой и может вылиться в потерю конверсий. Преимущество in-memory application в NodeJS заключается для меня в том, что все изменения в файлы движка будут внесены только после его перезагрузки. Это очень удобно, поскольку можно скопировать все необходимые файлы с изменениями и только после этого перезагрузить сервер. Процесс занимает не более 1-2 секунд и не вызовет даунтайма.
Такой же подход используется в nginx, например. Вы сначала редактируете конфигурацию, проверяете её при помощи nginx -t и только потом вносите изменения с service nginx reload


Кластеризация NodeJS-приложения


В NodeJS есть очень удобный инструмент — менеджер процессов pm2. Как мы обычно запускаем приложения в Node? Заходим в консоль и пишем node index.js. Как только мы закрываем консоль — приложение закрывается. По крайней мере, так происходит на сервере с Ubuntu. Чтобы избежать этого и держать приложение запущенным всегда, достаточно добавить его в pm2 простой командой pm2 start index.js --name production. Но это ещё не всё. Инструмент позволяет проводить мониторинг (pm2 monit) и кластеризацию приложения.


Давайте вспомним о том, как организованы процессы в PHP. Допустим, у нас есть nginx, обслуживающий http-запросы и нам нужно передать запрос на PHP. Можно либо сделать это напрямую и тогда при каждом запросе будет спавниться новый процесс PHP, а при его завершении — убиваться. А можно использовать fastcgi-сервер. Думаю, все знают что это такое и нет необходимости вдаваться в подробности, но на всякий случай уточню, что в качестве fastcgi чаще всего используется PHP-FPM и его задача — заспавнить множество процессов PHP, которые в любой момент готовы принять и обработать новый запрос. В чём недостаток такого подхода?


Во-первых, в том, что вы никогда не знаете, сколько памяти будет потреблять ваше приложение. Во-вторых, вы всегда будете ограничены в максимальном количестве процессов, а соответственно, при резком скачке трафика ваше PHP-приложение либо использует всю доступную память и упадёт, либо упрётся в допустимый предел процессов и начнёт убивать старые. Это можно предотвратить, установив не-помню-какой-параметр в конфигурационном файле PHP-FPM в dynamic и тогда будет спавниться столько процессов, сколько необходимо в данное время. Но снова-таки, элементарная DDoS-атака выест всю оперативную память и положит ваш сервер. Или, например, багнутый скрипт съест всю оперативную память и сервер зависнет на какое-то время (были прецеденты в процессе разработки).


Кардинальное отличие в NodeJS заключается в том, что приложение не может потребить более чем 1,5 гигабайта оперативной памяти. Нет никаких ограничений по процессам, есть только ограничение по памяти. Это стимулирует писать максимально легковесные программы. К тому же очень просто рассчитать количество кластеров, которые мы можем себе позволить в зависимости от имеющегося ресурса CPU. Рекомендуется на каждое ядро "вешать" не более одного кластера (ровно как и в nginx — не более одного воркера на одно ядро CPU).


Кластеризация в PM2


Преимущество такого подхода ещё и в том, что PM2 перезагружает все кластеры по очереди. Возвращаясь к предыдущему абзацу, в котором говорилось о 1-2 секундном даунтайме при перезагрузке. В Cluster-Mode при перезагрузке сервера ваше приложение не испытает ни миллисекунды даунтайма.


NodeJS — это хороший швейцарский нож


Ныне сложилась такая ситуация, когда PHP выступает в качестве языка для написания сайтов, а Python выступает в качестве инструмента для краулинга этих самых сайтов. NodeJS — это 2 в 1, с одной стороны вилка, с другой — ложка. Вы можете писать быстрые и производительные приложения и веб-краулеры на одном сервере в пределах одного приложения. Звучит заманчиво. Но как это может быть реализовано, спросите вы? Сама компания Google выкатила официальное API с Chromium — Puppeteer. Вы можете запускать Headless Chrome (браузер без интерфейса пользователя — "безголовый" Chrome) и получить максимально широкий доступ к API-браузера для обхода страниц. Максимально просто и доступно о работе Puppeteer.


Например, в нашей группе ВКонтакте происходит регулярный постинг скидок и специальных предложений на различные направления из городов СНГ. Мы генерируем изображения для постов в автоматическом режиме, а чтобы они были ещё и красивыми — нам нужны красивые картинки. Я не любитель подвязываться на различные API и заводить на десятках сайтов аккаунты, поэтому я написал простое приложение, имитирующее обычного пользователя с браузером Google Chrome, который ходит по сайту со стоковыми картинками и забирает случайным образом изображение, найденное по ключевому слову. Раньше для этого я использовал Python и BeautifulSoup, но теперь в этом отпала необходимость. А самая главная особенность и преимущество Puppeteer заключается в том, что вы можете с лёгкостью краулить даже SPA-сайты, ведь вы имеете в своём распоряжении полноценный браузер, понимающий и исполняющий JavaScript-код на сайтах. Это до боли просто:


const browser = await puppeteer.launch({headless: true, args:['--no-sandbox']})
const page = (await browser.pages())[0]
await page.goto(`https://pixabay.com/photos/search/${imageKeyword}/?cat=buildings&orientation=horizontal`, { waitUntil: 'networkidle0' })

Вот так в 3 строчки кода мы запустили браузер и открыли страницу сайта со стоковыми изображением. Теперь мы можем выбрать случайный блок с изображением на странице и добавить к нему класс, по которому в дальнейшем сможем точно так же обратиться и уже перейти на страницу непосредственно с самим изображением для его дальнейшей загрузки:


var imagesLength = await page.evaluate(() => {
    var photos = document.querySelectorAll('.search_results > .item')

    if(photos.length > 0) {
        photos[Math.floor(Math.random() * photos.length)].className += ' --anomaly_selected'
    }

    return photos.length
})

Вспомните, сколько бы потребовалось кода, чтобы написать подобное на PhantomJS (который, кстати, закрылся и вступил в тесное сотрудничество с командой разработки Puppeteer). Разве наличие такого чудесного инструмента может остановить кого-нибудь от перехода к NodeJS?


В NodeJS заложена асинхронность на фундаментальном уровне


Это можно считать огромным преимуществом NodeJS и JavaScript, особенно с приходом async/await в ES2017. В отличии от PHP, где любой вызов выполняется синхронно. Приведу простой пример. Раньше у нас в поисковике страницы генерировались на сервере, но кое-что нужно было выводить на страницу уже в клиенте с помощью JavaScript, а на тот момент Яндекс ещё не умел в JavaScript на сайтах и специально для него пришлось реализовывать механизм снапшотов (снимков страниц) при помощи Prerender. Снапшоты хранились у нас на сервере и выдавались роботу при запросе. Дилемма заключалась в том, что эти снимки генерировались в течение 3-5 секунд, что совершенно недопустимо и может повлиять на ранжирование сайта в поисковой выдаче. Для решения этой задачи был придуман простой алгоритм: когда робот запрашивает какую-то страницу, снимок которой у нас уже есть, то мы просто отдаём ему уже имеющийся у нас снимок, после чего "в фоне" выполняем операцию по созданию нового снимка и заменяем им уже имеющийся. Как это было делано в PHP:


exec('/usr/bin/php ' . __DIR__ . '/snapshot.php -a ' . $affiliation_type . ' -l ' . urlencode($full_uri) . ' > /dev/null 2>/dev/null &');

Никогда так не делайте.
В NodeJS этого можно добиться вызовом асинхронной функции:


async function saveSnapshot() {
    getSnapshot().then((res) => {
        db.saveSnapshot().then((status) => {
            if(status.err) console.error(err)
        })
    })
}

/**
 * И вызываем функцию без await
 * Т.е. не будем дожидаться resolve() от промиса
 */

saveSnapshot()

Вкратце, вы не пытаетесь обойти синхронность, а сами определяете, когда использовать синхронное выполнение кода, а когда асинхронное. И это действительно удобно. Особенно когда вы узнаете о возможностях Promise.all()


Сам движок поисковика авиабилетов устроен таким образом, что он отсылает запрос на второй сервер, собирающий и агрегирующий данные, и затем обращается к нему за уже готовыми к выдаче данными. Для привлечения трафика из органики используются страницы направлений.


Например, по запросу "Авиабилеты Москва Санкт-Петербург" будет выдана страница с адресом /tickets/moscow/saint-petersburg/, а на ней нужны данные:


  1. Цены авиабилетов по этому направлению на текущий месяц
  2. Цены авиабилетов по этому направлению на год вперёд (средняя цена по каждому месяцу для следующих 12 месяцев)
  3. Расписание авиарейсов по этому направлению
  4. Популярные направления из города отправки — из Москвы (для перелинковки)
  5. Популярные направления из города прибытия — из Санкт-Петербурга (для перелинковки)

В PHP все эти запросы выполнялись синхронно — один за другим. Среднее время ответа API по одному запросу — 150-200 миллисекунд. Умножаем 200 на 5 и получаем в среднем секунду только на выполнение запросов к серверу с данными. В NodeJS есть замечательная функция Promise.all, которая выполняет все запросы параллельно, но записывает результат поочерёдно. Например, так выглядел бы код выполнения всех пяти выше описанных запросов:


var [montlyPrices, yearlyPrices, flightsSchedule, originPopulars, destPopulars] = await Promise.all([
    getMontlyPrices(),
    getYearlyPrices(),
    getFlightSchedule(),
    getOriginPopulars(),
    getDestPopulars()
])

И получаем все данные за 200-300 миллисекунд, сократив время генерации данных для страницы с 1-1,5 секунд до ~500 миллисекунд.


Заключение


Переход с PHP на NodeJS помог мне ближе познакомиться с асинхронным JavaScript, научиться работе с промисами и async/await. После того, как движок был переписан, скорость загрузки страниц была оптимизирована и отличалась разительно от результатов, которые показывал движок на PHP. В этой статье можно было бы ещё рассказать о том, насколько просто используются модули для работы с кэшем (Redis) и pg-promise (PostgreSQL) в NodeJS и устроить сравнение их с Memcached и php-pgsql, но эта статья итак получилась достаточно объёмной. А зная мой "талант" к писательству, она получилась ещё и плохо структурированной. Цель написания этой статьи — привлечь внимание разработчиков, которые до сих пор работают с PHP и не знают о прелестях NodeJS и разработки веб-ориентированных приложений на нём на примере реально существующего проекта, который когда-то был написан на PHP, но из-за предпочтений своего владельца ушёл на другую платформу.


Надеюсь, что мне удалось донести мои мысли и более-менее структурировано изложить их в этом материале. По крайней мере, я старался :)


Пишите любые комментарии — доброжелательные или гневные. Буду отвечать на любой конструктив.

Комментарии (88)


  1. MeGaPk
    19.03.2019 15:46

    Зачем вы пересаживаетесь на новый ЯП не разобравшись с PHP? И после этого пишете статью диплом (с литром воды). Такое ощущение возникло, когда решение проблемы нагугливается легко. Хоть я и любитель в пхп программировании и новичок в JS, но:

    В PHP все эти запросы выполнялись синхронно — один за другим. Среднее время ответа API по одному запросу — 150-200 миллисекунд. Умножаем 200 на 5 и получаем в среднем секунду только на выполнение запросов к серверу с данными. В NodeJS есть замечательная функция Promise.all, которая выполняет все запросы параллельно, но записывает результат поочерёдно. Например, так выглядел бы код выполнения всех пяти выше описанных запросов:

    php.net/curl_multi_init

    В NodeJS заложена асинхронность на фундаментальном уровне

    callbackhell.com


    1. smarthomeblog
      19.03.2019 16:01
      +1

      callbackhell.com


      лечится промисами


      1. t_kanstantsin
        20.03.2019 15:10

        А ещё есть Promise hell :)


        1. smarthomeblog
          20.03.2019 16:08

          Я подозреваю, что количество hell-ов в PHP просто может зашкаливать ;)


    1. Djeux
      19.03.2019 16:02
      +1

      Зачем вы пересаживаетесь на новый ЯП не разобравшись с PHP?

      Потому что php модно закидывать говном ;)


    1. Carduelis
      19.03.2019 16:13

      Ну про callbackhell модно было говорить лет 5 назад. Это подмножество лапшевидного кода, который может состоять из простых и вложненных условий `if {} else {}`, которые присущи любому языку. Как и в случае с вложенными условными операторами, callbackhell можно упрощать.

      В целом, от статьи действительно сложилось впечатление: не разобрался с ЯП1 перехожу на ЯП2, всем советую.

      Но человек учится, делится опытом, комментарии появляются, энтропия растет. Всем хорошо.


    1. JamesJGoodwin Автор
      19.03.2019 16:16

      callbackhell.com

      Похоже, что вы совсем не знакомы с async/await :)


      php.net/curl_multi_init

      Сами http-запросы можно выполнить параллельно, но с данными все равно придётся работать поочерёдно. В Node с помощью Promise.all() можно вызывать асинхронные функции, которые обратятся к кэшу, при необходимости сделают запрос и вернут уже готовый результат целого ряда действий, а не просто массив данных с ответом от удалённого сервера.


      1. akeinhell
        19.03.2019 22:04

        Похоже, что вы совсем не знакомы с async/await

        похоже вы не знакомы с отладкой и трейсами которые он порождает :-)

        Я сам все пишу уже на async/await, но на бою осознать где именно упало не всегда является тривиальной задачей


        1. JamesJGoodwin Автор
          19.03.2019 22:58
          +1

          Обычно же достаточно завернуть потенциально опасный блок в try catch и в catch сделать console.trace()


          1. jhonyxakep
            20.03.2019 20:05

            Особенно когда падает неизвестно где


    1. Suvitruf
      19.03.2019 16:18
      -1

      Занятно, что вы набросились на человека за то, что он «пересаживается на новый ЯП не разобравшись с PHP», при этом пишете про callbackhell, которого уже много лет как нет в ноде.


  1. zzzmmtt
    19.03.2019 15:57
    +2

    Статья и серии «Я не освоил PHP + CI/CD поэтому пересел на ноду».
    Проблемы с даунтаймом при апргрейде сайта на php решаются парой строк sh-скрипта + git.
    Есть сторонние инструменты, типа того же jenkins.
    По поводу асинхронности, если не путаю, reactphp.
    Композер да, иногда упирается в оперативу. Но никто не запрещает в тестовом окружении установить пакеты и зааплоадить вместе с автолоадером на сервак, хоть это и не очень правильно. Да и NPM не безгрешен.


    1. JamesJGoodwin Автор
      19.03.2019 16:07
      -1

      Дело в том, что все вышеперечисленные проблемы в PHP так или иначе решаются с помощью различных надстроек, на изучение которых нужно тратить время. Лучше потратить это драгоценное время написание кода с использованием нативных инструментов.


      1. TheYellingChives
        19.03.2019 17:40
        +4

        Лучше потратить это драгоценное время написание кода с использованием нативных инструментов.

        Знание о которых вы впитали в себя с молоком матери или что?
        Драгоценное время вы потратили на написание этой статьи например…


        1. JamesJGoodwin Автор
          19.03.2019 17:59
          -1

          Документация по нативным инструментам собрана в одном месте — на сайте NodeJS, где приведены исчерпывающие примеры. На PHP.net есть полным-полно примеров, которые заминусили и которые однозначно нельзя использовать в теперешнее время. Большинство проблем в PHP решается с помощью поиска ответов на StackOverflow, где тоже нужно вчитываться в текст и переводить его с английского, что, опять-таки, для меня совершенно не проблема, но для новичков без знания английского от этого станет больно.


          1. Ashot
            19.03.2019 19:12
            +4

            Большинство проблем в PHP решается с помощью поиска ответов на StackOverflow

            Так решается большинство проблем независимо от ЯП – хоть PHP, хоть JS. И ничего плохого, в этом, кстати, нет. Вполне себе такой нормальный кейс: не знаешь/не понимаешь как решить проблему, гуглишь, и с большой долей вероятности попадаешь на stackoverflow с решением проблемы, PHP тут не при чём от слова совсем.


            1. vladkorotnev
              20.03.2019 11:35
              +2

              Причём в JS можно ещё и сократить зазор во времени между поломкой кода и поиском решения :-)

              try {
              myBusinessLogic();
              } catch (e) {
              window.open('https://stackoverflow.com/?q=[js] '+e.message);
              }


      1. zzzmmtt
        19.03.2019 17:56
        +1

        С консолью линукса/юникса знакомы? Команда mv вам известна? А git pull? Эти сторонние инструменты вы в разработке не используете?


        1. JamesJGoodwin Автор
          19.03.2019 18:01
          -5

          С консольными инструментами не всегда удобно работать. Например, на 13-дюймовом ноутбуке. Для этого больше подходят решения с визуальным интерфейсом, например GitLab, который можно установить на свой виртуальный сервер и создать там закрытый репозиторий. Я бы так и сделал, но меня вполне устраивает текущий вариант деплоя. Учитывая, что я один единственный разработчик в этом проекте :)


          1. zzzmmtt
            19.03.2019 18:51

            Так в консоли то деплой можно заскриптовать на один алиас, что вам, как единственному разработчику на проекте сильно упростит жизнь)


          1. Free_ze
            19.03.2019 19:02
            +2

            С консольными инструментами не всегда удобно работать. Например, на 13-дюймовом ноутбуке.

            Чем вам мешает небольшая диагональ? Это GUI обычно грешат тем, что кнопки то не вмещаются, то сжимаются так, что нажать невозможно. А текст — есть текст, CLI пришел к нам из тех времен, когда 13" с разрешением хотя бы в 1024х768 было мечтой. Лишь бы адекватная клавиатура была.


          1. arkamax
            19.03.2019 20:22

            С консольными инструментами не всегда удобно работать. Например, на 13-дюймовом ноутбуке.

            Замечу, что консольные инструменты обычно намного проще и дешевле автоматизировать (и контролировать), что в продакшене дает экономию средств и ресурсов. Удобство деплоя через GUI очень быстро затирается неудобством поддержки и автоматизации дальнейшей эксплуатации (тестирования, обновлений, итп), и наоборот. А если вам неудобен 13-дюймовый экран (мне кстати тоже) — купите 15-дюймовый. В долгосрочном плане техника не должна быть основным критерием того, насколько эффективно вы будете решать проблемы клиентов / работодателя.


          1. vladkorotnev
            20.03.2019 11:38

            13" неудобно для консоли? Вы Gitkraken через elinks открыть пытаетесь что ли?

            На печально известном 7-дюймовом EEE PC 701 как раз наоборот в чисто консольном режиме только и было можно работать, иначе слишком мало места получалось.

            И причём тут гитлаб, который к командам консоли вообще никаким местом не связан?


          1. roscomtheend
            20.03.2019 12:20

            С консольными инструментами не всегда удобно работать. Например, на 13-дюймовом ноутбуке.

            Удобная консоль с дозированным выводом менее удобна, чем визуальный интерфейс, где то разъезжается, то не влезает из-за размера? Вот это сюрприз.
            Не удивительно что подобный разработчик не осили деплой в копию и переключение рабочего каталога сервера запуском одного скрипта (которое ещё и прозрачно для пользователя). Мышкой тыкать, конечно, удобнее (с возможностью что-то забыть или ошибиться).


    1. SerafimArts
      19.03.2019 17:46

      По поводу асинхронности, если не путаю, reactphp.


      Лучше всё же AMP или Swoole.


      1. zzzmmtt
        19.03.2019 17:58

        Возможно. Необходимости пока не было, но спасибо за наводку.


  1. NickyX3
    19.03.2019 16:02

    Вернёмся к тому проекту, где вылетала установка зависимостей. Это был проект, написанный в 2015 году на Laravel 4 с PHP 5.6. Казалось, прошло же всего 4 года, ан-нет — куча deprecation-предупреждений, устаревшие модули, невозможность нормально обновиться до Laravel 5 из-за кучи корневых обновлений движка.

    Вот поэтому я не люблю фреймворки и вот это все.
    P.S> свой велосипед, написанный еще под 5.3 пережил переезд через 5.6 до 7.2 без deprecation/warning


    1. SerafimArts
      19.03.2019 17:55
      +1

      Laravel 4 тоже полностью совместим с 7.0+. То, что автор поста нашёл какие-то проблемы — это результат создания этих проблем, либо самим автором, либо кем-либо ещё. Да и вообще я могу вспомнить только одну ошибку, связанную с OS библиотеками и версиями языка — это где-то в недрах доктрины switсh + continue использовался.


    1. arkamax
      19.03.2019 20:08

      свой велосипед, написанный еще под 5.3 пережил переезд через 5.6 до 7.2 без deprecation/warning

      Так часто бывает, если велосипед писался с умом и пониманием. Вот только это не отменяет проблем, связанных с безопасностью, масштабируемостью, итп — на небольших проектах это не проблема, но как только проект растет, велосипеды начинают падать. Не все, но статистика не в их пользу. P.S. Говорю с позиции «опытного» велосипедиста.


  1. fijj
    19.03.2019 16:02

    Это огромный плюс. У меня всё устроено так, что на сервере параллельно и независимо друг от друга существуют два отдельных сайта — версия для разработчика и production-версия. Представим, что я сделал какие-то изменения в PHP-файлы на сайте для разработки и мне нужно выкатить эти изменения на production. Для этого нужно останавливать сервер или ставить заглушку «извините, тех. работы» и в это время копировать файлы по отдельности из папки developer в папку production. Это вызывает какой-никакой простой и может вылиться в потерю конверсий.

    Я прям представил картину, как вы пишите код в «ide» хостинга:), потом руками переносите все измененные файлы на продакшен, предварительно записывая в блокноте измененные файлы, что бы ничего не забыть. Хотя раз вы от php плюетесь, git наверное вам не стоит предлагать


    1. JamesJGoodwin Автор
      19.03.2019 16:26

      Я прям представил картину, как вы пишите код в «ide» хостинга:), потом руками переносите все измененные файлы на продакшен

      На самом деле, все примерно так и происходит :)


      Я хотел использовать git, но так сложилось, что я немножечко параноик и опасаюсь загружать код в удалённый доступ. Смотрел в сторону GitLab, но он не понравился мне вот совсем. Да и держать 4 разных репозитория на двух машинах тоже может быть затратно.


      1. Suvitruf
        19.03.2019 16:29

        Вы гит можете хостить сами, необязательно заливать на gitlab или ещё куда.


      1. zzzmmtt
        19.03.2019 18:01
        +2

        Не гитхабом единым гит жив. Свой реп гита хранить можно где вам удобно, обвешать все шифрованием по желанию и не переживать, что кто-то увидит ваш код.


      1. Zibx
        20.03.2019 00:01

        Коллега! Тоже не люблю давать другим смотреть на свои тайные форичи и проверки на нулл!


  1. edogs
    19.03.2019 16:10
    +1

    Вы, возможно, правы, и возможно, NodeJS действительно круче.
    Но Ваша аргументация против php имеет тот недостаток, что она основывается на поверхностном знании php.
    Вы сами об этом пишите в начале

    Во время написания движка я использовал простейшие техники. Никаких менеджеров пакетов, никакого роутинга.
    .
    Дальше вот по этому поводу

    На самом деле, это не было бы придиркой и я бы не отнёс это к причинам моего ухода от PHP, если бы написанные мной проекты на PHP 7.0.* уже сейчас не вызывали deprecation warning при открытии.

    У нас некоторые проекты написанные на php 4.0 (на 4-ке, не на 5, не на 7) до сих пор работают без проблем. Многие (Не все) проблемы с совместимостью в php были вызваны использованием того, чего использовать не стоило. Самый простой пример с magic quotes и global variables — ах они стали deprecated, какой ужас. Но это проблема правильного программирования, а не языка пхп.

    Попробуйте взять любое приложение на PHP, написанное во времена активной поддержки первых версий PHP 7.0 и будьте готовы потратить свой вечер на поиск решений проблем, возникших в устаревших модулях PHP
    Как мы уже упомянули выше — крайне мало вещей стали deprecated из тех, которые был разумно использовать. Тем не менее для поиска остальных вещей и их исправления — много времени не потребуется, есть анализаторы php проектов указывающих на проблемы и их решения.

    Дальше, шаблонизаторы. Не будем трогать аргументацию по поводу «нативный пхп ад», с которой мы не согласны. но это слишком холиварно. Ответим лишь на это
    Использовать шаблонизатор. Наиболее удобный вариант, но не в PHP. Просто посмотрите синтаксис, предлагаемый в Twig или Blade с фигурными скобками и процентами.
    Во-первых, для php есть смарти. Который до кучи компилирует шаблоны, из-за чего получается отличный симбиоз скорости и удобства (при правильном использовании). И при чем считается почти стандартом, как можно было о нем не знать?
    Во-вторых, Вы пожаловавшись на «фигурные скобки и проценты», тут же приводите в качестве эталона пример шаблонизатора с «фигурными скобками и решеткой» #{current_year} — о_О?!

    Дальше «NodeJS держит своё приложение в оперативной памяти» и особенно
    Представим, что я сделал какие-то изменения в PHP-файлы на сайте для разработки и мне нужно выкатить эти изменения на production. Для этого нужно останавливать сервер или ставить заглушку «извините, тех. работы» и в это время копировать файлы по отдельности из папки developer в папку production
    Тут Вы дважды не правы.
    Во-первых, так как Вы выкатывали проекты проекты на пхп — так не делает вообще никто. никто не ставит заглушку и не копирует файлы по отдельности, Вы выбрали крайне кривой способ деплоя, а ругаете почему-то за это язык.
    Во-вторых, на пхп тоже по сути возможно " in-memory application ", достаточно включить опкэш без проверки таймстампов файлов и вуаля — без принудительного рефреша будет работать тот пхп который закэшировался в памяти, при чем уже из скомпилированного байт-кода.

    Дальше по поводу «Кластеризация NodeJS-приложения».
    Во-первых в пхп есть варианты ограничений — Вы просто с ними не знакомы, т.е. опять же, проблема не в пхп, проблема в Вашем знании вопроса.
    Во-вторых называть это ограничение NodeJS (если оно есть) преимуществом " приложение не может потребить более чем 1,5 гигабайта оперативной памяти. " это что-то из твиттерофилии с его 160 знаками. А если хочется обработать в памяти 2гб данных? Мы же не в нулевых, что бы «1.5гб достаточно для каждого».

    В целом как итог.
    Мы безусловно не спорим с тем, что NodeJS в чем-то лучше PHP.
    Но Ваша критика на 80% проистекает из неглубокого знания пхп и практик работы с ними.

    p.s.: Черт, пока писали телегу, сверху уже выразили то же самое, но намного короче «Статья и серии Я не освоил PHP + CI/CD поэтому пересел на ноду»© и «вы пересаживаетесь на новый ЯП не разобравшись с PHP»© Надо обновлять перед отправкой комментов:\


    1. MeGaPk
      19.03.2019 16:24

      Классный ответ, было интересно почитать и обновить свои познания в php. Спасибо!
      P/S: Плюсы ставить не могу.


      1. zzzmmtt
        19.03.2019 18:05

        Осторожнее с опкешем, это все ж не волшебная палочка ;)


    1. JamesJGoodwin Автор
      19.03.2019 17:50
      +1

      Дело в том, что PHP сам по себе — это не плохой инструмент. Он очень прост на этапе освоения. Его проблема заключается в том, что когда вы начинаете хоть сколь-нибудь углубляться в его познании, вам постоянно приходится устанавливать какие-то вспомогательные инструменты. В итоге проект становится сравним с панельной многоэтажкой с кучей пристроек и хаотично застеклённых/утеплённых балконов, разного цвета и формы кондиционеров и спутниковых тарелок".

      анализаторы php проектов указывающих на проблемы и их решения

      включить опкэш без проверки таймстампов файлов и вуаля

      в пхп есть варианты ограничений — Вы просто с ними не знакомы


      Вы просто не можете писать код, потому что будете заняты бесконечным чтением документации, вычитыванием форумов и StackOverflow. Чтобы заставить работать какую-то вещь, нужно сначала поковырять исходники, почитать кучу документации (читайте — перелопатить стог сена в поисках иглы).

      В NodeJS вы просто садитесь писать код и пишете его без оглядки, исправляя выявленные проблемы уже на этапе тестирования. И решаете вы их быстро потому, что пишете код с использованием нативных инструментов, которые просто работают.

      Но Ваша аргументация против php имеет тот недостаток, что она основывается на поверхностном знании php


      Если подытожить, то, в моём случае, это незнание обусловлено не ленью (даже осознавая тот факт, что я ленивый), а нежеланием проводить целые вечера за чтением литературы и в попытках заставить работать то, что должно было бы работать «из коробки», вместо того, чтобы заниматься тем, что действительно интересно — писать код и реализовывать алгоритмы.


      1. TheYellingChives
        19.03.2019 18:02

        чтобы заниматься тем, что действительно интересно — писать код и реализовывать алгоритмы.

        Дело в том, что если говорить о «писать код и реализовывать алгоритмы», то никаких «надстроек» и «вспомогательных инструментов» для PHP не требуется.


        1. JamesJGoodwin Автор
          19.03.2019 18:06

          Ну вы уж что-то совсем утрируете. При написании кода очень часто возникает необходимость что-то установить, но в NodeJS эта необходимость возникает значительно реже. И на PHP чаще всего вы не сможете решить проблему самостоятельно и будете именно вынуждены обратиться к вспомогательным инструментам.


          1. TheYellingChives
            19.03.2019 18:29
            -1

            При написании кода очень часто возникает необходимость что-то установить

            Вы что-то делаете не так.


          1. frostspb
            19.03.2019 22:32
            +2

            видели ли вы когда-нить папку node_modules? её размер и кол-во файлов? Это вопрос к ТС


      1. zzzmmtt
        19.03.2019 18:10

        Извините, не буду приводить цитаты из вашего комментария, отвечу кратко. Вы IDE пользуетесь при разработке на ноде? Я вот пользуюсь phpstorm, и он из коробки поддерживает и базовый анализ кода, а если поставить плагин(из настроек самого шторма), так ещё и статанализ будет.
        Опкеш — не сторонний инструмент, это часть пхп, при этом описана в документации.
        Для беспроблемной разработки на php достаточно официальной документации и понимания основ ООП(да и то не обязательно, можно и в процедурном стиле шпарить).


        1. JamesJGoodwin Автор
          19.03.2019 19:30

          Ну вот опять. Мне для работы с Node достаточно VS Code без каких-либо плагинов вообще. Для работы с PHP нужно ещё устанавливать целую IDE.


          1. arkamax
            19.03.2019 20:13

            VSCode в среднем не более и не менее IDE, чем PHPStorm. И вообще, не использовать IDE с мало-мальским анализом кода на данный момент (при ее наличии и доступности) в серьезной работе — ИМХО стоит где-то между чрезвычайной самоуверенностью и профессиональным саботажем. Мы не роботы, и делаем ошибки, которые машине легко подсветить, и в результате сделать наш продукт лучше.


          1. zzzmmtt
            19.03.2019 23:14

            Для работы с php не нужно устанавливать целую IDE. Есть же sublime, notepad++, far+colorer… Мой коллега вон пишет на пыхе в vim, при этом в макоси. Но мне лично комфортнее работать в IDE.


          1. SerafimArts
            22.03.2019 04:17

            Ну вот опять. Мне для работы с Node достаточно VS Code без каких-либо плагинов вообще. Для работы с PHP нужно ещё устанавливать целую IDE.


            Это предложение звучит как: «Ну вот опять. Мне для написания HTML достаточно блокнота без каких-либо редакторов и интерпретаторов вообще. А для работы с нодой нужно устанавливать целую ноду и vs code».

            На такой тезис можно ответить, либо грубо, вроде «вырастешь — поймёшь зачем нужны серверные ЯП (в вашем случае IDE)», либо пройти мимо, заметив, что «это всё не обязательно, только ничего кроме хоумпейджей на голом HTML не запилить».


      1. SerafimArts
        19.03.2019 18:21
        +2

        В NodeJS вы просто садитесь писать код и пишете его без оглядки, исправляя выявленные проблемы уже на этапе тестирования. И решаете вы их быстро потому, что пишете код с использованием нативных инструментов, которые просто работают.


        Это даже не смешно. Нода — эта та платформа, где надо установить гигабайты всякого софта, чтобы просто начать работать, начиная с cygwin и конфигурирования mingw g++/gcc для компиляции какого-нибудь sass, заканчивая установкой тех же самых линтеров и какого-нибудь puppeteer для тестов, а потом резко влетаем в компиляцию ассетов и начинаются конфиги вебпака (потому что стандарт), скрещенные с ужом поверх гулпа (потому что тогда вебпака не было), с инклудами на бауере (ладно, тут я перегибаю, простите), которые через одно место собирают TypeScript (так сейчас модно), вмерживая туда Coffee (так было модно), и параллельно прогоняя остатки JS через babel со stage-0 (ну мы думали эти декораторы зарелизятся...).

        Хм, кажется я перечислил дефолтный стек среднестатистического проекта на JS, да?

        Нода — это чёртов хаос из конфигов и настроек. На ней невозможно просто так взять и начать писать. Да блин, тот же express поставить надо же… А там зависимости подсасываются, а там какой-нибудь, наверняка, задепрекейченный vanilla stream… И всё заново, начинается скачки по жёсткому захардкоживанию версий в package.json.


        1. Ashot
          19.03.2019 19:23

          Ну вы уж совсем утрируете.


          чтобы просто начать работать, начиная с cygwin и конфигурирования mingw g++/gcc

          Издержки windows – на юникс системах просто ставишь nodeJS и уже можно работать.
          Да и когда я в последний раз устанавливал ноду на win, то всё ограничилось запуском установщика.


          влетаем в компиляцию ассетов и начинаются конфиги вебпака

          А это уже скорее для фронта актуально, на сервере с этим много проще обстоят дела, как минимум можно обходиться без сборщиков и компиляций.


          Нода — это чёртов хаос из конфигов и настроек

          Но да, npm install очень частая команда, но это даже не необходимость а удобство – зачем изобретать велосипеды, если оно уже есть в npm?


          В общем, если этим часто пользоваться и привыкнуть, то не так уж всё и плохо.


          1. SerafimArts
            19.03.2019 19:44

            Ну в общем-то да, я утрировал и довольно сильно. С другой стороны по сравнению с PHP, где ничего вообще делать не надо и даже сервер из коробки идёт — оно так и выглядит.


            1. Zibx
              21.03.2019 14:15

              Из которой коробки? Помню для разработки на пхп под виндой обычно ставился целый wamp в котором частенько жил тот же cygwin, отдельный веб сервер, и база данных поселяющаяся в сервисах.


              1. zzzmmtt
                21.03.2019 15:31

                В версии 5.4 добавлен веб-сервер.


        1. JamesJGoodwin Автор
          19.03.2019 19:25

          Всё бы хорошо, но вы перечислили проблемы работы с frontend. А статья как раз о серверной разработке и никакие SASS и WebPack здесь совершенно ни при чём. Если говорить именно о сервере, то всё предельно просто — npm i dependency --save и работаете по документации.

          Если говорить о frontend, то здесь уже проблема не самой Node, а того, во что превратили frontend-разработку. Препроцессоры, транспиляторы, сборщики и целая куча фреймворков — всё это напоминает ту самую панельку с кучей пристроек и хаотично утеплённых фасадов.


          1. SerafimArts
            19.03.2019 19:46

            Всё бы хорошо, но вы перечислили проблемы работы с frontend. А статья как раз о серверной разработке и никакие SASS и WebPack здесь совершенно ни при чём. Если говорить именно о сервере, то всё предельно просто — npm i dependency --save и работаете по документации.


            Согласен, да. Но с другой стороны — это на порядки проще `composer i dependency`?


          1. staticlab
            20.03.2019 12:25

            А статья как раз о серверной разработке и никакие SASS и WebPack здесь совершенно ни при чём

            Компиляция шаблонов вполне ложится на сценарий работы WebPack. Вы, внезапно, вместо готового инструмента накостыляли собственный сборщик :)


      1. Warrangie
        20.03.2019 09:07

        В ваш комментарий вместо php можно поставить ноду и он будет точно так же выглядеть. Все вроде недовольство возникло только из-за "такого себе" уровня, как программиста.


        1. Warrangie
          20.03.2019 09:07

          Не могу отредактировать — "Всё ваше", а не "все вроде".


    1. xRay
      19.03.2019 20:04

      Еще есть twig который легче Smarty. Есть Blade.

      p.s. Привет :)


    1. trawl
      20.03.2019 05:23

      Во-первых, для php есть смарти. Который до кучи компилирует шаблоны, из-за чего получается отличный симбиоз скорости и удобства (при правильном использовании).

      Twig и Blade тоже компилируют шаблоны. Плюсом они умеют наследование шаблонов из коробки (не знаю, как в Smarty с этим сейчас, но раньше реализовывалось только расширениями)


  1. Ashot
    19.03.2019 17:28
    +3

    PHP уже окончательно ушёл в закат и уступил своё место NodeJS

    Да никуда PHP не ушёл и никому своё место не уступал – у каждого своя ниша. И долго ещё не уйдёт.
    Как уже писали выше, вы не смогли в PHP, но вам зашёл nodeJS. Могу добавить ещё один стандартный комментарий к подобным постам: ЯП/фреймворк/платформа/etc – это инструмент, какие-то инструменты подходят лучше для одних задач, что-то лучше для других задач. В этом свете слова "окончательно ушёл в закат" звучат несколько громко.


    А в NodeJS есть свой собственный менеджер пакетов — npm

    npm такой же собственный для nodeJS, как и composer для PHP. Оба просто стали стандартным пакетным менеджером для своего языка. npm просто устанавливается сразу с nodeJS.


    1. alsii
      20.03.2019 00:33

      это у php composer стандартный. Для node есть еще как минимум yarn.


  1. iiifx
    19.03.2019 17:50
    +3

    Автор, я даже немножко рад, что вы ушли с PHP. Заранее приготовьте ЯП, в который вы пойдете после очередного разочарования. И да, хреновый с вас программист, вы уж простите за прямоту.


    1. JamesJGoodwin Автор
      19.03.2019 17:53
      -3

      Я уже присматриваю себе Go :) Возможно, через несколько лет Google приведёт его в порядок (что очень вероятно) и если я поборю нетерпимость к ООП (что находится за рамками возможного) — уйду в Golang.


      1. MikhailMKZ
        19.03.2019 18:38

        если я поборю нетерпимость к ООП

        В Go нет ООП в классическом понимании (с наследованием через классы). Там нет классов, только структуры и интерфейсы. Почитайте про подход Favor composition over inheritance, он в JS очень популярен. Ну и хорошее видео для понимания www.youtube.com/watch?v=wfMtDGfHWpA


      1. iiifx
        19.03.2019 19:36

        Я вам настоятельно рекомендую изучить ООП и все современные практики, которые используют его. В нем заключается колоссальная гибкость. Жаль, что вы опубликовали эту статью так и не разобравшись в языке и теперь она будет сбивать с толку других новичков.


      1. arkamax
        19.03.2019 20:16
        +2

        поборю нетерпимость к ООП

        ИМХО стоило бы очень серьезно попробовать. Профессионалу не стоит так резко отзываться о том, что подтвердило свою работоспособность для массы людей и миллиардов кейсов. Неприятие инструмента (даже если не единственного) попросту лишает вас еще одного способа решения клиентских задач, вот и все.


      1. zzzmmtt
        19.03.2019 23:15
        +1

        Вот тут вы мне сломали мозг. У вас нетерпимость к ООП, но вы пересели на ноду, в которой почти всё — объект, то бишь там волей-неволей будешь применять какие-нибудь ОО паттерны. Немного иначе чем в других ОО-ЯП, но всё же.


  1. JC_IIB
    19.03.2019 18:16

    возможно, через несколько лет Google приведёт его в порядок

    А что, по-Вашему, не в порядке с go?


    1. JamesJGoodwin Автор
      19.03.2019 18:59

      Очень часто встречаю от Golang программистов возмущения в адрес управления зависимостями. Нет конструкторов, неудобное управление ошибками. Это только то, что смог вспомнить.


  1. andreybotanic
    19.03.2019 18:16
    +2

    и я сделал выбор в пользу Jade (PugJS). Просто оцените простоту его синтаксиса

    Может это со мной что-то не так, но приведенный после этих слов фрагмент кода у меня вызывает отвращение. Это уже не верстка, но еще и не код. Это что-то иное. И даже на таком маленьком фрагменте это выглядит совершенно запутанно.
    При этом, столь ненавистный вам Twig довольно гармонично вписывается в HTML, не портя при этом его собственной структуры


    1. JamesJGoodwin Автор
      19.03.2019 19:13

      Ну это дело вкуса. Мне нравится, что нет необходимости открытия и закрытия тегов (это решено с помощью табуляции). Классы и идентификаторы как в CSS, а атрибуты указываются в скобках. Это очень минималистичный язык и это его основное преимущество.


      1. marsdenden
        20.03.2019 05:13

        Простота не всегда хорошо. Может наступить момент (и он наступит), когда эта простота не даст реализовать нечто очень нужное. И что тогда — очередной вопль "jade sucks!"?
        А вообще — во всем проглядывает юношеский максимализм. Осталось набраться опыта и прийти к пониманию, что и php хорош и нода хороша. Просто для кручения гаек отвертка плохо приспособлена, хотя зачастую и лежит рядом с гаечным ключом. Каждому инструменту свое применение.


  1. ligor
    19.03.2019 19:19

    Зато шаринг хостинги кругом с PHP, а вот с Node нет (хотя может и есть, специально не искал).


    1. marsdenden
      20.03.2019 05:16

      Дык кому охота заморачиваться? Это ж головняки какие будут у саппорта) Я бы не рискнул "даже за сто тыщ мильенов" (с) )))


  1. vasiljok
    19.03.2019 20:06

    Ждем статью — «Как я переписывал поисковик авиабилетов с NodeJS на Python» и конечно потом будет
    «Как я переписывал поисковик авиабилетов с Python на GoLang» и на последок
    «Как я переписывал поисковик авиабилетов с GoLang на Rust» ))))


  1. AlexTest
    19.03.2019 20:53
    +3

    В конце 2018 года… заказчик предоставил сервер с 1 ядром и 512 мегабайтами оперативной памяти
    Ну я бы с таким «щедрым» заказчиком работать не стал, если ему жалко пару копеек на нормальное железо, на секундочку, аж под целый «поисковик авиабилетов», то вполне логично, что его жаба давила и по оплате работы. В итоге был нанят студент. Так что тут проблема скорее всего в заказчике, а не в авторе статьи, хотя и автору все-таки стоило бы быть немного скромнее, чтобы не демонстрировать публично свою некомпетентность.


  1. Psih
    19.03.2019 21:53
    +2

    Я конечно извиняюсь, но я могу написать такую статью про любой язык программирования потратив день на его изучение и потом переключившись на любой другой язык — само собой оба языка должны подходить под задачу в целом.
    Вы бы хоть кому-то опытному на обзор дали бы прочитать прежде чем публиковать — в данной статье «прекрасно» всё — отсуствие опыта, отсуствие желания учится и разбираться, отсуствие оценки рисков и следование хайпу, самоуверенность, которой даже я позавидую со своими 14 годами в PHP разработке.


  1. zhulan0v
    19.03.2019 22:22
    +3

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


  1. Borro
    19.03.2019 22:37
    +3

    NPM и Composer.


    NPM много крови может попить, когда будет тянуть бинарные пакеты, а ещё может и начать собирать их у вас на виртуалочке.


    LTS


    Вы правильно написали, что и то и то поддерживается по 3 года и, если заметите, то LTS релизов ровно столько же, сколько у PHP, не LTS версии не используют в более-менее нормальных продашенах, они лишь для того чтобы посмотреть на функционал, пощупать его перед тем как выпустят нормальную LTS.


    Шаблонизатор


    Нравится вам лаконичный стиль, поискали бы на https://packagist.org/ нужный вам шаблонизатор. Вот 2, которые 1 в 1 как ваш Jade:



    "По моим ощущениям" — один из ужасных аргументов на хабре. Далее вы описываете всё время загрузки страницы, вместо сравнения шаблонизаторов.
    Вот как выглядит компиляция шаблонов в Twig:


    $loader = new \Twig\Loader\FilesystemLoader('/path/to/templates');
    $twig = new \Twig\Environment($loader, [
        'cache' => '/path/to/compilation_cache',
    ]);

    Не сложнее чем ваше.


    Про подключение JS я так и не понял, но это в вашем проекте всё просто и надо всего 2 файла загрузить сначала. Такую же функцию грабера всех JS файлов и функцию сортировки можно на любом ЯП сделать. Но вообще в фреймворках были средства, которые позволяют правильно подключать JS/CSS файлы.


    Деплой


    Про деплой — вы всё распаковываете в соседнюю директорию с вашим проектом, меняете конфиг в nginx и делаете его reload. Это один из способов, вообще есть и более правильные, но это тема отдельных статей, и вроде бы, когда-то давно на хабре проскакивали такие.


    Оперативная память


    С PHP-FPM всё так же просто. Вы ведите сколько памяти занимает 1 PHP-FPM (после нескольких заходов на разные страницы сайта), делите память, которую вам не жалко, на то, сколько занимает 1 процесс и получаете max_children, выше которого процессы размножаться не будут. Кстати, memory_limit и max_execution_time в PHP вам помогут не положить сервер, если вы накосячите в коде с временем выполнения и памятью.


    Швейцарский нож


    Я пишу разные консольные утилиты на PHP, писал грабберы, которые тоже в несколько потоков могут грабить сайты, асинхронно работать. Хотите Headless Chrome, его тоже можно запустить и управлять через PHP, слава богу API едино и слабо меняется от одного ЯП к другому. Вот вам и nesk/puphpeteer


    Асинхронность


    Тут, действительно, на JS изначально пишут асинхронно, поэтому у него больше пакетов. Но на PHP, так же есть возможность писать асинхронно. Вот хорошая подборка: https://github.com/elazar/asynchronous-php


    Пожелания


    Хотите что-то сравнить, разберитесь в каждом инструменте, либо найдите хорошего оппонента, который сможет на ваши выпады найти аргументы. Node.JS не плохой и не хороший, он просто другой с другой парадигмой. А вам желаю не терять огонь, с которым вы берётесь за работу, и больше углубляться в инструменты, которые помогут вам в будущем стать хорошим разработчиком. Читайте больше, ведь написание кода — это меньшая часть времени. Большая часть — это его отладка, изучение новых знаний, освоение новых инструментов и подходов.


    1. zhulan0v
      20.03.2019 06:37

      Про деплой — вы всё распаковываете в соседнюю директорию с вашим проектом, меняете конфиг в nginx и делаете его reload. Это один из способов, вообще есть и более правильные, но это тема отдельных статей, и вроде бы, когда-то давно на хабре проскакивали такие.


      Zero downtime deployment:
      1. Делаете директорию release-v1, в ней текущий релиз
      2. Делаете симлинк current на директорию release-v1
      3. Нужно выкатить новый релиз? Ок, делаете директорию release-v2
      4. Меняете симлинк current на release-v2
      5. Вуаля! Новый релиз задеплоился без остановки работы и троганья nginx.

      В случае проблем можно очень легко откатиться на предыдущую версию — просто обновить симлинк =)


      1. MetaDone
        20.03.2019 09:21

        собственно так и работает deployer


      1. Borro
        20.03.2019 09:32

        Тогда ещё не забыть почистить opcache. Про него хорошая статья была https://habr.com/ru/company/mailru/blog/310054/


      1. Djeux
        20.03.2019 10:21

        И если используется nginx, то не лишним будет использовать realpath_root, дабы избежать проблем с opcache.


  1. Dromok
    20.03.2019 12:22

    Разберитесь сначала с PHP, а потом уже пишите обличительные статьи. Абсолютно всё что написано в статье связано только с тем, что вы не разобрались «как его готовить». А уж не использовать систему управления версий (кстати, не обязательно git, хотя это и мейнстрим) скатывает вас на уровень самого начинающего джуниора, который только делает первые шаги в программировании.


    1. staticlab
      20.03.2019 12:27
      +1

      Для ТС просто git == github.


      И вообще, некогда изучать готовые инструменты и хорошие практики, нужно говнокодить, да побыстрее!


  1. de1vin
    20.03.2019 13:31

    О том, что от не знания одного языка программирования переходите на другой уже много написали.

    Без контроля версий, настроенного деплоя, линтера, фиксера и анализатора могут быть проблемы в не зависимости от языка.
    А так же из-за того, что вы никому не показываете свой код. Ревью — такой же инструмент для написания хорошего кода.


  1. evgwed
    20.03.2019 13:34

    Казалось, прошло же всего 4 года, ан-нет — куча deprecation-предупреждений, устаревшие модули, невозможность нормально обновиться до Laravel 5 из-за кучи корневых обновлений движка.

    Вы серьезно? Посмотрите в ту же nodeJS, там все еще быстрее устаревает.

    Для PHP это большой плюс, что язык обновляется при этом, стараясь не ломать обратную совместимость.


    1. SerafimArts
      20.03.2019 15:05

      Вы серьезно? Посмотрите в ту же nodeJS, там все еще быстрее устаревает.


      Самое весёлое — это когда ~год назад поломали синтаксис
      class A {
         *async a() { yield x; }
      }
      


      Заменив его на
      class A {
         async *a() { yield x; }
      }
      


      У меня тогда пол кода отвалилась после апдейта ноды. И при этом и в документации пустота, и гугл девственно чист.