iOS WKWebview + Ionic + Laravel

Chris Hand
4 min readNov 20, 2017

Ionic is an awesome hybrid mobile framework. With devices and browsers getting better and better, the experience for some apps can compete with native implementations. On the apps I work with, I couldn’t help but notice that some things felt inherently smoother on Android than iOS. Though I’m an Android user myself, I don’t kid myself that this is due to superior hardware. Something else was going on.

Turns out, by default Android devices will use the WKWebview and (in Ionic 3 and below) iOS will use UIWebview. The performance on WKWebview is vastly superior, and so my apps felt better on Android than iOS.

The newest version of Ionic (v4) will ship using WKWebview on iOS by default, but until then, you have to enable it manually to make it work. This can be a bit tedious, as there are some caveats to using it. Most notably, your app will now require CORS to be enabled on your server if you’re hitting an API. Let’s break down the steps:

  1. Install the plugin.

No worries there:

ionic cordova plugin add cordova-plugin-ionic-webview — save

After you do this, it’s a good idea to refresh all your plugins on iOS by removing and re-adding the platform:

ionic cordova platform rm ios
ionic cordova platform add ios

2. Update the config.xml file.

This hung me up for a while. You’ll need two new additions:

<feature name="CDVWKWebViewEngine">   
<param name="ios-package" value="CDVWKWebViewEngine" />
</feature>
<preference name="CordovaWebViewEngine" value="CDVWKWebViewEngine" />

This sets WKWebview as the default view engine.

Next, you’ll need to find this line in your config.xml file:

<allow-navigation href="http://ionic.local/*" />

And replace it with:

<allow-navigation href="http://localhost/*" />

If it’s not already in your config file, just add it, no need to replace anything, but the point here is that you don’t want both settings. Also, the point here is, if you find the initial setting don’t add to it, replace it. Now you’re ready for the last step:

3. Enable CORS on your API.

Wait… what’s CORS? No, not the beer. And no, not the band. CORS stands for Cross Origin Resource Sharing. Here’s the simple line: if you want to make an http request from a something that is not a server, then it is a CORS request. JavaScript running in a browser makes CORS requests to external servers. WKWebview changes the source of HTTP requests on your device, and they will now be made as a CORS request (formerly they were made from a file:// URL).

In a Laravel instance, this can be (fairly) easily done with middleware. To enable CORS is basically just putting a bunch of headers on your server responses to let callers know they are allowed to make HTTP requests. They’ll know this because, by default, browsers make an options request to servers before making your actual request (like a get request). This options request will return all the headers the server allows.

There are two things you’ll need:

  1. You’ll need some global middleware to allow options requests. With Laravel routing, unless you explicitly define routes that specify options as the HTTP verb to catch. You don’t want to have to do that with every route, so just make it a global middleware. Something like this would work:
<?php
namespace
App\Base\Http;

use Closure;

class PreflightMiddleware
{
/**
* Handle an incoming request.
*
*
@param \Illuminate\Http\Request $request
*
@param \Closure $next
*
@return mixed
*/
public function handle($request, Closure $next )
{
if ($request->getMethod() === "OPTIONS") {
return response('')
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Origin, Content-Type, X-Auth-Token, authorization, X-Requested-With');
}
return $next($request);
}
}

All this is doing is checking to see if the method is option and if it is, tell the requesting entity what you allow.

Make these headers specific to your needs, the above example is very broad and generic.

2. Allow CORS requests on your API endpoints.

This is very similar to the preflight middleware we have above, but this will live on only the resources we want exposed via API. Personally, I put this on our API middleware group:

<?php

namespace
App\Auth\Middleware;

use Closure;

class CorsMiddleware
{
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Origin, Content-Type, X-Auth-Token, authorization, X-Requested-With');
}
}

This is doing basically the same thing as our preflight middleware, but for all verbs. We want two different middlewares because we only want to expose CORS request at a global level for options requests.

Viola! Now WKWebview will work for your project. Enjoy the new experience.

--

--

Chris Hand

Helping teams take ownership of their product and empower themselves to do great things.