Author Archives: purpleblob

Yalc

Yalc is a package authoring tool, allowing us to create packages from JavaScript libraries locally. This is useful during package authoring and for testing as well as just plain, allowing us to create our own local packages and not need to have them distributed to some remote registry.

Installing yalc

To install yalc, execute the following command

yarn global add yalc

// or using npm

npm i yalc -g

Creating a package locally

First off we need a package.json file, so the simplest way is to run

yan init --yes

this will create a default package.json file which you should edit, so for example removing main and adding the private key, which will ensure the package cannot accidentally get published. For example

{
  "name": "MyPackage",
  "version": "1.0.0",
  "license": "MIT",
  "private": true
}

Running the following command will create a package based upon the package.json and files within the same folder as the package.json. As we’ve marked the package.json as private we’ll need to use the –private switch to force the package creation

yalc publish --private

The package will be stored in the folder listed below on Windows, obviously replacing the {username} with your user name and {packagename} with your package name.

C:\Users\{username}\AppData\Local\Yalc\packages\{packagename}

Using the newly created package

We’ll obviously now want to use our local package, so within your application run, again replacing the {packagename} with your newly created package name.

yalc add {packagename}

This command will add the package to your package.json in your application with a file: prefix. Obviously your package will also be added to your node_modules folder.

I’m not quite sure why, but I also found that this was a very useful technique for some code which seemed to have module problems when I tried to add the code to my application. Once packaged, the module issues went away.

Gulp

Whilst package manager’s such as yarn and npm make things pretty easy, sometimes we’ll want to extend our build workflow or the likes. Yarn allows the use of scripts, but another alternative would be a build tool such as Gulp. Ofcourse we could also write scripts in bash or Powershell etc. but Gulp offers a DSL in a similar way to tools such as Cake, Nant etc. to extend our various development and build workflows.

Getting started

A Gulp file is simply a JavaScript file (.js) in which we have the lines

var gulp = require('gulp');
// if we want to include yarn support in gulp
var yarn = require('gulp-yarn');

these include the gulp functions.

To create a gulp task we include the following

gulp.task('yarn-production', function() {
   // return from the function()
});

The string yarn-production is the task name, i.e. we can run the following command to execute our task

gulp yarn-production

Api’s

gulp.task

As we’ve seen gulp.task is one of the gulp API’s which defines a task along with the task name, which can be executed via the gulp command line, followed by the function to run for that task.

gulp.src

The src API allows us to declare an array of filenames/globs to be passed into the gulp pipeline, for example

gulp.task('yarn-production', function() {
    return gulp.src(['./package.json', './yarn.lock'])
       // pipeline
    );
});

This command basically creates an array of files etc. that will be used in the subsequent pipeline.

gulp.dest

We’ve got a src, so obviously we need a dest which denotes (as you’d expect) where the output from the pipeline goes to. So here’s an example which copies some files to a production folder

gulp.task('production', function() {
    return gulp.src(['./package.json', './yarn.lock'])
        .pipe(gulp.dest('production/'));
});

The .pipe creates the workflow of the gulp task.

The .pipe can also take a function, for example

gulp.task('production', function() {
    return gulp.src(['./package.json', './yarn.lock'])
        .pipe(log)
        .pipe(gulp.dest('production/'));
});

I’m not going to cover all the gulp functions as you can visit Gulp/Concepts for a list of the current API.

Writing our own pipe function

We’ve seen some example of using the pipe function with gulp functions but what about, if we want to write out own pipe functions.

Here’s an example which simply logs the files that are to be transformed

var gulp = require('gulp');
var through = require('through2');

function log() {
    return through.obj((file, encoding, callback) =>
    {
        console.log(file.path);
        return callback(null, file);
    });
}

gulp.task('production', function() {
    return gulp.src(['./package.json', './yarn.lock'])
        .pipe(log());
});

In this sample we simply log the file path, but if (for example) we wanted to make some changes to the files (transform them) we’d use something like this

var gulp = require('gulp');
var through = require('through2');

function configure() {
    return through.obj((file, encoding, callback) =>
    {   
        var transformedFile = file.clone();
        transformedFile.contents = new Buffer("Transformed file contents");
        callback(null, transformedFile);
    });
}

gulp.task('production', function() {
    return gulp.src(['./package.json'])
        .pipe(configure())
        .pipe(gulp.dest('production/'));
});

This will simply output files with the src names with the context “Transformed file” within it.

Generators in JavaScript and TypeScript

Generators within JavaScript (and TypeScript) are similar to C# IEnumerable’s such that you can yield a value multiple times from a generator function (in either JavaScript or TypeScript), i.e.

function* someValues() {
    yield 1;
    yield 2;
    yield 3;
}

or within a TypeScript class we can write

export default class MyClass {
    *someValues() {
       yield 1;
       yield 2;
       yield 3;
    }
}

To use the someValues function we can loop using

for(let i of someValues()) {
    console.log(i);
}

Each item returned is a type of { value, done }, so for example

var values = someValues();

console.log(values.next());
console.log(values.next());
console.log(values.next());
console.log(values.next());

which would output

{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: undefined, done: true }

Using lodash in TypeScript

Was trying to use lodash and couldn’t seem to get Visual Code to build my TypeScript files correctly, so here’s how to get it working…

Add the following esModuleInterop to your tsconfig.json

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "esModuleInterop": true,
        "sourceMap": true
    }
}

and then you can use

import _ from "lodash";

Otherwise you can use the following if esModuleInterop doesn’t exist or is set to false

import * as _ from "lodash";

Unit testing and React

If you’ve created a React application using yarn, you’ll actually have the script for yarn test as well as App.test.tsx for running unit tests against React code (i.e. capable of running against tsx/jsx files etc.).

Jest is used for unit testing by default, but if you need to install Jest yourself simple run

yarn add --dev jest

The test script (within package.json) will execute react-scripts test but if we want to add our own script you could add

"jest": "jest --watch"

–watch will allow jest to monitor file changes and rerun tests automatically.

Create a folder off of your src folder (it can be at any depth) named __tests__ and within this we’ll add a simple .js file (or .ts) named files, for example number.test.js which we’ll create as a simple demonstration of writing tests and running the test runner. We should use either .test. or .spec. within the filename.

Within my number.test.js file I have the following

export function getNumber() {
    return 1234;
}

test('Test 1', () => {
    expect(getNumber()).toEqual(123);
});

test('Test 2', () => {
    expect(getNumber()).toEqual(1234);
});

Note: we can use “it” instead of “test” in the above

Obviously we’d normally not have the actually function we want to test within the test file, this is solely for simplicity of writing this post.

As you can see, each test comes with a string which is the name/description of the test, followed by a function which is executed by the test runner. Obviously in the above code “Test 1” will fail and “Test 2” will pass, so let’s run the test runner and see.

Like other test frameworks, we have functions to assert/expect certain values within our tests.

If you’ve added the script now run yarn jest or use yarn test. The Jest test runner will run and remain running, watching for file/test changes. Select the “a” option to run all tests after executing the jest script.

From the test runner (jest) you might wish to filter file name by regex, simply running tests against the __test__ folder.

React Router

There are many way to route web calls to our web pages etc. React also comes with it’s own capability, which we can load by running

yarn add react-router-dom
yarn add @types/react-router-dom

If you’ve created your React application using yarn create react-app –typescript then go to the index.tsx and edit it to look like this

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { BrowserRouter, Route } from 'react-router-dom'
import * as serviceWorker from './serviceWorker';
import About from './components/About';
import Home from './components/Home';

ReactDOM.render((    
    <BrowserRouter>
      <Route exact path="/home" component={Home} />
      <Route exact path="/about" component={About} />
  </BrowserRouter>), 
    document.getElementById('root'));

serviceWorker.unregister();

Now, let’s create a couple of React components which will act as our routes. Create a folder named components off of the root folder and add two files, about.tsx and home.tsx to the folder. The code for each is shown below (and the files should go in the folder src/components)

// about.tsx

import React, { Component } from 'react';

export default class About extends Component {
    render() {
        return (
            <div>About</div>
        );
    }
}

and

// home.tsx

import React, { Component } from 'react';

export default class Home extends Component {
    render() {
        return (
            <div>Home</div>
        );

    }
}

We’re not using the App.* files, so they can be deleted.

Obviously we can also add a root route, i.e.

<Route exact path="/" component={Home} />

Starting out with Yarn

Yarn is a node package manager that can be used in place of npm. Beyond the basic package management functionality, such as adding and removing dependencies it can also execute scripts to create applications, such as React apps. and build them (i.e. get them ready for deployment) as well as run them.

Creating package.json

To get started we would run the following command within the project’s folder to generate a package.json file (or create one yourself using your preferred text editor).

yarn init

You’ll be presented with a set of questions which will then result in the contents of the package.json file. These include your project name, version, description, git repository etc. If you don’t have any response to the questions just press enter, we can always fill in missing data later.

Here’s an example package.json file

{
  "name": "MyProject",
  "version": "1.0.0",
  "description": "MyProject Description",
  "main": "index.js",
  "repository": {
     "url": "https://myproject-repos",
     "type": "git"
  },
  "author": "PutridParrot <emailaddress>",
  "license": "MIT"
}

Adding dependencies

I said at the start of this post that yarn is a package manager, so obviously we’ll want to add some package dependencies. Again, we can add our information to the package.json directly using our preferred text editor or use the yarn application from the command line to do this. Ofcourse the yarn command does a little more, it will check the yarn registry (by default this is https://registry.yarnpkg.com/)

To add a package dependency we use

yarn add [package]

So for example, we can add React using

yarn add react

This results in the addition for the following to the package.json

  "dependencies": {
    "react": "^16.8.6"
  }

Check out Packages to allow us to search for packages.

We can remove a package using

yarn remove react

Creating an application

We can also create an application. For example to create a React application (i.e. grabs the dependencies, generates the code etc.) we can use

yarn create react-app my-app
yarn create react-app my-app --typescript

Running scripts

We can also add scripts to the package.json, like this

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }

Now we can execute scripts using

yarn start

There’s much more yarn can do, but this post covers the most often used commands (or at least the one’s I’ve used most so far).

Connecting event handlers to React components using TypeScript

In the previous post we created React components which we can pass attributes/properties to. As TypeScript aims to make JavaScript type safe we need to ensure the correct types are expected and passed, so for example here’s some code from the TicTacToe tutorial on the React site, but in this example we’re passing an event handler property from the Board component to the Square component, where it’s wired up to the button

interface SquareProperties {value: number, onclick: (ev: React.MouseEvent<HTMLButtonElement>) => void};

class Square extends Component<SquareProperties, {}> {
  render() {
    return (
      <button className="square" onClick={this.props.onclick}>
        {this.props.value}
      </button>
    );
  }
}

class Board extends Component {
  renderSquare(i: number) {
    return <Square value={i} onclick={() => alert('click')}/>;
  }

JSX, TSX in React, what are they?

React allows us to write JavaScript code in the standard .js files along with TypeScript in the .ts files, but if you’ve created either a TypeScript or JavaScript React app using yarn’s create command, i.e.

yarn create react-app my-app

you’ll notice .jsx or .tsx files. These are similar to Razor, ASP/ASP.NET, JSP and the likes in that they allow us to embed XML (or strictly speaking in our usage XHTML) into source code.

Let’s look at a React component (I’ll use TypeScript in this example but JavaScript jsx components are much the same), in our App.tsx we might want to include our own tag/element, for example

<HelloMessage name="PutridParrot" />

Yes, we’re always obsessed with the Hello World example and this one’s no different.

The above doesn’t really give any context, so here’s the whole of the App.tdx file

import React, { Component } from 'react';
import './App.css';
import HelloMessage from "./components/HelloMessage";

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
            <HelloMessage name="Mark" />
        </header>
      </div>
    );
  }
}

export default App;

Now the HelloMessage element is a React component. In this example I’ve created a components folder off of the src folder and created the file named HelloMessage.tsx, let’s look at the code for this component and then discuss how it works, here’s the code

import React, { Component } from 'react';

export interface HelloMessageProps {name: string;}

class HelloMessage extends Component<HelloMessageProps, {}> {
    render() {
      return (
        <div>
          Hello World {this.props.name}
        </div>
      );
    }
  }

export default HelloMessage;

In this example we’ve imported React, hence need not type React.Component, see Import Declarations for more information on this syntax.

Next up, we’ve created and exported an interface. This acts as the shape of the data that the Component expects to see. As TypeScript supports duck typing, we’re basically saying we expect a thing that looks like HelloMessageProps (i.e. has a name of type string) to be passed into the component. This is our attribute list from the example in App.tsx.

The HelloMessage class extends/inherits from Component and we tell it what data shape we expect to be passed into it, but we do not want to pass any state hence we have a second generic parameter of {}. As we’re writing this as a .tsx we’ve embedded the XHTML along with the use of the property name passed as an attribute in the App.tsx. The render method simply returns the embedded XHTML and that’s it.

We can write the same thing without using the embedded syntax, like this

import React, { Component } from 'react';

export interface HelloMessageProps {name: string;}

class HelloMessage extends Component<HelloMessageProps, {}> {
    render() {
        return React.createElement('div', null, 'Hello World ' + this.props.name);
      }
  }

export default HelloMessage;

Or better still we can use string interpolation by using the ` (back tick), i.e. replacing the Hello World string section with

`Hello World ${this.props.name}`

References

TypeScript specification
React without JSX

Creating a React application by hand

By default it’s probably better and certainly simpler to create a React application using yarn create but it’s always good to know how to create such an application from scratch yourself.

To start with, create a folder for our application and within it create a folder named src, within this create an empty file named index.tsx. Then add the following to this file

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

We don’t actually have React dependencies available to our application at this point so run the following, these will add React as well as TypeScript and TypeScript definitions of React (obviously if you don’t want to work in TypeScript, remove the –typescript switches and the last three yarn commands).

yarn add react --typescript
yarn add react-dom --typescript
yarn add react-scripts
yarn add typescript
yarn add @types/react
yarn add @types/react-dom

yarn will create the package.json file and download the required dependencies. They purpose of the dependencies are probably pretty obvious – the first includes React, the second React-dom and the third gives us the scripts we’re used to when running the code generated React applications, such as supplying the script for yarn start.

Within the package.json add the following, which will add the scripts that we’re used to having available

"scripts": {
   "start": "react-scripts start",
   "build": "react-scripts build",
   "test": "react-scripts test",
   "eject": "react-scripts eject"
}

We’re going to need to also add a folder named public which we’ll place an index.html file in which will act as our default page. Here’s a minimal version copied from a React generated application

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta name="theme-color" content="#000000" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>Game App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

At this point we should be able to execute

yarn start

and now we should see a React application running in the browser.

If you want to add some CSS to the application, we can simply create index.css in the src folder, create your styles then to use it in index.tsx add the following at the top of the file

import './index.css';

If you’re using VSCode, as I am, you may wish to click on the status bar where it display a version of TypeScript, when index.tsx is open, and set to the most upto date version listed.