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

в 12:05, , рубрики: javascript, javascript nodejs, node.js, метки:

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

Простой разбор URL с помощью изоморфного Javascript - 1

Вы можете разобрать 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:

<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>

Отличий в использовании на сервере и клиенте, кроме способа подключения к коду, данная библиотека не имеет.

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

Автор: for7raid

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js