[Перевод] Простой разбор URL с помощью изоморфного Javascript

Во многих веб-приложениях требуется разбор URL, такой как извлечение доменного имени, имплиментация REST API или поиск пути к файлам изображений. Типичная структура URL показана на рисунке ниже: f7892b2ce7e24f53a8fa06482903f4aa.pngВы можете разобрать URL строку на компоненты используя регулярные выражения, но это неоправданное и сложное решение…

Серверный разборNode.js (как и его форк io.js) предоставляет URL API: // Server-side JavaScript var urlapi = require ('url'), url = urlapi.parse ('http://site.com:81/path/page? a=1&b=2#hash'); console.log ( url.href + '\n' + // the full URL url.protocol + '\n' + // http: url.hostname + '\n' + // site.com url.port + '\n' + // 81 url.pathname + '\n' + // /path/page url.search + '\n' + // ? a=1&b=2 url.hash // #hash ); Как вы видите в примере выше, метод parse () возвращает объект, содержащий все отдельные части URL, такие как протокол, порт, адрес хоста и т.п.Разбор на клиенте В браузере, к сожалению, нет похожего метода, зато браузер умеет хорошо манипулировать DOM элементами, которые реализуют простой интерфейс Location: // Клиентский JavaScript // найдем первую ссылку в DOM var url = document.getElementsByTagName ('a')[0]; console.log ( url.href + '\n' + // the full URL url.protocol + '\n' + // http: url.hostname + '\n' + // site.com url.port + '\n' + // 81 url.pathname + '\n' + // /path/page url.search + '\n' + // ? a=1&b=2 url.hash // #hash ); Если у нас есть URL строка, мы может разобрать ее в памяти используя якорный элемент (a) без использования регулярных выражений: // Клиентский JavaScript // создадим скрытую ссылку var url = document.createElement ('a'); url.href = 'http://site.com:81/path/page? a=1&b=2#hash'; console.log (url.hostname); // site.com Изоморфный разбор URL Aurelio De Rosa обсуждал недавно изоморфные JavaScript приложения. Вкратце, это прогрессивное улучшение, задающее новый уровень, когда приложения могут одинаково хорошо выполняться как на клиенте, так и на сервере. Пользователь с современным браузером будет использовать одностраничное (single-page) приложение. Старые браузеры и поисковые роботы будут использовать альтернативные механизмы, обрабатывающие запросы на сервере. В теории, приложения смогут реализовать разные уровни клиент-серверной обработки, в зависимости от ширины канала и возможностей клиента.Изоморфный Javascript обсуждается уже много лет и этот вопрос носит комплексный характер. Некоторые проекты пошли дальше, чем просто создание совместно используемых представлений, ведь на самом деле не так много ситуаций, когда прогрессивное улучшение не будет работать также хорошо (если не лучше, ведь большинство «изоморфных» Javascript фреимворков не существуют без клиентской обработки).Тем не менее, существует возможность создавать платформонезависимые микробиблиотеки, способные помочь сделать первый шаг на пути к изоморфной концепции.Давайте обсудим, как мы может создать такую библиотеку для разбора URL в файле lib.js. Для начала нужно определить где запущен наш код: // Это Node.js? var isNode = (typeof module === 'object' && module.exports); Это не самый лучший способ определить платформу, так как у вас может быть определен клиентский объект с методом module.exports, но я не знаю метода лучше. Другие разработчики проверяют объект window: // Это Node.js? var isNode = typeof window === 'undefined'; Давайте завершим наш код в файле lib.js // running on Node.js? var isNode = (typeof module === 'object' && module.exports); (function (lib) { «use strict»; // require Node URL API var url = (isNode? require ('url') : null); // parse URL lib.URLparse = function (str) { if (isNode) { return url.parse (str); } else { url = document.createElement ('a'); url.href = str; return url; } } })(isNode? module.exports: this.lib = {}); В этом примере для ясности я использовал переменную isNode. В любом случае вы можете заменить эту проверку, поместив ее прямо в последние скобки этого кода.На сервере URLParse экспортируется как стандартный Common.JS модуль. Пример: // include lib.js module var lib = require ('./lib.js'); var url = lib.URLparse ('http://site.com:81/path/page? a=1&b=2#hash'); console.log ( url.href + '\n' + // the full URL url.protocol + '\n' + // http: url.hostname + '\n' + // site.com url.port + '\n' + // 81 url.pathname + '\n' + // /path/page url.search + '\n' + // ? a=1&b=2 url.hash // #hash ); На клиенте URLParse объявлен как метод глобального объекта lib: Отличий в использовании на сервере и клиенте, кроме способа подключения к коду, данная библиотека не имеет.По правде сказать, это простой код и метод URLParse запускается (почти всегда) отдельно на сервере и клиенте. Но мы создали постоянное API, которое показывает как можно писать Javasctipt код, способный запускаться где угодно. Мы можем расширить библиотеку другим клиентскими и серверными функциями, такими как, валидация данных, разбор куков, обработка дат, форматирование валют и т.д. Но я не уверен в полной изоморфизации приложений в виду того, что часто требуется разная логика для обработки на клиенте и сервере. В любом случае, платфомонезависимые библиотеки могут уменьшить ваши затраты на создание разного кода, который делает одни и те же вещи.

© Habrahabr.ru