В этой статье мы рассмотрим понятия и методы, которые необходимо знать для создания инструмента на основе командной строки. Для этого мы будем использовать такие популярные программные платформы, как Node.js и PhantomJS. Создание инструмента на основе командной строки позволяет автоматизировать процессы, на выполнение которых в противном случае тратилось бы слишком много времени.
Инструменты на основе командной строки можно создать с помощью множества языков, но в данном случае мы сосредоточимся на программной платформе Node.js.
Что мы будем рассматривать.
- Секретный совет.
- Установка Node.js и npm.
- Процесс.
- Автоматизация.
- PhantomJS.
- Squirrel (белка).
- Принцип работы.
- Код.
- Упаковка.
- Публикация.
- Заключение.
Секретный совет.
Для тех из вас, у кого катастрофически не хватает времени, я разбил весь процесс на три основных этапа. Это секретный совет по преобразованию Node.js скрипта в полнофункциональный инструмент на основе командной строки. Внимательно следите за всем, что я показываю в этой статье.
- В вашем
package.json
файле используйте следующие параметры:"preferGlobal": "true"
"bin": { "name-of-command": "path-to-script.js" }
- Добавьте
#!/usr/bin/env node
вpath-to-script.js
. - Чтобы проверить новую команду (
name-of-command
), используйтеnpm link
.
Остальная часть процесса будет заключаться в выборе и реализации функциональных возможностей.
Установка Node.js И npm.
Для установки Node.js можно воспользоваться несколькими вариантами:
- Установка под конкретную операционную систему для Windows, Mac или для обеих систем;
- Менеджер пакетов homebrew:
brew install node
; - Nave;
- NVM.
Обратите внимание, что npm (New public management - пакетный менеджер) устанавливается как часть Node.js; отдельной инсталляции не существует.
Чтобы проверить правильность установки Node.js и npm, в терминале выполните следующие команды:
node --version
npm --version
Процесс.
Давайте рассмотрим типовой процесс: создание манифест файла кэша приложения .
В случае, если вы не знакомы с AppCache, то это оффлайн хранилище для приложений. Вы можете обеспечить функционирование приложения даже если пользователь теряет подключение к Интернету или пытается получить доступ к приложению в режиме оффлайн. Вам всего лишь нужно указать страницы и ресурсы, для которых необходимо выполнить кэширование.
Как правило, создается appcache.manifest файл, в котором хранится конфигурация оффлайн настроек.
Мы не будем вдаваться в подробности функционирования AppCache, поскольку это выходит за рамки нашей темы и отвлекает нас от целей настоящей статьи. Тем не менее, ниже представлены строки из типового файла:
CACHE MANIFEST
CACHE:
foo.jpg
index.html
offline.html
styles.css
behaviours.js
NETWORK:
*
FALLBACK:
/ /offline.html
Как вы уже наверное заметили, мы определили следующие объекты:
- JPG изображение,
- два HTML файла,
- CSS файл,
- JavaScript файл.
Это перечень тех ресурсов, которые необходимо кэшировать на тот случай, если у пользователя пропадет подключение к интернету.
Мы также определили все элементы, при запросе которых пользователем, должно должно присутствовать подключение к интернету.
Наконец, мы определились с тем, что любой файл, который должен быть кэширован и не перенаправляется пользователю, будет иметь название offline.html
.
Автоматизация.
Процесс последовательного просмотра всех изображений, таблиц стилей, скриптов и ссылок на другие веб-страницы может быть крайне утомительным. По этой причине мы попытаемся автоматизировать процесс генерации манифест файла.
Мы могли бы сделать это, написав специальный Node.js код и воспользовавшись дополнительными инструментами. Однако данная задача будет не такой уж и простой (даже для человека, который имеет огромный опыт создания скриптов), поскольку мы должны будем открыть код и указать, какую именно веб-страницу необходимо опросить.
Мы также хотим, чтобы и другие люди могли воспользоваться преимуществами этого инструмента, без необходимости загружать папку с кодом, вносить корректировки и инициировать команды запуска скриптов.
Вот почему особенно полезным будет инструмент на основе командной строки.
PhantomJS.
Во-первых, мы хотим выяснить, как можно решить эту проблему.
Мы будем использовать инструмент под названием PhantomJS, который представляет собой headless (безголовый) (т.е. Chromeless) браузер.
В частности, это headless WebKit браузер, который предоставляет интерфейс прикладного программирования (API) для JavaScript. С помощью этого интерфейса мы можем подключиться к необходимым нам ресурсам, что позволяет выполнять такие действия, как открытие веб-страниц и анализирование их сетевых запросов (он также имеет множество других функциональных возможностей, но в данном случае мы заинтересованы только в этих двух фундаментальных аспектах).
Мы можем использовать модуль Node.js для загрузки PhantomJS и налаживания взаимодействия с его API. С помощью Node.js менеджера пакетов, npm и package.json
файла мы с относительной легкостью можем преобразовать наш код в инструмент на основе командной строки.
Squirrel.
К счастью, я уже сделал за вас всю работу. Это проект с открытым исходным кодом под названием Squirrel (англ. «белка» — интерпретируемый язык программирования, разработанный специально для использования в качестве скриптового языка в приложениях реального времени, таких как компьютерные игры).
Чтобы установить его используйте команду npm install -g squirrel-js
.
После установки этого проекта вы можете приступить к его использованию просто запустив команду squirrel [url]
. Например, squirrel bbc.co.uk/news
.
Будет создан (в текущем каталоге) файл с названием appcache.manifest
, заполненный всеми соответствующими ресурсами страницы.
Принцип работы?
Я начал проект Squirrel с написания релевантного Node.js и PhantomJS кода, который позволил бы реализовать необходимые функциональные возможности.
Затем я добавил скрипт, который позволяет вносить изменения в этот код и использовать аргументы, предназначенные для настройки выполнения кода.
Результатом стало создание двух скриптов:
Первый скрипт отвечает за рабочие настройки:
- Мы задаем программную среду, в которой должен будет выполняться скрипт (в данном случае, Node.js).
- Анализ аргументов, передаваемых пользователем.
- Чтение внутреннего (т.е. фиктивного)
appcache.manifest
файла. - Открытие дочернего процесса, вызов PhantomJS и передача ему скрипта, который мы хотим выполнить (в данном случае,
appcache.js
), а также фиктивного манифест файла. - Когда второй скрипт завершает работу (сбор данных на веб-странице), происходит возврат к первому скрипту и отображение статистической информации для пользователя и генерация манифест файла.
Второй скрипт выполняет обработку веб-страницы, запрашиваемой пользователем:
- Берет фиктивный манифест файл.
- Создает слушателей для требуемых страничных ресурсов.
- Устанавливает размер окна просмотра.
- Открывает веб-страницу и сохраняет ресурсы.
- Получает все ссылки со страницы (путем выполнения JavaScript кода непосредственно на веб-странице).
- Преобразует содержимое манифест файла и вводит найденные ресурсы, а затем возвращает его как JSON файл.
Код.
Теперь, когда вы имеете представление о выполняемых действиях, давайте приступим к непосредственному рассмотрению кода. Сначала я приведу весь код целиком, а затем мы детально рассмотрим отдельные его фрагменты.
Squirrel.js
#!/usr/bin/env node
var userArguments = process.argv.slice(2); // Copies arguments list but removes first two options (script exec type & exec location)
if (userArguments.length > 1) {
throw new Error('Only one argument may be specified (the URL for which you want to generate the AppCache.)');
}
var fs = require('fs');
var shell = require('child_process').execFile;
var phantomjs = require('phantomjs').path;
var scriptToExecute = __dirname + '/appcache.js';
var manifest = __dirname + '/../appcache.manifest';
var url = userArguments[0];
var manifestContent;
var data;
fs.readFile(manifest, bootstrap);
function bootstrap(err, contentAsBuffer) {
if (err) throw err;
manifestContent = contentAsBuffer.toString('utf8');
shell(phantomjs, [scriptToExecute, url, manifestContent], function(err, stdout, stderr) {
if (err) throw err;
// Sometimes an error in the loaded page's JavaScript doesn't get picked up or thrown,
// but the error comes in via stdout and causes JSON parsing to break
try {
data = JSON.parse(stdout);
} catch(err) {
log('Whoops! It seems there was an error? You\'ll find the stack trace below.');
error(err);
}
displayStatistics();
createManifestFile();
});
}
function displayStatistics() {
log(''); // Adds extra line of spacing when displaying the results
log('Links: ' + data.links);
log('Images: ' + data.images);
log('CSS: ' + data.css);
log('JavaScript: ' + data.javascript);
}
function createManifestFile() {
fs.writeFile(process.cwd() + '/appcache.manifest', data.manifestContent, function(err) {
if (err) throw err;
log('\nManifest file created');
});
}
function log(message) {
process.stdout.write(message + '\n');
}
function error(err) {
process.stderr.write(err);
}
Первая строка, #!/usr/bin/env node
, имеет решающее значение для скриптов, используемых в оболочке. Мы должны сообщить оболочке, какой именно процесс должен обрабатывать скрипт.
Далее мы должны получить аргументы, передаваемые командой. Если мы запустим squirrel bbc.co.uk/news
, то process.argv
будет представлять собой массив, содержащий следующую информацию:
- тип исполнительного скрипта (
node
); - выполняемый скрипт (
squirrel.js
); - любые другие аргументы (в данном случае он будет только один,
bbc.co.uk/news
).
Не обращайте внимания на первые два аргумента, и сохраняйте аргументы пользовательских настроек, чтобы мы могли ссылаться на них позднее:
var userArguments = process.argv.slice(2);
Наш скрипт может обработать только один аргумент (который представляет собой URL-адрес страницы для загрузки). Следующая строка на самом деле не нужна, поскольку мы будем игнорировать любые аргументы, кроме первого. Но все же она представляет для кода определенную пользу, потому что в случае использования более одного аргумента будет выведено соответствующее сообщение об ошибке.
if (userArguments.length > 1) {
throw new Error('Only one argument may be specified (the URL for which you want to generate the AppCache.)');
}
Поскольку мы используем PhantomJS, то должны будем открыть оболочку и вызвать команду phantomjs
:
var shell = require('child_process').execFile;
Мы также должны ссылаться на bin
каталог, где хранится исполняемый PhantomJS код:
var phantomjs = require('phantomjs').path;
Следующим шагом является сохранение ссылки на скрипт, который должен выполняться PhantomJS, также как и на фиктивной манифест файл.
var scriptToExecute = __dirname + '/appcache.js';
var manifest = __dirname + '/../appcache.manifest';
var url = userArguments[0];
Поскольку PhantomJS скрипт, который мы будем выполнять, предполагает наличие ссылки на фиктивный манифест файл, то мы будем асинхронно считывать содерж …
Если вы хотите прочитать полностью статью, посетите сайт наших спонсоров