Author Archives: purpleblob

React and CSS

Standard approach to CSS

In a previous post we looked at an animated button and the issue(s) of having CSS in a separate .css file.

To recap, CSS can be implemented in a standalone .css file, for example AniButton.css might look like this (this is an abridged version of the CSS used in the previous post)

.button {
  background: #2B2D2F;
  height: 80px;
  width: 200px;
  text-align: center;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  left: 0;
  right: 0;
  margin: 0 auto;
  cursor: pointer;
  border-radius: 4px;
}

This can then be imported into our React jsx/tsx file using

import "AniButton.css"

and everything works as per standard CSS. A couple of downsides to this are the CSS is in global namespace and also we’re using another language/DSL to define CSS whereas, it’d be nice if we could do all this in one language, i.e. in this case JavaScript/TypeScript.

Inline the style

From this global approach we can look towards inline of the CSS and also at the same time, removing the different language/DSL issue by declaring CSS in a JavaScript JSON style object, for example we remove the .CSS file and it’s import and then include the CSS style as an object, like this

const styles = {
  button: {
    background: "#2B2D2F",
    height: "80px",
    width: "200px",
    textAlign: "center",
    position: "absolute",
    top: "50%",
    transform: "translateY(-50%)",
    left: "0",
    right: "0",
    margin: "0 auto",
    cursor: "pointer",
    borderRadius: "4px"
  }
};

to apply this style we will need to add a style attribute to each of the elements we want a style applied to, for example

<div className="button" style={styles.button}>
</div>

One obvious downside of this inclusion of CSS along with our code is the separation of concerns might be seen as being lost, i.e. styling is now included along with the component code, however I tend to see React as lacking that separation of markup and code which you get with something like XAML/WPF, so I suppose it’s simply down to your interpretation of such things.

Styled components

Another solution which is a bit of a combination of CSS (syntax wise the names do not change to camelCase nor are values wrapped in quotes) and JavaScript is to use a library such as styled-components or emotion.

I’m going to look at Emotion’s implementation, so run the following

yarn add @emotion/styled @emotion/core

Now we can replace our button CSS and inline JavaScript CSS with style components, for example within your JSX/TSX file implement the following

import styled from '@emotion/styled'

const Button = styled.div`
  background: #2B2D2F;
  height: 80px;
  width: 200px;
  text-align: center;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  left: 0;
  right: 0;
  margin: 0 auto;
  cursor: pointer;
  borderRadius: 4px;
`;

Now in usage our code looks like this

<Button className="button" onClick={this.handleOnClick}>
  <div className="text" style={styles.text} onClick={this.handleOnClick}>Submit</div>
</Button>

Converting animated button to React

I was looking at a nice little animation of a button on https://codepen.io/andrewmillen/pen/MoKLob and thought it’d be interesting turning it into a React component especially as I’m currently playing with animejs. As usual such things never “just work” but that also means it’s a good learning process.

So here goes, first off create your React application and add the animejs library…

  • yarn create react-app animatedbutton –typescript

From within the generated application run the following

  • yarn add animejs
  • yarn add @types/animejs

Note: I will not list all the code here, it’s available on GitHub, but I’ll list the changes and things of interest.

Next create a components folder off of the src folder and create AniButton.css, copying the CSS from the original link into that and then create AniButton.jsx which I’ve included here

Note: I used a jsx file as opposed to tsx simply because I didn’t want to spend too long fixing “type” issues initially, but when I did try this I found the ref is not expected on a path element, so we’ll stick with JSX for now.

export class AniButton extends React.Component {

  checkRef = React.createRef();

  constructor(props) {
    super(props);

    this.handleOnClick = this.handleOnClick.bind(this);
  }

  handleOnClick() {

    var pathEls = this.checkRef.current;
    var offset = anime.setDashoffset(pathEls);
    pathEls.setAttribute("stroke-dashoffset", offset);

    var basicTimeline = anime.timeline({
      autoplay: false
    })
    .add({
      targets: ".text",
      duration: 1,
      opacity: 0
    })
    .add({
      targets: ".button",
      duration: 1300,
      height: 10,
      width: 300,
      backgroundColor: "#2B2D2F",
      border: "0",
      borderRadius: 100
    })
    .add({
      targets: ".progress",
      duration: 2000,
      width: 300,
      easing: "linear"
    })
    .add({
      targets: ".button",
      width: 0,
      duration: 1
    })
    .add({
      targets: ".progress",
      width: 80,
      height: 80,
      delay: 500,
      duration: 750,
      borderRadius: 80,
      backgroundColor: "#71DFBE"
    })
    .add({
      targets: pathEls,
      strokeDashoffset: [offset, 0],
      opacity: 1,
      duration: 200,
      easing: "easeInOutSine"
    });

    basicTimeline.play();
  }

  render() {
    return (
      <main>
        <div className="button" onClick={this.handleOnClick}>
          <div className="text" onClick={this.handleOnClick}>Submit</div>
        </div>
        <div className="progress"></div>
        <svg x="0px" y="0px"
          viewBox="0 0 25 30">
          <path ref={this.checkRef} className="check st0" d="M2,19.2C5.9,23.6,9.4,28,9.4,28L23,2" />
        </svg>
      </main>
    )
  }
}

Note: A couple of changes I made to the CSS was change the progress bar name and fixed the background to gray. The reason I did this was simply because I had problems initially with the CSS displaying incorrectly and messed with things to try to resolve – I think the problem is unrelated to the changes I made though.

Also I seem to periodically lose the progress bar, not 100% why but just saying.

The key differences to the original source code are – obviously it’s coded into a React.Component. Event handlers are within the class, but really the main difference is the way we get access to the DOM path element via the ref={this.checkRef}. I’ve removed the loop from the original code which found the paths as we only have one here.

Next, the original code uses the Poppins font, so add the following the public/index.html

<link 
   href="https://fonts.googleapis.com/css?family=Poppins:600" 
   rel="stylesheet">    

The animejs code

At this point everything works nicely, so let’s look at the animejs code.

We need to get a reference to the DOM path object using

var pathEls = this.checkRef.current;
var offset = anime.setDashoffset(pathEls);
pathEls.setAttribute("stroke-dashoffset", offset);

The anime.setDashoffset code does the following

“Creates path drawing animation using the ‘stroke-dashoffset’ property. Set the path ‘dash-offset’ value with anime.setDashoffset() in a from to formatted value.”

Next we create an animejs, which basically allows us to coordinate each stage/step of the animation. Hence the first timeline is to immediately hides the .text using the opacity property and a very short duration.

Now we change the shape of the .button to a thinner button etc.

The next step is to display a progress overlay which starts from the centre (based upon the CSS) and expands out over it’s duration in a linear easing.

Once the previous step’s completed which reduce the .button to zero width to basically hide it and the .progress then changes colour and eventually turns into a circle.

Finally the check/tick is displayed using the strokeDashOffset, so basically this animates the drawing of the check.

CSS

For the most part the animejs timeline code is pretty simple and works a treat, so let’s take a look at the CSS side of things.

Firstly we can import the CSS using

import "./AniButton.css";

Which basically tells webpack (in a standard React application) to include the CSS in the bundle. Now the CSS can be applied to our elements in the usual ways, on an element type or via id or class (in React class becomes classname).

As stated previously though, if you require actual access into the DOM you’ll need to use something like a ref, but use sparingly.

CSS files like the ones we’re using are not really the preferred way to use CSS in React (see the React: CSS in your JS by Christopher Chedeau for some reasons why this is the case, admittedly it’s a few years old but still relevant now).

To save you watching the video, CSS files defines CSS globally which can make styling difficult to debug or understand at times. Also it’s equally difficult to know when CSS is redundant, i.e. an element s no longer used but we still maintain it’s CSS etc.

I’m not going to go into all the others ways to use CSS it this post, but obviously our best way to use CSS would be to have it used locally inlined with our component.

Hence we can instead convert our CSS to the following code within our AniButton.jsx file like this

const styles = {
  main: {
    height: "100vh",
    width: "100vw"
  },
  button: {
    background: "#2B2D2F",
    height: "80px",
    width: "200px",
    textAlign: "center",
    position: "absolute",
    top: "50%",
    transform: "translateY(-50%)",
    left: "0",
    right: "0",
    margin: "0 auto",
    cursor: "pointer",
    borderRadius: "4px"
  },
  text: {
    font: "bold 1.25rem/1 poppins",
    color: "#71DFBE",
    position: "absolute",
    top: "50%",
    transform: "translateY(-52%)",
    left: "0",
    right: "0"
  },
  progress: {
    position: "absolute",
    height: "10px",
    width: "0",
    right: "0",
    top: "50%",
    left: "50%",
    borderRadius: "200px",
    transform: "translateY(-50%) translateX(-50%)",
    background: "gray",
  },
  svg: {
    width: "30px",
    position: "absolute",
    top: "50%",
    transform: "translateY(-50%) translateX(-50%)",
    left: "50%",
    right: "0",
    enableBackground: "new 0 0 25 30"
  },
  check: {
    fill: "none",
    stroke: "#FFFFFF",
    strokeWidth: "3",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    opacity: "0"
  }   
}

Note: underline or hyphens turn into camelCase names and values get wrapped in quotes.

Now we will need to explicitly add the styles to our render code using style={} syntax, so it looks like this

<main style={styles.main}>
  <div className="button" style={styles.button} 
       onClick={this.handleOnClick}>
     <div className="text" style={styles.text} 
       onClick={this.handleOnClick}>Submit</div>
  </div>
  <div className="progress" style={styles.progress}></div>
  <svg x="0px" y="0px"
    viewBox="0 0 25 30" style={styles.svg}>
    <path ref={this.checkRef} style={styles.check} 
      className="check st0" d="M2,19.2C5.9,23.6,9.4,28,9.4,28L23,2" />
  </svg>
</main>

We can now delete our AniButton.css file.

Lost your Resharper keyboard commands in VS2015?

For some reason I lost CTRL+T which I use a lot to find types using Resharper in Visual Studio. Here’s how to get the shortcuts back.

You may only need to do the following

  • Goto Resharper menu item
  • Select Options | Environment, then Keyboard & Menus
  • Press the Apply Scheme button

Now if this works you may have the key combination working again. If not then go the following route

  • From Tools menu, select Options
  • Now select Environment and Keyboard
  • Press the Reset button on the top right and then OK
  • Now, as per the earlier suggestion, goto Resharper menu item
  • Select Options | Environment, then Keyboard & Menus
  • Press the Apply Scheme button

If you now try CTRL+T and the Resharper keyboard mapping dialog appears, select Use Resharper Command and check the Apply to all Resharper shortcuts.

If all goes well (as it did for me) then CTRL+T should be back.

Extension methods in TypeScript

Extension methods in C# are a great way to modularise functionality within a class in such a way (for example) to have a basic object with minimal methods and then extend this with further functionality that can be reference only if required.

Hence you might only have a need for the bare bones class in some cases and therefore only need to include that in your code base, alternatively you might also depend upon some advanced functionality that can be added when required. Another use case is adding functionality to third party libraries to extend their functionality.

Ofcourse we might simple extend/inherit from the class to add our new functionality but this ultimately mean’s we’re using a different type. With extension methods in C# we extend a String (for example) with extra functionality as opposed to created a subclass named something else, like ExtendedString.

So can we implement something similar to C#’s extension methods in TypeScript (and therefore JavaScript)? Yes we can, let’s look at a simple example, an Option class for handling defined/undefined values in a functional way. Here’s the Option.ts file

export class Option {
    value: any;

    constructor(value: any) {
        this.value = value;
    }

    isSome(): boolean {
        return this.value != null;  
    } 

    isNone(): boolean {
        return !this.isSome();
    }
}

Hence this is a bare bones implementation which we might extend further with further functionality. Let’s create a file for our extension methods, mine’s named OptionExtensions.ts, which might look something like this

import { Option } from './Option';

declare module './Option' {
    interface Option {
        ifElse(elseValue: any): any;
    }
}

Option.prototype.ifElse = function(elseValue: any): any {
    return this.isSome() ? this.value : elseValue;
}

In the above code we declare a module with the same name as the one which wish to extend and then declare an interface with our new methods. The interface in essences merges with the type to allow us to view our new methods as if they’re on the original Option type.

Finally we can start implementing our new functionality via the JavaScript prototype functionality.

In this example you can see we also have access to the this reference to allow our new functionality to hook into the Option fields etc.

Now let’s look at this in usage

import { Option } from "./Option"
import "./OptionExtensions";

const o = new Option(undefined);
console.log(o.ifElse(999));

That’s it, we pull in the extension methods via the import “./OptionExtensions”; when we want the extended functionality and we can call our extension methods as if they were written into the Option class itself.

Property based testing in JavaScript with fast-check

Property testing is a way to test functionality by automatically generating many different inputs.

We’re going to use the fast-check library

yarn add fast-check -D

Let’s create a rather contrived example function to test

export const divide = (a: number, b: number): number => {
  if(b === 0) {
    throw new Error("Denominator cannot be 0");
  }
  return a / b;
}

As you can see, this function simply divides a by b but will fails in the denominator is 0. This was done on purpose to ensure that there is a failing test available for a specific input value (I did say it was contrived).

Now to test this we might implement the following test

import * as fc from 'fast-check';

test("Divide property test", () => {
   fc.assert(
      fc.property(fc.nat(), fc.nat(), (a, b) => {
         return divide(a, b) === a / b; 
      })
  );
});

In this instance we create the assert which wraps the property generation code, i.e. the call to property, which itself generates two natural numbers properties as input to the lambda/fat arrow function.

We then call the code that we wish to test, passing in the generated values and then returning whether the expectation was true or false.

We can use Jest or the likes in place of the return divide(a, b) === a / b, i.e.
replacing it with if we prefer and just use fast-check to generate the properties

expect(divide(a, b)).toEqual(a / b);

Now the only problem with the property based testing like this is that it will randomly generate values as opposed to inspecting the flow of your code to generate values (like tools such as Pex for .NET). Hence these values may not always include the edge cases that we might not have coded for.

For example, executing this test in Jest I find that sometimes it will pass a 0 as a denominator and other times it will not, therefore we do not always get a clear idea of all possible inputs, but it’s a great starting point for proving your functions.

In the test we generated natural numbers, we can also generate restricted ranges of values, along with integers, floating point, doubles, strings and more, see Arbitraries.

Loading JavaScript objects from a string

As mentioned in a previous post – I’ve been working on dynamically loading TypeScript/JavaScript as required (i.e. like a runtime plugin system) and whilst investigating the process have come across several libraries that I felt I’d document in case I need them in the future. First up is require-from-string.

I’ll assume for this and any follow up posts, that you’ve created a basic set-up, i.e.

  • yarn init –typescript
  • tsc –init

Although I’ve added TypeScript in the above, for simplicity we’re going to start out just using JavaScript, but we’ve covered all bases with TypeScript’s inclusion.

Next create an index.js that looks like this

import requireFromString from 'require-from-string';

const classA = requireFromString('class A { output() { console.log("Remote class called") } } module.exports = A;');
new classA().output();

Adding webpack-dev-server

In previous posts we’ve used serve as our server, an alternative is the webpack-dev-server. This will give up live reloading and also built-in compilation so that we don’t need to run the build script.

Simply add the relevant package using

yarn add webpack-dev-server -D

Now add the following to your webpack.config.js, first the requires

const path = require('path');

and now the code for the server

module.exports = {
  // ... other config
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 5000

By default “Live reloading” is enabled and hence, now when we make changes to our code and save them, the browser automatically relaods.

We can now just change our “start” script within package.json to

"start": "webpack-dev-server --config config/webpack.config.js"

Modules and webpack

One of the things I wanted to do is allow my React application to “dynamically” load code from another website for an internal application. The idea being other teams can work on their code and the main application will load the latest deployed version if the user navigates to something that uses it – basically we’re talking about writing plugins.

Note: This is not a great idea for any code you cannot 100% control as you’ll obviously have no idea whether it’s malicious, so if you’re thinking of doing something similar make sure you know what code is being downloaded etc.

Where’s my Module gone

To begin with I wrote an “importer” class in a separate application which successfully loaded code – using axios to download it, Typescript to transpile it (if needed) and the standard Module to compile (module._compile) it, then I slotted the code into a Module and away you go. All worked great until it got deployed within the React application and all of a sudden _compile (and other methods) were missing from Module.

The thing is, webpack basically uses it’s own module system.

webpack modules

The post I wrote on getting up and running with webpack was inspired by the module dilemma as I needed to better understand what webpack was doing under the hood.

If we create and build a webpack project we’ll end up with main.js, here’s a snippet from it for the __webpack_require__ function

function __webpack_require__(moduleId) {
   if(installedModules[moduleId]) {
      return installedModules[moduleId].exports;
   }

   var module = installedModules[moduleId] = {
      i: moduleId,
      l: false,
      exports: {}
   };

   modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
   module.l = true;
   return module.exports;
}

Note: I’ve removed all the comments just to reduce it to the minimal code.

So within the functions web pack generates for our code/exports etc. we’ll see __webpack_require__ used a fair bit, i.e. to load import/require code (import/require is replaced with __webpack_require__) and looking at the function itself we can see that __webpack_require__ uses it’s own module system, i.e. it caches modules in installedModules (which becomes __webpack_require__.c). We can also see that if the module is not cached a new one is created which looks very different from a NodeModule.

Finally, after the module is created a call is made to the new module, which in this case is one of the functions that’s passed to the __webpack_require__ within main.js which basically returns a function to our code which then becomes the “exports” code returned by the __webpack_require__ function.

Up and running with webpack

Don’t read this blog post if you want to learn about webpack, instead go and read the webpack book.

If you’re still reading this post then let’s go ahead and create a minimal project to start learning about webpack.

Creating our project

  • Create a folder for our starter app., mine’s webpack-starter
  • Within the folder run
    yarn init -y
    

    to create our package.json

  • Now install/add webpack and webpack client using
    yarn add webpack webpack-cli
    
  • Create a src folder off of you project’s root – webpack, by default expects a src folder
  • Add a file index.js to the src folder and we’ll include the minimal code, below
    console.log("Hello World");
    
  • To your package.json file add the following
    "scripts": {
       "build": "webpack --mode development"
    }
    

At this point let’s take a look at what we’ve done. We’ve created a minimal package.json and to this added webpack and the webpack-cli. We’ve created a bare bones entry point (index.js) and a build script.

Now if we run the build script using

yarn build

webpack will generate a dist folder off our root folder along with a main.js file, one look at this and you’ll see far more than you probably expected. Webpack’s created a bootstrap along with a lot of module related code. At the bottom of the file is a function that simply executes the eval function which basically evaluates/runs the code that was in the index.js.

Testing our application

I know it’s a rather minimal application, but it’d be nice to see it actually working, so let’s add the relevant piece to the jigsaw

Run the following

yarn add html-webpack-plugin

We’re going to need to tell webpack to use this plugin, so create a new folder off of the root named config within this create a file name webpack.config.js and here’s the contents for this

const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      title: "Webpack starter",
    }),
  ],
};

If you don’t have serve installed then add it using either the command below or add it globally (see React and serve).

yarn add server

Next up we’ll need to rebuild our dist source but before we do that, we placed the webpack.config.js into the config folder, running the build script as it stands will not pickup this file so you can either move it to the root folder or better still update the script to look like this

"scripts": {
   "build": "webpack --mode development --config config/webpack.config.js"
}

Now running yarn build will create, both an index.html file and main.js file within the dist folder. So now we can run the server. Before we do that, let’s add another script task to package.json, so add the following

"start": "serve dist"

Now we can run yarn start which will start a server up (by default it will be http://localhost:5000). Obviously we’re outputting text to the console so you’ll need to switch your browser to dev mode and view the console output.

Webpack output

When you ran yarn build, webpack used the configuration and the HTML plugin within it to generate our index.html file and also supply the title “Webpack starter”. The output from running webpack looked like this (for me at least)

Hash: af14b7dabddfbc78edb6
Version: webpack 4.35.2
Time: 507ms
Built at: 07/02/2019 10:43:49 AM
     Asset       Size  Chunks             Chunk Names
index.html  181 bytes          [emitted]
   main.js    3.8 KiB    main  [emitted]  main
Entrypoint main = main.js
[./src/index.js] 27 bytes {main} [built]
Child html-webpack-plugin for "index.html":
     1 asset
    Entrypoint undefined = index.html
    [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {0} [built]
    [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built]
        + 2 hidden modules
Done in 3.17s.

As you can see the Child html-webpack-plugin for “index.html”: text tells us what code was generated by the HtmlWebpackPlugin

Along with the creation of the index.html file HtmlWebpackPlugin setup a script tag for calling the webpack generated main.js file.

Before we move on let’s change our index.js file to include an import. So create the folder components off of the src folder and create the file helloComponent.js (code for this is shown below)

export default (text) => {
    const element = document.createElement("div");
    element.innerHTML = text;
    return element;
}

and change the index.js code to the following

import hello from "./components/helloComponent";

document.body.appendChild(hello("Hello World"));

Note: again the above is fundamentally the same as the webpack book. The main difference is that I’m wanting to make this look similar to how I’ve learned to use/set-up React as it helps give a feel for how one might transition between React and lower level webpack designed projects or vice versa.

Now run yarn build followed by yarn start. If all goes well you’ll see some interesting changes to the main.js file and ofcourse you should now see actual HTML elements in your browser. I’m far more interested in the main.js changes than the fact we have any output.

More on main.js

If you compare the original main.js file with the new one, you’ll notice that it’s fundamentally the same, it has the webpackBootstrap section as well as all the code setting up the __webpack_require__ properties. Ultimately though the original main.js came down to this line

(function(module, exports) {
eval("console.log(\"Hello World\");\n\n//# sourceURL=webpack:///./src/index.js?");
})

and we can clean this up further just turning it into

(function(module, exports) {
eval("console.log(\"Hello World\");");
})

With regards to the second implementation, although the bulk of the file is still made up with the webpackBootstrap code etc. now we have the following code combined into the single main.js file (I’ve removed comment blocks etc. to clean the code up somewhat)

(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = 
((text) => {\r\n    const element = document.createElement(\"div\");\r\n    element.innerHTML = text;\r\n    return 
element;\r\n});\n\n//# sourceURL=webpack:///./src/components/helloComponent.js?");
}),

/*! no exports provided */
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var 
_components_helloComponent__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./components/helloComponent */ \"./src/components/helloComponent.js\");\n\r\n\r\ndocument.body.appendChild(Object(_components_helloComponent__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(\"Hello World\"));\n\n//# sourceURL=webpack:///./src/index.js?");
})

The first function is our helloComponent.js file wrapped in a function, notice how we no longer simply eval the JavaScript but instead eval __webpack_require__. The second function is our index.js.

There’s a lot going on, especially with all the commented code and new lines etc. so let’s clean it up, remove the eval function and format it and then we see that this is the index.js code in a function

__webpack_require__.r(__webpack_exports__);
var _components_helloComponent__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(\"./src/components/helloComponent.js\");
document.body.appendChild(Object(_components_helloComponent__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(\"Hello World\"));

The function that this code is within is passed a module, __webpack_exports__ and __webpack_require__, so firstly we call the function __webpack_require__.r with the __webpack_exports__ and this defines the property for either Module or __esModule.

Next we declare a variable named after the folder and filename (i.e. components/helloComponent changes to _components_helloComponent) which in turn is suffixed with the __WEBPACK_IMPORTED_MODULE_0__ (the number 0 increments for each addition module included). This variable is assigned the resultant module after passing the string “./src/components/helloComponent.js” to __webpack_require__. The string is simply a module id, hence as it’s based upon the file system will be unique to the project containing it.

The final line is a call to the document.body.appendChild (as per our index.js) but the function hello (exported from helloComponent) has been replaced by the _components_helloComponent__WEBPACK_IMPORTED_MODULE_0__ variable indexed by the default export.

Basically what’s happened is webpack has parsed our code, replacing the imports with functions which wrap the code from the imports. It’s created it’s own module system using __webpack_require__

What on earth are all the __webpack_require__ properties doing?

What’s happening is that the first function function(modules) (the webpackBootstrap function) is called, next the __webpack_require__ object is setup, with modules and installed modules being assigned to __webpack_require__.m, em>__webpack_require__.c and the rest of the properties setup with functions and so on.

Here’s a list of the current _webpack_require__ properties and their usage (taken from the webpack source)

  • __webpack_require__.s = the module id of the entry point
  • __webpack_require__.c = the module cache
  • __webpack_require__.m = the module functions
  • __webpack_require__.p = the bundle public path
  • __webpack_require__.i = the identity function used for harmony imports
  • __webpack_require__.e = the chunk ensure function
  • __webpack_require__.d = the exported property define getter function
  • __webpack_require__.o = Object.prototype.hasOwnProperty.call
  • __webpack_require__.r = define compatibility on export
  • __webpack_require__.t = create a fake namespace object
  • __webpack_require__.n = compatibility get default export
  • __webpack_require__.h = the webpack hash
  • __webpack_require__.w = an object containing all installed WebAssembly.Instance export objects keyed by module id
  • __webpack_require__.oe = the uncaught error handler for the webpack runtime
  • __webpack_require__.nc = the script nonce

Webpack Loaders

I’m going to end this post with a very quick look at webpack loaders. Whilst there’s nothing wrong with using plain JavaScript, I come from a statically typed world and rather like using TypeScript to catch those stupid mistakes. So let’s set-up webpack to work with TypeScript.

Webpack comes with the concept of loaders, these are basically file processors that become part of the webpack pipeline. For example, they might generate code from configuration files or transpile from other languages etc. Everything then gets bundled via the webpack pipeline.

To add typescript capabilities to webpack we need to edit the webpack.config.js, adding the following

module: {
   rules: [
      {
         test: /\.tsx?$/,
         use: 'ts-loader',
         exclude: /node_modules/
      }
    ]
  },
  resolve: {
    extensions: [ '.tsx', '.ts', '.js' ]
  }

We’ll also need to run

yarn add typescript ts-loader

To installed typescript (if not already installed) and ts-loader, which is used within webpack. Assuming you’re going to now change all .js files (including index.js) to .ts files you’ll also need to amend the webpack.config.js entry to this

entry: './src/index.ts',

Now run your build script as normal and assuming your code is valid TypeScript then you should successfully created a webpack bundle based upon your TypeScript code.

I think that about covers getting webpack up and running, but I’m sure there’ll be more posts on the topic as I delve deeper.

animejs

I was working on some code to display a green circle with a tick (for success) and a red circle with a cross (for failure) within rows in ag-Grid to denote whether service calls succeeded or failed for each row of data. Having the graphics seemed good but what I really wanted was to animate the display of these graphics to make it obvious to the user that these graphics changes/updated.

animejs looked to be a perfect solution to the problem.

There’s lots of great examples using animejs here.

Obviously to begin with I’ve created a React application using the standard scaffolding, and then using yarn installed anime, i.e.

yarn add animejs
yarn add @types/animejs

We’ll create a standard React component (SuccessFailureComponent.tsx) for displaying our new animated component.

import React from 'react';
import anime from "animejs";

interface SuccessFailureProps {
    success: boolean;
}

export class SuccessFailureComponent 
   extends React.Component<SuccessFailureProps, {}> {
      render() {
         // to be implemented
      }
}

In this code we’ve added the property success, which when true will display the green circle with a tick and when false the red circle with the cross.

To begin with we’ll add the following code to draw our graphics to the render function

const backColour = this.props.success ? 
   "#0c3" : 
   "red";
const symbol = this.props.success ? 
   "M9 16l5 5 9-9": 
   "M9 9l14 14 M23 9L9 23";

return (
   <svg className="status" xmlns="http://www.w3.org/2000/svg"
      width="32"
      height="32"
      viewBox="0 0 42 42">
      <circle className="circle"
         cx="16"
         cy="16"
         r="16"
         fill={backColour}/>
      <path d={symbol}
         fill="none"
         stroke="white"
         stroke-width="2.5"   
         stroke-linecap="round"/> :
   </svg>
);

In the above we use the Scalable Vector Graphics element to wrap drawing primitives to first draw a circle with the required fill colour and then using the symbol const which is the drawing of a tick or cross.

If we run the React app at this point (assuming we’ve also added the following component to the App.tsx render method

<SuccessFailureComponent success={false}/>
<SuccessFailureComponent success={true}/>

then we’ll see the two SVG graphics displayed.

Animating our graphics

We’ve come all this way in a post about animation and not animated anything, so let’s now do that. Back in the component, add

componentDidMount() {
   var timeline = anime.timeline({ 
      autoplay: true
   });

   timeline
      .add({
         targets: '.status',
         scale: [{ 
            value: [0, 1], 
            duration: 600, 
            easing: 'easeOutQuad' }
         ]
      });
}

When the application is refreshed you’ll see the graphics scale from nothing to full sized.

In the first line we create the anime timeline which has parameters which will simply start the animation immediately. We then use the add function with the target “status” (our SVG element) to scale the SVG from nothing to full sized with a duration of 600ms. Finally we specify the easing function to use.

We can also add more animation transitions to the timeline, for example the following additions to the timeline code (above) will result in the icons moving right by 10 pixels then returning to where they started

.add({
   targets: '.status',            
   translateX: 10
})
.add({
   targets: '.status',
   translateX: 0
});

Or maybe we’d like to just spin the graphics using

.add({
   targets: '.status',            
   rotate: 360
});

There’s more than just the timeline function, there’s also stagger which allows the animation of multiple elements. Also keyframes which allows us to create an array of keyframes for our animations.

This easings.net is a great resource for seeing how different easing functions might look. If you want to (for example) add a little bounce back to the easing try, easeOutBack.

The anime documentation also has some great examples along with the documentation of fairly simple transitions.