Skip to content
Mike Byrne edited this page Aug 24, 2022 · 5 revisions

A17 Behaviors have principally been developed to work with a Webpack build process. The build includes both ESM and CommonJS modules.

This setup guide will talk through:

  • installing a17-behaviors and webpack
  • a note on a17-behaviors dependencies
  • a file structure,
  • a basic Webpack set up,
  • required CSS
  • creating a behavior,
  • importing behaviors,
  • and finally, initialising behavior management.

Installation

$ npm install @area17/a17-behaviors
$ npm install webpack
$ npm install webpack-cli
$ npm install webpack-merge
$ npm install webpack-watch-files-plugin

a17-behaviors dependencies

a17-behaviors has a dependency on a17-helpers for:

  • isBreakpoint - a utility to compare a given breakpoint name with the currently displayed breakpoint, allows straight comparisons like "is breakpoint medium?" (isBreakpoint('md')) and also, more useful comparisons like "is breakpoint larger than medium?" (isBreakpoint('md+')), used when wanting to trigger behaviors at certain breakpoints
  • purgeProperties - a utility to remove all properties from an object, used when destroying behaviors on DOM nodes removed from the document
  • resized - a debounced resize event which also keeps track of the currently active breakpoint

Webpack config

Webpack configuration is a world and mystery all to itself sometimes. This setup guide assumes Webpack 5. Your exact set up will change depending on your project needs, this example intentionally keeps it simple.

This set up is split into 3 files:

  • webpack.common.js - shared set up between environments
  • webpack.dev.js - development specific setup (you may want to include Webpack dev server here)
  • webpack.prod.js - production code specific set up

For dynamic behaviors, there is a little more Webpack setup required, see Dynamic behaviors.

webpack.common.js

const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry: {
    application: './src/application.js',
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'public'),
    clean: true,
    publicPath: process.env.ASSET_PATH || '/'
  }
};

webpack.dev.js

const webpack = require('webpack');
const path = require('path');
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  plugins: [
    new webpack.DefinePlugin({
      'process.env.MODE': JSON.stringify('development'),
    }),
  ]
});

webpack.prod.js

const webpack = require('webpack');
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'production',
  plugins: [
    new webpack.DefinePlugin({
      'process.env.MODE': JSON.stringify('production'),
    }),
  ],
});

Key difference between dev and prod

Is sending process.env.MODE = 'development' instead of process.env.MODE = 'production'. This allows for additional debugging options when running behaviors in the browser. If you don't require them, then you don't need to send any process.env.MODE.

Required CSS

To enable breakpoint checking we need a way for the JavaScript to easily be able to determine the currently active breakpoint, this simple CSS allows this.

Set up :root variables changing a --breakpoint value at each of your breakpoints, with the name of your breakpoint. If using A17 Tailwind Plugins or A17 SCSS Utilities then this set up is likely done for you.

We could use window.matchMedia for this instead, but, it would mean sharing and comparing breakpoint information and its easier just to read it from a CSS variable.

<style>
    :root {
      --breakpoint: xs;
    }
    @media screen and (min-width: 544px) {
      :root {
        --breakpoint: sm;
      }
    }
    @media screen and (min-width: 650px) {
      :root {
        --breakpoint: md;
      }
    }
    @media screen and (min-width: 990px) {
      :root {
        --breakpoint: lg;
      }
    }
    @media screen and (min-width: 1300px) {
      :root {
        --breakpoint: xl;
      }
    }
    @media screen and (min-width: 1520px) {
      :root {
        --breakpoint: xxl;
      }
    }
</style>

Creating a behavior - myBehavior.js

import { createBehavior } from '@area17/a17-behaviors';

const myBehavior = createBehavior('myBehavior',
    {
        alert(val) {
            window.alert('Hello world!');
        }
    },
    {
        init() {
            this.$node.addEventListener('click', this.alert);
        },
        destroy() {
            this.$node.removeEventListener('click', this.alert);
        }
    }
);

export default myBehavior;

Importing behaviors (Critical behaviors) - src/behaviors.js

export { default as myBehavior } from './behaviors/myBehavior';
export { default as anotherBehavior } from './behaviors/anotherBehavior';

Of course, in your project, you're likely to have many "critical" behaviors.

Initialising behavior management - src/application.js

import { manageBehaviors } from '@area17/a17-behaviors';
import * as Behaviors from './behaviors'; // Critical behaviors

window.A17 = window.A17 || {}; // currently namespaced name *is* important

document.addEventListener('DOMContentLoaded', () => {
    // expose manageBehaviors
    window.A17.behaviors = manageBehaviors;
    // init behaviors!
    window.A17.behaviors.init(Behaviors, {
      breakpoints: ['sm', 'md', 'lg', 'xl'] // tell this app what your breakpoint names are, in size order, manageBehaviors will read a CSS variable and compare for media scoped behaviors, default is ['xs', 'sm', 'md', 'lg', 'xl', 'xxl']
    });
});

Build JS

In your terminal, in your project root directory:

$ webpack --config webpack.dev.js
Clone this wiki locally