Рубрики
Без рубрики

Fireedit: построить редактор в режиме реального времени с JavaScript & Firebase

Создайте редактор в режиме реального времени с JavaScript & Firebase.

Автор оригинала: Johnny B. (Ionică Bizău).

Я всегда был взволнован приложениями в реальном времени в Интернете. Несколько лет назад мои первые попытки состояли из реализации повторяющихся запросов, которые в конечном итоге приведут информацию от сервера имитации поведения в реальном времени. Работал, но это не было эффективным. С тех пор я узнал о веб-розетках.

Я слышал, что разработчики говорят о том, что называется Firebase Отказ Недавно Эмма – Хороший друг, коллеги-программист и удивительный человек – нужна помощь с Firebase, и мы решили узнать его вместе.

Теперь мы не эксперты, но так как мы достаточно хорошо У этого мы думали, что мы покажем вам, как создать приложение, используя Firebase и JavaScript – в частности, текстовый редактор в реальном времени, который живет в вашем браузер.

TL; доктор

Это наш окончательный результат: Fireedit – 📝 Используйте его, 🌟 🌟 it it, 🍴 вилка и наслаждаться ! 🚀.

Что мы сделали: 🔥 fireedit 📝

Сотрудничество важно везде. EMMA и я часто разделяем фрагменты кода (особенно когда нам нужно быстрое исправление к ошибке). Тем не менее, совместное использование маленьких фрагментов кода через чат приложения не является самой гладким опытом – им часто отсутствует функциональность редактирования, выделение синтаксиса, моносмасных шрифтов и т. Д.

Чтобы упростить процесс, я придумал идею построить редактор FireBase Powered, где мы можем поделиться кодом во время изучения FireBase (своего рода кругового опыта, не так ли?).

Мы позвонили наше приложение: Fireedit (Мы использовали Firebase для создания такого редактора, отсюда и имени). Это последний результат: https://coltaemanuela.github.io/fireedit/

(Вы заметите прекрасный спиннер, пока редактор загружается)

О, да, я знаю, что есть существующие решения, которые лучше, чем то, что у нас здесь, но эй, мы на самом деле имели это как наш опыт из первых рук, это открытый источник (вы можете сделать практически все, что списали код, который мы написали) , и мы собираемся показать вам, как мы это сделали!

С этой точки зрения этот технический пост собирается показать вам, как вы можете построить аналогичный редактор.

Итак, что именно Firebase?

Firebase – это мобильная платформа (iOS, Android) и веб-приложений, которая предоставляет различные инструменты и инфраструктуру, направленные на поддержку разработчиков в создании приложений в реальном времени. Поскольку мы говорим о веб-приложениях, мы забудем, что это мобильно удобно.

Когда вы просто начинаете работать с Firebase, первый шаг, который вы должны завершить, это Зарегистрируйтесь для этого. Затем вы можете начать создавать и управлять своими базами данных и интегрировать Firebase в вашем приложении.

Важно знать, что данные, которые вы хранят в базе данных, структурированы как объекты JSON.

Быстрое руководство о том, как начать работу с Firebase, доступен здесь Отказ Мы также очень быстро объясним, что вы должны знать об этом.

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

Есть несколько ограничений, если вы выбираете бесплатный план, но они все еще довольно либеральные. Это не должно иметь значения слишком много – если вам нужны суперсистемы, вы всегда можете Обновление до платного плана Отказ

Редактор ACE

Представьте себе текстовый редактор (например, Sublime Text), который на самом деле работает в вашем браузере (без установки любого дополнительного программного обеспечения, кроме самого браузера – который у вас уже есть, так как вы читаете этот очень текст).

Это то, что редактор ACE: модный текстовый редактор в вашем браузере (он поставляется с выделением синтаксиса, тем, опциональные привязки Vim/Emacs-yay!). Проверьте Официальные демонстрации – Кстати, у них тоже отличная документация!

Есть так же другие альтернативы. Вы можете найти их в Хороший и подробный список на Википедии Отказ

Создание приложения

Это будет веб-приложение. Поэтому нам понадобится немного HTML, CSS и, конечно, JavaScript! Давайте создадим эти файлы после этой структуры:

├── css
│   └── style.css
├── index.html
└── js
    └── index.js

index.html это файл, который собирается загрузить CSS/style.css и js/index.js Как только он открыт в браузере.

Давайте начнем с минимального HTML-кода в index.html :




    
        
        FireEdit
        
    
    
        

Welcome to FireEdit!

Мы не будем сосредоточиться на части CSS (которая позаботится о стиле) на данный момент. Вместо этого мы сосредоточимся на функциональной части (файл JavaScript). Одна из первых вещей, которые мы должны сделать, это создать приложение FireBase.

Конфигурация Firebase

  1. Создайте новое приложение FireBase

  2. Загрузите скрипт Firebase в вашем приложении:

    У нас уже есть в HTML-коде выше. Поскольку новые версии FireBase выделяются, вам придется изменить версию ( 3.6.4 ) в URL.

  3. Установите конфигурацию (вы можете найти это, нажав на Добавить FireBase в ваше веб-приложение Кнопка в обзоре Обзор Раздел)

Быстрое введение для использования FireBase в JavaScript

Представьте себе базу данных FireBase, как большой объект, где вы можете хранить данные. Мы разработали схему, как ниже (это пример, как может выглядеть объект):

{
    "root": {
        "editor_values": {
            "johnny+emma+article": {
                "content": "Hello world. This is how we started this very article. :D",
                "lang": "markdown",
                "queue": {...}
            }
        }
    }
}

Итак, как мы можем взаимодействовать с такой структурой формы JavaScript? Сначала нам нужна ссылка на корень узел. firebase.database () собирается вернуть это:

// Get the database object
var db = firebase.database();

После того, как у нас есть корне, мы можем получить конкретные данные. Предположим, мы хотим, чтобы содержание редактора с ID Джонни + Эмма + статья :

// We know what's the editor id
var editorId = "johnny+emma+article";

// Get the reference to the editor values
var editorValues = db.ref("editor_values");

// Get the entire editor object
editorValues.child(editorId).once("value", function (snapshot) {
    console.log(snapshot.value());
    /* {
        "content": "Hello world. This is how we started this very article. :D",
        "lang": "markdown",
        "queue": {...}
    } */
});

// Get the value of the `content` field only:
editorValues.child(editorId).child("content").once("value", function (snapshot) {
   console.log(snapshot.value());
   // "Hello world. This is how we started this very article. :D"
});

Используя Установить или Обновить Методы мы можем записать данные в базе данных FireBase.

Например, давайте изменим содержимое:

// This is going to set the content in the editor to "hello world"
editorValues.child(editorId).update({
    content: "hello world"
});

Синхронизация контента с другими клиентами

Когда мы производим обновление в базе данных, это обновление события распространяется всем клиентам, слушающим его. Например, когда я изменяю данные в моем редакторе, я хочу, чтобы EMMA посмотреть, что я изменил.

Мы начали с простого элемент, чтобы иметь доказательство концепции. В псевдо-коде, который будет выглядеть так:

[textarea]
 onchange -> save the value in Firebase

Firebase:
 - on change: update the textarea value

Мы получили это работать, но мы быстро поняли, что это не будет работать, потому что, на каждом обновлении, курсор будет прыгать в конце текстареа. Нам нужно что-то более мощное: Реальный редактор Отказ Это когда мы определились с редактором ACE. Во-первых, давайте инициализируем редактор.

var editor;
...
// Initialize the editor
editor = ace.edit("editor");

// Set the editor theme
// The getTheme() is returning a string
// which is the user's selected theme
editor.setTheme(getTheme());

Как только у нас есть редактор ACE инициализирован, следующая часть – заменить Onchange и настройка значения с ACE API. Давайте посмотрим, что произойдет, когда мы изменим контент в редакторе:

// Get the reference to the editor id
var currentEditorValue = editorValues.child(editorId);

// Get the `queue` child (which looks like an array where we push update events)
var queueRef = currentEditorValue.child("queue");

// This boolean is going to be true only when the value is being set programmatically
// We don't want to end with an infinite cycle since ACE editor triggers the
// `change` event on programmatic changes (which, in fact, is a good thing)
var applyingDeltas = false;

// Listen for the `change` event
editor.on("change", function(e) {

    // In case the change is emitted by us, don't do anything
    // (see below, this boolean becomes `true` when we receive data from Firebase)
    if (applyingDeltas) {
        return;
    }

    // Set the content in the editor object
    // This is being used for new users, not for already-joined users.
    currentEditorValue.update({
        content: editor.getValue()
    });

    // Generate an id for the event in this format:
    //  :
    // We use a random thingy just in case somebody is saving something EXACTLY
    // in the same moment
    queueRef.child(Date.now().toString() + ":" + Math.random().toString().slice(2)).set({
        // Store the data we get from ACE editor
        event: e,
        // Store the pseudo-user id
        by: uid
    }).catch(function(e) {
        // In case of errors, we want to see them in the console
        console.error(e)
    });
});

Теперь, когда мы знаем «Сохранение вещей» в базе данных работает, мы можем начать ждать обновления:

// Listen for updates in the queue
queueRef.on("child_added", function (ref) {

    // Get the timestamp
    var timestamp = ref.key.split(":")[0];

    // Do not apply changes from the past
    if (openPageTimestamp > timestamp) {
        return;
    }

    // Get the snapshot value
    var value = ref.val();
    
    // In case it's me who changed the value, I am
    // not interested to see twice what I'm writing.
    // So, if the update is made by me, it doesn't
    // make sense to apply the update
    if (value.by === uid) { return; }

    // We're going to apply the changes by somebody else in our editor
    //  1. We turn applyingDeltas on
    applyingDeltas = true;
    //  2. Update the editor value with the event data
    doc.applyDeltas([value.event]);
    //  3. Turn off the applyingDeltas
    applyingDeltas = false;
});

Обратите внимание, что Изменить Событие содержит внутренние метаданные о том, что было фактически изменилось. Он отлично работает с ApplyDELTAS , который получает массив объектов событий и просто применяет эти изменения в другой редактор без взаимодействия пользователя. Поскольку это пост конкретно адресованы туз, мы не будем слишком глубоко, объясняя, что магия за ApplyDetlas Метод есть, но мы можем легко догадаться, что у него много математики.

TL; доктор

Следующее изображение дает лучшее объяснение того, что происходит:

Установка языка редактора

Подобным, но намного проще, мы устанавливаем выделение языка:

// Select the desired programming language you want to code in 
var $selectLang = $("#select-lang").change(function () {
    // Set the language in the Firebase object
    // This is a preference per editor
    currentEditorValue.update({
        lang: this.value
    });
    // Set the editor language
    editor.getSession().setMode("ace/mode/" + this.value);
});

...

// Somebody changed the lang. Hey, we have to update it in our editor too!
currentEditorValue.child("lang").on("value", function (r) {
    var value = r.val();
    // Set the language
    var cLang = $selectLang.val();
    if (cLang !== value) {
        $selectLang.val(value).change();
    }
});

Установка темы

Поскольку мы не хотим распространять тему другим пользователям (например, я люблю темные темы, но, возможно, кто-то еще любит более светлые темы), мы будем хранить выбранную тему в местном хранилище:

// This function will return the user theme or the Monokai theme (which
// is the default)
function getTheme() {
    return localStorage.getItem(LS_THEME_KEY) || "ace/theme/monokai";
}

// Select the desired theme of the editor
$("#select-theme").change(function () {
    // Set the theme in the editor
    editor.setTheme(this.value);
    
    // Update the theme in the localStorage
    // We wrap this operation in a try-catch because some browsers don't
    // support localStorage (e.g. Safari in private mode)
    try {not focus
        localStorage.setItem(LS_THEME_KEY, this.value);
    } catch (e) {}
}).val(getTheme());

Мы не вставим весь файл здесь в этом руководстве, но Не стесняйтесь проверить это на Github Отказ

Но как я могу провести его в интернете?

Поскольку код размещен на Github, Страницы GitHub Вероятно, самый простой и самый быстрый способ пойти жить.

  1. Вы должны войти в «Настройки» вашего репозитория GitHub ( https://github.com///settings )
  2. Прокрутите вниз до раздела « Github Pages »
  3. Выберите Мастер ветвь (у нас нет модных вещей в нескольких ветках)
  4. Нажмите Сохранить И проект будет жить в https://<владелец> .github.io/ Отказ

В нашем случае Эмма является владельцем, а имя репозитория – Fireedit Отказ Вы можете получить доступ к приложению по адресу:

https://coltaemanuela.github.io/FireEdit/

Идеи

У нас есть некоторые идеи, которые вы можете захотеть реализовать. Вот несколько из них:

  • 🔐 аутентификация
  • ⚡️ Инструмент CLI подключается к одному и тому же редактору и позволяет вам редактировать Содержание прямо в вашем терминале.
  • ⏰ История пересмотра
  • ⚙️ Улучшить правила безопасности (это сильно связано с аутентификацией)
  • 👥 Показать активных пользователей

Еще кое-что

Не стесняйтесь Откройте проблему Для любой функции/ошибки/улучшения. Взносы тоже добро пожаловать!

Наслаждайтесь редактированными вещами с Fireedit И не делай это один. 😊.

Если вы построите что-то подобное или на основе fireedit, не забудьте пинг: @Emanuelacolta и @Ionicabizau Отказ 😇.

PS: Да, мы отредактировали эту статью, используя fireedit. 😅.