The background,

Nowadays, App development more or less uses Hybrid mode. When it comes to WebView, it often loads some JS files (such as bridle.js used for Native communication with WebView), and these JS files will not change often. Therefore, we hope that after loading JS in WebView once, if js does not change, there is no need to initiate network request to load next time, so as to reduce traffic and resource occupation. So what are some ways to do this? Let’s start with the caching principle of WebView.

Second, WebView cache type

WebView mainly includes two types of caches. One is the browser’s own web page data cache, which is supported by all browsers and defined by the HTTP protocol. The other type is H5 Cache, which is set by the developers of web pages. H5 Cache mainly includes App Cache, DOM Storage, Local Storage, Web SQL Database Storage mechanism, etc. Here we mainly introduce App Cache to Cache JS files.

Third, the browser’s own web data cache

1. Working principle

The browser Cache mechanism is a mechanism that controls file caching through cache-Control (or Expires) and Last-Modified (or Etag) fields in the HTTP protocol Header. About the role of these fields and the browser cache update mechanism, we can take a look at these two articles (H5 cache mechanism analysis of mobile Web loading performance optimization, Android: Hand-by-hand teaching you to build WebView cache mechanism & resource preloading scheme), there is a detailed introduction. From my practical point of view, I’ll take a look at the headers that are commonly encountered in the HTTP protocol.

These two fields are received when the browser decides whether the file needs to be cached; Or when the file needs to be loaded, the browser decides if it needs to issue the requested field.

  • Cache-control :max-age=315360000, which indicates that the Cache duration is 315360000 seconds. If the file needs to be requested again within 315,360,000 seconds, the browser will not make the request and will use the locally cached file. This is a field in the HTTP/1.1 standard.
  • Expires: Thu, 31 Dec 2037 23:55:55 GMT This means that the file Expires at 23:55.55 p.m. on December 31, 2037, and the browser won’t make another request to retrieve the file until then. This is a field in HTTP/1.0. If the client and server time is out of sync, it can cause caching problems, hence the above cache-control, which takes higher precedence when both appear in HTTP Response headers.

The following two fields are where the server decides whether the file needs to be updated when the request is made.

  • Last-modified :Wed, 28 Sep 2016 09:24:35 GMT,This indicates that the file was last modified at 9:24:35 on September 28, 2016. This field is carried by the browser as the if-Modified-since field of the Request Header on the next Request. For example, if a browser’s Cache of a file has exceeded cache-control (or Expires), a request is made when the file needs to be loaded. The Header of the request has a field calledIf-modified-since: Wed, 28 Sep 2016 09:24:35 GMTAfter receiving the request, the server compares the last-Modified time of the file to this time. If the time has not changed, the browser returns the request304 Not ModifiedTo the browser, and content-Length must be 0 bytes. If the time changes, the server returns200 OKAnd returns the corresponding content to the browser.
  • ETag: eb8c5c 57-129 “,”This is the character string of the file. The function is the same as last-Modified above. It’s just that the ETag is in the Request Header the next time the browser requests itIf-None-Match:"57eb8c5c-129"Field to the server. Compare the server with the latest file character string, return if the same304 Not ModifiedIf not, return200 OK. When ETag and last-Modified are present together, the file is considered unupdated as long as either field is in effect.

2. How can WebView be set to support the above protocol

As you can see from the above, any mainstream, qualified browser should be able to support these fields at the HTTP level. This is not something we developers can change, nor is it something we should change. On Android, our WebView also supports these fields. However, we can use code to set the Cache Mode of the WebView to make the protocol valid or invalid. A WebView has the following Cache modes:

  • LOAD_CACHE_ONLY: no network is used and only local cached data is read.
  • LOAD_DEFAULT: determines whether to fetch data from the network according to cache-control.
  • LOAD_CACHE_NORMAL: this parameter is deprecated in API level 17 and applies to the LOAD_DEFAULT mode starting from API level 11
  • LOAD_NO_CACHE: does not use the cache and only gets data from the network.
  • LOAD_CACHE_ELSE_NETWORK, as long as it is locally available, regardless of expiration, or no-cache, uses the data in the cache. It is obtained from the network only when there is no local cache.

Example Cache Mode code for setting the WebView Cache is as follows:

WebSettings settings = webView.getSettings();
settings.setCacheMode(WebSettings.LOAD_DEFAULT);Copy the code

Set Cache Mode to LOAD_DEFAULT when there is a network and LOAD_CACHE_ELSE_NETWORK when there is no network. However, in my business, js file updates are non-override updates, meaning that the URL of the file must change every time the JS file is changed, so I want the browser to cache the JS file and use it all the time, so I set it to LOAD_CACHE_ELSE_NETWORK only. If you can change the cache-control field of the JS CDN server, then you can use LOAD_DEFAULT. Whether files should be overwritten or not is not what I’m going to discuss today, but in the web front-end area, it’s a topic that can be talked about.

As for the iOS WebView, my colleague actually found in the actual test that the Response Header controlling the file cache was the Expires field. In addition, iOS cannot set Cache Mode for the entire WebView, only for each URLRequest. I will learn about iOS later when I have a chance.

3. The storage path in the mobile phone

How do files that browsers cache by default get stored there? This question has been a puzzle since we came into contact with WebView. For my work, I root two phones, one Redmi 1 (Android 4.4) and one Mi 4C (Android 5.1). After the failure of the two Nexus versions (6.0 and 7.1), I decided to first look at 4.4 and 5.1. Where the WebView’s own cache is stored.

First of all, without thinking, these files must be in the /data/data/ package name/directory, which, as I mentioned in a previous blog post, is the internal storage directory of each application.

Next, we open the terminal, use ADB to connect to the phone, and follow the following command.

Go to shell adb shell // 2. Enable the root account su // 3. Change folder permissions chmod 777 data/data/ your application package name // / 4 Change the permissions of subfolders, because the Android command line does not support recursive chmod like the Linux -r command... Chmod 777 data/data/ your application package name /* // 5. So if you're deeper into the app directory hierarchy, you need to chmod further... Chmod 777 data/data/ your application package name /*/* // 6. Until terminal prompt you say, no such file or directory, indicating that chmod is finished, all internal storage inside the folder and file can be seen, if you have a better way please tell me, thank you ~Copy the code

  • Android 4.4 directory:/ data/data/package/app_webview/cache /, the second folder as shown below.

As you may have noticed, the first folder is called Application Cache, and we’ll talk about it later.

  • Android 5.1 directory:/ data/data/package/cache/org. Chromium. Android_webview /Below, as shown below.

In 5.1, the /data/data/ package name /app_webview/ folder still exists, but the app_webview/cache folder that stores the WebView cache in 4.4 no longer exists (note that the App cache directory still exists), as shown in the figure below.

In summary, WebView’s built-in browser protocol supports caches in different locations on different versions of the system. Maybe in addition to 4.4, 5.1, other versions of the system WebView built-in cache may also exist in different directories.

The other one is about the cache file storage format and index format, which may be different on different mobile phones, because before I saw the Internet people said that there is a file called webview.db or webviewcache. db, this file, Not yet under app_webview/cache or org.chromium.android_webview, but in /data/data/ package name /database/. However,, neither of my two root phones can see this file, and I opened all the db files below /data/data/ package name/and found no table storing URL records.

In fact, in 5.1 system, for example, I saw the/data/data/package/cache/org. Chromium. Android_webview/below is called index and the index – dir/real – the index file, As well as a pile of files named MD5 + underscore + number, can also be seen in the picture above, the principle of this piece is still some questions, also hope professional god can answer it.

Iv. Cache of H5

The App Cache in H5. The Cache is controlled by the developer of the Web page, not by Native, but the WebView in Native also needs to be set up to support this feature of H5.

1. Working principle

When writing Web page code, specify the manifest attribute to make the page use the App Cache. A typical HTML page code would look like this:

 

<html manifest="xxx.appcache">
</html>Copy the code

XXX. The appCache file uses a relative path, in which case the appCache file has the same path as the page. You can also use an absolute path, but keep the domain name consistent with the page.

A complete xxx.appcache file usually contains three sections, and the basic format is as follows:

CACHE MANIFEST # 2017-05-13v1.0.0 /bridge.js NETWORK: * FALLBACK: /404.htmlCopy the code

  • The CACHE MANIFEST file is the file to be cached by the browser
  • The files under NETWORK are the ones to be loaded
  • The file below the FALLBACK is the page displayed when the target page fails to load

How AppCache works: When an HTML page is loaded with the manifest file, the files specified in the CACHE manifest file are cached in the browser’s App CACHE directory. The next time the page is loaded, a request is made to the server to load the XXX. Appcache file. If the file has Not been Modified, the server returns 304 Not Modified to the browser. If the XXX. Appcache file has been modified, the server will return 200 OK and the contents of the new XXX. Appcache file to the browser, which will load the specified contents of the new XXX.

As you can see, the AppCache cache needs to issue an xxx. AppCache request every time a page is loaded to check for an update to the manifest file (byte by byte). According to this article, AppCache has some bugs and is officially deprecated, but it is still supported by mainstream browsers. The following pits are mainly mentioned in the article:

  • To update a cached file, you need to update the manifest file that contains it, if only with a space. The common approach is to change the version number in the manifest file comments. For example: # 2012-02-21 v1.0.0
  • The browser uses the cached file first and then updates the cache file by checking the manifest file for updates. The cached file may not be the latest version.
  • During the cache update process, if one file fails to update, the entire update fails.
  • The manifest and the HTML that references it should be at the same HOST.
  • A list of files in the manifest file or, if relative, relative paths to the manifest file.
  • It is also possible to update the manifest incorrectly, causing the cache file to fail to update.
  • Resources that are not cached cannot be loaded in cached HTML, even if there is a network. For example: [url =] appcache-demo.s3-website-us-east-1.amazonaws.com/without-net… ]
  • The manifest file itself cannot be cached, and updates to the manifest file use the browser caching mechanism. Therefore, the Cache-Control Cache time of the manifest file cannot be set too long.

2. How can WebView be set to support AppCache

AppCache support is not enabled for WebView by default. Add the following lines of code to set this up:

WebSettings webSettings = webView.getSettings(); webSettings.setAppCacheEnabled(true); String cachePath = getApplicationContext().getCacheDir().getPath(); / / the internal private cache directory '/ data/data/cache/package name/' as the WebView AppCache storage path webSettings setAppCachePath (cachePath); webSettings.setAppCacheMaxSize(5 * 1024 * 1024);Copy the code

Note: Both setAppCacheEnabled and setAppCachePath for WebSettings must be called.

3. Path for storing AppCache

According to the Android SDK API, setAppCachePath can be used to set the AppCache path, but my tests found that no matter how you set the path, it doesn’t work on the app’s own internal private directory or external SD card. AppCache cache files can eventually to/data/data/package/app_webview/cache/Application cache the folder below, in the above system directory screenshots can see the Android 4.4 and 5.1, But if you don’t call setAppCachePath, WebView won’t generate the directory. This is a bit strange for me, but I suspect that from one system version, the SDK implemented the AppCache cache directory as internal private storage for the sake of file integrity and security.

Five, the summary

The same

WebView’s own cache and AppCache can be used to do file level cache, basically better meet the update of non-overwriting JS, CSS and other files.

The difference between

  • WebView’s own cache is protocol layer implementation (browser kernel standard implementation, developers can not change); AppCache is implemented at the application level.
  • The WebView cache directory may be different on different systems; For AppCache, the storage path of AppCache is set by method, but it is eventually stored in a fixed internal private directory.
  • WebView’s built-in cache eliminates the need to send HTTP requests when the cache is in effect. AppCache must issue a manifest file request.
  • You can change the WebView cache mechanism by setting CacheMode. The AppCache cache policy is controlled by the manifest file, which is the web page developer.

Finally, most of the time, these two types of caches work together. When the manifest file does not control the loading of certain resources, such as the XXX. Appcache file I wrote above, the NETWORK section is marked with *, meaning that all files that are not cached must be loaded from the NETWORK. At this point, these resources will go to the WebView cache mechanism, combined with the WebView CacheMode, we actually do a WebView cache for these files. Understanding the principles of these two types of caching can help us better design our pages and apps, minimize network requests, and improve the efficiency of App operation.

Classic front-end technology books


comments