Create a RingCentral web app that works in IE 11
Today I am going to show you how to create a RingCentral web app that works in IE 11. I know you might be wondering: why do you want to support IE 11? Well, there are lots of legacy systems or environments. IE 11 is dying, but not dead yet. One real sample is the RingCentral Scheduler Outlook add-in. It is an Outlook plugin so it runs inside Outlook, which uses IE 11 as the web engine. For such an add-in app, we’d have to support IE 11. We are going to divide this article into 3 parts:
- Setup the project
- Make it work in Chrome
- Make it work in IE 11
Setup the project
When you start working on the app, forget about IE 11, just make sure that it could work in the Chrome browser. Because the chrome browser is way more modern and it supports most of the new features of the JavaScript language. Chrome browser is also the most popular browser in the world. It is always a good idea to start your app with the Chrome browser supported.
We will start with a “Hello world” app:
alert('Hello world');
This app is very simple, it does nothing but alert the user by saying “Hello world”. In order to make it work in the browser, we need a webpack to bundle it. Below is the webpack.config.js
file:
const HtmlWebpackPlugin = require('html-webpack-plugin');const config = {
mode: 'development',
devtool: 'source-map',
plugins: [
new HtmlWebpackPlugin({
title: 'RingCentral IE 11 Demo',
})
],
};module.exports = config;
Please note that for this article we are using
webpack
4.x andhtml-webpack-plugin
4.x. The latest webpack 5.x versions has some major changes which we don’t want to touch in this article.
When you run it, you will see the following alert message:
Make it work in Chrome
Now let’s add some RingCentral features. The first feature we want to add is to login RingCentral:
const RingCentral = require('@rc-ex/core').default;
const AuthorizeUriExtension = require('@rc-ex/authorize-uri').default;
const localforage = require('localforage');const rc = new RingCentral({
clientId: 'xxxxxxyyyyyyzzzzzz',
server: 'https://platform.ringcentral.com',
});const redirectUri = window.location.origin + window.location.pathname;const authorize = async code => {
await rc.authorize({
code,
redirect_uri: redirectUri,
code_verifier: (await localforage.getItem('code_verifier')),
});
};const showGreetings = async () => {
alert('Hello guest!');
};const urlSearchParams = new URLSearchParams(
new URL(window.location.href).search
);
const code = urlSearchParams.get('code');
if(code == null) { // need to login
const authorizeUriExtension = new AuthorizeUriExtension();
rc.installExtension(authorizeUriExtension);
authorizeUri = authorizeUriExtension.buildUri({
redirect_uri: redirectUri,
code_challenge_method: 'S256',
});
const codeVerifier = authorizeUriExtension.codeVerifier;
localforage.setItem('code_verifier', codeVerifier);
document.writeln(`<a href="${authorizeUri}">Login</a>`);
} else { // already logged in
(async () => {
await authorize(code);
await showGreetings();
})();
}
In the code snippets above, we used Authorization Code PKCE to login. For more information about PKCE, please check this project. We will just skip the details about login. So far our app does nothing but login and show us greetings:
The greeting message is “Hello guest!” which is not quite right, because I have logged in. I am going to update the code so that it will show the greeting message as “Hello Tyler Liu!”. Tyler Liu is the current logged in RingCentral user name:
const showGreetings = async () => {
// @rc-ex/debug
const debugExtension = new DebugExtension();
await rc.installExtension(debugExtension); const extInfo = await rc.restapi().account().extension().get();
alert(`Hello ${extInfo.name}!`);
};
Please note that the
@rc-ex/debug
part is completely optional, it is used to print some information for debugging purposes. The RingCentral Extensible project has a couple of extensions. You install those extensions based on your requirements.
OK, that’s our simple demo. You can find the full code here.
Make it work in IE 11
Now let’s test the website in IE 11:
The error is expected. IE 11 doesn’t support ES6, we’d need to compile the source code to ES5. Add the following to webpack.config.js
:
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
targets: {
browsers: ['IE >= 11'],
},
},
],
],
},
},
},
],
},
Test it in IE again, this time we will get a different error:
This error is also expected. Because IE 11 doesn’t support some modern JavaScript language features, such as Promise and async/await. We need to add polyfills to our project. At the beginning of our source code, add:
require('babel-polyfill');
Test again:
This time it is kind of unexpected. URLSearchParams
is not a language feature but a browser feature. We replace the following code:
const urlSearchParams = new URLSearchParams(
new URL(window.location.href).search
);
const code = urlSearchParams.get('code');
with
function getParameterByName(name, url = window.location.href) {
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
const code = getParameterByName('code');
Test again:
Hooray! Finally we’ve made it! You can find the full source code for the final project here.
Summary
Although IE is dying — it is not dead yet. In case your project needs to support IE 11, start by making it support Chrome. Then compile the code to ES5, apply proper polyfills and fix other miscellaneous issues to make it properly work.
Please let us know what you think by leaving your questions and comments below. To learn even more about other features we have make sure to visit our developer site and if you’re ever stuck make sure to go to our developer forum.
Want to stay up to date and in the know about new APIs and features? Join our Game Changer Program and earn great rewards for building your skills and learning more about RingCentral!