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
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:
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.
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 following configuration has worked for me, successfully transpiling my cordova app.
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
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.
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:
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.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.extensions
section must contain the .svelte
extension, or else your own app’s code won’t go through babel.core-js
from transpilation, because of a circular reference issue with rollup-plugin-babelI’ve used this post by simey.me as a basis for the configuration described here.