Локальное хранение файлов cookie, Storage, indexDB, автономный доступ ServiceWork к веб-сайтам

база данных сервер JavaScript браузер
Локальное хранение файлов cookie, Storage, indexDB, автономный доступ ServiceWork к веб-сайтам

личный блог

В повседневной разработке файлы cookie и Session/Local редко используются для последних двух.

cookie

Файл cookie — это клиентское решение, впервые изобретенное в марте 1993 года Лу Монтулли, бывшим сотрудником Netscape. Как мы все знаем, HTTP — это протокол без сохранения состояния.Клиент инициирует запрос, сервер обрабатывает запрос от клиента, а затем отправляет ответ обратно клиенту. После завершения обмена данными между клиентом и сервером соединение между сервером и клиентом будет закрыто Веб-сервер почти не имеет информации, чтобы определить, какой пользователь отправил запрос, и не может записать последовательность запросов посещения пользователь. Необходимо установить новое соединение. Позже, когда появятся пользователи, веб-сайт захочет понять потребности пользователей. Однако, согласно ситуации в то время, очевидно, что бизнес-потребности не могут быть удовлетворены, поэтому файлы cookie рождаются, что может компенсировать отсутствие части HTTP-протокола без сохранения состояния.


Давайте сначала посмотрим, как этот файл cookie используется в повседневной работе.


Перед запуском удалите все локальные значения файлов cookie.


Введите «Наггетс», Baidu слушаетfocusа такжеinputсобытие, поэтому 2 запроса запускаются в первый раз, и странно то, что в первый раз не возвращается Set-cookie:



Focus() срабатывает впервые, в это время заголовок запроса Request Header не содержит файлов cookie, а поле запросаwdПараметр отсутствует, историческая запись Hisdata считывает исторический запрос и метку времени клиента в LocalStorage. см. второй запрос

Сервер возвращает 7 Set-Cookies, а клиент сохраняет данные после получения данных.


В это время вы можете увидетьCookieЕсть все файлы cookie, возвращаемые сервером, и соответствующие значения и другие конфигурации;

Каждый раз, когда клиент запрашивает в первый раз, сервер устанавливает его для клиента после получения запроса.cookie, сервер отправляет клиентуCookieчерезHTTPОтветное сообщение реализовано вSet-CookieУстановите сообщение, которое необходимо отправить клиенту вcookie, браузер получает кеш ответаcookieв память или на жесткий диск (в зависимости от механизма браузера), и он будет переноситься каждый раз, когда вы отправляете запросcookie:


Формат файла cookie следующий:

Полученный формат файла cookie

Set-cookie: name=value [; expires=date] [; path=path] [; domain=domain] [;secure=secure]

формат куки отправлен

Cookie: name1=value1 [; name2=value2]

  • name: Уникально определенное имя файла cookie. Вообще говоря, имена файлов cookie не чувствительны к регистру. 
  • value: строковое значение, хранящееся в файле cookie. Лучше всего закодировать в URL имя и значение файла cookie.
  • домен: имя домена, под которым действителен файл cookie. Все запросы к этому домену будут включать информацию об этом файле cookie. Это значение может включать субдомены (например, m.baidu.com) или нет (например, .baidu.com, оно действительно для всех субдоменов baidu.com). 
  • путь: указывает путь, на который влияет этот файл cookie. Затем браузер отправит файл cookie по соответствующему пути в указанном домене в соответствии с этой конфигурацией.
  • expires: время истечения срока действия, указывающее отметку времени самоудаления файла cookie. Если эта метка времени не установлена, файл cookie станет файлом cookie сеансового типа, и браузер удалит все файлы cookie при закрытии страницы. Это значение указано в формате времени по Гринвичу. Если время клиента и сервера несовместимы, использование expires будет Там является отклонением. 
  • max-age: так же, как и expires, он используется, чтобы сообщить браузеру, как долго этот файл cookie истекает (в секундах), а не фиксированный момент времени. Обычно max-age имеет приоритет над expires. 
  • HttpOnly: говорит браузеру не разрешать скрипту document.cookie изменять это значение, также это значение не отображается в document.cookie. Но файл cookie по-прежнему будет передаваться в http-запросе. Обратите внимание, что это значение, хотя и недоступно в сценарии, все же существует в виде файла в каталоге установки браузера. Этот параметр обычно задается на стороне сервера. 
  • secure: флаг безопасности, если он указан, он будет отправлен на сервер только при использовании ссылки SSL (https).Если это ссылка http, это значение не будет передано. Но есть и другие способы локального просмотра файлов cookie.

Мы можем вручную установить возврат куки,

var http = require('http');
var fs = require('fs');

http.createServer(function(request, responed) {
    responed.setHeader('status', '200 OK');
    responed.setHeader('Set-Cookie', 'userStatus=true;domain=.juejin.com;path=/;max-age=1000');
    responed.write('掘金');
    responed.end();
}).listen(8888);

Затем запустите сервер, и вы увидите, как сервер возвращается при посещении.

Set-Cookie:userStatus=true;domain=.juejin.com;path=/;max-age=1000    

Преимущества файлов cookie

  • Форма пары ключ-значение файла cookie, простая структура
  • Время истечения срока действия можно настроить, не требуя наличия каких-либо ресурсов сервера на стороне клиента,
  • Это может компенсировать отсутствие части HTTP-протокола без сохранения состояния.
  • Никаких проблем с совместимостью.

Недостатки файлов cookie

  • Размер и количество ограничены, каждый домен может иметь не более 20 файлов cookie, а длина каждого файла cookie не может превышать 4096 байт, в противном случае он будет обрезан. Хотя сегодняшние новые браузеры и клиентские устройства начинают поддерживать 8192 байта.
  • Конфигурация пользователя может быть отключена. Некоторые пользователи отключили возможность своего браузера или клиентского устройства получать файлы cookie, тем самым ограничивая эту функциональность.
  • Чтобы увеличить потребление трафика, каждый запрос должен приносить информацию о файлах cookie.
  • Угрозы безопасности. Хакеры могут выполнять перехват файлов cookie, атаки с использованием межсайтовых сценариев XSS и обман файлов cookie. Исторически сложилось так, что многие пользователи веб-сайтов подвергались атакам с помощью файлов cookie. Хотя файлы cookie можно шифровать и расшифровывать, это повлияет на производительность.

Сводка файлов cookie

В сценариях развития бизнеса файлы cookie больше используются в качестве идентификатора для записи поведения пользователя, а не идентификационной информации пользователя.После входа пользователя в систему создается определенный файл cookie, и когда снова инициируется другой запрос, сервер может определить, является ли user is Если вы можете продолжить эту операцию, если нет, действуйте соответственно. Очень опасно помещать идентификационную информацию пользователя и другую важную информацию в файлы cookie, а для веб-сайтов с большим трафиком потребление каждого байта исчисляется десятками терабайт в год.

Возьмите Google в качестве примера:
googleтрафик с учетом всего интернета40%,2016Годовой глобальный сетевой трафик достигает1.3ZB(1ZB = 10^9TB),Такgoogleсуществует2016Годовой поток1.3ZB*40%,еслиgoogleКаждый1MBзапросить уменьшение байта, сэкономив почти500TB。

Session/Local

SessionStorage называется хранилищем сеансов, а LocalStorage — это наиболее широко используемое и простое в эксплуатации локальное хранилище во внешнем интерфейсе. Оба следуют политике одного и того же источника (имя домена, протокол, порт). большой, обычно 5M, что значительно решает проблему, прежде чем для хранения данных можно использовать только файлы cookie с небольшой емкостью, неудобным доступом и простым удалением. Эта функция обеспечивает большую гибкость для клиентов.

Не только поддерживает IE8 и выше, вы можете пройтиОфициальный метод MDN, который хранится в куки в замаскированном виде, но в этом случае теряется смысл существования объекта Хранилище.

Session只作用于当前窗口,不能跨窗口读取其他窗口的SessionStorage数据库信息,浏览器每次新建、关闭都是直接导致当前窗口的数据库新建和销毁。 Совместимость следующая:


Локальный действует на текущий браузер, даже если вы открываете два браузера Chrome (не два окна), все равно остается общий адрес пути. Никогда не удаляются автоматически, поэтому, если мы используем LocalStorage для сохранения конфиденциальной и важной информации, следует также обратить внимание не на локальное, а на сессию, очистку после закрытия, иначе злоумышленник может украсть информацию с помощью XSS-атак. Совместимость следующая:


На стороне ПК только Chrome и Firefox имеют небольшое отклонение в совместимости, а совместимость на мобильной стороне такая же.


PS: когда браузер входит в режим приватного просмотра, будет создана новая временная база данных для хранения данных локального хранилища; когда режим приватного просмотра выключен, база данных будет очищена и удалена.

Просто имя API другое.

localStorage.setItem('key', 'value');  // 设置
localStorage.getItem('key');  // 获取
localStorage.removeItem('key'); // 删除
localStorage.clear(); //清除所有

Однако при хранении и чтении данных данные должны быть JSON.stringify и JSON.parse, иначе тип данных будет вынужден измениться.

var obj = {
    name:'掘金',
    url:'juejin.com'
    }
var arr = [1,2,3]

//错误方法
localStorage.setItem('object',obj);  //object:"[object Object]" 无法读取
localStorage.setItem('array',arr);  //array:"1,2,3" 变成string格式

//正确方法:Object
localStorage.setItem('object',JSON.stringify(obj));//存储 object:"{"name":"掘金","url":"juejin.com"}"
JSON.parse(localStorage.getItem('object'));//读取 {name: "掘金", url: "juejin.com"}

//正确方法:Array
localStorage.setItem('array',JSON.stringify(arr));  //存储 array:"[1,2,3]"
JSON.parse(localStorage.getItem('array'));//读取  [1,2,3]

Сеанс/локальные преимущества

  • Объем хранимых данных большой, 5Мб.
  • Не будет отправлен с HTTP-запросом, что эффективно уменьшит размер запроса.
  • Локальная обработка данных в разных окнах может сократить значительную часть состояния локальной обработки и обслуживания.

Сессионные/локальные недостатки

  • Суть в том, чтобы читать и записывать файлы, а запись большого количества данных скажется на производительности (firefox записывает в память localstorage)
  • XSS-атака для кражи информации (для безопасности поставим сессию)
  • Совместимость, хоть и говорят, что IE6 умер, но я видел много Nuggets Duan, вы все еще пишете статьи, которые совместимы с IE6... Это действительно собака, если ваш проект все еще пишет совместимость с IE6, я вас уважаю за быть мужчиной!
  • не может быть прочитан поисковыми роботами

Сеанс и локальная сводка

Первоначально это было решение для файлов cookie, подходящее для хранения небольших данных простой структуры и поддержания состояния, но не подходящее для хранения конфиденциальной информации. Может использоваться во всех бизнес-сценариях.

IndexedDB

IndexedDB — это новая встроенная в браузер база данных в спецификации HTML5. Подобно NoSQL, он обеспечивает способ хранения и использования данных, аналогичный базе данных. Однако данные в IndexedDB хранятся постоянно, что подходит для хранения большого объема структурированных данных.Некоторые данные должны существовать на сервере, но через indexedDB можно уменьшить большую нагрузку на сервер, а локальное чтение , модификация и использование могут быть реализованы, и все данные хранятся в виде объектов.Объекты имеют индекс значения ключа.

Операции в IndexedDB являются транзакционными. Объект хранится в хранилище объектов, которое эквивалентно таблице в реляционной базе данных. IndexedDB может иметь много хранилищ объектов, и в хранилище объектов может быть много объектов.

Первый взгляд на совместимость


Собственный браузер Windows поддерживается лишь частично, а IE11 поддерживается только Windows 8.1 и выше.

Сначала мы создаем базу данных

//首先定义一个自己的版本
var my = {
    name:'juejin',
    version:'1',
    db:null
}
//打开仓库,没有则创建
var request = window.indexedDB.open(my.name);
//window.indexedDB.open()的第二个参数即为版本号。在不指定的情况下,默认版本号为1.
//版本号不能是一个小数,否则会被转化成最近的整数。同时可能导致不会触发onupgradeneeded版本更新回调
console.log(request);

Возвращается объект с именем IDBOpenDBRequest.


Для каждого состояния есть параметры обратного вызова, и все они равны нулю при инициализации. Вам необходимо вручную смонтировать пользовательские параметры обратного вызова для достиженияwindow.indexedDB.openУправление обратным вызовом состояния функции, а затем перейдите к indexedDB консольного приложения для просмотра


Мы успешно добавили объект базы данных с именем juejin, и источник безопасности представляет собой источник безопасности (я создал его в консоли личного блога).

request.onerror = function(event){ //打开失败回调
    console.log(`${my.name} open indexedDB is Fail`);
}
request.onsuccess = function(event){ //打开成功回调
    console.warn(`${my.name} open indexedDB is success`);
    //将返回的值赋给自己控制的db版本对象,下面两种方法都能接收到。
    my.db = event.target.result|| request.result;
}
request.onupgradeneeded = function (event) {//版本变化回调参数,第一次设置版本号也会触发
    console.log('indexDB version change');
}
console.log(my.db);

Возвращается объект базы данных, который содержит методы обратного вызова для последующего управления состоянием объекта базы данных. Эти методы еще должны быть определены сами по себе.


Как закрыть объект БД и удалить объект БД? Закрыть и удалить - два понятия.

//关闭db对象,之后无法对其进行插入、删除操作。
my.db.close();

//而删除方法则挂载在window.indexedDB下,删除该db仓库
window.indexedDB.deleteDatabase(my.db);

Здесь следует отметить, что этоonclose()Метод не вызывается приведенным выше кодомclose()метод,my.db.close()Вызывается метод в прототипе __proto__.

Узнав, как создавать и работать с indexedDB, мы добавляем таблицы в хранилище объектов. Как мы упоминали выше, в indexedDB используется концепция не таблицы, а хранилища объектов.База данных может содержать несколько хранилищ объектов.Хранилище объектов представляет собой гибкую структуру данных, которая может хранить различные типы данных. Другими словами, хранилище объектов эквивалентно таблице, и каждая часть данных, хранящихся в нем, связана с ключом.

Мы можем использовать указанное поле в каждой записи в качестве значения ключа (keyPath), или вы можете использовать автоматически сгенерированный увеличивающийся номер в качестве ключа (keyGenerator), или не указано. Тип ключа выбора отличается, и структура данных, которую может хранить объектное хранилище, также отличается.

Создание объекта хранилища объектов может быть выполнено только изonupgradeneededОбратный вызов изменения версии.

//创建object store对象
request.onupgradeneeded = function() {    
    var db = request.result;    
    var objectStore = db.createObjectStore("LOL", {keyPath: "isbn"});    
    var titleIndex = objectStore.createIndex("by_hero", "hero", {unique: true});    
    var authorIndex = objectStore.createIndex("by_author", "author");
    objectStore.put({title: "亚索", author: "Roit", isbn: 123456});    
    objectStore.put({title: "提莫", author: "Roit", isbn: 234567});    
    objectStore.put({title: "诺手", author: "Hang", isbn: 345678});
};

createObjectStoreМетод имеет 2 параметра, первый имя таблицы хранилища объектов, второй объект,keyPathДля хранения свойства объекта (в виде значения ключа) у options также есть параметр:autoIncrementУказывает, следует ли выполнять автоинкремент. Далее создайте индекс

var titleIndex = objectStore.createIndex("by_title", "title", {unique: true});    
var authorIndex = objectStore.createIndex("by_author", "author");

Первый параметр — это имя индекса, второй параметр указывает, какой атрибут хранимых данных строить индекс, а третий параметр объекта, где атрибутuniqueценностьtrueУказывает, что значения индекса не могут быть равными. Второй индекс не имеет объекта параметров, и тогда мы можем добавить данные через метод put.

objectStore.put({hero: "亚索", author: "Roit", isbn: 123456});    
objectStore.put({hero: "提莫", author: "Roit", isbn: 234567});    
objectStore.put({hero: "诺手", author: "Hang", isbn: 345678});

Напишите общий код

var my = {//定义控制版本       
    name:'juejin',       
    version:'1',       
    db:null     
};
var request = window.indexedDB.open(my.name);  //创建打开仓库     
request.onupgradeneeded = function() {//更新版本回调    
    var db = request.result;    
    var objectStore = db.createObjectStore("LOL", {keyPath: "isbn"});    
    var heroIndex = objectStore.createIndex("by_hero", "hero", {unique: true});    
    var authorIndex = objectStore.createIndex("by_author", "author");
    objectStore.put({hero: "亚索", author: "Roit", isbn: 123456});        
    objectStore.put({hero: "提莫", author: "Roit", isbn: 234567});        
    objectStore.put({hero: "诺手", author: "Hang", isbn: 345678});
};
request.onsuccess = function() {//成功回调    
    my.db = event.target.result|| request.result;    
    console.warn(`${my.name} indexedDB is success open Version ${my.version}`);
};
request.onerror = function() {//失败回调    
    console.warn(`${my.name} indexedDB is fail open  Version ${my.version}`);
};

Обратите внимание, что хранилище будет выполняться только в работающей среде.Локальные открытые статические файлы не будут хранить indexedDB, хотя они могут всплывать.juejin indexedDB is success open. Таким образом, мы успешно создали хранилище объектов, давайте перейдем в консоль, чтобы увидеть



by_heroУказывает, что при создании индекса передатьcreateObjectStore('by_hero','hero',{unique:true})Когда , передать значение ключаheroОбъект, данные для индексной фильтрации. еще разby_authorСмотреть,


Точно так же ключевое значениеauthor, данные для индексации. Это позволяет хранить большие объемы структурированных данных. И имеет возможность индексации, которая сильнее, чем хранилище. Конечно, API тоже хлопотно. Далее займитесь хозяйственными операциями.

существуетIndexedDB, используйте транзакции для выполнения операций с базой данных. Транзакции имеют три режима, по умолчанию только для чтения.

  • readOnlyТолько чтение.
  • readwriteпрочти и напиши.
  • versionchangeИзменения версии базы данных
//首先要创建一个事务,
var transaction = my.db.transaction('LOL', 'readwrite');
//获取objectStore数据
var targetObjectStore = transaction.objectStore('LOL');
//对预先设置的keyPath:isbn进行获取
var obj = targetObjectStore.get(345678);
//如果获取成功,执行回调
obj.onsuccess = function(e){    
    console.log('数据成功获取'+e.target.result)
}
//获取失败obj.onerror = function(e){    
    console.error('获取失败:'+e.target.result)
}


Приобретение успешно, и данные с isbn 345678 получены.

Первый параметр — это имя хранилища объектов, которое необходимо связать, а второй параметр — режим транзакции, который доступен для чтения и записи.Как и в indexedDB, методы обратного вызова onsuccess и onerror будут запущены после успешного вызова. можно прочитать мы пытаемся добавить

targetObjectStore.add({hero: "盖伦", author: "Yuan", isbn: 163632});        
targetObjectStore.add({hero: "德邦", author: "Dema", isbn: 131245});        
targetObjectStore.add({hero: "皇子", author: "King", isbn: 435112});

Следует отметить одну вещь: добавление дубликатов обновлений. После добавления перейдите в консоль, чтобы увидеть


Нет, должно быть.После обновления бесчисленное количество раз, я наконец нашел решение. Это может быть ошибка в Chrome.


удалить данные

//获取数据是get,删除数据是delete
targetObjectStore.delete(345678);


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

обновить данные

var obj = targetObjectStore.get(123456);
//如果获取成功,执行回调
obj.onsuccess = function(e){    
    console.log('数据成功获取'+e.target.result);
    var data = e.target.result;
    data.hero = '亚索踩蘑菇挂了';
    //再put回去
    var updata = targetObjectStore.put(data);
    updata.onsuccess = function(event){
        console.log('更新数据成功'+event.target.result);
    }
}


Чтобы снова отфильтровать.

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

var request = window.indexedDB.open('juejin');

request.onsuccess = function (event) {
    var db = event.target.result;
    var transaction = db.transaction('LOL', 'readwrite');
    //获取object store数据
    var objectStore = transaction.objectStore('LOL');
    //获取该数据的浮标
    var eachData = objectStore.openCursor();
        //openCursor有2个参数(遍历范围,遍历顺序)
    eachData.onsuccess = function (event) {
        var cursor = event.target.result;
        if (cursor){    
            console.log(cursor);
            cursor.continue();
        }
    };

    eachData.onerror = function (event) {
        consoe.error('each all data fail reason:'+event.target.result);
    };
}

так черезopenCursorПолученные данные аналогичныforEachВывод, когда в таблице нет данных, он все равно вызовет ее один разonsuccessПерезвоните

упомянутый вышеopenCursorДва параметра, первый — это диапазон обхода по indexedDB:IDBKeyRangeAPI для реализации, в основном имеет следующие значения

//区间向上匹配,第一个参数指定边界值,第二个参数是否包含边界值,默认false包含。
lowerBound('边界值',Boolean);
var index = IDBKeyRange.lowerBound(1);//匹配key>=1
var index = IDBKeyRange.lowerBound(1,true);//匹配key>1

//单一匹配,指定参数值
only('值');
var index = IDBKeyRange.only(1);//匹配key===1;

//区间向下搜索,第一个参数指定边界值,第二个参数是否包含边界值,默认false包含。
upperBound('边界值',Boolean);
var index = IDBKeyRange.upperBound(2);//匹配key<=2
var index = IDBKeyRange.upperBound(2,true);//匹配key<2

//区间搜索,第一个参数指定开始边界值,第二个参数结束边界值,
//        第三个指定开始边界值是否包含边界值,默认false包含。第四个指定结束边界值是否包含边界值,默认false
bound('边界值',Boolean);
var index = IDBKeyRange.bound(1,10,true,false);//匹配key>1&&key<=10;

Второй параметр openCursor, порядок обхода, указывает порядок, в котором перемещается курсор, и метод обработки, когда повторяется один и тот же идентификатор (поле, заданное атрибутом keyPath). Диапазон изменения получается через определенную строку. в:

  • IDBCursor.next, получить все данные от начала до конца (включая дубликаты)
  • IDBCursor.prev, извлекает все данные сзади наперед (включая дубликаты)
  • IDBCursor.nextunique, получить данные спереди назад (за дублирующиеся данные берется только первый)
  • IDBCursor.prevunique, получить данные сзади наперед (за дублирующиеся данные берется только первый)

давай попробуем

var request = window.indexedDB.open('juejin');
request.onsuccess = function (event) {
    var db = event.target.result;
    var transaction = db.transaction('LOL', 'readwrite');
    //获取object store数据
    var objectStore = transaction.objectStore('LOL');
    //bound('边界值',Boolean);匹配key>22000&&key<=400000;
    var index = IDBKeyRange.bound(220000,400000,true,false);
    //获取该数据的浮标,从前往后顺序索引,包括重复数据
    var eachData = objectStore.openCursor(index,IDBCursor.NEXT);
    eachData.onsuccess = function (event) {
        var cursor = event.target.result;
        console.log(cursor);
        if (cursor) cursor.continue();
    };
    eachData.onerror = function (event) {
        consoe.error('each all data fail reason:'+event.target.result);
    };
}

Найдите данные со значением ключа от 220 000 до 400 000 000 и найдите его.


Что ж, indexedDB в основном то же самое, что и транзакционная операция. Теперь давайте поговорим о другом ее аспекте:

Пока известно то,IndexedDBв паре ключ-значениеkeyValue может принимать следующие типы значений:

  • Number
  • String
  • Array
  • Object
  • Двоичный двоичный

Но при хранении данных следует иметь в виду, что если вы храните данныеisbnОдни и те же данные являются недопустимой операцией и могут даже вызвать ошибку.

keyPathДопустимые форматы данных, в примереcreateObjectStoreустановить, когда{KeyPath:'isbn'}, первичный ключ

  • Blob
  • File
  • Array
  • String

Что касается значения, то оно может принимать практически все форматы данных.

Преимущества indexedDB

  • Заменяя веб-SQL, он непобедимо сочетается с работой службы, а автономный доступ не представляет проблемы.
  • Объем хранилища данных не ограничен (пока достаточно вашего жесткого диска), а Chrome оговаривает, что он занимает только 1/3 доступного места на жестком диске.Преимущество хранения структурированных данных заключается в том, что это может сэкономить расходы на сервер .

Недостатки IndexedDB

  • Проблемы совместимости, только ie11 или выше, внимательно рассмотрите требования в соответствии с бизнес-сценариями.
  • Политика того же происхождения, некоторые браузеры, такие как режим конфиденциальности мобильной версии Safari при доступеIndexedDB, исключения могут возникать из-за отсутствия разрешений (также LocalStorage), и требуется обработка исключений.
  • Как и в случае с SQL, этот API более сложен, и при работе с большим объемом данных может снижаться производительность.
  • Когда пользователь очищает кеш браузера, он может очиститьIndexedDBсвязанные данные.

ServiceWork

Что такое СервисВорк? serviceWork — это проект, предложенный W3C в 2014 году. Это скрипт, который работает в фоновом режиме независимо от текущей страницы. Фон здесь относится к фону браузера, который позволяет веб-приложению иметь те же возможности автономного доступа к программам, что и собственное приложение, позволяя пользователям работать в автономном режиме и получать сообщения. Сервис-воркер — это скрипт, который, как и веб-воркер, работает в фоновом режиме. Как независимый поток среда выполнения отличается от среды обычных сценариев, поэтому она не может напрямую участвовать в веб-взаимодействии. Нативные приложения можно использовать в автономном режиме, отправлять сообщения и автоматически обновляться в фоновом режиме.

Значение ServiceWork

Мы открыли единый поток текущего браузера.По мере того, как производительность интерфейса становится все сильнее и сильнее, а требования становятся все выше и выше, мы все знаем, что в браузере JavaScript выполняется в одном потоке.Если он предполагает большое количество операций, это очень может затруднить отрисовку CSS-дерева, тем самым блокируя скорость выполнения последующего кода.Появление ServiceWork как раз решает эту проблему.Некоторые ресурсные файлы, требующие масштабного расчета данных и захват обрабатываются в фоновом режиме, а затем результат возвращается в основной поток.Основной поток выполняет рендеринг, что позволяет избежать блокировки основного потока огромным количеством логики и операций. Это значительно улучшает способность потоков JavaScript обрабатывать крупномасштабные операции, что также является огромным преимуществом самого ServiceWork.Например, нам нужно выполнять операции с 3D-моделями и данными в сцене WebGBL.Обычные данные могут быть такими же высокими. как несколько МБ. Если операция выполняется в основном потоке, это будет серьезно мешать рендерингу страницы. В это время очень удобно, чтобы ServiceWork выполнял фоновый расчет, а затем возвращал результат в основной поток для рендеринг.

Особенности СервисВорк

Работники службы могут:

  1. push сообщения, доставка
  2. Операции фоновой синхронизации выполняются, не влияя на взаимодействие страниц и блокируя потоки.
  3. Перехват сети, проксирование, переадресация запросов, подделка ответов
  4. Автономный кеш
  5. Таргетинг на геозоны

Сказав так много, какая польза от этого в нашей реальной работе?Здесь мы представим Google PWD (прогрессивные веб-приложения), новую модель веб-приложения, прогрессивное веб-приложение, которое опирается на сервисную работу. для обеспечения базового доступа к странице даже в среде без сети, без «не подключенного к Интернету», может оптимизировать рендеринг страницы и доступ к сетевым данным и может быть добавлен на рабочий стол мобильного телефона с полноэкранным статусом и сообщениями, как обычные приложения функция push.



ЭтоService WorkЖизненный цикл , во-первых, если нет работ по обслуживанию, будет выполнено состояние установки, аpromiseНапример, отклонение перейдет на шаг Ошибка,resolveУстановка прошла успешно, по завершении установки введитеActivatedАктивное состояние, на этом этапе вы также можете обновитьservice worker的版本,具体内容我们会在后面讲到。 После активацииservice workerвозьмет на себя все страницы в пределах своего домена, но если страница только что зарегистрированаservice worker, то на этот раз он не будет использован до следующей загрузки страницы,service workerвступит в силу. когдаservice workerПосле захвата страницы она может находиться в двух состояниях: либо завершена для экономии памяти, либо обработанаfetch(перехватывать и делать сетевые запросы) иmessage(передача информации), эти два события происходят, когда сетевой запрос возникает при инициализации страницы или при отправке сообщения на странице.

Какие страницы в настоящее время поддерживаютсяservice WorkШерстяная ткань?

Введите в адресной строке браузера Chromechrome://inspect/#service-workers, вы можете увидеть всю поддержку, которую вы посетили до сих порservice workвеб-сайт

Вы также можете открыть консоль, перейти в Application, щелкнуть столбец serviceWork,

Итак, как мы можем испытать работу сервиса?Давайте возьмем в качестве примера официальный сайт Vue.Сначала откройте https://cn.vuejs.org/, дождитесь завершения загрузки, а теперь отключите свой WiFi и все инструменты, которые могут подключиться к Интернету. Обновите страницу адресной строки



Это чувствует себя очень новым, как это сделать, продолжайте смотреть вниз. Вам нужно запустить локальную среду, и вы можете использовать различные методы для Baidu.Я использую облачный сервер Tencent, который я купил сам, и nginx открывает еще несколько портов, и SFTP загружается автоматически. Вы также можете построить локальныйlocalhost, помните, что нельзя использовать IP-адрес,ServiceWorkВеб-сайты, чьи доменные имена являются IP-адресами, не поддерживаются, поэтому приступим.

Сначала создайте папку, затем создайтеindex.html,index.css,app.js,servicework.jsМы будем использовать эти файлы позже.

index.html

<!DOCTYPE html>
<html lang="en">
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <meta http-equiv="X-UA-Compatible" content="ie=edge">  
    <title>ServiceWork</title>
</head>
<body>
    <h1>ServiceWork</h1>
</body>
<script src="./app.js"></script>
<link rel="stylesheet" href="./index.css">
</html>

Добавлен файл main.css и app.js.

main.css

h1{  
    color:red;
    text-align:center;
}

app.js

alert(1);

После успешной проверки всплывающего оповещения (1) приступаем к написанию кода.

Первое, что нужно сделать, это определить, поддерживает ли онServiceWork.

app.js

if (navigator.serviceWorker) {   
//先注入注册文件,第二个参数为作用域,为当前目录    
navigator.serviceWorker.register('./servicework.js', {
        scope: './'    
    }).then(function (reg) {
        console.warn('install ServiceWork success',reg)    
    }).catch(function (err) {        
        console.error(err)    
    })
} else {    
    //不支持serviceWork操作
}

Импортируйте файл конфигурации регистрации, верните обещание, активируйте соответствующий обратный вызов, а затем измените его.servicework.jsдокумент,

//self是serviceWorker的实例。
console.log(self)//
给实例监听安装事件,成功触发回调self.addEventListener('install', function (e) {
    //ExtendableEvent.waitUntil()扩展事件的生命周期。    
    e.waitUntil(        
    //我们通过打开名称为'app-v1'的缓存,将读取到的文件储存到cache里
        caches.open('app-v1').then(function (cache) {
           console.log('caches staticFile success');
           //添加cache
           return cache.addAll([
               './app.js',
               './servicework.html',
               './servicework.js',
               './index.css'
           ]);
         })
    );
 });

ExtendableEvent.waitUntil()принять одинpromiseОбъект, который продлевает время жизни, продлевая время жизни события, тем самым не позволяя браузеру завершать рабочий поток службы до тех пор, пока не завершится асинхронная операция в событии. Он продлевает время жизни события, продлевая время жизни события, тем самым предотвращая завершение потока работника службы браузером до завершения асинхронной операции в событии.


install, это задержит установкуworksрассматривается какinstalling, пока не прошлоPromiseбыл успешноresolve. Убедитесь, что сервисные работники не установлены до тех пор, пока все зависимые основные кэши не будут кэшированы.

однаждыService Workerуспешно установлен, он перейдет кActivationсцена. если предыдущийService Worker по-прежнему обслуживает любые открытые страницы, новый Service Worker Войтиwaitingусловие. новыйService Workerтолько в старомService WorkerАктивируется, когда ни одна страница не загружена. Это гарантирует, что в каждый момент времени работает только одна версия сервис-воркера. когда проводится

activited
Когда это будет отложеноactive workсчитается активированным до тех пор, пока не пройдетPromiseбыл успешноresolve. Убедитесь, что время функции не отправляетсяServiceWorkerGlobalScopeобъект.


Более подробную информацию можно найти наПосмотреть API на MDNБольше объяснения.

После успешного бросания его в кеш вы можете использовать Fetch для сетевого перехвата.


  //同样的方法,监听fetch事件, 
self.addEventListener('fetch', function (event) {
    //respondWith方法产生一个request,response。
    event.respondWith(
      //利用match方法对event.request所请求的文件进行查询
      caches.match(event.request).then(
        function (res) {
          console.log(res, event.request);
          //如果cache中有该文件就返回。
          if (res) {
            return res
          } else {
            //没有找到缓存的文件,再去通过fetch()请求资源
            fetch(res.url).then(function (res) {
              if (res) {
                if (!res || res.status !== 200 || res.type !== 'basic') {
                  return res;
                }
                //再将请求到的数据丢到cache缓存中..
                var fetchRequest = event.request.clone();
                var fileClone = res.clone();
                caches.open('app-v1')
                  .then(function (cache) {
                    cache.put(event.request, fileClone);
                  });
              } else {
                //没有请求到该文件,报错处理
                console.error('file not found:' + event.reuqest + '==>' + res.url)
              }
            })
          }
        }
      )
    );
  });

Вы должны быть знакомы с интерфейсомrequest,responseчто он представляет,event.respondWith()создаст страницу на основе текущей контролируемой страницыrequest,requestдля создания пользовательскихresponse,network errorилиFetchПутьresolve.


fetch() перехватывает сеть, прокси-запросы, сначала читает локальные файлы, а затем запрашивает, если ресурсов нет, что значительно экономит потребление сетевых запросов.

Теперь давайте попробуем проверить, работает ли это!


Ага, красиво! Таким образом достигается автономный доступ, но в реальных проектах старайтесь не кэшировать файл servicework.js, который может вовремя не вступить в силу и внести последующие модификации. Заходим в консоль

Он установлен и работает.

Общий процесс выглядит следующим образом

Обновления в сервисе work.js

Обновление Service Work.js — это не просто обновление, есть еще много способов повысить надежность пользователей.

  • Сначала обновите файл ServiceWork.js, это главное. Только после обновления файла ServiceWork.js последующие процессы не будут запускаться. Обновление ServiceWork.js также очень просто, просто измените файл ServiceWork.js напрямую. Браузер автоматически проверит различия (даже если это всего 1 байт) и выберет их.
  • Начнется загрузка нового файла ServiceWork.js, иinstallсобытие запускается
  • В этот момент старый ServiceWork все еще работает, и вступает в действие новый ServiceWork.waitingусловие. Обратите внимание, что на данный момент замены нет.
  • Теперь оба ServiceWorks существуют одновременно, но прежний ServiceWork по-прежнему отвечает за текущую веб-страницу. только если старая сервисная работа не работает, т.е.terminatedПосле этого новый ServiceWork вступит в силу. Конкретное поведение заключается в том, что страница закрывается на определенный период времени или очищается вручную.service worker. Затем новая работа по обслуживанию тратитwaitingположение дел.
  • Как только новая работа по обслуживанию вступит во владение, она сработает.activateмероприятие.

Весь блок-схема:

                

После создания версии кеша мы также можем настроить несколько кешей, так как же удалить кеш, которого нет в белом списке?

self.addEventListener('activate', function(event) {
    //上个版本,我们使用的是'app-v1'的缓存,所以就需要进行清除,进行'app-v2'版本的缓存储存
  var cacheWhitelist = ['app-v1'];

  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

еслиnew service workЧтобы подействовало немедленно, вам нужно использоватьskipWaiting,существуетinstallсценическое использованиеself.skipWaiting();, так как выше упоминалось, что после загрузки будет запущена новая Service Workinstallзатем введитеwaitingусловие. Тогда мы можем напрямуюinstallСтадия пропускает ожидание и просто позволяет новой Работе по Служению вступить во владение.

self.addEventListener('install',function(event) {
  self.skipWaiting();

  event.waitUntil(
    // caching etc
  );
});

надservice workОбновления выполняются в начале загрузки, поэтому, если пользователям необходимо оставаться на вашей веб-странице в течение длительного времени, есть ли способ проверять наличие обновлений через определенные промежутки времени?

Да, вы можете использоватьregistration.update()Что нужно сделать.

navigator.serviceWorker.register('./ServiceWork.js').then(function(reg){
  // sometime later…
  reg.update();
});

Кроме того, если вы используетеServiceWork.jsИ после определения маршрута, пожалуйста, не меняйте маршрут, потому что браузер судитServiceWork.jsОбновлять ли, согласно ServiceWork.jsс пути. если вы изменитеServiceWork.js путь, в то время как предыдущийServiceWork.js все еще работает, то ваш новыйServiceWorkникогда не работай. если вы вручную не включитеupdateобновить.

Вы хотите обновить файл, просто нужно быть в обслуживанииfetchСцену можно кэшировать с помощью caches. В начале нашinstallКод этапа:

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('app-v1').then(function(cache) {
      return cache.addAll([
        './app.js',
        './servicework.html',
        './index.css'
      ]);
    })
  );
});


self.addEventListener('install', function (event) {
      var now = Date.now();
      // 事先设置好需要进行更新的文件路径
      var urlsToPrefetch = [
        './index.css',
        './servicework.html'
      ];
      event.waitUntil(
        caches.open(CURRENT_CACHES.prefetch).then(function (cache) {
          var cachePromises = urlsToPrefetch.map(function (urlToPrefetch) {
            // 使用 url 对象进行路由拼接
            var url = new URL(urlToPrefetch, location.href);
            url.search += (url.search ? '&' : '?') + 'cache-bust=' + now;
            // 创建 request 对象进行流量的获取
             var request = new Request(url, {
              mode: 'no-cors'
            });
            // 手动发送请求,用来进行文件的更新
            return fetch(request).then(function (response) {
              if (response.status >= 400) {
                // 解决请求失败时的情况
                     throw new Error('request for ' + urlToPrefetch +
                  ' failed with status ' + response.statusText);
              }
             // 将成功后的 response 流,存放在 caches 套件中,完成指定文件的更新。
              return cache.put(urlToPrefetch, response);
            }).catch(function (error) {
              console.error('Not caching ' + urlToPrefetch + ' due to ' + error);
            });
          });
          return Promise.all(cachePromises).then(function () {
            console.log('Pre-fetching complete.');
          });
        }).catch(function (error) {
             console.error('Pre-fetching failed:', error);
         })
        );
});

Портал ГитхабПроверьте этот код.


Когда кеш будет успешно получен, ServiceWork не будет заменять его напрямую, а будет ждать, пока пользователь не обновит страницу в следующий раз, чтобы использовать новый файл кеша.

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.open('app-v1').then(function(cache) {
      return cache.match(event.request).then(function(response) {
        var fetchPromise = fetch(event.request).then(function(res) {
          cache.put(event.request, res.clone());
          return res;
        })
        return response || fetchPromise;
      })
    })
  );
});

               

Более подробные другие методы могут быть использованыобратитесь к этой статье.

В этой статье говорится только о локальном кеше, а затем информация, связанная с геозоной и отправкой сообщений, будет обновлена ​​вблог, заинтересованные друзья могут добавить эту статью в закладки, а более конкретный и стандартизированный код можно найти здесь.Проверить.

Недостатки сервисной работы (PWA):

  • Проблема кеша надо чистить регулярно. появляется при превышенииUncaught (in promise) DOMException: Quota exceeded.аномальный. После очистки необходимо перезапустить браузер, чтобы изменения вступили в силу.
  • Совместимость с браузером, проблема с головной болью. IE и сафари несовместимы


преимущество:

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

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