Gaiety's visual representation as a fursona (an original furry fandom character) depicted as an animated gif falling downward with a controlled hand outstretched. Faer hair and tail waves in the wind while their floppy dog ears flop about as well. Fae are an anthromorphic canine like a german shepherd clothed like a human in a t-shirt and denim shorts. Art is by Lynte.

On Web Components in Posts

They're ready for the mainstream. Automation testable. Even IE11 compatible, mostly.

Components were designed to share reusable code within a project. Sometimes between projects. But, what if a projects' base technology is fundamentally different (Ember, React, Vue)? Luckily all web apps speak Javascript and the DOM which is where native web components come in.

Hybrids (Web Component Framework)

Hybrids Logo

Frameworks serve the purpose of abstracting away browser inconsistencies, providing a richer API for development and tools for automation testing. Hybrids accomplishes all this in a small 19.6kb (6.3kb gzipped) plus some for browser compatibility.

Hybrids Browser Support

Polyfills (Browser support)

To achieve this level of browser support with a modern web standard such as web components a polyfill. There are additional challenges such as CSS scoping that are essential for true web components. Hybrids integrates conditional shims and polyfills to handle this as best as it can.

Testing (Automation)

I've found leveraging Hybrids, Karma and Jasmine can lead to some really clean automation tests. Hybrids offers an importable html helpers, which is the same helper it uses under the hood for its own testing and base functionality. So long as you pay close attention to when you need to target a shadowRoot rendering tests become easy with standard DOM methods to manipulate and access the details of your component.

it('renders logo with src and alt', () => {
  return renderComponent(html`<my-component></my-component>`).then(component => {
    let img = component.shadowRoot.querySelector('[data-test-id=componentImg]')
    expect(img.getAttribute('src')).toEqual('foo.png')
    expect(img.getAttribute('alt')).toEqual('foo')
  })
})
javascript

Bundling

Parcel

Initially I had great success bundling together Hybrids with Parcel. It was as simple as pointing parcel to my html index.

However, Parcel is built for websites rather than consumable libraries. Thus I moved on to Webpack.

Webpack

Assuming you have a src/index.js file that imports a component it's pretty simple to get started. I unfortunately cannot include a reference to the closed source repository here but it should get the idea across for a base webpack configuration. This config also supports JS files that importing CSS into components which Hybrids supports.

// ./webpack.config.js
const path = require('path');

module.exports = function(env, argv) {
  return {
    context: path.resolve(__dirname),

    entry: path.resolve(__dirname, 'src/index.js'),
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: argv.mode === 'test' ? '[name].js' : 'index.js',
    },

    module: {
      rules: [
        {
          // Inline/Component CSS
          test: /\.css$/,
          use: [ "css-loader" ],
        }, {
          // Javascript
          test: /\.m?js$/,
          exclude: /(node_modules)/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: [
                [ '@babel/preset-env', { modules: false } ]
              ]
            }
          }
        }
      ]
    },
  };
};
javascript

Component Structure

Finally, I landed on the this project structure which I hope you may be inspired by if you follow in these footsteps.

  • src
    • components
      • component-name
        • index.js
        • view.js
        • test.js
        • style.css

Wish I could post the full project here and go into more detail. Even still, I hope this serves as a guiding light for those interested in exploring web components in their next project.

ava@wroten.me

Wish to contact me about meetup or conference talks, work opportunities or otherwise? Reach out to me via email.

Resume

Work history, skills, volunteering and talks given all in a one page PDF.

Blog

Programming, art, design, and other queer things.

Git

Coding projects and such on a self hosted Forgejo instance.