Start with AJAX (Asynchronous JavaScript + XML), especially when AngularJS comes out. Single-page apps have become a must for front-end apps. SPA can provide complete routing, page rendering, and even some data processing on the client side; This often requires a much heavier JavaScript framework than in the jQuery era to implement this logic on the back end. Most frameworks like React and Vue have built-in componentalization mechanisms to help developers organize their code, and they’ve even evolved to be specifically responsible for view components, with routing and data handled by plug-ins like Vuex, Redux, Vue Router, and so on. These tools are already fairly advanced and complete, providing routing schemes, server-side rendering schemes, and front-end state management schemes.

But the essence of SPA is still a browser-side App, and the underlying technology still relies on the History API, defineProperty, and AJAX. The power and completeness of these apis determine the user experience and superarchitecture design that SPA can achieve. It is these deficiencies and shortcomings of the underlying APIS that make it difficult for SPA to match the architectural benefits of the original Web. For example, in terms of content Accessibility, Independent Deployment and evolution of services, it is far behind the similar sites built ten years ago. They also broke the semantics of HTTP, URL, and HTML to varying degrees, and required a lot of work to fix logging statistics, performance tuning, first screen rendering, static analysis, and testing. The pitfall is that decisions to use SPA solutions may not be made with enough foresight to see the profound impact of these issues on the architecture.

At the same time, Web standards continue to iterate. Standards such as Web Bluetooth, Push API, Web of Things, and Service Worker are now supported to varying degrees in mainstream browsers (especially considering the popularity of the WebKit kernel in China). In particular, the introduction of the Progressive Web App (PWA) concept provides a way to achieve a smooth user experience without breaking the Web architecture. This article discusses some of the shortcomings of the SPA architecture, discusses the value of the PWA solution (a solution, but more of a technology direction choice) and the best way for private platforms to evolve.

What kind of Web App do we want?

The distinction between Web pages, especially dynamic Web pages, and Web App is very vague, but in order to discuss SPA, PWA and other technical solutions more clearly, we will first qualitatively analyze the product requirements behind Web App:

  1. Smooth, uninterrupted interaction. If the page reloads during the interaction and loses its state, or the page cannot be displayed due to network reasons, the user experience will be interrupted and the App will not be sufficient.
  2. Layout appropriate to the equipment. For example, displaying the complete layout of a PC page in a mobile browser will require users to zoom and drag to view information, which is not the experience of an App.
  3. Fast rendering and response. The long wait to get to each page, or the lack of immediate feedback after user actions, can be common problems with Web pages.
  4. Conforms to the interaction habits of mobile terminals. Native apis are enriched by mobile hardware, such as Bluetooth, QR code, camera, payment, gesture sliding, gesture zooming, touch feedback, etc.

This is my understanding of the requirements for Web apps (feel free to leave a comment) and the rest of the discussion is based on it.

Advantages of the Web architecture

It’s worth considering that even though Web pages are nowhere near what we need for mobile apps, Web technology is still an essential part of the current mobile App architecture. Where we rely on Web technology is precisely the strength of the Web architecture:

  1. Can link. The Web is technically classified as distributed documents that are linked to each other through urls. It can be opened directly between different pages within a single site or across sites without the need to download and install. There is an implicit feature to emphasize here: Deep Linking, which means jumping from one App to a specific page within another App, or even to a specific browsing location.
  2. Can be accessed. HTML is one of the cornerstones of the Web. On the one hand, it provides a separation of content and style, making it readable by both machines and humans and facilitating the development of more complex styles and interactions. On the other hand, a unified markup language has better accessibility, which is difficult to build on other platforms. For example, it can select and copy, blind people can enable screen readers, and even find a command line to view a Web page.
  3. Zero threshold. You don’t need any licenses or fees to participate in developing and providing Web services. This means that there are countless ways to develop a website at the same time, partly contributing to the Web technology boom.
  4. Independent deployment. Different Web services, or even parts of the same Web service, can be deployed and evolved independently. New and old websites can run on the platform at the same time, which is an iterative principle of the HTML5 standard.
  5. Robustness. Web pages have the unique robustness of distributed systems. There are no hard dependencies on the Web page and its dependent resources such as pictures, videos, scripts and styles. On the other hand, Web apps can be downloaded and executed at the same time, which is very robust for other platforms.

The issues of compatibility, responsive design, accessibility (or accessibility), and page performance that have been widely discussed since the rise of SPA are all advantages of Web architecture, and here is a slightly tongue-in-hand example of a page: Motherfuckingwebsite.com/ only 81 lines of the page, not only has a considerable amount of content; And it excels in compatibility, responsive design, accessibility, and page performance. The important thing is that the technologies used in this page are from the early days of the Web, in other words, these non-functional requirements are the inherent strength of the Web. Since the problems we’re struggling with don’t come from the Web itself, where do they come from? Is it a heavy JavaScript framework problem, a componentized solution problem, or falling into the developer experience trap?

Difficulties with the SPA program

This article does not discuss the success or failure or strengths and weaknesses of a specific SPA framework, but only the difficulties of implementing the desired Web App with a SPA solution and the impact of the SPA solution on existing Web pages. The following is a list of some of the most important impacts of SPA scheme on architecture, which are analyzed from the aspects of URL, accessibility and service independence.

A SPA is a set of highly coupled pages (page coupling)

The SPA scheme requires that all pages in the App be on the same service instance, which means that each instance that processes a SPA page request must have information about all pages in the App, which is usually a declaration of a page component.

This is because SPA requires page switching without browser hopping. Imagine the process of “open page A -> pushState to page B -> refresh -> return”. Instead of the browser reloading page A, the popstate event is triggered to B. Therefore, for any page A and any page B, page B in turn needs information of A. Of course, page A also knows information of page B, so any two pages with A jump relationship need to know each other’s information or reference each other’s components.

In this way, a set of pages coupled with each other constitute a Web App of SPA scheme. All pages in such an App can no longer be “independently deployed” and therefore cannot iterate independently. This often means that their development and debugging, front-end compilation, and deployment processes are all coupled together, which is the cost of SPA solutions:

  • Development dependencies: Because the corresponding components must be referenced in order to open a page, these components must be tied together during development and debugging. If the two pages are involved in the business and cross the team, it will undoubtedly add a lot of cost.
  • Compile dependencies: Consider compiling using MD5 stamps, where a set of files that reference each other must be compiled together, which reduces collaboration because they belong to different businesses or teams. Of course, it is also possible to dynamically adjust the reference relationship without using MD5 stamps and online separately. The problem is that it cannot balance the contradiction between HTTP cache and fast validity.

In addition, a Web App is restricted to sharing a domain name due to the browser’s same-origin policy. Otherwise, cross-domain is a very complex problem in a rich interaction scenario, unless of course you are willing to use an insecure interface like JSONP.

Strong componentization tends to fall into technical silos (technical closure)

SPA solutions, with their strong componentization, tend to fall into closed technical silos. In other words, it’s easy to go dark and lose the architectural advantage the Web deserves. This is because of the asynchronous nature of asynchronous pages. When the browser rerenders a page, global variables, timers, and event listeners are all initialized as new, which is what “refresh” means. Asynchronous pages do not:

  • Between asynchronous pages, global variables, timers are shared, no hosting is easy to mess up.
  • Asynchronous page<script>Between,The order of execution is not guaranteedWithout hosting, error prone.

So most SPA solutions don’t let you directly insert

This is the logic behind the various SPA frame family buckets. The final business environment is not the browser, but the componentized solution. Community componentization schemes do not iterate as Web standards do, nor are they necessarily downward compatible, which can incur significant costs in version upgrades or framework migrations.

URL can no longer locate resources (URL weakening, poor accessibility)

For the original Web page, the URL can not only locate the resource page, but also locate the specific browsing location of the page. But in SPA pages are rendered by the SPA framework. The classic configuration is to return the same resource for all urls, and browser-side scripts render different pages via location.href. So what’s wrong with that?

  1. The first screen performance is poor. Browser-side rendering, white screen during page download; The browser renders the page directly by streaming, rendering as much as it downloads.
  2. Machine unreadable. User agents that do not support scripts, such as search engines and CLI user agents, cannot parse the page because the contents of different urls are the same.
  3. Unable to locate browsing location. Because browsers no longer host full-page renderings and cannot record and recover browsing positions.

You can see that not only is the concept of links (urls) weakened, but accessibility is inherently poor. More advanced SPA frameworks provide server-side rendering (SSR) to remedy this, but with an additional architectural requirement: page rendering can be done on both the front and back ends, often requiring isomorphism on both ends.

Since the browser no longer records browsing locations, the SPA framework is needed to do so. But since any piece of content can be rendered locally within a Web App. The concept of a page gets pretty fuzzy in SPA, and the tree-like DOM structure really doesn’t map to a linear URL structure (unless you’re going to continue to break REST and stuff data into urls). So even if you put a lot of effort into it, you can’t achieve a perfect browsing location record.

Incomplete History API (inconsistent experience)

The History API is a browser-provided BOM API for browsing History, including the pushState method, popState event, history.state attribute, and so on. Leaving aside the lack of APIS in some browsers, performance in current standard and mainstream browsers such as Safari and Chrome is problematic. These problems can lead to a very erratic experience, such as invalid forward and backward moves, urls that don’t correspond to page content, and even unresponsive interactions. In short, it is unacceptable for a Web App that pursues extreme experience. Here are a few I’ve come across:

  • A popState event is delayed when a page resource is loaded that is rendered synchronously. This allows the page to be pushed out by pushState but not returned.
  • PopStateEvent.stateAlways equal to thehistory.state. So when a popState event occurs, no one can retrieve the state being popped out, making the state almost unavailable.
  • The popState event handler cannot distinguish between forward and backward. Scenarios considering page refreshes cannot be stored as variables only, only in sessionStorage, but this is not a simple and reliable solution because synchronous calls add routing latency and need to maintain quotas.
  • Some high-end browsers (such as some Huawei built-in browsers)history.state, but supports pushState and popState.
  • In all browsers in iOS, setscrollRestoration 为 manualThis causes the page to freeze for 1s when the gesture returns, making it impossible to find an easy and reliable solution to restore the browsing position.
  • There are no URL change events. The popState event is not triggered when pushState/replaceState is pushed. Therefore, there is no uniform URL change event, and a routing tool is often required to wrap these inconsistencies.
  • Gesture forward/return behavior is not defined in the standard. This means that some browsers animate and some don’t. Because these animations do not define any APIS, the SPA framework does not take over the page switching animations to ensure a consistent experience.

Referer semantics no longer source (log error)

In the Web age, the Referer HTTP Header is used to identify the source of a request, primarily for logging, statistics, and cache optimization. A typical SPA framework breaks the semantics of Referer.

There are two types of page hopping in SPA: one is when users interact with DOM and change the URL by using pushState script; The other is when the user interacts with the browser, such as a forward or back button or gesture, and the browser triggers a PopState event to notify the script. In the latter case, the POPState event occurs when the page URL has changed and the SPA framework is notified to load the next page. The Referer header must therefore be the URL of the current page, not the URL of the source page.

Opportunities presented by PWA

Those of you who are not familiar with PWA are advised to read my 2017 survey: PWA Exploration: Basic Features and standards Status, except that PWA is currently supported by all major browsers. In addition to Harttle Land’s support for PWA earlier this year, you can now add it to your desktop, add it to your home screen, and browse offline (e.g., disconnect the Internet now and refresh this page).

The term PWA comes from Alex Russell’s Progressive Web Apps: Escaping Tabs Without Losing Our Soul, the essence of PWA can be seen in the title of this article: implementing the App experience Without Losing the benefits of the Web architecture. Therefore, it can avoid the above problems of SPA and give full play to the advantages of Web.

Incremental improvement

Progressive refers to the construction process of PWA. The standards that make up the PWA come from Web technologies, which are browser-provided, backward compatible technologies with no additional runtime costs. Therefore, any existing framework developed Web pages can be transformed into PWA, and unlike SPA solutions, there is no strong componentalization mechanism, so migration and improvement can be achieved gradually without a handful of refactorings.

Performance improvement

The performance improvement of PWA mainly depends on the Service Worker, which is an added layer between the traditional Client and Server. The level of performance improvement depends on the specific strategy at this layer. Such as:

  1. If a cache first policy is used. Loading times must be significantly shorter. But users may see outdated content.
  2. If the network first policy is used. The load time is necessarily longer because of the additional cache query time.

Of course you can also apply the Race strategy, but the performance depends on how we control it. The PWA gives us the opportunity to customize this strategy, which is certainly worth exploring.

Enhancement of experience

The PWA solution is closer to the Web approach in that it is an enhancement rather than a replacement for the Web. So the interactive experience that the Web should have is guaranteed, and PWA also provides some App enhancements. Specifically, compared with SPA, PWA can achieve the following experience effects:

  • Stable interactive feedback. Page switches are hosted directly by the browser, which avoids the use of the History API, especially since operations involving the browsing history stack, such as forward and backward operations, are more stable and interactive feedback is more predictable.
  • Offline availability. This is perhaps the most obvious experience advantage of PWA, which can significantly increase media duration and interaction times.
  • Better equipment integration. PWA has some new browser capabilities, such as add to desktop, push notifications, that SPA doesn’t have.
  • Page view location. Compared to SPA, there is no huge implementation code, but the browsing position is more stable and robust.

The downside of PWA is that it cannot host page switching, which must be done by the browser. PWA’s benefit on speed is also worth noting: if the existing system may have been more radically optimized (such as resource packaging or local storage),

  • The PWA solution may not improve load times, but it should have a perceptible improvement in TTI and real user experience. Because PWA is closer to the raw Web page that the browser can easily understand, it makes better use of browser optimizations such as HTTP caching, file-by-file compilation caching, and so on.
  • On the other hand, the ARCHITECTURE of PWA solution is simpler and decoupled. Pages tend to be smaller and load faster than spAs in the long run. In this regard, it is recommended to consider the long-term evolution of the architecture, as discussed in the next section.

Architectural advantages

I prefer PWA because of its architectural advantages, which are beneficial to the iterative efficiency and long-term evolution of software. Choosing the right architecture may not have immediate benefits, but it can help the software evolve and the team grow, which in turn can better support business needs.

  1. Independent deployment and evolution

    The PWA scheme does not require reference relationships between page components, or even the same component abstraction between pages. This means that pages are decoupled from each other.

    Therefore, services/pages can still be deployed and evolved independently, and different pages can still choose the technology stack that suits their business. It can not only reduce the complexity of team management, but also benefit the efficiency of iteration of each line of business.

  2. Business development is more lightweight

    JavaScript engines have been optimized to cope with the growing size of Web pages to match the speed of some compiled languages. But today’s Web page scripts are ridiculously large, and not only do large scripts slow down loading, but relying too heavily on scripts can make pages less accessible and interactions unpredictable.

    PWA scheme is beneficial to reduce page volume and improve page loading performance. For example, it eliminates the need for bulky SPA frameworks, and more importantly, page decoupling makes page development lighter.

  3. More possibilities

    Service workers enable a layer of custom policies to exist in addition to clients, servers, and intermediate agents. Service workers can be used for performance optimization or even client-side Dr. This is a new architectural element in the Web architecture that could have a lot to offer.

  4. Simpler architecture

    For architecture, simplicity is a prerequisite for stability. Taking advantage of browsers and existing Web architectures can make the front end simpler.

    • Instead of hosting the resource load, leave it entirely to the browser and ask for the Referer.
    • Leaving the browsing history out of the way and leaving the page switching to the browser not only decouples the pages, but also makes the interaction more stable.

    The key to achieving simplicity is not to fight the browser, but to work on improving the browser. By using the Web approach to solve problems, you stay on the Web path and don’t lose the experience and architectural advantages of the Web.

Participation in standard construction

For a large website, no matter SPA program or PWA series technology in the industry, there will be deficiencies and defects. The important thing is that the two are improved in completely different ways:

  • Improving SPA schemes often means building more complex abstractions and unified site-wide componentization in the Web front end (i.e. the browser side).
  • Improving the PWA solution means working with the browser side to solve the problem, while keeping the Web front-end architecture simple.

Front-end and browser-side collaboration has been well practiced in the industry, including interest gathering, access and review of existing methods. Collaboration between the Web front end and the proprietary platform (own end) should also be done in this way. Not only can architecture advancement be maintained through collaboration with standardization organizations, but technology inclusion can be ensured through close community collaboration so that the home end has its own technology ecosystem and is more easily integrated into the iteration of standards. This is also a source of influence for proprietary platform technology.

Conclusions and Recommendations

All we want is a fast, smooth, feature-rich Web App. The difference between the SPA solution and the PWA solution is the way the problem is solved.

  • The idea of SPA is to encapsulate everything and make developers look at the framework rather than the Web itself. The architecture is complex enough that there are no obvious problems.
  • PWA is a progressive enhancement of the Web that is technically neutral and allows developers to still face the Web. The architecture is simple enough that there is obviously no problem.

The complexity of SPA lies in the coupling between businesses due to framework technology (especially componentalization), deep and closed technology stack, poor accessibility and stability of javasjavascript pages, and JavaScript framework instead of browser hosted page loading such a new interaction. It also causes errors and troubles in user interaction, log statistics, etc. In contrast, the PWA concept involves techniques that are the product of Web standards iterations, do not force any component module framework, can be progressively enhanced on any existing Web page, and allow different businesses to iterate independently, thus making it easier to produce smaller, faster loading pages. At the same time, new Service Worker technologies make Web architectures more technologically possible.

Therefore, PWA solution is recommended for large Web apps. Because PWA is part of the Web standard, it is JavaScript framework-neutral, does not impose any componentization solutions or introduce additional architectural constraints, and therefore does not burden subsequent architectural iterations. If you have your own end, you can iterate as Web standards do. Web-based apis also make it easier to participate in W3C standards and keep up with the community.

reference

MDN, Infreqently Noted, W3C, Wikipedia, React, Vue, HarttleLand, etc.

  • Calibreapp.com/blog/time-t…
  • Developers.google.com/web/updates…
  • Harttle. Land / 2016/11/26 /…
  • Harttle. Land / 2016/11/26 /…
  • Harttle. Land / 2016/11/26 /…
  • Harttle. Land / 2017/01/16 /…
  • Presents the IO/API/core/Ng…
  • angular.io
  • Reactjs.org/docs/react-…
  • Harttle. Land / 2016/11/26 /…
  • Zh.wikipedia.org/wiki/%E5%8D…
  • Developer.mozilla.org/zh-CN/docs/…
  • Developer.mozilla.org/zh-CN/docs/…
  • Developer.mozilla.org/zh-CN/docs/…
  • Harttle. Land / 2015/08/16 /…
  • Harttle. Land / 2017/01/28 /…
  • reactjs.org/
  • cn.vuejs.org/index.html
  • vuex.vuejs.org/zh/guide/
  • redux.js.org/api/store
  • router.vuejs.org/zh/
  • Harttle. Land / 2017/04/09 /…
  • Harttle. Land / 2017/12/24 /…
  • Harttle. Land / 2016/12/30 /…
  • Developer.mozilla.org/zh-CN/docs/…
  • Developer.mozilla.org/zh-CN/docs/…
  • Developer.mozilla.org/zh-CN/docs/…
  • En.wikipedia.org/wiki/Fragme…
  • medium.com/@baphemot/w…
  • Developer.mozilla.org/en-US/docs/…
  • Jakearchibald. Making. IO/isservicewo…
  • Infrequently.org/2015/06/pro…
  • Infrequently.org/2017/10/can…
  • www.w3.org/2019/Proces…
  • Developer.mozilla.org/zh-CN/docs/…
  • Harttle. Land / 2019/03/14 /…

This article is licensed under the Creative Commons Attribution 4.0 International License (CC-BY 4.0). Source: Hartuttle. Land /2019/03/27/… You are welcome to critique the citations and point out any inaccuracies and ambiguities. You can comment in the comments section below or email us at [email protected].