java web 速成

tech2022-09-05  85

java web 速成

Progressive Web Apps (PWAs) try to overlap the worlds of the mobile web apps and native mobile apps by offering the best features of each to mobile users.

渐进式Web应用程序(PWA)试图通过向移动用户提供每种功能的最佳功能来重叠移动Web应用程序和本机移动应用程序的世界。

They offer an app-like user experience (splash screens and home screen icons), they’re served from HTTPS-secured servers, they can load quickly (thanks to page load performance best practices) even in low quality or slow network conditions, and they have offline support, instant loading and push notifications. The concept of PWAs was first introduced by Google, and is still supported by many Chrome features and great tools, such as Lighthouse, an open-source tool for accessibility, performance and progressiveness auditing which we’ll look into a bit later.

它们提供类似应用程序的用户体验(启动屏幕和主屏幕图标),由受HTTPS保护的服务器提供服务,即使在低质量或缓慢的网络条件下,它们也可以快速加载(由于页面加载性能的最佳做法),并且他们具有离线支持,即时加载和推送通知。 PWA的概念最初是由Google引入的,但仍受许多Chrome功能和出色工具的支持,例如Lighthouse,这是一个用于辅助功能,性能和渐进性审核的开源工具,我们将在稍后进行探讨。

Throughout this crash course, we’ll build a PWA from scratch with ES6 and React and optimize it step by step with Lighthouse until we achieve the best results in terms of UX and performance.

在整个崩溃过程中,我们将使用ES6和React从零开始构建PWA,并使用Lighthouse逐步对其进行优化,直到获得用户体验和性能方面的最佳结果。

The term progressive simply means that PWAs are designed in a such a way that they can be progressively enhanced in modern browsers where many new features and technologies are already supported but should also work fine in old browsers with no cutting-edge features.

术语“ 渐进式”仅表示PWA的设计方式使其可以在已经支持许多新功能和新技术的现代浏览器中逐步增强,但在没有尖端功能的旧浏览器中也可以正常工作。

原生vs移动=渐进 (Native vs Mobile = Progressive)

A native app is distributable and downloadable from the mobile OS’s respective app store. Mobile web apps, on the other hand, are accessible from within a web browser by simply entering their address or URL. From the user’s point of view, launching a browser and navigating to an address is much more convenient than going to the app store and downloading, installing, then launching the app. From the developer/owner’s point of view, paying a one-time fee for getting an app store account and then uploading their apps to become accessible to users worldwide is better than having to deal with the complexities of web hosting.

本地应用程序可以从移动操作系统的相应应用程序商店中分发和下载。 另一方面,只需在Web浏览器中输入地址或URL,即可访问它们。 从用户的角度来看,启动浏览器并导航到某个地址比去应用商店并下载,安装然后启动应用要方便得多。 从开发者/所有者的角度来看,支付一次费用来获取应用商店帐户,然后上载其应用以供全世界的用户访问,这比必须处理网络托管的复杂性要好。

A native app can be used offline. In the case of remote data that needs to be retrieved from some API server, the app can be easily conceived to support some sort of SQLite caching of the latest accessed data.

本机应用程序可以脱机使用。 如果需要从某个API服务器检索远程数据,则可以轻松地设计该应用程序以支持对最新访问数据的某种SQLite缓存。

A mobile web app is indexable by search engines like Google, and through search engine optimization you can reach more users. This is also true for native apps, as the app stores have their own search engines where developers can apply different techniques — commonly known as App Store Optimization — to reach more users.

谷歌等搜索引擎可为移动网络应用编制索引,并且通过搜索引擎优化,您可以吸引更多用户。 对于本机应用程序也是如此,因为应用程序商店拥有自己的搜索引擎,开发人员可以在其中应用不同的技术(通常称为“应用程序商店优化”)来吸引更多用户。

A native app loads instantly, at least with a splash screen, until all resources are ready for the app to execute.

本地应用程序会立即加载,至少会在启动屏幕上加载,直到为执行该应用程序准备好所有资源为止。

These are the most important perceived differences. Each approach to app distribution has advantages for the end user (regarding user experience, availability etc.) and app owner (regarding costs, reach of customers etc.). Taking that into consideration, Google introduced PWAs to bring the best features of each side into one concept. These aspects are summarized in this list introduced by Alex Russell, a Google Chrome engineer. (Source: Infrequently Noted.)

这些是最重要的感知差异。 每种应用程序分发方法都对最终用户(关于用户体验,可用性等)和应用程序所有者(关于成本,客户覆盖范围等)都有好处。 考虑到这一点,Google引入了PWA,将双方的最佳功能整合到一个概念中。 Google Chrome工程师Alex Russell在这份清单中总结了这些方面。 (来源: 不经常提及 。)

Responsive: to fit any form factor.

响应式:适合任何尺寸。 Connectivity independent: progressively-enhanced with service workers to let them work offline.

独立的连接性:逐步增强了服务人员的能力,使他们可以脱机工作。 App-like-interactions: adopt a Shell + Content application model to create appy navigations & interactions.

类应用互动:采用Shell + Content应用模型创建应用导航和互动。 Fresh: transparently always up-to-date thanks to the service worker update process.

新鲜:由于服务人员的更新过程,透明地始终保持最新。 Safe: served via TLS (a service worker requirement) to prevent snooping.

安全:通过TLS(服务工作者要求)提供服务以防止监听。 Discoverable: are identifiable as “applications” thanks to W3C Manifests and service worker registration scope allowing search engines to find them.

可发现:由于W3C清单和服务人员注册范围允许搜索引擎找到它们,因此可识别为“应用程序”。 Re-engageable: can access the re-engagement UIs of the OS; e.g. push notifications.

可重新参与:可以访问操作系统的重新参与用户界面; 例如推送通知。 Installable: to the home screen through browser-provided prompts, allowing users to “keep” apps they find most useful without the hassle of an app store.

可安装:通过浏览器提供的提示进入主屏幕,使用户可以“保留”他们认为最有用的应用,而无需麻烦应用商店。 Linkable: meaning they’re zero-friction, zero-install, and easy to share. The social power of URLs matters.

可链接:表示它们零摩擦,零安装且易于共享。 URL的社会力量很重要。

灯塔 (Lighthouse)

Lighthouse is a tool for auditing web apps created by Google. It’s integrated with the Chrome Dev Tools and can be triggered from the Audits panel.

Lighthouse是用于审核Google创建的网络应用程序的工具。 它与Chrome开发工具集成在一起,可以从“审核”面板中触发。

You can also use Lighthouse as a NodeJS CLI tool:

您还可以将Lighthouse用作NodeJS CLI工具:

npm install -g lighthouse

You can then run it with:

然后可以使用以下命令运行它:

lighthouse https://sitepoint.com/

Lighthouse can also be installed as a Chrome extension, but Google recommends using the version integrated with DevTools and only use the extension if you somehow can’t use the DevTools.

Lighthouse也可以作为Chrome扩展程序安装,但是Google建议使用与DevTools集成的版本,并且仅在您因某种原因无法使用DevTools时才使用该扩展程序。

Please note that you need to have Chrome installed on your system to be able to use Lighthouse, even if you’re using the CLI-based version.

请注意,即使您使用的是基于CLI的版本,也需要在系统上安装Chrome才能使用Lighthouse。

从头开始构建您的第一个PWA (Building your First PWA from Scratch)

In this section, we’ll be creating a progressive web app from scratch. First, we’ll create a simple web application using React and Reddit’s API. Next, we’ll be adding PWA features by following the instructions provided by the Lighthouse report.

在本节中,我们将从头开始创建一个渐进式Web应用程序。 首先,我们将使用React和Reddit的API创建一个简单的Web应用程序。 接下来,我们将按照Lighthouse报告提供的说明添加PWA功能。

Please note that the public no-authentication Reddit API has CORS headers enabled so you can consume it from your client-side app without an intermediary server.

请注意,公共无身份验证Reddit API启用了CORS标头,因此您可以在没有中间服务器的情况下从客户端应用程序使用它。

Before we start, this course will assume you have a development environment setup with NodeJS and NPM installed. If you don’t, start with the awesome Homestead Improved, which is running the latest versions of each and is ready for development and testing out of the box.

在我们开始之前,本课程将假定您已经安装了NodeJS和NPM的开发环境设置。 如果您没有这样做,请从令人敬畏的Homestead Improvementd开始 ,它正在运行每个版本的最新版本,并且可以立即进行开发和测试。

We start by installing Create React App, a project boilerplate created by the React team that saves you from the hassle of WebPack configuration.

我们首先安装Create React App,这是一个由React团队创建的项目样板,可以使您摆脱WebPack配置的麻烦。

npm install -g create-react-app create-react-app react-pwa cd react-pwa/

应用程序外壳架构 (The application shell architecture)

The application shell is an essential concept of progressive web apps. It’s simply the minimal HTML, CSS and JavaScript code responsible for rendering the user interface.

应用程序外壳是渐进式Web应用程序的基本概念。 这只是负责呈现用户界面的最少HTML,CSS和JavaScript代码。

This app shell has many benefits for performance. You can cache the application shell so when users visit your app next time, it will be loaded instantly because the browser doesn’t need to fetch assets from a remote server.

此应用程序外壳程序对性能有很多好处。 您可以缓存应用程序外壳程序,以便当用户下次访问您的应用程序时,将立即加载该外壳程序,因为浏览器不需要从远程服务器获取资产。

For building a simple UI we’ll use Material UI, an implementation of Google Material design in React.

为了构建一个简单的UI,我们将使用Material UI,这是React中Google Material design的一个实现。

Let’s install the package from NPM:

让我们从NPM安装软件包:

npm install material-ui --save

Next open src/App.js then add:

接下来打开src/App.js然后添加:

import React, { Component } from 'react'; import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; import AppBar from 'material-ui/AppBar'; import {Card, CardActions, CardHeader,CardTitle,CardText} from 'material-ui/Card'; import FlatButton from 'material-ui/FlatButton'; import IconButton from 'material-ui/IconButton'; import NavigationClose from 'material-ui/svg-icons/navigation/close'; import logo from './logo.svg'; import './App.css'; class App extends Component { constructor(props) { super(props); this.state = { posts: [] }; } render() { return ( <MuiThemeProvider> <div> <AppBar title={<span >React PWA</span>} iconElementLeft={<IconButton><NavigationClose /></IconButton>} iconElementRight={<FlatButton onClick={() => this.fetchNext('reactjs', this.state.lastPostName)} label="next" /> } /> {this.state.posts.map(function (el, index) { return <Card key={index}> <CardHeader title={el.data.title} subtitle={el.data.author} actAsExpander={el.data.is_self === true} showExpandableButton={false} /> <CardText expandable={el.data.is_self === true}> {el.data.selftext} </CardText> <CardActions> <FlatButton label="View" onClick={() => { window.open(el.data.url); }} /> </CardActions> </Card> })} <FlatButton onClick={() => this.fetchNext('reactjs', this.state.lastPostName)} label="next" /> </div> </MuiThemeProvider> ); } } export default App;

Next we need to fetch the Reddit posts using two methods fetchFirst() and fetchNext():

接下来,我们需要使用两种方法fetchFirst()和fetchNext()来获取Reddit帖子:

fetchFirst(url) { var that = this; if (url) { fetch('https://www.reddit.com/r/' + url + '.json').then(function (response) { return response.json(); }).then(function (result) { that.setState({ posts: result.data.children, lastPostName: result.data.children[result.data.children.length - 1].data.name }); console.log(that.state.posts); }); } } fetchNext(url, lastPostName) { var that = this; if (url) { fetch('https://www.reddit.com/r/' + url + '.json' + '?count=' + 25 + '&after=' + lastPostName).then(function (response) { return response.json(); }).then(function (result) { that.setState({ posts: result.data.children, lastPostName: result.data.children[result.data.children.length - 1].data.name }); console.log(that.state.posts); }); } } componentWillMount() { this.fetchFirst("reactjs"); }

You can find the source code in this GitHub Repository.

您可以在此GitHub Repository中找到源代码。

Before you can run audits against your app you’ll need to make a build and serve your app locally using a local server:

您必须先进行构建并使用本地服务器在本地提供服务,然后才能对应用进行审核:

npm run build

This command invokes the build script in package.json and produces a build in the react-pwa/build folder.

此命令将调用package.json的构建脚本,并在react-pwa/build文件夹中生成一个构建。

Now you can use any local server to serve your app. On Homestead Improved you can simply point the nginx virtual host to the build folder and open homestead.app in the browser, or you can use the serve package via NodeJS:

现在,您可以使用任何本地服务器来服务您的应用程序。 在Homestead Improvementd上,您可以简单地将nginx虚拟主机指向build文件夹并在浏览器中打开homestead.app ,也可以通过NodeJS使用serve软件包:

npm install -g serve cd build serve

With serve, your app will be served locally from http://localhost:5000/.

使用serve ,您的应用程序将从http:// localhost:5000 /在本地提供。

You can audit your app without any problems, but in case you want to test it in a mobile device you can also use services like surge.sh to deploy it with one command!

您可以审核您的应用程序而没有任何问题,但是如果您想在移动设备上对其进行测试,则还可以使用surge.sh服务通过一个命令来部署它!

npm install --global surge

Next, run surge from within any directory to publish that directory onto the web.

接下来,从任何目录中运行涌流,以将该目录发布到Web上。

You can find the hosted version of this app from this link.

您可以通过此链接找到此应用的托管版本。

Now let’s open Chrome DevTools, go to Audits panel and click on Perform an audit.

现在,我们打开Chrome DevTools,转到“审核”面板,然后单击“执行审核”。

From the report we can see we already have a score of 45/100 for Progressive Web App and 68/100 for Performance.

从报告中我们可以看到, 渐进式Web App的得分为45/100 , 性能为68/100 。

Under Progressive Web App we have 6 failed audits and 5 passed audits. That’s because the generated project already has some PWA features added by default, such as a web manifest, a viewport meta and a <no-script> tag.

在Progressive Web App下,我们有6个失败的审核和5个通过的审核。 这是因为默认情况下,生成的项目已经添加了一些PWA功能,例如Web清单,视口meta和<no-script>标记。

Under Performance we have diagnostics and different calculated metrics, such as First meaningful paint, First Interactive, Consistently Interactive, Perceptual Speed Index and Estimated Input Latency. We’ll look into these later on.

在“ 性能”下,我们具有诊断程序和不同的计算指标,例如“第一有意义的油漆”,“第一交互式”,“一致交互式”,“感知速度指数”和“估计输入延迟”。 稍后我们将研究这些。

Lighthouse suggests improving page load performance by reducing the length of Critical Render Chains either by reducing the download size or deferring the download of unnecessary resources.

Lighthouse建议通过减少下载大小或推迟不必要的资源下载来减少关键渲染链的长度,从而提高页面加载性能。

Please note that the Performance score and metrics values can change between different auditing sessions on the same machine, because they’re affected by many varying conditions such as your current network state and also your current machine state.

请注意, 性能得分和指标值可以在同一台计算机上的不同审核会话之间改变,因为它们受许多不同条件的影响,例如您当前的网络状态以及您当前的计算机状态。

为什么页面加载性能和速度很重要 (Why Page Load Performance and Speed Matter)

According to DoubleClick (a Google advertising company), 53% of mobile sites visits are abandoned if it takes more than 3 seconds to load the page. By optimizing page load performance and speed, PWAs offer instant web experiences to users via a set of techniques and strategies that we’ll look at next.

根据DoubleClick(一家Google广告公司)的说法,如果加载网页需要3秒钟以上的时间,则将有53%的移动网站访问被放弃 。 通过优化页面加载性能和速度,PWA通过一系列技术和策略为用户提供即时的Web体验,我们接下来将介绍它们。

在开始构建PWA 之前,请考虑性能 (Consider performance before you start building your PWA)

The majority of client-side apps are built using some sort of JavaScript library or framework such as React, Preact, Angular, Vue etc. If you’re building a PWA you need to make sure you choose a mobile-first library or, in other words, a library that’s designed for the mobile web in the first place. Otherwise, optimizing your app for performance will be an impossible mission.

大多数客户端应用是使用某种JavaScript库或框架(例如React,Preact,Angular,Vue等)构建的。如果要构建PWA,则需要确保选择移动优先的库,或者换句话说,首先是为移动网络设计的库。 否则,优化应用程序的性能将是一项不可能的任务。

You need to use different testing tools, like Chrome DevTools, Lighthouse, Google PageSpeed and others, to test your app heavily under different and simulated network conditions, so you can successfully optimize your app page load performance.

您需要使用不同的测试工具(例如Chrome DevTools,Lighthouse,Google PageSpeed等)在不同的模拟网络条件下对应用程序进行大量测试,以便成功优化应用程序页面加载性能。

您需要关注的PWA性能指标 (PWA performance metrics you need to put on your radar)

You can use Lighthouse for measuring and optimizing your app’s page load performance with different metrics, diagnostics, and opportunities.

您可以使用Lighthouse通过不同的指标,诊断和机会来衡量和优化应用程序的页面加载性能。

Lighthouse uses different metrics. Let’s cover them one by one:

Lighthouse使用不同的指标。 让我们一一介绍它们:

第一种有意义的涂料 (First meaningful paint)

First meaningful paint is a measure that simply indicates the time at which the user can see meaningful or primary content on the screen. The lower this audit is, the better the perceived performance of your app.

第一有意义的绘画是仅指示用户可以在屏幕上看到有意义或主要内容的时间的度量。 审核次数越少,您的应用感知性能越好。

Here’s this metric for our app.

这是我们应用的指标。

We see that from 1.3s the browser started to render the empty background, then from 2s the browser started rendering the header, 2.4s both the buttons on the header and the bottom are rendered. It’s not until the third second that the posts are rendered. The whole process took 3.4 seconds and the first meaningful paint equals 2.340ms — when the header without the next button is rendered.

我们看到,从1.3s开始,浏览器开始呈现空白背景,然后从2s开始,浏览器开始呈现标题,而2.4s则显示了标题和底部的按钮。 直到第三秒才发布帖子。 整个过程耗时3.4秒,第一个有意义的绘制时间为2.340毫秒 -呈现了没有下一个按钮的标题时。

A first meaningful paint is really dependent on what we can consider as meaningful, which can be different between different users. If a user is only interested in reading the posts, then the first meaningful paint for them is after the 3 seconds mark. You can see how Google calculates this metric from this document.

首先有意义的绘画实际上取决于我们认为有意义的内容,不同用户之间可能会有所不同。 如果用户只对阅读帖子感兴趣,那么对他们来说,第一个有意义的绘画是在3秒标记之后。 您可以查看Google如何根据此文档计算该指标。

This is another filmstrip for the same app where Lighthouse reported the FMP as 2.560ms at the last screenshot where post headlines are fully displayed in the above-the-fold area.

这是同一应用程序的另一个幻灯片,在最后一个屏幕截图中,Lighthouse报告FMP为2.560ms ,其中帖子标题完全显示在首屏区域中。

Secondly, you can see that the page is rendered progressively, not at once, which is a good indication of performance.

其次,您可以看到页面是逐步呈现的,而不是一次呈现的,这很好地表明了性能。

You can optimize this measure by optimizing the critical rendering path.

您可以通过优化关键渲染路径来优化此度量。

关键渲染路径 (The critical rendering path)

The critical rendering path is a concept related to how web browsers render pages — that is, from the first moment of receiving HTML, CSS and JavaScript assets to the step where the browser processes and renders actual meaningful content. To optimize the critical rendering path, you need to give higher priority to content that’s related to the user’s current action. That is, if they’re about to visit your app, you can start by first displaying the visible part of the UI, or what’s called the above-the-fold area.

关键的渲染路径是一个与Web浏览器如何渲染页面有关的概念,即从接收HTML,CSS和JavaScript资产的第一刻到浏览器处理并渲染实际有意义的内容的步骤。 要优化关键渲染路径,您需要赋予与用户当前操作相关的内容更高的优先级。 也就是说,如果他们要访问您的应用程序,则可以首先显示UI的可见部分,即所谓的“首屏”区域。

For more details, you can read “Optimizing the Critical Rendering Path”.

有关更多详细信息,您可以阅读“ 优化关键渲染路径 ”。

You can also see this list of curated tools for inlining critical CSS assets. Also check these tools for inlining JavaScript and other assets:

您还可以看到此精选工具的列表,这些工具用于内联关键CSS资产。 还要检查以下工具以内联JavaScript和其他资产:

inliner: a Node utility to inline images, CSS and JavaScript for a web page

inliner :一个Node实用程序,用于内嵌网页的图像,CSS和JavaScript

inline-source: a tool for inlining flagged JS, CSS, and IMG sources in HTML

inline-source :用于内嵌HTML中标记的JS,CSS和IMG源的工具

inline-source-cli: a CLI tool for inline-source.

inline-source-cli : 内联源的CLI工具。

关键请求链 (Critical Request Chains)

Critical Request Chains is a concept related to the Critical Rendering Path and can be represented by a diagram which breaks down critical resources to render a page, how much time each resource takes and how many bytes to download for each resource. You can use the Critical Request Chains diagram to get a better understanding of critical resources to eliminate, defer or mark as async. Here is a screen shot from our example PWA report:

关键请求链是与关键渲染路径相关的概念,可以由分解表示关键资源以绘制页面,每个资源花费多少时间以及为每个资源下载多少字节的图表表示。 您可以使用“关键请求链”图更好地了解关键资源,以消除,延迟或标记为异步。 以下是我们的示例PWA报告的屏幕截图:

Now let’s try to resolve this issue using inline-source and inline-source-cli:

现在,我们尝试使用inline-source和inline-source-cli解决此问题:

npm install -g inline-source inline-source-cli

We then navigate inside the build folder and open index.html, then add the keyword inline to <link> and <script> elements we want to inline:

然后,我们在build文件夹中导航并打开index.html ,然后将关键字inline添加到要内联的<link>和<script>元素中:

<link inline href="/static/css/main.5c745aa1.css" rel="stylesheet"> <script inline type="text/javascript" src="/static/js/main.c35c5a6e.js"></script>

Let’s inline these resources:

让我们内联这些资源:

cd build cat ./index.html | inline-source --root ./ > ./index.html

By inlining CSS and JavaScript assets, we’ve reduced the Critical Request Chains to 2.

通过内联CSS和JavaScript资产,我们将关键请求链减少到2个。

首次互动和始终如一的互动 (First Interactive and Consistently Interactive)

These two metrics both indicate the time for the user to be able to interact with the app. Both metrics express engage-ability and usability, but there’s a difference between them. First Interactive measures when the page is minimally interactive, while consistently Interactive measures when the page is fully interactive.

这两个指标均指示用户能够与该应用进行交互的时间。 两种指标都表示参与性和可用性,但是它们之间存在差异。 “首次互动”衡量的是页面最少互动的时间,而“ 持续互动”衡量的是页面完全互动的时间。

You can optimize the time to be interactive by optimizing the critical rendering path.

您可以通过优化关键渲染路径来优化交互时间。

感知速度指数 (Perceptual Speed Index)

Perceptual Speed Index is a metric that measures the above-the-fold visual performance of a page while taking into consideration the layout stability (no sudden displacement of UI elements). It simply indicates how quickly the page contents are visibly populated.

感知速度指数是一种度量页面的视觉性能的指标,同时考虑了布局稳定性(UI元素没有突然移位)。 它只是指示页面内容的可见填充速度。

PSI is a modified version of the SI or Speed Index metric, which is the average time at which the above-the-fold (visible) area is displayed without taking into account the visual stability.

PSI是SI或Speed Index度量标准的修改版本,SI或Speed Index度量标准是显示首屏(可见)区域而不考虑视觉稳定性的平均时间。

You can also optimize this metric by optimizing the critical rendering path.

您还可以通过优化关键渲染路径来优化此指标。

估计的输入延迟 (Estimated input latency)

Estimated input latency is a metric that indicates when the main thread becomes ready to process input.

估计的输入等待时间是一个指标,它指示主线程何时准备好处理输入。

You can read more about this metric and how to pass it here.

您可以在此处阅读有关此指标的更多信息以及如何通过它。

到第一个字节的时间(TTFB) (Time to first byte (TTFB))

Wikipedia defines TTFB as:

维基百科将TTFB定义为:

Time to first byte (TTFB) is a measurement used as an indication of the responsiveness of a web server or other network resource. TTFB measures the duration from the user or client making an HTTP request to the first byte of the page being received by the client’s browser.

到第一字节的时间(TTFB)是一种度量,用于指示Web服务器或其他网络资源的响应能力。 TTFB测量从用户或客户端发出HTTP请求到客户端的浏览器接收到页面的第一个字节的持续时间。

You can use tools like WebpageTest and Lighthouse to measure TTFB of your PWA. For more information see this link.

您可以使用WebpageTest和Lighthouse等工具来测量PWA的TTFB。 有关更多信息,请参见此链接 。

Let’s now see a set of concepts and common techniques used by developers to optimize these metrics.

现在,让我们看一下开发人员用来优化这些指标的一组概念和常用技术。

代码拆分和基于路由的分块 (Code Splitting and Route-based Chunking)

The JavaScript ecosystem has changed drastically in recent years, with new tools such as module bundlers like WebPack and Browserify, which are used to bundle all scripts into one file. This is considered good practice, since it helps reduce network requests for multiple script files to just one request (for getting the whole bundle), optimizing the critical rendering path (no long-blocking JavaScript and CSS assets). But the problem is, for large apps, the bundle will have a larger size, making the process of downloading the bundle, processing it, then booting up the application very inefficient, which affects the instant web experience (increasing the time for the first meaningful paint and the time for the UI to become interactive).

近年来,JavaScript生态系统发生了翻天覆地的变化,诸如WebPack和Browserify之类的模块捆绑器等新工具将所有脚本捆绑到一个文件中。 这被认为是一种好习惯,因为它有助于将对多个脚本文件的网络请求减少到一个请求(用于获取整个捆绑包),从而优化关键的渲染路径(没有长时间阻塞JavaScript和CSS资产)。 但是问题是,对于大型应用程序,捆绑包的大小会更大,从而导致下载捆绑包,处理捆绑包,然后启动应用程序的过程效率非常低下,从而影响了即时Web体验(增加了首次有意义的时间绘画和UI互动的时间)。

As a solution for this problem, different apps use code splitting and route-based chunking (splitting code into chunks which are only required for each route). So the browser only needs to download the first chunk needed to render the first page/route, then lazy loads the remaining chunks when the user is navigating other routes.

作为此问题的解决方案,不同的应用程序使用代码拆分和基于路由的分块(将代码拆分为仅对每个路由都是必需的块)。 因此,浏览器只需要下载呈现第一个页面/路线所需的第一个块,然后在用户导航其他路线时就懒加载剩余的块。

服务器端渲染 (Server-side Rendering)

Server-side rendering is the process of rendering the initial content on the server instead of the browser — which may, in many situations, improve the page load performance, since the browser can display content (plain HTML) immediately after downloading it.

服务器端渲染是在服务器而非浏览器上渲染初始内容的过程-在许多情况下,这可以提高页面加载性能,因为浏览器可以在下载内容后立即显示内容(纯HTML)。

Server-side rendering alone won’t help much in optimizing the time for the user to be interactive, since JavaScript assets need to be downloaded and booted up.

由于需要下载和启动JavaScript资产,因此仅服务器端渲染对优化用户交互时间没有太大帮助。

PRPL绩效模式 (PRPL Performance Pattern)

PRPL is a performance pattern which makes use of concepts such as HTTP/2 Server Push, Preload headers, service workers, and lazy loading to improve the performance of PWA delivery and launch.

PRPL是一种性能模式,它利用诸如HTTP / 2服务器推送,预加载标头,服务工作程序和延迟加载之类的概念来提高PWA交付和启动的性能。

PRPL stands for:

PRPL代表:

Push critical resources for the initial URL route

P USH关键资源初始URL路径

Render initial route

ř安德初始路径

Pre-cache remaining routes

P重新缓存剩余路由

Lazy load and create remaining routes on demand.

大号 AZY负荷和按需创建其余路线。

Source: Google Web Fundamentals

资料来源:Google Web基础知识

通过缓存优化性能 (Optimizing performance via caching)

Caching is the process of keeping frequently requested data in a close storage location. For the web, that’s the browser memory or database. A browser actually has a cache location specifically designed for caching network responses, but developers can also leverage other storage mechanisms such as the HTML5 Local Storage API and IndexedDB.

缓存是将经常请求的数据保存在紧密存储位置的过程。 对于网络,这就是浏览器的内存或数据库。 浏览器实际上具有专门用于缓存网络响应的缓存位置,但是开发人员还可以利用其他存储机制,例如HTML5 Local Storage API和IndexedDB。

You can cache the application shell (assets responsible for rendering the UI), data, or ideally both. Caching the UI is crucial for achieving an instant web experience. But what about data?

您可以缓存应用程序外壳程序(负责呈现UI的资产),数据或理想情况下两者。 缓存UI对于实现即时Web体验至关重要。 但是数据呢?

We can consider two categories of apps here. Apps that only need a network connection for getting assets responsible for rendering the UI and/or need it for providing the core functionality. Think, for example, of an app that provides personal accounting for users, which only depends on algorithms and calculations (local CPU).

我们可以在这里考虑两类应用。 仅需要网络连接来使资产负责呈现UI和/或需要它来提供核心功能的应用程序。 例如,考虑一个为用户提供个人核算的应用程序,该应用程序仅取决于算法和计算(本地CPU)。

The second category are apps that depend on remote servers to get updated information. You may wonder why you need to cache data, given that it will soon become obsolete and users mostly need updated information. The thing is, in many parts of the world the problem is not the permanent interruption of the network connection, but the fluctuating state of the network between slow and good signals, and that’s what affects the user experience even if the app is already loaded.

第二类是依赖远程服务器获取更新信息的应用程序。 您可能想知道为什么要缓存数据,因为它很快就会过时并且用户大多需要更新的信息。 问题是,在世界许多地方,问题不在于网络连接的永久中断,而是网络在缓慢信号和良好信号之间的波动状态,即使在已加载应用程序的情况下,这也会影响用户体验。

The app can make use of data caching (taking advantage of the Background Sync API) to guarantee its service when users are navigating between pages, or even if they leave and come back to the app in a short period of time, by continuously watching the network state, then resume fetching/sending data without interrupting the user.

该应用程序可以利用数据缓存(利用Background Sync API的优势)来保证用户在页面之间导航时(即使他们在短时间内离开并回到应用程序中)的服务,方法是持续观看网络状态,然后继续在不中断用户的情况下获取/发送数据。

Now let’s resolve the failed issues for better scores.

现在,让我们解决失败的问题以获得更高的分数。

注册服务人员 (Registering a Service Worker)

The first failed audit is saying that the app does not register a service worker. Before changing that, let’s first understand service workers and related features.

第一次失败的审核是说该应用程序未注册服务工作者。 在进行更改之前,让我们首先了解服务人员和相关功能。

A service worker is a modern browser technology that can be used as a client-side proxy that allows your app (by intercepting network requests) to implement caching for adding features such as instant loading and offline support etc.

服务工作者是一种现代浏览器技术,可以用作客户端代理,允许您的应用程序(通过拦截网络请求)实现缓存以添加诸如即时加载和脱机支持等功能。

Service workers can also be used for implementing updates and engaging with push notifications.

服务人员还可以用于实施更新和处理推送通知。

Service workers can’t access the page DOM, but can communicate with a client (a Window, Worker, or SharedWorker) via the postMessage() method.

服务人员无法访问页面DOM,但可以通过postMessage()方法与客户端(Window,Worker或SharedWorker)进行通信。

Many browser APIs are available for use inside service workers, such as:

许多浏览器API可在服务工作者内部使用,例如:

the Fetch API: for fetching content (sending requests and getting responses) from a remote server

Fetch API:用于从远程服务器获取内容(发送请求和获取响应) the Cache API: for caching content (create cache stores of responses keyed by requests)

缓存API:用于缓存内容(创建以请求为键的响应的缓存存储) the Push API: for getting push notifications

推送API:用于获取推送通知 the Background Sync API: allows the web app to defer actions until the user has stable connectivity.

Background Sync API:允许Web应用将操作推迟到用户连接稳定之前。

A service worker has many lifecycle events that need to be handled properly.

服务人员有许多生命周期事件,需要适当处理。

an install event: you get install events when the app is first visited by a user and the service worker is downloaded and installed

安装事件:当用户首次访问该应用程序并下载并安装服务工作者时,您将获得安装事件

an activate event: triggered after calling .register() (after download and install events)

激活事件:在调用.register()之后触发(在下载和安装事件之后)

a fetch event: you get fetch events in case of navigation within a service worker’s scope or any requests triggered scope pages.

提取事件:如果在服务工作者的范围内或任何请求触发的范围页面内进行导航,则将获取事件。

The React project already contains a service worker. We can either use it or create a new one so we can get a better idea of how service workers work.

React项目已经包含一个服务工作者。 我们可以使用它,也可以创建一个新的库,以便更好地了解服务人员的工作方式。

In the public folder, let’s create a new file named service-worker.js, then register it from the public/index.html file by adding the following code before</body>:

在public文件夹中,我们创建一个名为service-worker.js的新文件,然后通过在</body>之前添加以下代码从public/index.html文件中注册该文件:

<script> if ('serviceWorker' in navigator) { window.addEventListener('load', function() { navigator.serviceWorker.register('service-worker.js').then(function(registration) { console.log('Service Worker successfully registered'); }, function(err) { console.log('Error when registering the Service Worker ', err); }).catch(function(err) { console.log(err) }); }); } else { console.log('No Support For Service Workers'); } </script>

This piece of code first checks if service workers are supported in the browser, then listens for the page load event. When the page is loaded, it invokes the navigator.serviceWorker.register method to register public/service-worker.js.

这段代码首先检查浏览器是否支持服务人员,然后侦听页面加载事件。 加载页面后,它将调用navigator.serviceWorker.register方法来注册public/service-worker.js 。

Now we need to create a JavaScript file public/service-worker.js and add this code to set up caching:

现在,我们需要创建一个JavaScript文件public/service-worker.js并添加以下代码来设置缓存:

self.addEventListener('install', function(event) { event.waitUntil( caches.open('react-pwa-v1') .then(function(cache) { // The asset-manifest.json contains the names of assets to cache fetch("asset-manifest.json") .then(response => { return response.json() }) .then(assets => { cache.addAll( [ "/", "https://fonts.googleapis.com/css?family=Roboto:300,400,500", assets["main.js"], assets["main.css"], assets["static/media/logo.svg"] ] ); }) }) ); });

In the service worker install event, we first open the cache with the caches.open() method, then we use fetch() to get the asset-manifest.json file that’s generated by WebPack to map hashed assets to their original names. Next, we invoke cache.addAll() to add these assets to the application cache:

在服务工作者安装事件中,我们首先使用caches.open()方法打开缓存,然后使用fetch()获取WebPack生成的asset-manifest.json文件,以将哈希资产映射到其原始名称。 接下来,我们调用cache.addAll()将这些资产添加到应用程序缓存中:

// Serves the cached response for the corresponding request self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request).then(function(response) { if(response) return response; return fetch(event.request); }) ); });

This code intercepts every network request by listening to the fetch event and responding with the cached response if it exists in the application cache (using the caches.match() method). Otherwise, we normally call fetch() to get the asset:

此代码通过侦听fetch事件并在应用程序缓存中存在缓存的响应(使用caches.match()方法)时对其进行响应,从而拦截每个网络请求。 否则,我们通常调用fetch()来获取资产:

self.addEventListener("activate", event => { event.waitUntil( caches.keys() .then(keys => Promise.all(keys.map(key => { if (key !== 'react-pwa-v1') { return caches.delete(key); } })) ) ); });

When the app is activated, we delete the old cache if different from the current one.

激活该应用后,如果与当前缓存不同,我们将删除旧缓存。

This is a simple service worker for caching static assets. We can also use advanced tools for generating service workers such as:

这是用于缓存静态资产的简单服务工作者。 我们还可以使用高级工具来生成服务工作者,例如:

sw-precache: a NodeJS module created by Google, designed to be integrated with your build system to generate a service worker for adding offline support

sw-precache :由Google创建的NodeJS模块,旨在与您的构建系统集成,以生成用于添加离线支持的服务工作者

sw-toolbox: also created by Google to provide helpers and common caching strategies for dynamic caching to help you create your own service worker.

sw-toolbox :也由Google创建,旨在为动态缓存提供帮助程序和常见的缓存策略,以帮助您创建自己的服务工作者。

最终结果 (Final Results)

If we run audits against our app now, we should get a PWA score of 91.

如果我们现在对应用程序进行审核,则PWA分数应为91。

The app can now prompt users to install it on the home screen or shelf of a device.

该应用程序现在可以提示用户将其安装在设备的主屏幕或架子上。

We have one failed audit, which says that we need to redirect HTTP traffic to HTTPS, but that’s a little outside the scope of this post. Once we do this, however, these are the final results for performance:

我们的审核失败了,这表明我们需要将HTTP流量重定向到HTTPS,但这超出了本文的范围 。 但是,一旦执行此操作,这些就是性能的最终结果:

By reducing the critical request chains via JavaScript and CSS inlining, we’ve optimized the critical rendering path, which most of the performance metrics we saw previously depend on. But please keep in mind, this PWA is very simple; it only has one page, and React is designed with performance in mind. That’s the reason we have achieved a score of 95/100 for performance so quickly.

通过通过JavaScript和CSS内联减少关键请求链 ,我们优化了关键渲染路径 ,这是我们之前看到的大多数性能指标所依赖的。 但是请记住,这个PWA非常简单; 它只有一页,React在设计时考虑了性能。 这就是我们如此之快获得95/100得分的原因。

通过灯塔审核 (Passed Lighthouse Audits)

In order to cover all core tenets of progressive web apps, I’ll also explain the passed audits in Lighthouse report.

为了涵盖渐进式Web应用程序的所有核心原则,我还将在Lighthouse报告中解释通过的审核。

HTTPS (HTTPS)

Since we’re auditing the app locally (origin: http://localhost), Lighthouse assumes it’s secured, so the HTTPS audit is marked as passed, but that’s not going to happen once you use an actual host and link a top-level domain name unless you actually have an SSL certificate. (Note that service workers are only served from secure origins, except in the case of localhost.)

由于我们是在本地审核该应用程序(来源: http://localhost ),Lighthouse假定它是安全的,因此HTTPS审核被标记为已通过,但是一旦使用实际主机并链接到顶层,就不会发生这种情况。域名,除非您实际拥有SSL证书。 (请注意,仅从安全来源为服务工作者提供服务,本地主机除外)。

You can host your app with GitHub Pages which gives you an HTTPS-secured subdomain (github.io). You can also use Firebase hosting with a secured subdomain or Surge (surge.sh) that also comes with a basic SSL certificate for free.

您可以使用GitHub Pages托管您的应用程序,从而为您提供HTTPS保护的子域(github.io)。 您还可以将Firebase托管与受保护的子域一起使用,也可以免费使用Surge(surge.sh)(还附带基本的SSL证书)。

If you decide to link your own top-level domain, you also have the opportunity to get a free SSL certificate with Let’s Encrypt or Cloudflare.

如果您决定链接自己的顶级域,则还可以通过Let's Encrypt或Cloudflare获得免费的SSL证书。

For this course, we don’t actually need to host the application with an HTTPS-secured server, since Lighthouse passes this audit when testing locally.

在本课程中,我们实际上不需要使用受HTTPS保护的服务器来托管应用程序,因为Lighthouse在本地测试时会通过此审核。

网络应用清单 (The web app manifest)

A web app manifest is a JSON file that provides information about a PWA, such as name, icons and description, among many other things. It allows users to install the web app on the home screen just like native apps, but without going through an app store.

Web应用程序清单是一个JSON文件,可提供有关PWA的信息,例如名称,图标和说明等。 它允许用户像本地应用程序一样在主屏幕上安装Web应用程序,而无需通过应用程序商店。

A web app manifest needs to be referenced from an index.html file using a <link> tag with rel property set as manifest.

需要使用rel属性设置为manifest的<link>标记从index.html文件引用Web应用程序的清单 。

For example, the simple generated React app has a public/manifest.json file with the following content:

例如,简单生成的React应用程序具有一个public/manifest.json文件,其内容如下:

{ "short_name": "ReeditPWA", "name": "Reedit React PWA", "icons": [ { "src": "icon-192x192.png", "sizes": "192x192", "type": "image/png" } ], "start_url": "./index.html", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" }

It’s referenced from public/index.html:

从public/index.html引用:

<link rel="manifest" href="%PUBLIC_URL%/manifest.json">

感知性能和启动画面 (Perceived performance and the splash screen)

Browsers had no support for PWA splash screens before, so when users run the app from the home screen icon they often go through a white screen for a few seconds before they can see the actual app user interface. From Chrome 47 onwards, users can see a splash screen, which increases the perceived performance and transitions the user from tapping the home screen icon to an app’s first paint.

浏览器以前不支持PWA初始屏幕,因此,当用户从主屏幕图标运行应用程序时,他们通常会经过白屏几秒钟,才能看到实际的应用程序用户界面。 从Chrome 47开始,用户可以看到启动屏幕,该屏幕可以提高感知性能,并使用户从轻按主屏幕图标过渡到应用的第一幅画。

Simply put, perceived performance is a measure that’s more related to a user’s perspective and experience than the real performance/page load speed — providing information about how fast your app actually feels to end users.

简而言之,感知性能是一种与用户的观点和体验有关的指标,而不是与实际性能/页面加载速度相关的指标-提供有关您的应用对最终用户的实际感觉的信息。

You can read the perception of performance article for more on this.

您可以阅读有关性能感知的文章,以了解更多信息。

This splash screen is constructed for your app dynamically from the information in the web manifest, but (according to Lighthouse) you need to have an icon of at least 512×512 size in your manifest.json file for a high-quality splash screen.

此初始屏幕是根据Web清单中的信息动态地为您的应用程序构建的,但是(根据Lighthouse),您需要在manifest.json文件中至少具有512×512大小的图标,才能获得高质量的初始屏幕。

So just prepare an icon of at least 512×512 size, then add the following to your manifest.json under the icons array:

因此,只需准备一个尺寸至少为512×512的图标,然后将以下内容添加到manifest.json下的manifest.json :

{ "src": "splashscreen-icon-512x512.png", "sizes": "512x512", "type": "image/png" }

渐进增强 (Progressive enhancement)

One of the core tenets of PWAs is progressive enhancement, which refers to the capability of PWAs to run on different browsers but provide more advanced features only if they’re supported.

PWA的核心原则之一是渐进增强,它是指PWA在不同的浏览器上运行的功能,但只有在受支持的情况下,才能提供更高级的功能。

You can also read “The JavaScript-Dependency Backlash: Myth-Busting Progressive Enhancement” to understand more about progressive enhancement.

您也可以阅读“ JavaScript依赖反弹:神话般的渐进增强 ”,以了解有关渐进增强的更多信息。

A simple example of progressive enhancement is when an app is executed in a browser that doesn’t support JavaScript, or at least when JavaScript is disabled. Instead of showing nothing, you can use the HTML <noscript> tag to tell users that they should enable JavaScript:

渐进增强的一个简单示例是在不支持JavaScript的浏览器中执行应用程序时,或者至少在禁用JavaScript时。 您可以使用HTML <noscript>标记告诉用户应该启用JavaScript,而不是什么都不显示:

<noscript> You need to enable JavaScript to run this app. </noscript>

适用于PWA的Chrome DevTools (Chrome DevTools for PWAs)

Chrome is the first browser with official support for PWAs. As such, Chrome’s DevTools have excellent features for debugging PWAs, specifically contained in two panels — the Audit panel and the Application panel.

Chrome是第一个正式支持PWA的浏览器。 因此,Chrome的DevTools具有出色的PWA调试功能,特别是包含在两个面板(“ 审核”面板和“ 应用程序”面板)中。

Under the Audit panel you can find the Lighthouse tool we saw previously. Under the Application panel you can find many useful tools for debugging the core aspects of PWAs, such as:

在“ 审核”面板下,您可以找到我们之前看到的Lighthouse工具。 在“ 应用程序”面板下,您可以找到许多有用的工具来调试PWA的核心方面,例如:

the Web Manifest displayer, which displays the web manifest file related to your PWA and allows you to install the app on the shelf

Web清单显示器,它显示与PWA相关的Web清单文件,并允许您将应用程序安装在架子上 the Service Worker debugger, which allows you to see all service workers installed with your app, to start and stop them and emulate offline state

Service Worker调试器,可让您查看与您的应用一起安装的所有Service Worker,以启动和停止它们并模拟脱机状态 the Storage viewer, which allows you to see and clear IndexedDB, LocalStoarge and Session Storage for your app

存储查看器,使您可以查看和清除应用的IndexedDB,LocalStoarge和会话存储 the Cache viewer, which allows you to see and clear the app cache created using the Cache API.

缓存查看器,可让您查看和清除使用缓存API创建的应用缓存。

Chrome DevTools,用于模拟网络条件 (Chrome DevTools for Emulating Network Conditions)

In many parts of the world, mobile devices are connected through slow and flaky networks, so in order to provide a better user experience and acceptable load time — or, better yet, for instant web experiences for a large base of users with varying network speeds — you need to optimize your app under potentially different conditions. Thanks to the Chrome DevTools Network panel, you can emulate multiple network conditions such as slow 3G, fast 3G and offline state, and you can even create custom profiles with your own custom values for Download, Upload and Latency parameters.

在世界许多地方,移动设备通过速度较慢且不稳定的网络进行连接,因此为了提供更好的用户体验和可接受的加载时间,或者更好的是,对于网络速度各异的大量用户而言,它们是即时的Web体验-您需要在可能不同的条件下优化应用程序。 借助Chrome DevTools的“ 网络”面板,您可以仿真多种网络条件,例如慢速3G,快速3G和离线状态,甚至可以使用自己的“ 下载” ,“ 上传”和“ 延迟”参数自定义值创建自定义配置文件。

The Network panel provides other features such as cache disabling, turning offline state and taking app screenshots in load time.

“网络”面板提供了其他功能,例如禁用缓存,关闭脱机状态以及在加载时间内获取应用程序屏幕截图。

Both disabling cache and activating offline state are particularly useful for debugging PWAs.

禁用缓存和激活脱机状态对于调试PWA尤其有用。

For more information, check out Google’s “Network Analysis Reference”.

有关更多信息,请查看Google的“ 网络分析参考 ”。

结论 (Conclusion)

A PWA is not just another performance-focused app. It’s more than that! Thanks to the big players in the software industry — Google, Microsoft etc. — they’re becoming first-class apps on multiple platforms.

PWA不仅是另一个注重性能的应用程序。 不仅如此! 得益于软件行业的大公司-Google,Microsoft等-他们正在成为多个平台上的一流应用程序。

Aside from the performance benefits you can also incorporate into any web app, even if you don’t intend to build a fully qualified PWA, PWAs provide the following:

除了性能优势之外,您也可以将其集成到任何Web应用程序中,即使您不打算构建完全合格的PWA,PWA也可以提供以下功能:

Delivery of the best experiences to users by taking advantages of modern standards and best practices.

利用现代标准和最佳实践为用户提供最佳体验。 Add-to-home-screen banners so users can be prompted to add your PWA to their home screens. This happens when browsers detect that your app is engaging. The simplest example of the level of engagement needed is when the user uses your PWA again after a short period of time.

添加到主屏幕横幅,以便提示用户将PWA添加到主屏幕。 当浏览器检测到您的应用正在参与时,就会发生这种情况。 所需参与程度的最简单示例是用户在短时间内再次使用您的PWA时。

Samsung Internet 5.2 introduced a feature called ambient badging that alerts users when they’re viewing a PWA, so that it can be installed on their home screen.

三星Internet 5.2引入了一项称为“ 环境标志”的功能,该功能可在用户查看PWA时向​​用户发出警报,以便可以将其安装在其主屏幕上。

Opera for Android also introduced ambient badging.

Opera for Android还引入了环境标志。

As of Chrome 59, when a user installs your PWA, an APK will be created and installed on the user’s device, meaning that your PWA becomes a real Android app with an <intent-filter>, which tells Android to intercept clicks on any links belonging to your app scope and open your PWA instead of Chrome.

从Chrome 59开始,当用户安装您的PWA时,将会创建一个APK并将其安装在该用户的设备上,这意味着您的PWA成为具有<intent-filter> 的真正的Android应用 ,它告诉Android拦截任何链接上的点击属于您的应用范围,然后打开PWA(而不是Chrome)。

Microsoft announced Edge support for PWAs is coming soon. More than that, at the Edge Web Summit in 2017, Microsoft announced it’s bringing PWAs to the Windows Store so they’ll be searchable, discoverable and installable as first-class apps from Windows Store and the Bing search engine.

微软宣布Edge对PWA的支持即将推出。 不仅如此,在2017年的Edge Web Summit上,微软宣布将PWA引入Windows应用商店,以便它们可以作为Windows应用商店和Bing搜索引擎中的一流应用程序进行搜索,发现和安装。

Hopefully, this crash course has helped you get started with PWA-ifying your own web app!

希望该速成课程能够帮助您开始使用PWA验证自己的Web应用程序!

翻译自: https://www.sitepoint.com/progressive-web-apps-a-crash-course/

java web 速成

相关资源:《Java Web从入门到精通》高清完整PDF版
最新回复(0)