Versioning git pushes of React websites 
Tags: npm, react, git, devops
Published: 2020-04-03 01:32:14

Create a web page with an auto-incremented version number. Let git and npm automate it. Perfect for a small project with a single developer. It's the [package.json](https://docs.npmjs.com/files/package.json) approach with auto-bump.

### Auto-Increment the package.json version number

Here's how to auto-increment a version number in package.json with git, npm, and react. Three steps.

**Step 1**: Create one [git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) for the `pre-push` git command.  It's just a text file. Create one file named 'pre-push' in the directory .git/hooks.

Example file structure:
```shell
$ tree .git/hooks
.git/hooks
├── applypatch-msg.sample
├── commit-msg.sample
├── post-update.sample
├── pre-applypatch.sample
├── pre-commit.sample
├── prepare-commit-msg.sample
├── pre-push
├── pre-push.sample
├── pre-rebase.sample
├── pre-receive.sample
└── update.sample
```

**Step 2**: Add the executable file permission. On linux, with `chmod`.   

Example command:
```shell
 $ chmod +x .git/hooks/pre-push
```

**Step 3**: Place the following two lines into the file 'pre-push':

Example hook content:
```shell
npm version patch
exit 0
```
**Done!**

### Trigger the auto-increment

[`git push`](https://git-scm.com/docs/git-push) triggers the auto-increment. git will execute the hook first. The hook is the shell script above. git then executes the push command to the upstream git repository. `[npm version](https://docs.npmjs.com/cli/version)` increments the version number and commits the package.json to the git repository. `npm version` shoves the new version number into the commit message. A one-liner.

`npm version` tags the local git repository. npm is nifty. The tag is a version number and it matches the package.json's 'version' value. Whether the tag is pushed to the upstream repository depends on the 'git push' command line arguments. By default, git does not push tags upstream.

### Give the version number to the users

Place the version number in a react component.  Then, users will see the exact version number!  

Example react component:
```jsx
import React from 'react';
import { version } from '../../../package.json';

// about page
export default class About extends React.Component {
  render() {
    return (<div>
      <p>Thanks to all my friends!</p>
      <p>v{version}</p>
    </div>);
```

The package.json file is a private file with important information.  Don't import the whole file.  Scope the import to one key/value pair.  It's safe.

### Versioning website content

Website content is kinda like code.  A version number is like a sync point. A small project can benefit too from one that is auto-bumped. That's why a teeny tiny automated commit hook is perfect for a web site with a single developer. 

### 'version' in package.json

The package.json is a simple place to keep the version number. So let's use that file. '[npm version](https://docs.npmjs.com/cli/version)' can bump it. JavaScript can simply [import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) it. JavaScript can import a single 'version' key/value pair from the json file in the website content and exclude the rest of the file.  

Example package.json:
```json
{
  "name": "scotch",
  "version": "0.1.3",
  "private": true,
  "dependencies": {
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-scripts": "3.2.0"
  },
  "scripts": {
    "start": "react-scripts start"
  },
  "eslintConfig": {
    "extends": "react-app"
  }
}
```

### Version numbers are not cache busters

I've never really liked cache busters.  Cache invalidation is simpler.  An amazing number of website bugs root from web browser cache staleness.  A version number isn't a cache buster.  It simply a sync point.  git and npm are beautiful tools and I really like them.  That's why I let these two tools handle my version number increments for my small website projects. Is is the simplest? Please share any other simple solutions as a comment!