Hello everyone, this is my first post here, and I hope my English is going to be smooth enough to make it enjoyable to read 👍.
It looks cool to create a npm package and type :
npx my-dream-boilerplate app-name
And boom ! Your project is magically there all setup with your favorite configs, tools and more.
That's what we will do right now.
Why ?
Before we really start, let's try to answer to this question :
Why would you create your own wep-app boilerplate when there are great tools already in place such as create-react-app which also do a lot more that a simple project boilerplate ?
Here is what motivated me :
When I create a web application, I started to be very bored of having to install each time the same packages, commands, folders, etc. over and over.
I can extract some kind of layout of my projects.
I mostly use React.js and I do need EACH TIME (or almost) to install/change the same bunch of things (react-router-dom, styled-component, build my components structure, redux, etc.) while at the contrary I don't need create-react-app to make a small app or fast prototyping stuffs.
I waste time installing packages, add configs and organizing my folders.
So I get interested in making that npx my-dream-boilerplate app-name command works to generate the project starter i like.
Initialize the project
For demo purpose let's keep things very very (and very) simple.
We'll do like in a lot of projects: add a package.json and install all the dependencies we need.
Installing dependencies and setup
First let's initialize the project :
Create a new foler, for example "create-my-boilerplate" and run inside it :
npm init
The only dependencies we will use here are parcel and rimraf.
- Parcel is a web application bundler, there are others Javascript bundlers (webpack, rollup, etc.) but parcel comes up with (almost) no config, a development server, hot module replacement, etc. So this is well enough for our need here.
- rimraf is a npm package used as the UNIX command equivalent rm -rf for node. We will only use it for a command in the script part.
npm install -D parcel-bundler
npm install rimraf
Change the npm scripts field in your package.json :
"scripts": {
"start": "parcel index.html",
"build": "parcel build index.js"
}
Create the structure
Create an index.html and an index.js file.
Your index.html looks like this :
<html>
<body>
<div>Cool</div>
<script src="index.js"></script>
</body>
</html>
Now verify that everything is working :
npm start
Again, the project structure is ridiculous here but how to setup a web project isn't the point of the article.
Script + Npx = speed
More setup
All right so how do i automatized all of this ? We want to type some kind of command like npx create-react-app app-name and boom my project appears !
This is possible thanks to the 'bin' field in the package.json and npx the package runner command.
Add to your package.json
"bin": {
"create-boilerplate": "./generate-app.js"
}
Create at the root of the project a 'bin' repository with a generate-app.js file (name it as you want).
So ./bin/generate-app.js is the script executed when we will type the command npx create-my-boilerplate name-of-your-app.
Before going any further we need to create a git repository.
So run git init and create a .gitignore file..
Your .gitignore file have to ignore folders that parcel generate when you run/build : .cache, dist and build.
To finish the setup part, push your project to a new git repository, your git repo url is going to be use in the next part because we want to clone the repo.
The script
We are working on create-app.js now.
Again, let's keep things simple, the script have to handle this :
- We want to execute a command who accepts an argument representing the application name and validate it.
- If it is valid, verify if the project name doesn't already exist in the current folder.
- Then we want to clone the github repository of this project boilerplate.
- We want to install all the dependencies.
- We want to delete files not useful.
Firstly we require the packages we need : (you don't need to install them).
#!/usr/bin/env node
const { execSync } = require('child_process');
const path = require('path');
const fs = require('fs');
We verify that an app name is provided (npx create-boilerplate with no argument isn't a valid command) :
if (process.argv.length < 3) {
console.log('You have to provide a name to your app.');
console.log('For example :');
console.log(' npx create-my-boilerplate my-app');
process.exit(1);
}
Declare variables we need :
const projectName = process.argv[2];
const currentPath = process.cwd();
const projectPath = path.join(currentPath, projectName);
const git_repo = YOUR_GIT_URL;
Verify the project name is available otherwise cancel the process :
try {
fs.mkdirSync(projectPath);
} catch (err) {
if (err.code === 'EEXIST') {
console.log(`The file ${projectName} already exist in the current directory, please give it another name.`);
} else {
console.log(error);
}
process.exit(1);
}
Now we reach the main part :
async function main() {
try {
console.log('Downloading files...');
execSync(`git clone --depth 1 ${git_repo} ${projectPath}`);
process.chdir(projectPath);
console.log('Installing dependencies...');
execSync('npm install');
console.log('Removing useless files);
execSync('npx rimraf ./.git');
fs.rmdirSync(path.join(projectPath, 'bin'), { recursive: true});
console.log('The installation is done, this is ready to use !');
} catch (error) {
console.log(error);
}
}
main();
Read lines with console.log(), they pretty much explain every command.
This is a very basic CLI but you could do a lot more thanks to node environment, add colors, package.json generator, etc.
That's it.
You can test your package locally :
npm link
It creates a symbolic link so that you can use it as a node module in the folder you are currently located.
And now it is the great time, where the magic comes :
npx create-my-boilerplate app-name
Your script runs and your project spawns.
Congratulation.
As you can see, a basic generation is definitely not complicated.
You can start :
npm start
Go further, make your own boilerplate with your favorite setup and learn to publish on npm.
npm login
npm publish
Now check your package on https://www.npmjs.com/ !
I hope It wasn't too confused and that it will inspire you a little bit about Node.js scripting possibilities, yours project needs and/or new packages ideas.
I myself ending up building my own project boilerplate last week (and in fact thats my first npm package ever) for react-applications with parcel, which include features I use regularly such as prettier, css autoprefixer and reset, tests, styled-components, etc.
If you are interested you can have a look to the code on my github particularly the ./bin/ folder where i have a bit more advanced script than in this article : https://www.npmjs.com/package/react-parcel-app
Thanks for reading and have a good day.
Top comments (10)
Hey Leopold, in the case of Create React App (CRA) you can create your custom template if you want, so you dont need to expend time making the same configuration every time. Here the link create-react-app.dev/docs/custom-t...
NOTE: don't forget to add
shebang
to your .js file inside of bin folder.Hey, I am trying to follow your steps to convert my angular boilerplate into npx command. I'm not using parcel anyways. But rest, I have bin command setup and js file.
but when I run npm link 'create-angular-bolerplate' it gives me
I don't understand where I am going wrong, I tried removing and adding back node-modules. Please help.
Fixed it.. thanks for article. ❤️ but there needs a lot of corrections. you have changed your file name, command name thrice above. also its only 'npm link' we have to run to create symbolic link. then in other folders you can run that command otherwise it tries to fetch from npm registry.
Hey, thanks for the feedback, I will have a look at this !
Hi Pranav, looks like the corrections you mentioned are correct. Would you mind sharing those corrected steps for linking and running
hello, I am a student studying programming.
I looked up your blog to make my own CRA.
My boilerplate is installable with npx on mac, but on windows it gives me an error.
As a result of looking for the cause, it seems that the command to run as "Node" was not specified when running create-app.js.
How did you solve this problem?
Your project can be installed with npx in both Mac and Windows environments. but my project is only on mac.
The Facebook CRA team specified the node environment via the scripts field in package.json, but you didn't.
How is that possible? Did you process it in the file registered in .gitignore?
I would really appreciate it if you could reply. Have a nice day!
here is my project repo!!
Hey, I'm slightly confuse about your issue, but I tested to install your project and it works ! I answered in the github issue you opened.
Thanks for putting this out there! Am I correct in ascertaining that because you use git clone in your commands to build the repository, anyone using the npx command with your package will start off with the original repo as a remote by default that they then will need to point to their own project?
You're partially right yes but for my package this is the reason why I am deleting the git repo during the installation process, so you can just type git init afterwards.
They are probably more elegants ways to do this and for example we could have a closer look at how something like create-react-app is handling this to have a fresh new git folder once we install the app.