Большинство веб-приложений требуют парсинга URL, будь то для извлечения имени домена, реализации REST API или поиска пути к изображению. Типичная структура URL описана изображением ниже:
Вы можете разбить строку URL на составные части, используя регулярные выражения, но это сложно и не нужно …
Разбор URL на стороне сервера
Node.js (и вилки, такие как io.js) предоставляют API URL :
// 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 на стороне клиента
В браузере нет эквивалентного API. Но если есть что-то, что браузеры делают хорошо, это разбор URL, и все ссылки в DOM реализуют подобный интерфейс Location , например:
// Client-side JavaScript // find the first link in the 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
), чтобы ее можно было проанализировать без регулярных выражений, например:
// Client-side JavaScript // create dummy link 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
Аурелио недавно обсуждал изоморфные приложения JavaScript . По сути, это прогрессивное усовершенствование, доведенное до экстремального уровня, когда приложение будет успешно работать на клиенте или сервере. Пользователь с современным браузером будет использовать одностраничное приложение. Старые браузеры и роботы поисковых систем увидят альтернативу, предоставляемую сервером. Теоретически, приложение может реализовывать различные уровни обработки клиент-сервер в зависимости от скорости и пропускной способности устройства.
Изоморфный JavaScript обсуждался много лет, но он сложен. Несколько проектов идут дальше, чем
реализация разделяемых представлений, и не так много ситуаций, когда стандартное прогрессивное улучшение не сработало бы так же хорошо (если не лучше, учитывая, что большинство «изоморфных» фреймворков не работают без JavaScript-кода на стороне клиента) . Тем не менее, можно создать независимые от среды микробиблиотеки, которые предлагают предварительный первый шаг в изоморфных концепциях.
Давайте рассмотрим, как можно написать библиотеку для разбора URL-адресов в файле lib.js
Сначала мы определим, где работает код:
// running on Node.js? var isNode = (typeof module === 'object' && module.exports);
Это не особенно module.exports
так как вы могли бы иметь функцию module.exports
определенную на стороне клиента, но я не знаю лучшего способа (предложения приветствуются) . Аналогичный подход, используемый другими разработчиками, заключается в проверке наличия объекта window
:
// running on Node.js? var isNode = typeof window === 'undefined';
Давайте теперь дополним наш код URLparse
функцией URLparse
:
// lib.js library functions // 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
:
<script src="./lib.js"></script> <script> 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 ); </script>
За исключением метода включения библиотеки, API клиента и сервера идентичны.
Следует признать, что это простой пример, и URLparse
выполняет (в основном) отдельный код на клиенте и сервере. Но мы реализовали непротиворечивый API, и он показывает, как можно написать код JavaScript для запуска в любом месте. Мы могли бы расширить библиотеку, чтобы предлагать дополнительные функции клиент / сервер, такие как проверка полей, анализ файлов cookie, обработка дат, форматирование валюты и т. Д.
Я не уверен, что полные изоморфные приложения практичны или возможны, учитывая различные типы логики, требуемые на клиенте и сервере. Однако независимые от среды библиотеки могут облегчить необходимость написания двух наборов кода для выполнения одной и той же задачи.