How to make your Svelte 3 Cordova app work on old phones using Babel 7 and Rollup

21.08.20194 Min Read — In cordova

When working with a relatively new framework like svelte you come across issues that more "battle tested" frameworks have solved already. One such issue is transpiling your code to work on older browsers. This is meaningful especially for a cordova app, because it runs in a system WebView, which version depends on various factors, and is not always updated.

I wrote more about WebView versions in the post: should you transpile your cordova app

What should be transpiled?

We're going to use babel of course, in order to transpile.

From the babel docs:

Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.

But which code needs to be transpiled? We need to consider two levels of transpilation:

1. Our app's code

If you're using ES6 and above in your app (and you should), you need to transpile that. This includes you .svelte files and .js files.

2. Dependencies

Your dependencies are also code that's bundled along with your app. If they were published with ES6 syntax, then they'll cause your bundle.js to contain untranspiled code. By the way, here is babel's take on external dependencies:

Ideally, you should only be transforming your source code, rather than running all of your external dependencies through Babel – hence the exclude: 'node_modules/**' We encourage library authors not to distribute code that uses untranspiled ES6 features (other than modules) for this reason. Consumers of your library should not have to transpile your ES6 code, any more than they should have to transpile your CoffeeScript, ClojureScript or TypeScript.

Unfortunately, not all libraries abide by this rule. One such library is axios:

Up until the 0.6.0 release ES6 Promise was being polyfilled using es6-promise. With this release, the polyfill has been removed, and you will need to supply it yourself if your environment needs it.

Another is svelte. According to this svelte GitHub issue, it's still a WIP to list exactly what needs transpiling / polyfills.

The solution

The following configuration has worked for me, successfully transpiling my cordova app.

1. Install dependencies

First let's install the required babel packages, and the rollup plugin.

npm i -D @babel/core @babel/preset-env rollup-plugin-babel core-js

2. Configure babel

Now add the following configuration to babel.config.js:

module.exports = function (api) {
    api.cache(true);
    const presets = [
        ["@babel/preset-env", {
            // "debug": true,
            useBuiltIns: "usage",
            corejs: 3, // or 2,
            targets: {
                browsers: "last 2 versions",
            }
        }]
    ];
    return {
        presets
    }
}

Notice the browsers: "last 2 versions" line. It's a feature of @babel/preset-env that makes it transpile to last 2 major versions of all browsers. Also, the debug field can come in handy if you want to see exactly what files are being transpiled.

3. Configure rollup

Add the following babel section at the end of the plugins section of rollup.config.js, assuming you're using the same directory structure as in the svelte cordova template:

import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import replace from 'rollup-plugin-replace';
import babel from 'rollup-plugin-babel';


export default {
	...
	plugins: [
		...
		production && babel({
			exclude: [
				// 'node_modules/**',
				/\/core-js\//,
			],
			extensions: ['.svelte', '.js', '.jsx', '.es6', '.es', '.mjs', '.ts']
		}),
	]
};

Several things to notice here:

  • The line production && babel is a js trick to make the babel plugin not execute in dev mode. You can turn this on or off as you please, if you're testing how the transpiled code works, it might be handy to let it run in dev mode too.
  • The exclude section does not contain node_modules. We're transpiling our dependencies, because some of them are untranspiled. If this is not the case for you, you can ignore them, but you still need to transpile the svelte module itself.
  • The extensions section must contain the .svelte extension, or else your own app's code won't go through babel.
  • We are excluding core-js from transpilation, because of a circular reference issue with rollup-plugin-babel

Credits

I've used this post by simey.me as a basis for the configuration described here.