本港台最快开奖结果_本港台118kj开奖现场_明日大富翁开奖结果

[2019]本港台最快开奖结果是给大家带来了一个可以免费下载正版的机会,1本港台118kj开奖现场为玩家提供免费好玩的iPad游戏下载,点击明日大富翁开奖结果了解更多优惠信息,因为只有在注册之后下载下来的平台才是官方指定的。

同构应用

来源:http://www.alloutofdebt.com 作者:新闻资讯 人气:151 发布时间:2019-11-26
摘要:React 同构应用 PWA 晋级指南 2018/05/25 · JavaScript· PWA,React 原稿出处:林东洲    前言 最近在给本身的博客网址 PWA 晋级,顺便就记下下 React 同构应用在应用 PWA时碰着的难点,这里不会从

React 同构应用 PWA 晋级指南

2018/05/25 · JavaScript · PWA, React

原稿出处: 林东洲   

前言

最近在给本身的博客网址 PWA 晋级,顺便就记下下 React 同构应用在应用 PWA 时碰着的难点,这里不会从头开头介绍如何是 PWA,纵然您想学学 PWA 相关知识,能够看下上边小编收藏的片段稿子:

  • 你的第三个 Progressive Web App
  • 【ServiceWorker】生命周期那一个事儿
  • 【PWA学习与施行】(1) 2018,开头你的PWA学习之旅
  • Progressive Web Apps (PWA) 中文版

PWA 特性

PWA 不是单独的某项本领,而是一批技能的集纳,比方:ServiceWorker,manifest 加多到桌面,push、notification api 等。

而就在新近时间,IOS 11.3 刚刚援救 Service worker 和周围 manifest 增加到桌面包车型客车表征,所以此番 PWA 改换首要还是促成这两片段机能,至于其余的特征,等 iphone 协理了再晋级吗。

Service Worker

service worker 在作者眼里,近似于三个跑在浏览器后台的线程,页面第三回加载的时候会加载这些线程,在线程激活之后,通过对 fetch 事件,能够对每一种收获的财富拓宽支配缓存等。

大千世界什么财富供给被缓存?

那么在起来使用 service worker 在此以前,首先须要精晓哪些财富须求被缓存?

缓存静态能源

首先是像 CSS、JS 那些静态财富,因为自己的博客里援引的脚本样式都以透过 hash 做漫长化缓存,相同于:main.ac62dexx.js 这样,然后展开强缓存,那样后一次客商下一次再寻访笔者的网址的时候就不要再行央求财富。直接从浏览器缓存中读取。对于那有的财富,service worker 没供给再去管理,直接放行让它去读取浏览器缓存就能够。

自己以为后生可畏旦您的站点加载静态能源的时候小编并未有张开强缓存,并且你只想通过前端去得以完毕缓存,而无需后端在参加举行调治,那能够运用 service worker 来缓存静态能源,不然就有一点点节外生枝了。

缓存页面

缓存页面显著是不能缺少的,那是最焦点的片段,当你在离线的意况下加载页面会之后现身:

图片 1

究其原因正是因为您在离线状态下不能加载页面,往后有了 service worker,就算你在没网络的情状下,也足以加载以前缓存好的页面了。

缓存后端接口数据

缓存接口数据是须求的,但亦非必需通过 service worker 来兑现,前端存放数据的地点有不胜枚举,举例通过 localstorage,indexeddb 来开展仓储。这里作者也是由此 service worker 来贯彻缓存接口数据的,假如想通过其余方法来实现,只须要介怀好 url 路线与数码对应的映射关系就能够。

缓存战略

远近著名了如何能源须求被缓存后,接下去就要探究缓存计策了。

页面缓存攻略

因为是 React 单页同构应用,每一趟加载页面包车型大巴时候数据都是动态的,所以小编使用的是:

  1. 网络优先的措施,即优先拿到网络上风行的财富。当网络须要战败的时候,再去获得service worker 里在此以前缓存的财富
  2. 当互联网加载成功之后,就校订 cache 中对应的缓存财富,保险后一次每回加载页面,都是上次拜谒的新颖能源
  3. 设若找不到 service worker 中 url 对应的能源的时候,则去获取 service worker 对应的 /index.html 暗中认可首页

// sw.js self.add伊夫ntListener('fetch', (e) => { console.log('现在正在呼吁:' + e.request.url); const currentUrl = e.request.url; // 相称上页面路线 if (matchHtml(currentUrl)) { const requestToCache = e.request.clone(); e.respondWith( // 加载网络上的资源fetch(requestToCache).then((response) => { // 加载战败 if (!response || response.status !== 200) { throw Error('response error'); } // 加载成功,更新缓存 const responseToCache = response.clone(); caches.open(cacheName).then((cache) => { cache.put(requestToCache, responseToCache); }); console.log(response); return response; }).catch(function() { // 获取对应缓存中的数据,获取不到则战败到收获暗中同意首页 return caches.match(e.request).then((response) => { return response || caches.match('/index.html'); }); }) ); } });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// sw.js
self.addEventListener('fetch', (e) => {
  console.log('现在正在请求:' + e.request.url);
  const currentUrl = e.request.url;
  // 匹配上页面路径
  if (matchHtml(currentUrl)) {
    const requestToCache = e.request.clone();
    e.respondWith(
      // 加载网络上的资源
      fetch(requestToCache).then((response) => {
        // 加载失败
        if (!response || response.status !== 200) {
          throw Error('response error');
        }
        // 加载成功,更新缓存
        const responseToCache = response.clone();
        caches.open(cacheName).then((cache) => {
          cache.put(requestToCache, responseToCache);
        });
        console.log(response);
        return response;
      }).catch(function() {
        // 获取对应缓存中的数据,获取不到则退化到获取默认首页
        return caches.match(e.request).then((response) => {
           return response || caches.match('/index.html');
        });
      })
    );
  }
});

为何存在命中穿梭缓存页面包车型地铁动静?

  1. 首先要求明显的是,客商在第二回加载你的站点的时候,加载页面后才会去运维sw,所以首先次加载十分的小概由此 fetch 事件去缓存页面
  2. 自家的博客是单页应用,然则用户并不一定会通过首页踏向,有非常大大概会经过其余页面路线进入到自个儿的网站,那就形成自个儿在 install 事件中常常有不能够内定要求缓存那二个页面
  3. 最后促成的作用是:客商率先次展开页面,立时断掉互联网,如故得以离线访谈笔者的站点

重新整合方面三点,小编的措施是:第一回加载的时候会缓存 /index.html 那一个能源,而且缓存页面上的多少,假设客户立即离线加载的话,那时候并未缓存对应的渠道,例如 /archives 能源访问不到,这重临 /index.html 走异步加载页面包车型客车逻辑。

在 install 事件缓存 /index.html,保障了 service worker 第二回加载的时候缓存暗中认可页面,留下退路。

import constants from './constants'; const cacheName = constants.cacheName; const apiCacheName = constants.apiCacheName; const cacheFileList = ['/index.html']; self.addEventListener('install', (e) => { console.log('Service Worker 状态: install'); const cacheOpenPromise = caches.open(cacheName).then((cache) => { return cache.addAll(cacheFileList); }); e.waitUntil(cacheOpenPromise); });

1
2
3
4
5
6
7
8
9
10
11
12
import constants from './constants';
const cacheName = constants.cacheName;
const apiCacheName = constants.apiCacheName;
const cacheFileList = ['/index.html'];
 
self.addEventListener('install', (e) => {
  console.log('Service Worker 状态: install');
  const cacheOpenPromise = caches.open(cacheName).then((cache) => {
    return cache.addAll(cacheFileList);
  });
  e.waitUntil(cacheOpenPromise);
});

在页面加载完后,在 React 组件中及时缓存数据:

// cache.js import constants from '../constants'; const apiCacheName = constants.apiCacheName; export const saveAPIData = (url, data) => { if ('caches' in window) { // 捏造 request/response 数据 caches.open(apiCacheName).then((cache) => { cache.put(url, new Response(JSON.stringify(data), { status: 200 })); }); } }; // React 组件 import constants from '../constants'; export default class extends PureComponent { componentDidMount() { const { state, data } = this.props; // 异步加载数据 if (state === constants.INITIAL_STATE || state === constants.FAILURE_STATE) { this.props.fetchData(); } else { // 服务端渲染成功,保存页面数据 saveAPIData(url, data); } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// cache.js
import constants from '../constants';
const apiCacheName = constants.apiCacheName;
 
export const saveAPIData = (url, data) => {
  if ('caches' in window) {
    // 伪造 request/response 数据
    caches.open(apiCacheName).then((cache) => {
      cache.put(url, new Response(JSON.stringify(data), { status: 200 }));
    });
  }
};
 
// React 组件
import constants from '../constants';
export default class extends PureComponent {
  componentDidMount() {
    const { state, data } = this.props;
    // 异步加载数据
    if (state === constants.INITIAL_STATE || state === constants.FAILURE_STATE) {
      this.props.fetchData();
    } else {
        // 服务端渲染成功,保存页面数据
      saveAPIData(url, data);
    }
  }
}

如此就确定保障了客商率先次加载页面,立即离线访谈站点后,就算无法像第三遍同样能够服务端渲染数据,不过随后能由此获取页面,异步加载数据的情势塑造离线应用。

图片 2

客商率先次访谈站点,假使在不刷新页面包车型大巴情事切换路由到此外页面,则会异步获取到的多少,当下次拜访对应的路由的时候,则战败到异步获取数据。

图片 3

当顾客第2回加载页面包车型地铁时候,因为 service worker 已经调节了站点,已经有所了缓存页面包车型客车能力,之后在拜会的页面都将会被缓存或许更新缓存,当客商离线访谈的的时候,也能访谈到服务端渲染的页面了。

图片 4

接口缓存攻略

谈完页面缓存,再来讲讲接口缓存,接口缓存就跟页面缓存很挨近了,唯黄金年代的两样在于:页面第三回加载的时候不分明有缓存,可是会有接口缓存的留存(因为杜撰了 cache 中的数据),所以缓存计策跟页面缓存相像:

  1. 互连网优先的方式,即优先获得互联网上接口数据。当网络乞请战败的时候,再去赢得 service worker 里在此之前缓存的接口数据
  2. 当网络加载成功之后,就修正 cache 中对应的缓存接口数据,保险后一次每趟加载页面,都是上次作客的风靡接口数据

就此代码就如这么(代码相同,不再赘述):

self.add伊夫ntListener('fetch', (e) => { console.log('今后正在号令:'

  • e.request.url); const currentUrl = e.request.url; if (matchHtml(currentUrl)) { // ... } else if (matchApi(currentUrl)) { const requestToCache = e.request.clone(); e.respondWith( fetch(requestToCache).then((response) => { if (!response || response.status !== 200) { return response; } const responseToCache = response.clone(); caches.open(apiCacheName).then((cache) => { cache.put(requestToCache, responseToCache); }); return response; }).catch(function() { return caches.match(e.request); }) ); } });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
self.addEventListener('fetch', (e) => {
  console.log('现在正在请求:' + e.request.url);
  const currentUrl = e.request.url;
  if (matchHtml(currentUrl)) {
    // ...
  } else if (matchApi(currentUrl)) {
    const requestToCache = e.request.clone();
    e.respondWith(
      fetch(requestToCache).then((response) => {
        if (!response || response.status !== 200) {
          return response;
        }
        const responseToCache = response.clone();
        caches.open(apiCacheName).then((cache) => {
          cache.put(requestToCache, responseToCache);
        });
        return response;
      }).catch(function() {
        return caches.match(e.request);
      })
    );
  }
});

这里其实能够再打开优化的,举个例子在获取数据接口的时候,能够先读取缓存中的接口数据进行渲染,当真正的网络接口数据再次来到之后再开展交替,那样也能有效压缩顾客的首屏渲染时间。当然那恐怕会爆发页面闪烁的机能,能够增进一些动漫片来进展连接。

其余难题

到现行反革命完工,已经大约能够兑现 service worker 离线缓存应用的效果了,然而还应该有照旧存在有的标题:

赶快激活 service worker

暗中同意景况下,页面包车型的士央求(fetch卡塔 尔(英语:State of Qatar)不会经过 sw,除非它本人是透过 sw 获取的,也便是说,在设置 sw 之后,须要刷新页面本领有效用。sw 在装置成功并激活早前,不会响应 fetch或push等事件。

因为站点是单页面应用,那就导致了你在切换路由(未有刷新页面)的时候从不缓存接口数据,因为此时service worker 还从未开首专门的学问,所以在加载 service worker 的时候供给飞速地激活它。代码如下:

self.addEventListener('activate', (e) => { console.log('Service Worker 状态: activate'); const cachePromise = caches.keys().then((keys) => { return Promise.all(keys.map((key) => { if (key !== cacheName && key !== apiCacheName) { return caches.delete(key); } return null; })); }); e.waitUntil(cachePromise); // 快速激活 sw,使其能够响应 fetch 事件 return self.clients.claim(); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
self.addEventListener('activate', (e) => {
  console.log('Service Worker 状态: activate');
  const cachePromise = caches.keys().then((keys) => {
    return Promise.all(keys.map((key) => {
      if (key !== cacheName && key !== apiCacheName) {
        return caches.delete(key);
      }
      return null;
    }));
  });
  e.waitUntil(cachePromise);
  // 快速激活 sw,使其能够响应 fetch 事件
  return self.clients.claim();
});

部分小说说还需求在 install 事件中增多 self.skipWaiting(); 来跳过等待时间,不过本身在实行中开掘固然不增加也足以健康激活 service worker,原因未知,有读者掌握的话能够沟通下。

后天当你首先次加载页面,跳转路由,立即离线访问的页面,也足以安枕而卧地加载页面了。

并不是强缓存 sw.js

客商每一回访谈页面包车型客车时候都会去重新赢得 sw.js,依据文件内容跟在此之前的本子是还是不是相通来决断 service worker 是还是不是有创新。所以大器晚成旦你对 sw.js 开启强缓存的话,就将深陷死循环,因为老是页面得到到的 sw.js 都以相近,那样就无法晋级你的 service worker。

此外对 sw.js 开启强缓存也是还未须求的:

  1. 自个儿 sw.js 文件自己就非常的小,浪费不了多少带宽,认为浪费能够利用合同缓存,但附加扩充开销担当
  2. sw.js 是在页面空闲的时候才去加载的,并不会潜移暗化客商首屏渲染速度

制止改变 sw 的 U福特ExplorerL

在 sw 中那样做是“最差试行”,要在原地点上改进 sw。

譬释迦牟尼注脚为啥:

  1. index.html 注册了 sw-v1.js 作为 sw
  2. sw-v1.js 对 index.html 做了缓存,也正是缓存优先(offline-first卡塔 尔(英语:State of Qatar)
  3. 你更新了 index.html 重新登记了在新地点的 sw sw-v2.js

只要你像上边那么做,客户永世也拿不到 sw-v2.js,因为 index.html 在 sw-v1.js 缓存中,那样的话,假设你想翻新为 sw-v2.js,还索要退换原来的 sw-v1.js。

测试

自此,大家曾经实现了运用 service worker 对页面实行离线缓存的功效,即使想体会效果的话,访谈作者的博客:

自由浏览放肆的页面,然后关掉互联网,再度访问,此前您浏览过的页面都得以在离线的气象下开展访谈了。

IOS 须要 11.3 的本子才支撑,使用 Safari 举行访谈,Android 请选用扶植service worker 的浏览器

manifest 桌面应用

前方讲罢了何等选拔 service worker 来离线缓存你的同构应用,可是 PWA 不仅只限于此,你还足以选择安装 manifest 文件来将您的站点加多到运动端的桌面上,进而达到趋近于原生应用的心得。

使用 webpack-pwa-manifest 插件

本人的博客站点是经过 webpack 来创设前端代码的,所以本人在社区里找到 webpack-pwa-manifest 插件用来生成 manifest.json。

第黄金时代安装好 webpack-pwa-manifest 插件,然后在你的 webpack 配置文件中增多:

// webpack.config.prod.js const WebpackPwaManifest = require('webpack-pwa-manifest'); module.exports = webpackMerge(baseConfig, { plugins: [ new WebpackPwaManifest({ name: 'Lindz's Blog', short_name: 'Blog', description: 'An isomorphic progressive web blog built by React & Node', background_color: '#333', theme_color: '#333', filename: 'manifest.[hash:8].json', publicPath: '/', icons: [ { src: path.resolve(constants.publicPath, 'icon.png'), sizes: [96, 128, 192, 256, 384, 512], // multiple sizes destination: path.join('icons') } ], ios: { 'apple-mobile-web-app-title': 'Lindz's Blog', 'apple-mobile-web-app-status-bar-style': '#000', 'apple-mobile-web-app-capable': 'yes', 'apple-touch-icon': '//xxx.com/icon.png', }, }) ] })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// webpack.config.prod.js
const WebpackPwaManifest = require('webpack-pwa-manifest');
module.exports = webpackMerge(baseConfig, {
  plugins: [
    new WebpackPwaManifest({
      name: 'Lindz's Blog',
      short_name: 'Blog',
      description: 'An isomorphic progressive web blog built by React & Node',
      background_color: '#333',
      theme_color: '#333',
      filename: 'manifest.[hash:8].json',
      publicPath: '/',
      icons: [
        {
          src: path.resolve(constants.publicPath, 'icon.png'),
          sizes: [96, 128, 192, 256, 384, 512], // multiple sizes
          destination: path.join('icons')
        }
      ],
      ios: {
        'apple-mobile-web-app-title': 'Lindz's Blog',
        'apple-mobile-web-app-status-bar-style': '#000',
        'apple-mobile-web-app-capable': 'yes',
        'apple-touch-icon': '//xxx.com/icon.png',
      },
    })
  ]
})

简轻易单地论述下安插音信:

  1. name: 应用名称,正是Logo下边包车型客车显得名称
  2. short_name: 应用名称,但 name 不可能展示完全时候则显得这几个
  3. background_color、theme_color:顾名思义,相应的颜色
  4. publicPath: 设置 cdn 路径,跟 webpack 里的 publicPath 一样
  5. icons: 设置Logo,插件会活动帮您转移区别 size 的图形,不过图片大小必得超过最大 sizes
  6. ios: 设置在 safari 中哪些去增加桌面应用

设置完未来,webpack 会在塑造进程中变化对应的 manifest 文件,并在 html 文件中援用,下边就是生成 manifest 文件:

{ "icons": [ { "src": "/icons/icon_512x512.79ddc5874efb8b481d9a3d06133b6213.png", "sizes": "512x512", "type": "image/png" }, { "src": "/icons/icon_384x384.09826bd1a5d143e05062571f0e0e86e7.png", "sizes": "384x384", "type": "image/png" }, { "src": "/icons/icon_256x256.d641a3644ce20c06855db39cfb2f7b40.png", "sizes": "256x256", "type": "image/png" }, { "src": "/icons/icon_192x192.8f11e077242cccd9c42c0cbbecd5149c.png", "sizes": "192x192", "type": "image/png" }, { "src": "/icons/icon_128x128.cc0714ab18fa6ee6de42ef3d5ca8fd09.png", "sizes": "128x128", "type": "image/png" }, { "src": "/icons/icon_96x96.dbfccb1a5cef8093a77c079f761b2d63.png", "sizes": "96x96", "type": "image/png" } ], "name": "Lindz's Blog", "short_name": "Blog", "orientation": "portrait", "display": "standalone", "start_url": ".", "description": "An isomorphic progressive web blog built by React & Node", "background_color": "#333", "theme_color": "#333" }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
  "icons": [
    {
      "src": "/icons/icon_512x512.79ddc5874efb8b481d9a3d06133b6213.png",
      "sizes": "512x512",
      "type": "image/png"
    },
    {
      "src": "/icons/icon_384x384.09826bd1a5d143e05062571f0e0e86e7.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "/icons/icon_256x256.d641a3644ce20c06855db39cfb2f7b40.png",
      "sizes": "256x256",
      "type": "image/png"
    },
    {
      "src": "/icons/icon_192x192.8f11e077242cccd9c42c0cbbecd5149c.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icons/icon_128x128.cc0714ab18fa6ee6de42ef3d5ca8fd09.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "/icons/icon_96x96.dbfccb1a5cef8093a77c079f761b2d63.png",
      "sizes": "96x96",
      "type": "image/png"
    }
  ],
  "name": "Lindz's Blog",
  "short_name": "Blog",
  "orientation": "portrait",
  "display": "standalone",
  "start_url": ".",
  "description": "An isomorphic progressive web blog built by React & Node",
  "background_color": "#333",
  "theme_color": "#333"
}

html 中会援用这几个文件,而且增加对 ios 增加桌面应用的扶持,就如这么。

<!DOCTYPE html> <html lang=en> <head> <meta name=apple-mobile-web-app-title content="Lindz's Blog"> <meta name=apple-mobile-web-app-capable content=yes> <meta name=apple-mobile-web-app-status-bar-style content=#838a88> <link rel=apple-touch-icon href=xxxxx> <link rel=manifest href=/manifest.21d63735.json> </head> </html>

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang=en>
<head>
  <meta name=apple-mobile-web-app-title content="Lindz's Blog">
  <meta name=apple-mobile-web-app-capable content=yes>
  <meta name=apple-mobile-web-app-status-bar-style content=#838a88>
  <link rel=apple-touch-icon href=xxxxx>
  <link rel=manifest href=/manifest.21d63735.json>
</head>
</html>

就好像此轻便,你就能够动用 webpack 来增多你的桌面应用了。

测试

增加完之后你能够因此 chrome 开垦者工具 Application – Manifest 来查看你的 mainfest 文件是不是见到成效:

图片 5

那般表达你的陈设生效了,安卓时机自动识别你的布局文件,并询问客户是或不是丰盛。

结尾

讲到那差不离就完了,等之后 IOS 扶植 PWA 的其他功用的时候,届期候小编也会相应地去实行别的 PWA 的特点的。以往 IOS 11.3 也单独支持 PWA 中的 service worker 和 app manifest 的效应,不过相信在不久的以往,其余的效果与利益也会相应得到扶植,届时候相信 PWA 将会在运动端怒放异彩的。

1 赞 收藏 评论

图片 6

本文由本港台最快开奖结果发布于新闻资讯,转载请注明出处:同构应用

关键词:

频道精选

最火资讯