Расширения браузера — это небольшие программы, которые могут изменять и расширять функциональность веб-браузера. Их можно использовать для различных задач, таких как блокировка рекламы, управление паролями, организация вкладок, изменение внешнего вида и поведения веб-страниц и многое другое.
Хорошей новостью является то, что расширения для браузера не сложно написать. Они могут быть созданы с использованием уже знакомых вам веб-технологий — HTML, CSS и JavaScript — как обычная веб-страница. Однако, в отличие от обычных веб-страниц, расширения имеют доступ к ряду специфичных для браузера API-интерфейсов, и именно здесь начинается самое интересное.
В этом уроке я покажу вам, как создать простое расширение для Chrome, которое меняет поведение новой вкладки. В части расширения JavaScript я буду использовать фреймворк Vue.js, поскольку он позволит нам быстро приступить к работе и работать с ним очень весело.
Код для этого урока можно найти на GitHub .
Хотите узнать Vue.js с нуля? Получите полную коллекцию книг Vue, охватывающих основы, проекты, советы и инструменты и многое другое с SitePoint Premium. Присоединяйтесь сейчас всего за $ 9 / месяц .
Основы расширения Chrome
Основной частью любого расширения Chrome является файл манифеста и фоновый скрипт . Файл манифеста представлен в формате JSON и предоставляет важную информацию о расширении, например его версию, ресурсы или необходимые ему разрешения. Фоновый скрипт позволяет расширению реагировать на определенные события браузера, такие как создание новой вкладки.
Чтобы продемонстрировать эти концепции, давайте начнем с написания расширения Chrome «Hello, World!».
Создайте новую папку с именем hello-world-chrome
и двумя файлами: manifest.json
и background.js
:
mkdir hello-world-chrome cd hello-world-chrome touch manifest.json background.js
Откройте файл manifest.json
и добавьте следующий код:
{ "name": "Hello World Extension", "version": "0.0.1", "manifest_version": 2, "background": { "scripts": ["background.js"], "persistent": false } }
name
, version
и manifest_version
являются обязательными полями. Поля name
и version
могут быть любыми; версия манифеста должна быть установлена на 2 (начиная с Chrome 18).
background
ключ позволяет нам зарегистрировать фоновый скрипт, указанный в массиве после ключа scripts
. persistent
ключ должен иметь значение false
если расширение не использует API chrome.webRequest для блокировки или изменения сетевых запросов.
Теперь давайте добавим следующий код в background.js
чтобы браузер сказал привет при установке расширения:
chrome.runtime.onInstalled.addListener(() => { alert('Hello, World!'); });
Наконец, давайте установим расширение. Откройте Chrome и введите chrome://extensions/
в адресной строке. Вы должны увидеть страницу, показывающую установленные вами расширения.
Поскольку мы хотим установить наше расширение из файла (а не из Chrome Web Store), нам нужно активировать режим разработчика с помощью переключателя в верхнем правом углу страницы. Это должно добавить дополнительную строку меню с опцией Load unpacked . Нажмите эту кнопку и выберите папку hello-world-chrome
вы создали ранее. Нажмите « Открыть», и вы увидите, что расширение установлено и появится всплывающее окно «Hello, World!».
Поздравляем! Вы только что сделали расширение Chrome.
Переопределение новой вкладки Chrome
Следующим шагом будет приветствие нашего расширения при открытии новой вкладки. Мы можем сделать это, используя API Override Pages .
Примечание. Прежде чем приступить к работе, обязательно отключите все другие расширения, которые переопределяют новую вкладку Chrome. Только одно расширение за раз может изменить это поведение.
Мы начнем с создания страницы для отображения вместо новой вкладки. Давайте назовем это tab.html
. Это должно находиться в той же папке, что и файл манифеста и фоновый скрипт:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My New Tab Page!</title> </head> <body> <h1>My New Tab Page!</h1> <p>You can put any content here you like</p> </body> </html>
Далее нам нужно рассказать расширение об этой странице. Мы можем сделать это, указав ключ chrome_url_overrides
в нашем файле манифеста, например так:
"chrome_url_overrides": { "newtab": "tab.html" }
Наконец, вам необходимо перезагрузить расширение, чтобы изменения вступили в силу. Вы можете сделать это, щелкнув значок перезагрузки для расширения Hello World на странице расширений Chrome.
Теперь, когда вы открываете новую вкладку, вас должно приветствовать ваше собственное сообщение.
Добавление Vue к расширению
Теперь у нас есть базовая реализация нашего расширения, и пришло время подумать о том, как будут выглядеть остальные желаемые функции. Когда пользователь открывает новую вкладку, я хотел бы, чтобы расширение:
- Получите шутку от замечательного icanhazdadjoke.com .
- Показать эту шутку в хорошо отформатированном виде для пользователя.
- Покажите кнопку для пользователя, чтобы избрать шутку. Это сохранит шутку в
chrome.storage
. - Показать кнопку для пользователя, чтобы перечислить избранные шутки.
Конечно, вы можете сделать все это с помощью простого JavaScript или библиотеки, подобной jQuery — и если это ваше дело, не стесняйтесь!
Однако в целях данного руководства я собираюсь реализовать эту функциональность, используя Vue и потрясающий шаблон vue-web-extension .
Использование Vue позволяет мне писать лучше, более организованный код быстрее. И, как мы увидим, шаблон содержит несколько сценариев, которые облегчают выполнение некоторых из общих задач при создании расширения Chrome (например, необходимо перезагрузить расширение всякий раз, когда вы вносите изменения).
вя-веб-расширение-шаблонный
В этом разделе предполагается, что на вашем компьютере установлены Node и npm. Если это не так, вы можете либо перейти на домашнюю страницу проекта и получить соответствующие двоичные файлы для вашей системы, либо вы можете использовать менеджер версий . Я бы порекомендовал использовать менеджер версий.
Нам также понадобится установить Vue CLI и пакет @ vue / cli-init :
npm install -g @vue/cli npm install -g @vue/cli-init
Сделав это, давайте возьмем копию шаблона:
vue init kocal/vue-web-extension new-tab-page
Откроется мастер, который задаст вам кучу вопросов. Чтобы сфокусировать этот урок, я ответил следующим образом:
Вы можете адаптировать свои ответы в соответствии со своими предпочтениями, но главное, чтобы быть уверенным в том, что вы решили установить axios . Мы будем использовать это, чтобы получить шутки.
Затем перейдите в каталог проекта и установите зависимости:
cd new-tab-page npm install
И тогда мы можем построить наше новое расширение, используя один из сценариев, которые предоставляет шаблон:
npm run watch:dev
Это позволит встроить расширение в папку dist
в корне проекта для разработки и следить за изменениями.
Чтобы добавить расширение в Chrome, выполните тот же процесс, как описано выше, убедившись, что в качестве каталога расширений выбрана папка dist
. Если все идет по плану, вы должны увидеть сообщение «Hello world!» При инициализации расширения.
Настройка проекта
Давайте уделим минуту, чтобы осмотреть наш новый проект и посмотреть, что шаблон дал нам. Текущая структура папок должна выглядеть следующим образом:
. ├── dist │ └── <the built extension> ├── node_modules │ └── <one or two files and folders> ├── package.json ├── package-lock.json ├── scripts │ ├── build-zip.js │ └── remove-evals.js ├── src │ ├── background.js │ ├── icons │ │ ├── icon_128.png │ │ ├── icon_48.png │ │ └── icon.xcf │ ├── manifest.json │ └── popup │ ├── App.vue │ ├── popup.html │ └── popup.js └── webpack.config.js
Как вы можете видеть, из файла конфигурации в корне проекта, шаблон использует веб-пакет под капотом. Это потрясающе, так как это дает нам горячую перезагрузку модуля для нашего фонового скрипта.
Папка src
содержит все файлы, которые мы будем использовать для расширения. Файл манифеста и background.js
должны быть знакомы, но также заметить popup
папку, содержащую компонент Vue. Когда шаблон встраивает расширение в папку dist
, он .vue
любые файлы .vue
через загрузчик vue и выводит пакет JavaScript, который может понять браузер.
Также в папке src
находится папка с icons
. Если вы посмотрите на панель инструментов Chrome, вы должны увидеть новый значок нашего расширения (также известный как действие браузера ). Это извлекается из этой папки. Если вы щелкнете по нему, вы увидите всплывающее popup/App.vue
«Hello world!». Это создается с помощью popup/App.vue
.
И, наконец, обратите внимание на папку scripts
содержащую два сценария: один для удаления стандартных eval
использования в соответствии с политикой безопасности содержимого веб-магазина Chrome, а другой — для упаковки вашего расширения в файл .zip, который необходим при его загрузке в Интернет-магазин Chrome.
В файле package.json
объявлены также различные скрипты. Мы будем использовать npm run watch:dev
для разработки расширения, а позже npm run build-zip
для создания ZIP-файла для загрузки в Интернет-магазин Chrome.
Использование компонента Vue для новой вкладки
Начните с удаления раздражающего оператора alert
из background.js
.
Теперь давайте создадим новую папку tab
папке src
для размещения кода нашей новой вкладки. Мы добавим три файла в эту новую папку — App.vue
, tab.html,
, tab.js
:
mkdir src/tab touch src/tab/{App.vue,tab.html,tab.js}
Откройте tab.html
и добавьте следующее:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>New Tab Page</title> <link rel="stylesheet" href="tab.css"> </head> <body> <div id="app"></div> <script src="tab.js"></script> </body> </html>
Ничего особенного здесь не происходит. Это простая HTML-страница, которая будет содержать наш экземпляр Vue.
Далее в tab.js
добавьте:
import Vue from 'vue'; import App from './App'; new Vue({ el: '#app', render: h => h(App) });
Здесь мы импортируем Vue, передаем селектор для элемента, который мы хотим заменить нашим приложением, а затем сообщаем ему о необходимости визуализации нашего компонента App
.
Наконец, в App.vue
:
<template> <p>{{ message }}</p> </template> <script> export default { data () { return { message: "My new tab page" } } } </script> <style scoped> p { font-size: 20px; } </style>
Прежде чем мы сможем использовать эту новую вкладку, нам нужно обновить файл манифеста:
{ "name":"new-tab-page", ... "chrome_url_overrides": { "newtab": "tab/tab.html" } }
И нам также нужно, чтобы шаблон компилировал наши файлы и копировал их в папку dist
, чтобы они были доступны для расширения.
Измените webpack.config.js
примерно так, обновив ключи entry
и plugins
:
entry: { 'background': './background.js', 'popup/popup': './popup/popup.js', 'tab/tab': './tab/tab.js' }
plugins: [ ... new CopyWebpackPlugin([ { from: 'icons', to: 'icons', ignore: ['icon.xcf'] }, { from: 'popup/popup.html', to: 'popup/popup.html', transform: transformHtml }, { from: 'tab/tab.html', to: 'tab/tab.html', transform: transformHtml }, ... })
Вам нужно будет перезапустить задачу npm run watch:dev
чтобы эти изменения вступили в силу. После этого перезагрузите расширение и откройте новую вкладку. Вы должны увидеть «Моя новая вкладка».
Извлечение и показ шуток
Итак, мы перезаписали новую вкладку Chrome и заменили ее приложением mini Vue. Теперь давайте сделаем это больше, чем просто отобразим сообщение.
Измените раздел шаблона в src/tab/App.vue
следующим образом:
<template> <div> <div v-if="loading"> <p>Loading...</p> </div> <div v-else> <p class="joke">{{ joke }}</p> </div> </div> </template>
Измените раздел <script>
следующим образом:
<script> import axios from 'axios'; export default { data () { return { loading: true, joke: "", } }, mounted() { axios.get( "https://icanhazdadjoke.com/", { 'headers': { 'Accept': 'application/json' } } ) .then(res => { this.joke = res.data.joke this.loading = false; }); } } </script>
И наконец, измените раздел <style>
следующим образом:
<style> body { height: 98vh; text-align: center; color: #353638; font-size: 22px; line-height: 30px; font-family: Merriweather,Georgia,serif; background-size: 200px; display: flex; align-items: center; justify-content: center; } .joke { max-width: 800px; } </style>
Если вы запускаете задачу npm run watch:dev
, расширение должно автоматически перезагрузиться, и вы должны увидеть шутку, отображаемую при каждом открытии новой вкладки.
Как только вы убедились, что это работает, давайте уделим минуту, чтобы понять, что мы сделали.
В шаблоне мы используем блок v-if для отображения сообщения загрузки или шутки, в зависимости от состояния свойства loading
. Первоначально для этого параметра будет установлено значение true
(с отображением сообщения о загрузке), затем наш скрипт выполнит запрос Ajax для получения шутки. Как только Ajax-запрос завершится, свойство loading
будет установлено в false
, что приведет к повторной визуализации компонента и отображению нашей шутки.
В разделе <script>
мы импортируем axios, а затем объявляем пару свойств данных — вышеупомянутое свойство loading
свойство joke
для хранения шутки. Затем мы используем mounted
хук жизненного цикла , который срабатывает после монтирования нашего экземпляра Vue, чтобы сделать запрос Ajax к API-интерфейсу шутки . Как только запрос завершается, мы обновляем оба наших свойства данных, чтобы вызвать повторную визуализацию компонента.
Все идет нормально.
Сохранение шуток в хранилище Chrome
Далее, давайте добавим несколько кнопок, чтобы позволить пользователю добавить в избранное шутку и перечислить избранные шутки. Поскольку мы будем использовать API хранилища Chrome для сохранения шуток, возможно, стоит добавить третью кнопку, чтобы удалить все избранные шутки из хранилища.
Добавьте кнопки в блок v-else:
<div v-else> <p class="joke">{{ joke }}</p> <button @click="likeJoke" :disabled="likeButtonDisabled">Like Joke</button> <button @click="logJokes" class="btn">Log Jokes</button> <button @click="clearStorage" class="btn">Clear Storage</button> </div>
Здесь нет ничего захватывающего. Обратите внимание, как мы привязываем свойство disabled
кнопки like к свойству data в нашем экземпляре Vue, чтобы определить его состояние. Это потому, что пользователь не должен иметь возможность шутить больше одного раза.
Затем добавьте обработчики кликов и likeButtonDisabled
в наш раздел скриптов:
export default { data () { return { loading: true, joke: "", likeButtonDisabled: false } }, methods: { likeJoke(){ chrome.storage.local.get("jokes", (res) => { if(!res.jokes) res.jokes = []; res.jokes.push(this.joke) chrome.storage.local.set(res); this.likeButtonDisabled = true; }); }, logJokes(){ chrome.storage.local.get("jokes", (res) => { if(res.jokes) res.jokes.map(joke => console.log(joke)) }); }, clearStorage(){ chrome.storage.local.clear(); } }, mounted() { ... } }
Здесь мы объявили три новых метода для работы с тремя новыми кнопками.
Метод likeJoke
ищет свойство jokes
в хранилище Chrome. Если он отсутствует (то есть пользователю еще не понравилась шутка), он инициализирует его пустым массивом. Затем он помещает текущую шутку в этот массив и сохраняет ее обратно в хранилище. Наконец, он устанавливает для likeButtonDisabled
значение true
, отключая кнопку «Нравится».
Метод logJokes
также ищет свойство jokes
в хранилище Chrome. Если он находит один, он перебирает все свои записи и записывает их на консоль.
Надеюсь, что метод clearStorage
делает, ясно.
Попробуйте эту новую функциональность в расширении и убедитесь, что она работает.
Добавление польского в расширение
Ладно, похоже, это работает, но кнопки уродливы, а страница немного проста. Давайте закончим этот раздел, добавив немного блеска в расширение.
В качестве следующего шага установите библиотеку vue-awesome . Это позволит нам использовать некоторые иконки Font Awesome на нашей странице и сделать эти кнопки более приятными:
npm install vue-awesome
Зарегистрируйте библиотеку с помощью нашего приложения Vue в src/tab/tab.js
:
import Vue from 'vue'; import App from './App'; import "vue-awesome/icons"; import Icon from "vue-awesome/components/Icon"; Vue.component("icon", Icon); new Vue({ el: '#app', render: h => h(App) });
Теперь измените шаблон так:
<template> <div> <div v-if="loading" class="centered"> <p>Loading...</p> </div> <div v-else> <p class="joke">{{ joke }}</p> <div class="button-container"> <button @click="likeJoke" :disabled="likeButtonDisabled" class="btn"><icon name="thumbs-up"></icon></button> <button @click="logJokes" class="btn"><icon name="list"></icon></button> <button @click="clearStorage" class="btn"><icon name="trash"></icon></button> </div> </div> </div> </template>
Наконец, давайте добавим еще несколько стилей к кнопкам и добавим фотографию любимого папы :
<style> body { height: 98vh; text-align: center; color: #353638; font-size: 22px; line-height: 30px; font-family: Merriweather,Georgia,serif; background: url("https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2018/12/1544189726troll-dad.png") no-repeat 1% 99%; background-size: 200px; display: flex; align-items: center; justify-content: center; } .joke { max-width: 800px; } .button-container { position: absolute; right: 0px; top: calc(50% - 74px); } .btn { background-color: #D8D8D8; border: none; color: white; padding: 12px 16px; font-size: 16px; cursor: pointer; display: block; margin-bottom: 5px; width: 50px; } .btn:hover { background-color: #C8C8C8; } .btn:disabled { background-color: #909090; } </style>
Расширение должно перезагрузиться. Попробуйте открыть новую вкладку, и вы должны увидеть что-то вроде этого.
Загрузка расширения в Интернет-магазин Chrome
Если вы хотите, чтобы ваше расширение было доступно для загрузки другими пользователями, вы должны сделать это через Интернет-магазин Chrome .
Первое, что вам нужно для этого, — это учетная запись Google, которую вы можете использовать для входа на панель разработчика . Вам будет предложено указать данные разработчика, а перед публикацией первого приложения вы должны заплатить единовременный сбор за регистрацию разработчика в размере 5 долларов США (с помощью кредитной карты).
Далее вам нужно создать ZIP-файл для вашего приложения. Вы можете сделать это локально, запустив npm run build-zip
. Это создаст папку dist-zip
в корневом каталоге вашего проекта, содержащую ZIP-файл, готовый для загрузки в Интернет-магазин.
Для минимального расширения это все, что вам действительно нужно сделать. Однако, прежде чем что-либо загружать, стоит прочитать официальное руководство по публикации в Интернет-магазине Chrome .
Вывод
И с этим мы закончили. В этом уроке я выделил основные части расширения Chrome и показал, как использовать шаблон vue-web-extension для создания расширения с использованием Vue.js. Мы закончили, посмотрев, как загрузить расширение в Интернет-магазин и все, что с этим связано.
Надеюсь, вам понравился этот урок, и вы можете использовать его, чтобы начать создавать собственные расширения Chrome. Дайте мне знать, если вы сделаете что-нибудь классное .