Svelte3, Rollup and Babel7

Svelte3 rocks. Please check it out if you haven't yet!

Transpiling

After cloning the REPL and initialising your Svelte3 project; one thing that you don't seem to get is transpiling.

When using VueCLI, for example, transpiling comes as standard.

I am running an experiment to see how to convert a Vue2 project over to Svelte3 for learning purposes, but I found that I couldn't get transpiling with Babel working easily.

Jump directly to the code

Issues

After following the tutorials/documentation for adding the rollup-plugin-babel, @babel/core, @babel/preset-env packages, and setting up everything as described; I simply found that it hadn't transpiled my bundle.js as I expected.

After some time messing around, and being new to svelte/rollup/babel, I figured out that it was in-fact transpiling some code, but not the svelte/imported module code.

Reason

By what I can tell, the reason I was not getting the expected results is because the documentation or tutorials for these Svelte/Rollup/Babel are not sufficiently up-to-date in order to get it working correctly. All the tools have recently gone through major updates. The main issues were surrounding the .babelrc and the rollup.config.js.

Resolution

I discovered a couple of steps needed to get transpiling down to ie9 working (or you may use a es2015preset instead).

1. Install the dependencies

yarn install --dev @babel/core @babel/preset-env rollup-plugin-babel  

2. Create a babel.config.js file in root

module.exports = function (api) {  
    api.cache(true);
    const presets = [[ "@babel/env", { "targets": "ie 9" } ]];
    return { presets }
}

This is based on the documentation as it appears by using the default .babelrc file, each imported module (including Svelte3) will have it's own Babel config. This is what prevents transpiling the Svelte code.

3. Add the Babel plugin to rollup.config.js

Firstly import babel;

import babel from 'rollup-plugin-babel';  

then add the babel() plugin after the svelte() plugin;

babel({  
    extensions: [ ".js", ".mjs", ".html", ".svelte" ]
})

A key part of this config, is the .mjs and .svelte values in the extensions property. Inside the Svelte3 package; a lot of the compiler is written in .mjs, and your project's Svelte code is likely written in .svelte components. Both of these are not handled by Babel by default.

Another key part is removing the exclude: 'node_modules/**' configuration. This is because we need to transpile the code that comes from the Svelte3 compiler.

Success

After these steps, your bundle.js or whatever you've called it should be completely transpiled down to the environment you've specified in the babel.config.js.

Just Code

If you just came here for the code reference; here it is;

Package.json

  "devDependencies": {
    "@babel/core": "^7.4.5",
    "@babel/preset-env": "^7.4.5",
    "npm-run-all": "^4.1.5",
    "rollup": "^1.10.1",
    "rollup-plugin-babel": "^4.3.2",
    "rollup-plugin-commonjs": "^9.3.4",
    "rollup-plugin-livereload": "^1.0.0",
    "rollup-plugin-node-resolve": "^5.0.0",
    "rollup-plugin-svelte": "^5.0.3",
    "rollup-plugin-terser": "^4.0.4",
    "sirv-cli": "^0.4.0",
    "svelte": "^3.0.0"
  }

rollup.config.js

import svelte from 'rollup-plugin-svelte';  
import resolve from 'rollup-plugin-node-resolve';  
import commonjs from 'rollup-plugin-commonjs';  
import babel from 'rollup-plugin-babel';  
import livereload from 'rollup-plugin-livereload';  
import { terser } from 'rollup-plugin-terser';

const production = !process.env.ROLLUP_WATCH;

export default {  
    input: 'src/main.js',
    output: {
        sourcemap: true,
        format: 'iife',
        name: 'app',
        file: 'public/bundle.js'
    },
    plugins: [
        svelte({
            // enable run-time checks when not in production
            dev: !production,
            // we'll extract any component CSS out into
            // a separate file — better for performance
            css: css => {
                css.write('public/bundle.css');
            }
        }),

        babel({
            extensions: [ ".js", ".mjs", ".html", ".svelte" ]
        }),

        // If you have external dependencies installed from
        // npm, you'll most likely need these plugins. In
        // some cases you'll need additional configuration —
        // consult the documentation for details:
        // https://github.com/rollup/rollup-plugin-commonjs
        resolve(),
        commonjs(),

        // Watch the `public` directory and refresh the
        // browser on changes when not in production
        !production && livereload('public'),

        // If we're building for production (npm run build
        // instead of npm run dev), minify
        production && terser()

    ],
    watch: {
        clearScreen: false
    }
};

babel.config.js

module.exports = function (api) {

    api.cache(true);

    const presets = [
        [ "@babel/env", { "targets": "ie 9" } ]
    ];

    return {
        presets
    }

}