gwt格式
渐进或不渐进…
如果您已经设计或开发Web应用程序已有一段时间,那么您可能会遇到无数次“渐进式Web应用程序”一词,并且可能会在未来几年内使用。 您可能想知道PWA的确切定义是什么,如何识别PWA,以及如何构建PWA。 根据字典,渐进一词是指可以改善或变得更好的东西,但是这与Web应用程序有什么关系呢? 我们真的不知道。 PWA似乎是Google引起人们兴趣的流行语,与PWA的真正含义并没有真正的关系。 Alex Russel将PWA定义为“摄取正确维生素的网站”。 为简单起见,让我们首先说说PWA是经过优化以适合其环境的Web应用程序:在移动设备或平板电脑上,它们可以扮演移动本机应用程序的角色,而在PC上,它们可以扮演普通Web应用程序的角色。
PWA的基本原理:
PWA是具有常规Web应用程序以及用于不同移动平台的捆绑应用程序的替代方法。 维护和升级所有这些程序可能会花费很大,尤其是在应用程序频繁更改的情况下。 使用PWA,只有一个适用于所有平台的应用程序,可以通过浏览器中的链接进行访问。 PWA旨在使用“移动优先”方法进行设计。 可以安装它们,但它们也可以作为常规网站正常工作。 Google为PWA创建了一个专用网站 ,并介绍了通过将应用程序/网站转换为PWA而受益的公司的不同案例。
PWA的特征:
Google的开发倡导者Rob Dodson在他的演讲中强调了Web应用程序的不同特征:
–React灵敏:适应设备
–快速加载:优化以快速绘制或渲染 –脱机工作:使用服务人员来缓存内容,以允许脱机使用或慢速网络连接的应用程序 –可安装:可以在主屏幕中安装应用程序(例如本机应用程序) –参与度:通过推送通知使用户了解情况
既然我们知道了渐进式Web应用程序的外观,我们就可以开始研究可以帮助我们使GWT应用程序渐进式的各种工具。
用于PWA的GWT食谱:
- #1响应式:
为了使您的GWT应用程序具有响应能力,GWT用户有几个选项。 如果您具有设计技能,则可以使用自定义代码和CSS使应用程序具有响应能力。 否则,您可以依赖其他框架。 GWT的Bootstrap( https://github.com/gwtbootstrap3/gwtbootstrap3 )是我想到的第一件事。 它提供了著名的Twitter框架的所有组件。 另一种选择是GWTMaterialDesign( https://github.com/GwtMaterialDesign/gwt-material )。 它提供了具有响应性的材料设计,可以随时为您的应用程序使用元素。 最后, gwt-polymer-element是GWT的Polymer包装材料,它还提供了随时可用的响应式Web组件,并且可以在设计构建响应式应用程序时派上用场。 我们在之前的一篇文章中提供了Polymer的新手指南。
- #2快速加载:
为了减少第一次喷涂的时间,可以做很多事情。 首先,可以使用代码拆分来减少gwt模块文件的大小。 它基本上将模块分成多个片段,从而使GWT模块在启动时仅下载所需的片段。 其次,可以将PWA 准则指定的应用程序外壳方法应用于GWT应用程序。 这可以通过从应用程序Java代码中提取静态元素和数据并将其直接放入.html入口点来完成。 例如:
GWT用户的常见做法是将.html的正文留空,并以编程方式从应用程序添加其视图:
<body>
</body>
//....AppMainView view = AppMainView();RootPanel.get().add(view);
尽管这种做法没有错,但是由于.js模块文件将包含更多指令,因此它可能会延长应用程序的加载时间,因此执行起来将花费更多时间。 作为解决方法,我们可以尝试识别视图中的所有静态元素并将其放入.html中,然后可以从入口点加载单个视图:
<div id="appShell"><img src="logo.png" alt="" />
<div id="menu"></div>
<div id="mainContent"></div>
//...
MenuView menu = new MenuMeview();
ContentView content = new ContentView();RootPanel.get("menu").add(menu);
RootPanel.get("mainContent").add(content);
为了说明的目的,这当然是简化的示例。 到目前为止,我们已经看到了代码拆分和应用程序外壳如何减少呈现应用程序的时间。 还有HTML5的async脚本属性,该属性并非真正专用于GWT。 例如:
<!-- Inside HEAD --!>
<script src="polymerstarter/polymerstarter.nocache.js" async="" type="text/javascript">
这将指示浏览器不要阻止解析,并在可用时尽快加载我们的应用脚本。
另一种选择是将应用程序脚本放入正文中。
- #3离线工作:
这主要可以使用服务人员来完成。 没有官方的GWT库与服务人员进行交互。 甚至gwt-polymer-elements都不包装Platinum Elements,Platinum Elements是用于与浏览器的服务人员交互的Polymer元素。 GWT用户将不得不手动编写一些Javascript来实现应用程序资产的缓存机制。 JSNI或Jsinterop可用于与浏览器进行交互并调用服务工作者服务。 定义缓存事件的服务工作者脚本需要在单独的脚本上,因此,目前,将服务工作者代码和GWT应用程序模块代码混合在同一.js文件中有点复杂。 GWT唯一可以完成的任务是注册服务工作者。 我们将在下一节的后面进行演示。 另请注意,并非所有浏览器都支持服务工作者,您可以在Mozilla的API文档页面中找到有关此服务的更多详细信息。
有关如何使用Service Worker缓存应用程序数据和资产的更多详细信息,Google提供了一些有用的指南。
- #4无法安装:
此收据也不特定于GWT。 要使Web应用程序可安装,您需要添加一个名为app manifest的json文件,并将其链接到.html入口点:
<link rel="manifest" href="manifest.json">
有关如何编写清单文件的指南,请参考W3C的指南: https : //www.w3.org/TR/appmanifest/ 。 您也可以使用此在线工具: http : //brucelawson.github.io/manifest/ ,该工具可以为您生成清单,但是您的应用程序必须已经在线。 您可以使用标语要求用户安装该应用程序,也可以让他从浏览器的选项中手动进行操作。
- #5参与:
再次没有正式的GWT推送通知库。 这可能是呼吁GWT社区填补这一空白。 在此之前,GWT用户可以使用JSNI或Jsinterop与浏览器进行交互并订阅推送通知。
演示应用
为了说明上述特征,我们使用gwt-polymer-elements和gwty-leaflet构建了一个地图应用程序。 该应用程序显示用户的收藏夹地图。
来源: https : //github.com/gwidgets/gwt-pwa-demo
直播: https : //gwt-pwa-demo.herokuapp.com/pwademo.html/
使用Polymer,我们的应用程序默认情况下是响应式的,因此此步骤已完成。
为了使应用程序快速加载,我们首先移除所有静态html,然后将其放入.html入口点文件: https : //github.com/gwidgets/gwt-pwa-demo/blob/master/src/main /webapp/pwademo.html
我们使用聚合物元素与dom元素进行交互。 例如:
PaperMenuLEement paperMenu = (PaperMenuElement) Polymer.getDocument().getElementById("paperMenu");paperMenu.select("paris");
我们还使应用脚本异步加载:
<script type="text/javascript" language="javascript" src="pwademo/pwademo.nocache.js" async></script>
并且我们引入了一些代码拆分方法,因为每个部分只有一个地图,因此我们只需要在加载页面时在显示的部分上加载地图。
loadStartupMap();//Maps are not loaded on start up, but only when iron selector selects a new map
ironPages.addEventListener("iron-select", e -> {if(ironPages.getSelected().equals("london") && !londonMapInitialized){//Some code splitting to reduce initial module sizeGWT.runAsync(new RunAsyncCallback(){@Overridepublic void onFailure(Throwable reason) {Document.get().getElementById("londonMap").setInnerHTML("Could not load this map, please try again later");}@Overridepublic void onSuccess() {Maps.initializeLondonMap(); }});londonMapInitialized = true;}
});
我们还添加了一个应用程序清单,以允许手动安装该应用程序
{"name": "Favorite Maps PWA","short_name": "Favorite Maps PWA","icons": [{"src": "image/mapicon.png","sizes": "144x144","type": "image/png"}],"start_url": "/pwademo.html","display": "standalone","background_color": "#3E4EB8","theme_color": "#2E3AA1"
}
最后,我们添加了JsInterop类来注册服务工作者。
if (Navigator.serviceWorker != null) {Navigator.serviceWorker.register("sw.js").then(new Function<JavaScriptObject, JavaScriptObject>() {@Overridepublic JavaScriptObject call(JavaScriptObject arg) {GWT.log("registred service worker successfully");return null;}});} else {GWT.log("service worker unavailable in this browser");}
我们创建了一个名为sw.js的服务工作者脚本,并将其添加到应用程序的资源中。
var cacheName = 'GWT-PWA';
var filesToCache = [ '/gwt-pwa/pwademo.html', '/gwt-pwa/pwademo.css', '/gwt-pwa/styles/app-theme.html', '/gwt-pwa/styles/shared-styles.html', '/gwt-pwa/leaflet/leaflet.js', '/gwt-pwa/leaflet/leaflet.css','/gwt-pwa/image/mapicon.png','/gwt-pwa/pwademo/pwademo.nocache.js'];self.addEventListener('install', function(e) { console.log('[ServiceWorker] Install'); e.waitUntil( caches.open(cacheName).then(function(cache) { console.log('[ServiceWorker] Caching app shell'); return cache.addAll(filesToCache); }) );
});self.addEventListener('activate', function(e) { console.log('[ServiceWorker] Activate'); e.waitUntil( caches.keys().then(function(keyList) { return Promise.all(keyList.map(function(key) { console.log('[ServiceWorker] Removing old cache', key); if (key !== cacheName) { return caches.delete(key); } })); }) ); });self.addEventListener('fetch', function(e) { console.log('[ServiceWorker] Fetch', e.request.url); e.respondWith( caches.match(e.request).then(function(response) { return response || fetch(e.request); }) ); });
该脚本将安装并激活服务工作者。 它还允许服务工作者预订获取事件,该事件在每次请求资源时触发。 然后,服务工作者根据其当前状态决定是使用本地缓存还是从网络中获取资源。
加载应用程序后,我们可以在Google chrome的缓存存储中找到我们的资产:
http://www.g-widgets.com/wp-content/uploads/2016/08/cacheChrome.png
如果我们在Google Chrome浏览器上禁用了网络并尝试运行该应用程序,则会得到类似的信息(由于未缓存地图,因此未渲染):
该应用程序即使没有网络也可以提供服务。 如果我们看一下Chrome开发工具中的网络请求,就会注意到服务工作者正在提供应用程序资源:
由于这是一个演示应用程序,因此我们没有添加任何推送通知,因为它需要设置推送服务器。
我们已从Android手机将应用程序安装到主屏幕,并且得到了类似以下内容:
结论
在Web开发领域,PWA仍然是新事物。 一些人预测他们将在未来几年接管本地应用程序。 我们知道,GWT开发人员一直在使用Phonegap将其Web应用程序转换为移动本机应用程序,也许有了PWA,他们将不再需要这样做。 我们已经在本教程中看到了如何使用诸如Polymer之类的库将GWT用于构建PWA。 到目前为止,还没有GWT库可以与浏览器服务工作者进行交互,因此GWT社区需要填补这一空白。
有趣的链接
Addy Osmani初学者指南: https : //addyosmani.com/blog/getting-started-with-progressive-web-apps/
2016年SpringIO关于PWA和Spring Boot的讨论: https : //www.youtube.com/watch?v= zAZQeQ0CRpQ
来自Web开发在线代理商https://skilled.co/的PWA用例摘要图表:
由Skilled.co提出
翻译自: https://www.javacodegeeks.com/2017/07/progressive-web-apps-recipes-gwt.html
gwt格式