Use Your Own Template With Create-React-App
By: Teddy Morin
Tags: JavaScript, React, Productivity, Process, Typescript

Enhance it

While it may well be a fantastic tool, chances are your projects always start with a big overhead. If your first step after running CRA is to spend a day setting up default functionalities and configuration, creating your own template will definitely boost your productivity.

Creation

Using GIT the right way can resolve a lot of headaches regarding the creation and maintenance of your custom template.

Using a fork of create-react-app and by doing so, keeping its GIT history, allow you to later sync your fork with the official repository.

If you are a GitHub user, you only need to use the Fork button on the homepage of create-react-app.

If you use any other GIT repository hosting service, the approach is slightly different. It consist in creating your own repository and creating an upstream remote:

$ mkdir create-react-app

$ cd create-react-app

$ git init

$ git remote add origin <YOUR_REMOTE_REPOSITORY>

$ git remote add upstream https://github.com/facebook/create-react-app

$ git pull upstream master

$ git push origin master

Customization

This repository doesn’t only hold templates. It uses lerna to handle a variety of packages related to creating a react application.

Inside create-react-app/packages you can find, among others:

cra-template: the default template

cra-template-typescript: the template used when passing --template typescript using CRA .

using . react-scripts: the official react-scripts including webpack configuration, init , start , build , test , and eject scripts.

The react-script directory contains a template and template-typescript folders. They were used previously but were then moved to cra-template and cra-template-typescript. They are not to be used anymore.

Depending on your Type System, you have to update cra-template , cra-template-typescript , or both.

Templates folder always have the same structure:

package.json

(Optional) README.md

template.json

template/

The template folder must contain everything that will be generated, except for your package.json . The content of this file must be written inside the parent directory template.json .

The reason being, the init script will use template.json in order to generate a package.json with more information and then install your dependencies.

As explained in this issue, devDependencies cannot be used, only dependencies.

On the contrary, the package.json file is made to be used by npm, not to be confused with template.json .

Local Testing

You are trying to create a custom template but don’t want to set up an automated quality process yet?

You can use and test a local template with create-react-app , for example:

$ npx create-react-app my-app --template file:<path-to-cra-template>

Deployment

Deployment is rather straightforward. You have to update the template package.json name with your own and deploy it to npm.

On a personal note, I’ve been using a custom typescript template in a private organization. My package name was @<MY_ORGANIZATION>/cra-template-typescript .

I created an Access Token on npm through Account > Access Token > Generate New Token > Publish > Generate Token . I’m using GitLab and always automate this step:

My Access Token was added as NPM_TOKEN in my CI/CD variables.

Depending on your usage of GIT and npm, this step might be different for you.

Usage

If you deployed your template in a private organization, be sure to run npm login to use an account with the right access.

You can then use create-react-app to generate a default React application with your custom template:

$ npx create-react-app my-app --template <TEMPLATE_PACKAGE_NAME>

React-scripts

By setting up your custom create-react-app repository, not only are you able to create your own template, but also to customize react-scripts.

The main reason to create your own react-scripts is to customize the default webpack configuration. Indeed, templates do not contain a webpack configuration, react-scripts does.

Webpack configuration can be found under react-scripts > config > webpack.config.js .

Do you need to add a plugin? Extend the default babel configuration? Tweak some options? Solutions are:

Eject.

Use a fork of react-scripts that allows more configuration options.

Use your own react-scripts.

Setting up

Setting up your own react-scripts follows the same process as templates. You need to update files in react-scripts and deploy it to npm.

Using a custom react-scripts is possible by setting --scripts-version <alternative-package> with CRA, using a local package or from npm:

$ npx create-react app my-app --template <TEMPLATE> --scripts-version file:<path-to-local-react-scripts>

or

$ npx create-react app my-app --template <TEMPLATE> --scripts-version <NPM_REACT_SCRIPTS_PACKAGE>

Motivation

It’s common to require functionalities or configurations that are outside of the default create-react-app / react-scripts. On the other hand, the given solutions do not have the same implications:

Ejecting from CRA means you’ll have to maintain your own build configuration inside your project. This is a heavy investment we try to avoid by using CRA.

Using a tool such as react-app-rewired imply learning how it works. Also, it gives you the following warnings:

As of Create React App 2.0 this repo is “lightly” maintained mostly by the community at this point. By doing this you’re breaking the “guarantees” that CRA provides. That is to say you now “own” the configs. No support will be provided. Proceed with caution.

Eventually, you can use your own version of react-scripts so you don’t manage your whole build system inside every project but still control it.

Maintenance

With a custom fork created months ago, you now need to update it with the last patch and functionalities from create-react-app. Thanks to setting everything correctly, this step is pretty straightforward:

$ cd create-react-app

$ git fetch upstream

$ git checkout master

$ git merge upstream/master

You might have some conflict, which will depend on your own updates. If you are not used to resolving merge conflicts, see GitHub docs.