Tutorial

Polyfills and Transpilation for Your Custom Elements

Published on September 8, 2017
    Default avatar

    By Alligator.io

    Polyfills and Transpilation for Your Custom Elements

    While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

    We covered the basics of creating custom elements using Web Component specs, but at the end we hinted that our simple custom element was not yet production-ready because of the use of new JavaScript features and the fact that Custom Elements and Shadow DOM are not supported in all popular browsers yet.

    In this post, we’ll quickly go over the steps to transpile your custom element code to be compatible with ES5 and to include the necessary Web Components polyfills.

    Transpilation

    Your custom element code will contain ES6 classes and will probably also contain string literals and arrow functions. These features are great to use at author-time, but the code has to be transpiled using a tool like Babel so that it can run in browsers that only understand ES5 code. We’ll go ahead and use babel-cli and the babel-preset-es2015 preset do to just that.

    If your project doesn’t have a package.json file just yet, go ahead an create one using either npm or Yarn. This will allow you to install the necessary packages.:

    $ npm init
    
    # or, using Yarn
    $ yarn init
    

    Once this is done, you can go ahead and install the necessary packages:

    $ npm install babel-cli babel-preset-es2015 --save-dev
    
    # or, using Yarn
    $ yarn add babel-cli babel-preset-es2015 --dev
    

    We’ll output our transpiled code into a dist folder, so you can go ahead and create that folder at the root of your project. Now you can add a build script to your package.json file that runs Babel with the es2015 preset and outputs the result in the dist folder:

    package.json
    {
      "name": "my-title",
      "version": "0.0.1",
      "main": "index.js",
      "license": "MIT",
      "scripts": {
        "build": "babel --presets es2015 my-title.js --out-file dist/my-title.js"
      },
      "devDependencies": {
        "babel-cli": "^6.26.0",
        "babel-preset-es2015": "^6.24.1"
      }
    }
    

    Now you can go ahead and run the transpilation:

    $ npm run build
    
    # or, using Yarn
    $ yarn build
    

    Polyfills

    Polyfills are small plugins that implement a feature to replace a missing native implementation for browsers that don’t have support yet. For Web Components, we’ll need polyfills for Custom Elements, Shadow DOM and the template element. Luckily for us WebComponents.org maintains a suite of polyfills that makes it easy to include the needed polyfills in your projects.

    The suite provides a set of ready-made bundles to choose from. For example, the webcomponents-lite.js bundle, which polyfills HTML imports, Custom Elements, Shadow DOM (with polyfills called Shady DOM and Shady CSS) and the template element. That bundle will ensure that your custom elements will work all the way back to Internet Explorer 11.

    webcomponents-loader.js

    There’s also a loader available, webcomponents-loader.js, that will perform some feature detection and include the necessary polyfills on the fly. Using the loader is probably the simplest way to get everything working, and this is what we’ll use here for our example.

    Custom elements need to be defined using ES6 classes that extend HTMLElement, but now we’re using transpiled code that has the class syntax stripped away. We’ll need to use a file called custom-elements-es5-adapter.js to fix that for us.


    At the time of this writing, webcomponents-loader.js should installed via Bower, so you’ll want to make sure you have Bower available by running npm install -g bower.

    Simply install the webcomponentsjs package into your project using Bower. This will install the necessary files in the bower_components folder:

    $ bower install --save webcomponents/webcomponentsjs
    

    Now, in your page’s head, include custom-elements-es5-adapter.js and webcomponents-loader.js:

    index.html (partial)
    <script src="bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
    <script src="bower_components/webcomponentsjs/webcomponents-loader.js"></script>
    

    The final step is only include the script for your transpiled custom element when the WebComponentsReady event fires. That’s a custom event that gets fired by the loader when the necessary polyfills have been loaded. We’ll simply create a script element, set its src property to the path of our transpiled custom element code and append it to the document’s head:

    window.addEventListener('WebComponentsReady', function () {
      var myTitleScript = document.createElement('script');
      myTitleScript.src = 'dist/my-title.js';
      document.head.appendChild(myTitleScript);
    });
    

    Here’s how our final index.html file looks like:

    index.html
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>My Custom Element!</title>
    
      <script src="bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
      <script src="bower_components/webcomponentsjs/webcomponents-loader.js"></script>
    </head>
    
    <body>
      <my-title></my-title>
    
      <script>
        window.addEventListener('WebComponentsReady', function () {
          var myTitleScript = document.createElement('script');
          myTitleScript.src = 'dist/my-title.js';
          document.head.appendChild(myTitleScript);
        });
      </script>
    </body>
    
    </html>
    

    🔧 And done! Your custom element is now ready to be included in your production projects.

    Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

    Learn more about us


    About the authors
    Default avatar
    Alligator.io

    author

    Still looking for an answer?

    Ask a questionSearch for more help

    Was this helpful?
     
    Leave a comment
    

    This textbox defaults to using Markdown to format your answer.

    You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

    Try DigitalOcean for free

    Click below to sign up and get $200 of credit to try our products over 60 days!

    Sign up

    Join the Tech Talk
    Success! Thank you! Please check your email for further details.

    Please complete your information!

    Get our biweekly newsletter

    Sign up for Infrastructure as a Newsletter.

    Hollie's Hub for Good

    Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

    Become a contributor

    Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

    Welcome to the developer cloud

    DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

    Learn more
    DigitalOcean Cloud Control Panel