WebKit源码探索 |
您所在的位置:网站首页 › webkit源码下载 › WebKit源码探索 |
前言
众所周知在iOS端有两种WebView:UIWebView和WKWebView,UIWebView在2020年已遭appstore禁止上传,也就意味着这个写起来代码少但是性能不咋地的WebView退出了iOS开发的舞台。关于WKWebView,我们知道它是多进程模型,拥有独立进程,性能高,但它究竟是如何运行的?好在WebKit是开源的,我们可以从源码角度窥探一二。本文将从WebView加载网页请求开始探索WebKit的运行机制 准备工作所有的源码准备工作可以参考这篇文章 深入理解 WKWebView(入门篇)—— WebKit 源码调试与分析,这里有两个需要注意的点: 1、xcode workspace setting 的设置要将编译产物放到WebKitBuild,以及reletive到workspace,如下: 2、需要注意的是可以用源码里 Tools/Scripts 目录下的编译命令编译如下: 源码工程编译在我的17年丐版MacBookPro上消耗了两个多小时,接下来就是创建测试工程并添加到WebKit源码workspace中,然后在源码workspace内添加测试工程的scheme,至此准备工作完成。 进程创建流程探索测试第一步,在默认的ViewController.m里编写一个简单的WebView加载网页的代码如下 #import "ViewController.h" #import @interface ViewController () @property (strong, nonatomic) WKWebView *webView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:self.webView]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://m.baidu.com"]]; [self.webView loadRequest:request]; // Do any additional setup after loading the view. } - (WKWebView *)webView { if (!_webView) { WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init]; configuration.preferences.javaScriptCanOpenWindowsAutomatically = YES; [configuration.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"]; if (@available(iOS 10.0, *)) { [configuration setValue:@YES forKey:@"allowUniversalAccessFromFileURLs"]; } WKUserContentController *wkUController = [[WKUserContentController alloc]init]; configuration.userContentController = wkUController; _webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration]; _webView.backgroundColor = [UIColor whiteColor]; _webView.opaque = NO; _webView.scrollView.backgroundColor = [UIColor whiteColor]; _webView.scrollView.showsVerticalScrollIndicator = NO; _webView.scrollView.showsHorizontalScrollIndicator = NO; _webView.UIDelegate = self; _webView.navigationDelegate = self; _webView.scrollView.bounces = NO; } return _webView; } -(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{ } -(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ } -(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error{ }选中对应的测试工程的scheme,运行。这几行代码只是简单加载一个网页,但我们可以在Xcode的debug navigator非常直观的看到WKWebView的多进程模型 可以看到这里有三个进程,按照进程创建顺序分别是APP进程,网页渲染进程,网络加载进程。 我们再来看看webview是如何创建的,在initWithFrame: configuration: 方法里打断点,重新运行 接下来到私有化初始化方法看下 这里可以通过打印看到_configuration对象的信息 继续执行 这里是一些process和UI界面的配置代码,接下来是contentview的创建 在创建代码执行完,可以在左侧debug navigator里看到渲染进程创建完成,后续的H5代码解析渲染将在这个进程中进行。我们有必要看下content view创建过程,点击跳转进去 继续跳转进入_commonInitializationWithProcessPool: configuration: 这里看到_page的初始化及设置,我们到头文件去看下这个_page是什么东西 这里可以看到_page是一个WebPageProxy对象,也就是说网页相关的操作都这这个对象来管理的,接下来是_page的一些初始化设置 这里可以看到在contentview上添加了子视图,和app生命周期的通知。最后返回WKWebview对象也就是self,完成webview初始化。 接下来代码进入webview loadRequest,为了看清具体方法的执行顺序,我们先给loadRequest下一个符号断点,然后找到WKWebview的loadRequest方法,可以看到最终通过_page调用loadRequest,在此处添加断点 然后放跑断点,程序断在_page->loadRequest(request),继续放跑,来到WebPageProxy的loadRequest 可以看到这里有个判断是否有正在运行的进程的代码,没有就初始化进程,但是通过调试发现并没有执行launchProcess代码,同时左侧debug navigator也并没有产生网络加载进程,说明网络加载进程并不是在这里生成的,接下来是创建navigation的代码,然后跳转到loadRequestWithNavigationShared函数继续加载请求 我们跳转到loadRequestWithNavigationShared函数内部看一下 这里可以看到构造了一个loadParameters参数,包装了一些配置信息,继续往下 这里进入了preconnectTo,那我们给这个函数下一个符号断点,放跑执行 这里执行了三个函数websiteDataStore(),networkProcess(),preconnectTo(),这里分别下符号断点,看一下 只是返回了m_websiteDataStore对象,这个对象存储了什么信息可以看一下,如下 这里内容很多,包括session,cookie,configuration等等的信息,接下来调用networkProcess,我们放跑看一下 可以看到这里是网络进程创建的代码,最后返回网络进程,我们可以验证一下,继续执行代码,观察左侧debug navigator是否会产生新的进程 可以看到网络进程是在这里创建的,我们再来看下网络进程是什么东西 可以看到是网络进程代理对象NetworkProcessProxy,那我们在文件导航里搜索一下,可以找到这个类定义的c++头文件 到这,webview的所有进程全部创建完毕。 总结WKWebview的多进程模型,我们通过对源码的探索可以窥探其中的冰山一角。通过断点调试可以清楚的看到一个WKWebview包含的所有进程以及创建顺序: app本身进程 webview页面UI进程 网络进程那么接下来网络进程是如何请求数据和接收数据的?接收到的数据又是如何渲染到UI进程的?这些问题值得我们进一步去探索。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |