| Введение в Node.js |
|
| Добавил(а) microsin | |||||||||||||||||||||||||||||||||||||||||||||
|
Node.js - кроссплатформенная среда выполнения JavaScript с открытым исходным кодом. Это популярный инструмент практически для любого проекта! Node.js использует JavaScript-движок V8, ядро Google Chrome, вне браузера. Это обеспечивает Node.js высокую производительность. Приложение Node.js работает в одном процессе, без создания нового потока для каждого запроса. Node.js предоставляет в своей стандартной библиотеке набор асинхронных примитивов ввода/вывода (asynchronous I/O), предотвращающие блокировку кода JavaScript. Кроме того, библиотеки Node.js в основном написаны в парадигме отсутствия блокировок. Соответственно, поведение блокировки в Node.js это исключение вместо нормы. Когда Node.js выполняет операцию I/O, наподобие чтения из сети, доступа к базе данных или файловой системе, вместо того чтобы блокировать поток и тратить циклы ЦП впустую, Node.js возобновляет операции после получения ответа. Эта особенность позволяет Node.js обрабатывать тысячи одновременных соединений с одним сервером без лишней головной боли по обслуживанию конкуренции многопоточности, что является значительным источником багов. Node.js обладает уникальным преимуществом, поскольку миллионы разработчиков интерфейсов, пишущих JavaScript для браузера, теперь могут писать код на стороне сервера в дополнение к коду на стороне клиента, без необходимости изучать совершенно другой язык. В Node.js новые стандарты ECMAScript могут использоваться без проблем, поскольку вам не нужно ждать, пока все ваши пользователи обновят свои браузеры — вы сами решаете, какую версию ECMAScript использовать, изменяя версию Node.js, а также можете включить определенные экспериментальные функции, запустив Node.js с флагами. Это две основные системы модулей в JavaScript, которые важно понимать для современной разработки. [CJS (CommonJS) — серверные модули] CommonJS — это стандарт модулей, созданный для Node.js (серверного JavaScript). Синтаксис CJS: // Импорт Характеристики CJS: - Синхронная загрузка — модули загружаются сразу [ESM (ECMAScript Modules) — современные модули] ESM — native-стандарт модулей для JavaScript, работающий и в браузерах, и в Node.js. Синтаксис ESM: // Импорт Характеристики ESM: - Асинхронная загрузка — модули загружаются по мере необходимости Сравнительная таблица:
[Практические примеры] CJS (типично для старых Node.js проектов): // math.js ESM (современные проекты, включая Vue): // math.js Vite по умолчанию использует ESM — это одна из причин его высокой скорости: // Vue компоненты используют ESM В файле package.json указывается тип модулей: {
[Проблемы совместимости] Смешивание модулей (обычно не рекомендуется): // ESM → CJS (работает) Решение — динамический импорт: // В CJS файле импортируем ESM [Почему ESM становится стандартом] 1. Универсальность — один стандарт для браузера и сервера В контексте инструментов сборки: - Vite — использует нативные ESM в разработке [Пример приложения Node.js] Традиционный общий Node.js пример Hello World это web-сервер: const { createServer } = require('node:http'); Чтобы запустить этот код, сохраните его как файл server.js, и запустите команду node server.js в терминале. Если вы используете mjs-версию кода, то нужно сохранить этот файл как server.mjs и выполнить команду node server.mjs. Различие между `.js` и `.mjs` файлами связано с системой модулей (см. выше врезку "Что такое CJS, ESM"). [`.js` файлы — стандартные JavaScript файлы] Поведение по умолчанию: - В Node.js трактуются как CommonJS (CJS) Пример server.js (CommonJS): const http = require('http'); [`.mjs` файлы — ES Modules файлы] Поведение: - Всегда трактуются как ESM (ECMAScript Modules) Пример server.mjs (ES Modules): import { createServer } from 'http'; Сравнение:
Node.js определяет тип модулей двумя способами. 1. По расширению файла (приоритетный способ). - `.mjs` → всегда ESM 2. Через package.json (для `.js` файлов) {
[Практические примеры] Сценарий 1: проект с "type": "module" package.json: {
Файловая структура: project/ Сценарий 2: проект без `"type": "module` (по умолчанию) package.json: {
Файловая структура: project/ [Проблемы совместимости] ❌ Смешивание модулей (ошибка): // server.mjs (ESM) ✅ Правильное смешивание: // server.mjs (ESM) В контексте Vue 3 + Vite, поэтому в проекте: // Все .vue и .js файлы используют ESM синтаксис Если бы вы писали серверную часть: // Рекомендуется для новых проектов - server.mjs [Рекомендации] 1. Новые проекты → используйте `"type": "module"` в package.json + `.js` файлы Вывод: расширение `.mjs` явно указывает Node.js использовать ESM систему модулей, что делает код более предсказуемым и современным. Для Vue-проекта это особенно актуально, так как вся современная фронтенд-экосистема движется в сторону ESM. Этот код сначала подключает Node.js-модуль http. В стандартной библиотеке Node.js есть множество продвинутых функций, включая отличную поддержку сетевого обмена. Метод createServer() модуля http создает, запускает новый HTTP-сервер и возвращает его экземпляр. Этот сервер настраивается на прослушивание определенного порта port на определенном имени hostname. Когда сервер готов к работе, будет вызвана callback-функция, информируя об этом пользователя. Всякий раз при поступлении нового запроса будет вызвано событие запроса (request event), с предоставлением двух объектов: запрос request (объект http.IncomingMessage) и ответ response (объект http.ServerResponse). Эти два объекта наиболее важные сущности для обработки вызовов HTTP. Первый предоставляет информацию о запросе. В этом простом примере он не используется, однако мог бы применяться для получения доступа к заголовкам запроса (request headers) и данным запроса (request data). Второй используется для возврата данных тому, кто выдал запрос. Для нашего простого примера это код состояния 200, означающий успешное выполнение запроса: res.statusCode = 200; Мы установили тип содержимого заголовка (Content-Type header): res.setHeader('Content-Type', 'text/plain'); И в завершение мы закрываем ответ, добавив содержимое ответа в качестве аргумента метода end(): res.end('Hello World\n');
[Что необходимо знать в JavaScript для использования Node.js?] При изучении JavaScript и Node.js новичку легко запутаться, где кончается одно и начинается другое, и наоборот. Для более глубокого погружения в Node.js рекомендуется ознакомиться со следующими темами: Lexical Structure Изучив эти концепции, вам откроется дорога профессиональной разработки на JavaScript, как в браузере, так и в Node.js. Асинхронное программирование. Следующие концепции являются ключевыми для понимания асинхронного программирования, они являются фундаментальными частями Node.js: Asynchronous programming and callbacks Понятие асинхронного программирования связано с многопоточностью и синхронизацией между потоками, когда внешние и внутренние события в программе обрабатываются специальными обработчиками событий. Асинхронное программирование - это подход, при котором операции могут выполняться независимо от основного потока выполнения программы, не блокируя его. Синхронное программирование подразумевает использование одного потока, когда в котором используются циклы ожидания и/или опроса для определения необходимости проведения различных операций. Синхронный код (блокирующий): console.log('Начало'); Асинхронный код (неблокирующий): console.log('Начало'); Где используется асинхронность: 1. Работа с сетью // Запросы к API, серверам fetch('/api/users') 2. Работа с файлами // Чтение/запись файлов fs.readFile('file.txt', 'utf8', (err, data) => { 3. Таймеры setTimeout(() => { console.log('Выполнилось через 2 секунды'); }, 2000); 4. Пользовательские события button.addEventListener('click', () => { [Механизмы асинхронности в JavaScript] 1. Callback-функции (старый подход) // "Callback hell" - сложная вложенность readFile('file1.txt', (err, data1) => { 2. Promise (Обещания) - современный подход readFile('file1.txt') 3. Async/Await - самый современный и читаемый async function readFiles() { [Event Loop (Цикл событий)] JavaScript имеет один основной поток, но асинхронность достигается через: ┌───────────────────────────┐ [Практический пример Vue 3] В Vue 3 компоненте: import { ref } from 'vue'; [Преимущества асинхронного программирования] 1. Не блокирует интерфейс - приложение остается отзывчивым. Ключевые концепции: - Неблокирующий код - программа продолжает работать во время ожидания. Вывод: асинхронное программирование — это фундаментальная концепция JavaScript, которая позволяет эффективно работать с операциями ввода-вывода, сохраняя приложение отзывчивым и производительным. [Различия между Node.js и браузером] И браузер, и Node.js, оба используют JavaScript в качестве своего языка программирования. Однако построение приложений, которые работают в браузере (фронтэнд), полностью отличается от построения приложения Node.js (приложение сервера, бэкэнд). Несмотря на то, что это всегда JavaScript, есть несколько ключевых отличий, которые делают опыт кардинально иным. С точки зрения frontend-разработчика, интенсивно использующего JavaScript, приложения Node.js дают ему большое преимущество: комфортное программирование в любом месте. И frontend, и backend реализуются на одном и том же языке программирования. Мы знаем, насколько сложно бывает изучить новый язык программирования, так что применение одного и того же языка как на клиенте, так и на сервере значительно облегчает решение прикладных задач. Меняется только экосистема, в которой работает код. В браузере больше всего времени вы проводите на обработке элементов DOM (Document Object Model), или других API-функций Web Platform наподобие Cookies. Конечно, ничего этого нет в Node.js. У вас нет ни document, ни window и всех других объектов, которые предоставляет браузер. И в бразуере у вас нет доступа к прекрасному API, которое Node.js предоставляет на базе своих модулей, набодобие функционала доступа к файловой системе. Ещё одно важное отличие заключается в том, что в Node.js вы контролируете рабочее окружение (environment). Если только вы не разрабатываете приложение с открытым исходным кодом, которое может быть развернуто где угодно, вы знаете, на какой версии Node.js оно будет запущено. Это очень удобно по сравнению с браузерной средой, где вы не можете выбрать, какой браузер будут использовать ваши посетители. Это означает, что вы можете писать все современные версии JavaScript ES2015+, поддерживаемые вашей версией Node.js. Поскольку JavaScript развивается очень быстро, а браузеры обновляются довольно медленно, иногда в вебе приходится использовать старые версии JavaScript/ECMAScript. Вы можете использовать Babel для преобразования кода в совместимый с ES5 перед отправкой в браузер, но в Node.js это не требуется. Другое отличие состоит в том, что Node.js поддерживает обе системы модулей - CommonJS и ES (начиная с Node.js v12), в то время как в браузере мы начинаем видеть реализацию стандарта ES-модулей. На практике это означает, что можно использовать в Node.js как require(), так и import, но в браузере вы ограничены import. [V8 JavaScript Engine] V8 это имя подсистемы языка (JavaScript engine) которую обеспечивает Google Chrome. Это то, что берет наш JavaScript и выполняет его во время просмотра страниц с Chrome. V8 — это движок JavaScript, который анализирует и выполняет код JavaScript. DOM и другие API веб-платформы (все они составляют среду выполнения) предоставляются браузером. Самое интересное, что движок JavaScript не зависит от браузера, в котором он размещён. Эта ключевая особенность способствовала развитию Node.js. V8 был выбран в качестве движка Node.js ещё в 2009 году, и с взрывным ростом популярности Node.js V8 стал движком, который теперь поддерживает невероятное количество серверного кода, написанного на JavaScript. Экосистема Node.js огромна, и благодаря V8 она также поддерживает десктопные приложения, в том числе проекты типа Electron. Другие движки JS. Другие браузеры содержат свои собственные подсистемы JavaScript. Вот возможно неполный список самых популярных движков: ● Firefox содержит SpiderMonkey. Все эти движки реализуют стандарт ECMA ES-262, также называемый ECMAScript - стандарт, используемый JavaScript. Производительность. V8 написан на C++, и непрерывно улучшается. Это портируемый код, и он работает на Mac, Windows, Linux и нескольких других системах. В этом кратком обзоре мы не будем концентироваться на деталях V8: для этого можно обратиться к первоисточникам (например к официальному сайту V8 https://v8.dev/), и эти детали со временем меняются, часто радикально. V8 постоянно развивается, как и другие движки JavaScript, чтобы ускорить работу Интернета и экосистемы Node.js. В Интернете уже много лет идет гонка за производительностью, и мы (как пользователи и разработчики) извлекаем из этой конкуренции большую выгоду, поскольку год за годом получаем более быстрые и оптимизированные машины. Компиляция. JavaScript главным образом считается интерпретируемым языком, но современные движки JavaScript могут не просто интерпретировать, они могут его компилировать. Это началось в 2009 году, когда в Firefox 3.5 был добавлен компилятор SpiderMonkey JavaScript, после чего все взяли на вооружение эту идею. JavaScript внутренне компилируется V8 в код just-in-time (JIT) для ускорения выполнения. Это может показаться нелогичным, но с момента появления Google Maps в 2004 году JavaScript превратился из языка, который обычно выполнял только несколько десятков строк кода, в законченные приложения с тысячами или сотнями тысяч строк, работающих в браузере. Наши приложения теперь могут работать часами в браузере, и не просто представлять собой несколько правил проверки форм или простых скриптов. В этом новом мире компиляция JavaScript имеет смысл, поскольку, хотя на подготовку JavaScript может потребоваться немного больше времени, после ее завершения он будет намного производительнее, чем чисто интерпретируемый код. [ECMAScript 2015 (ES6) и более поздние версии] Node.js создан на основе современных версий V8. Поддерживая актуальность последних версий этого движка, разработчики обеспечивают своевременное внедрение новых функций спецификации JavaScript ECMA-262 для Node.js, а также постоянное повышение производительности и стабильности. Все фичи ECMAScript 2015 (ES6) делятся на три группы: поставляемые (shipping), готовящиеся (staged) и находящиеся в разработке (in progress): ● Все shipping-фичи, которые V8 заявляет стабильными, включены по умолчанию в Node.js, и НЕ ТРЕБУЮТ никаких runtime-флагов. Поставляемое по умолчанию. Сайт node.green дает отличный обзор поддерживаемых фич ECMAScript в различных версиях Node.js, основанных на kangax compat-table. Kangax's compat-table — это масштабный проект по созданию таблиц совместимости, которые показывают поддержку различных функций ECMAScript (стандарта JavaScript) в браузерах, серверных средах выполнения (таких как Node.js) и транспайлерах. Проект, также известный как "ECMAScript compatibility tables", служит авторитетным источником информации для разработчиков, позволяя им точно определять, какие функции JavaScript можно безопасно использовать в их целевых средах. [Как пользоваться таблицами совместимости] Основной проект размещен на GitHub по адресу github.com/kangax/compat-table, а актуальные таблицы можно просматривать онлайн: ES2016 и новее: https://compat-table.github.io/compat-table/es2016plus/ На этих страницах вы найдете подробные таблицы, где по вертикали перечислены функции JavaScript, а по горизонтали — версии браузеров, Node.js и других платформ. Поддержка каждой функции отмечается цветом или галочкой. [Как это связано с Node.js и node.green] Проект node.green является прямой адаптацией оригинальной таблицы Kangax, но специализируется исключительно на Node.js. Как объясняется в репозитории node-compat-table, он предоставляет более глубокое представление о различиях между быстро обновляющимися версиями Node.js, что особенно ценно для серверных разработчиков. Почему это важный инструмент для разработчика: - Принятие обоснованных решений: позволяет точно знать, какие функции JavaScript поддерживаются в нужных версиях Node.js или браузеров, прежде чем использовать их в коде. Фичи в разработке. В движок V8 постоянно добавляются новые функции. В целом можно ожидать, что они появятся в будущем релизе Node.js, хотя точные сроки пока неизвестны. Вы можете получить список всех находящихся в разработке фич, доступных в каждом релизе Node.js пропустив его через grep-обработку аргумента --v8-options. Имейте в виду, что это может быть неполный, и даже содержащий неисправные фичи V8 список, так что используйте его на свой страх и риск: $ node --v8-options | grep "in progress"
Моя инфраструктура настроена на использование флага --harmony. Стоит ли его удалить? Текущее поведение флага --harmony в Node.js заключается в включении только подготовленных функций. В конце концов, теперь он является синонимом --es_staging. Как упоминалось выше, это завершённые функции, которые ещё не считаются стабильными. Если вы хотите действовать наверняка, особенно в производственных средах, рассмотрите возможность удаления этого флага времени выполнения, пока он не станет по умолчанию в V8 и, следовательно, в Node.js. Если вы оставите его включённым, будьте готовы к тому, что дальнейшие обновления Node.js могут нарушить ваш код, если V8 изменит свою семантику, чтобы более точно соответствовать стандарту. Как узнать, какая версия V8 поставляется с конкретной версией Node.js? Node.js предоставляет простой способ получить список всех зависимостей и соответствующих версий, поставляемых с конкретным исполняемым файлом, через глобальный объект процесса. В случае движка V8 введите в терминале следующую команду, чтобы узнать его версию: $ node -p process.versions.v8
13.6.233.10-node.28
13.6 — основная версия V8 233 — номер сборки Chromium 10 — патч-версия V8 node.28 — кастомная модификация для Node.js Чтобы узнать полную картину, выполните: $ node --version
24.11.1
Соответствие версий Node.js и V8: - Node.js 20.x → V8 11.3-11.4 Почему Node.js модифицирует V8? Изменения в Node.js версии V8 включают: 1. Улучшенная работа с памятью — серверные приложения работают дольше браузерных вкладок. [Практическое значение для разработчика] 1. Поддержка возможностей JavaScript // V8 13.6 поддерживает: 2. Производительность Каждая версия V8 приносит улучшения производительности: - Быстрее выполнение JavaScript 3. Совместимость с браузером: rод, работающий в современном Chrome, скорее всего будет работать и в вашей версии Node.js. 4. Как проверить доступные возможности? Используйте node.green. Зная версию V8 (13.6), можно проверить: - Поддержку ES2023, ES2022 функций [Native WebSocket Client в Node.js] Начиная с Node.js версии v21, WebSocket API было улучшено библиотекой Undici, где есть встроенный клиент WebSocket. Это упрощает коммуникации реального времени для приложений Node.js. В релизе Node.js v22.4.0 функционал WebSocket API был отмечен как stable, что показывает его готовность для использования в production. Что такое WebSocket. Это стандартизованный коммуникационный протокол, который позволяет реализовать одновременный двусторонний обмен через одиночное соединение TCP. Он обладает возможностями полнодуплексного или двунаправленного режима, что отличает его от HTTP. WebSocket обеспечивает совместимость с HTTP благодаря использованию заголовка HTTP Upgrade для перехода между протоколами. Он позволяет серверам отправлять контент клиентам без первоначальных запросов и поддерживает открытые соединения для непрерывного обмена сообщениями, что делает его идеальным для передачи данных в режиме реального времени с меньшими накладными расходами, чем альтернативные варианты, такие как опрос (HTTP polling). Коммуникации WebSocket обычно происходят через порт TCP 443 (secured) или 80 (unsecured), что помогает проходить через ограничения брандмауэров, которые фильтруют соединения, не относящиеся к web. Протокол определяет свои собственные URI-схемы ws:// и wss:// для нешифрованных и шифрованных соединений соответственно, и это поддерживается всеми современными браузерами. Native WebSocket Client. Node.js теперь может работать как клиент WebSocket, не полагаясь на внешние библиотеки наподобие ws или socket.io, чтобы реализовать клиентские соединения. Это позволяет приложениям Node.js напрямую инициировать и управлять исходящими соединениями WebSocket, оптимизируя такие задачи, как подключение к потокам данных в режиме реального времени или взаимодействие с другими серверами WebSocket. Пользователи могут создать соединение websocket стандартным конструктором new WebSocket(). Развивая вышесказанное, давайте добавим больше практических примеров для демонстрации новой функциональности клиента WebSocket, демонстрирующих основные варианты использования. Базовое соединение и обработка сообщения: // Создание нового соединения WebSocket к указанному URL. Отправка и прием данных JSON: const socket = new WebSocket('ws://localhost:8080'); Этот код javascript демонстрирует отправку и прием данных JSON, которые обычно используются приложениями WebSocket. Используется JSON.stringify() для преобразования объектов JavaScript в строки JSON перед отправкой. И обратно принятая строка преобразуется в JavaScript-объект с помощью JSON.parse(). И наконец, добавлена обработка ошибок для парсинга JSON. Это обеспечивает упрощенное управление зависимостями и улучшенную совместимость. Разработчикам не нужно устанавливать и поддерживать дополнительные клиентские библиотеки WebSocket. Встроенная реализация соответствует современным веб-стандартам, обеспечивая лучшую совместимость. Улучшение сосредоточено на клиентской стороне взаимодействия WebSocket, позволяя Node.js выступать в роли клиента WebSocket. Важно для понимания: Node.js v22 не предоставляет встроенную реализацию сервера WebSocket. Чтобы создать сервер WebSocket, который принимает входящие соединения из браузеров или других клиентов, по-прежнему нужно использовать библиотеки наподобие ws или socket.io. Это означает, что хотя Node.js может теперь просто подключаться к серверам WebSocket, ему все еще нужны внешние инструменты, чтобы стать WebSocket-сервером. В итоге: Node.js v22 позволяет приложениям без препятствий взаимодействовать с серверами WebSocket в качестве клиентов, но создание серверов WebSocket внутри Node.js остается зависимым от установленных библиотек. Это различие крайне важно понимать разработчикам при реализации взаимодействия в режиме реального времени в своих проектах Node.js. Ниже показан пример кода, который создал DeepSeek в ответ на запрос: "Напиши код на основе Node.js, чтобы HTTP-сервер на главной странице показывал падающие зеленые буквы, как в фильме 'Матрица'". В итоге получилось следующее. Файл server.js: const http = require('http'); const fs = require('fs'); const path = require('path'); const server = http.createServer((req, res) => { if (req.url === '/') { // Читаем HTML файл const filePath = path.join(__dirname, 'matrix.html'); fs.readFile(filePath, (err, data) => { if (err) { res.writeHead(500); res.end('Ошибка загрузки страницы'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(data); }); } else { res.writeHead(404); res.end('Страница не найдена'); } }); const PORT = 3000; server.listen(PORT, () => { console.log(`Сервер запущен на http://localhost:${PORT}`); console.log('Откройте браузер и перейдите по указанному адресу'); }); Файл matrix.html: <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Матрица - Падающие символы</title> <style> body { margin: 0; padding: 0; background-color: black; overflow: hidden; font-family: 'Courier New', monospace; } .matrix-container { position: relative; width: 100vw; height: 100vh; } .matrix-column { position: absolute; top: -50px; color: #0f0; font-size: 18px; font-weight: bold; text-shadow: 0 0 5px #0f0; animation: fall linear infinite; } @keyframes fall { to { transform: translateY(100vh); } } .symbol { opacity: 1; transition: opacity 0.1s; } .symbol.fading { opacity: 0.2; } .symbol.bright { opacity: 1; color: #fff; text-shadow: 0 0 10px #fff, 0 0 20px #0f0; } </style> </head> <body> <div class="matrix-container" id="matrixContainer"></div> <script> class MatrixRain { constructor(container) { this.container = container; this.columns = []; this.symbols = 'アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウ\ ゥクスツヌフムユュルグズブヅプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボポヴッン\ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; this.columnCount = Math.floor(window.innerWidth / 20); this.speedMultiplier = 1; this.init(); this.start(); } init() { // Создаем колонки for (let i = 0; i < this.columnCount; i++) { this.createColumn(i); } // Обработчики событий window.addEventListener('resize', () => this.handleResize()); document.addEventListener('mousemove', (e) => this.handleMouseMove(e)); } createColumn(index) { const column = document.createElement('div'); column.className = 'matrix-column'; column.style.left = `${(index * 20)}px`; column.style.animationDuration = `${2 + Math.random() * 3}s`; column.style.animationDelay = `${Math.random() * 2}s`; this.container.appendChild(column); this.columns.push(column); // Запускаем обновление символов в колонке this.updateColumn(column); } updateColumn(column) { const symbolCount = Math.floor(window.innerHeight / 24) + 5; // Очищаем колонку column.innerHTML = ''; // Создаем символы for (let i = 0; i < symbolCount; i++) { const symbol = document.createElement('div'); symbol.className = 'symbol'; symbol.textContent = this.getRandomSymbol(); // Случайно делаем некоторые символы яркими if (Math.random() < 0.1) { symbol.classList.add('bright'); } // Случайно делаем некоторые символы полупрозрачными if (Math.random() < 0.3) { symbol.classList.add('fading'); } column.appendChild(symbol); } } getRandomSymbol() { return this.symbols.charAt(Math.floor(Math.random() * this.symbols.length)); } start() { // Обновляем символы каждые 100ms setInterval(() => { this.columns.forEach(column => { const symbols = column.querySelectorAll('.symbol'); symbols.forEach(symbol => { // Случайно меняем символ if (Math.random() < 0.3) { symbol.textContent = this.getRandomSymbol(); } // Случайно меняем яркость if (Math.random() < 0.1) { symbol.classList.toggle('bright'); } // Случайно меняем прозрачность if (Math.random() < 0.2) { symbol.classList.toggle('fading'); } }); }); }, 100); } handleResize() { const newColumnCount = Math.floor(window.innerWidth / 20); if (newColumnCount > this.columns.length) { // Добавляем новые колонки for (let i = this.columns.length; i < newColumnCount; i++) { this.createColumn(i); } } else if (newColumnCount < this.columns.length) { // Удаляем лишние колонки for (let i = this.columns.length - 1; i >= newColumnCount; i--) { this.container.removeChild(this.columns[i]); this.columns.pop(); } } } handleMouseMove(e) { // Изменяем скорость в зависимости от положения мыши const mouseX = e.clientX; const speed = 1 + (mouseX / window.innerWidth) * 2; this.speedMultiplier = speed; this.columns.forEach(column => { const currentDuration = parseFloat(column.style.animationDuration); column.style.animationDuration = `${currentDuration / this.speedMultiplier}s`; }); } } // Запускаем матричный дождь когда страница загружена document.addEventListener('DOMContentLoaded', () => { new MatrixRain(document.getElementById('matrixContainer')); }); </script> </body> </html> Как запустить: 1. Сохраните код сервера в текстовый файл server.js, в кодировке UTF-8. Особенности реализации: - JavaScript-код, интегрированный в тег script файла matrix.html, выполняется на стороне клиента (в браузере). [Ссылки] 1. Introduction to Node.js site:nodejs.org. |