GitHub Pages is a static site hosting service designed to host your personal, organization, or project pages directly from a GitHub repository.
Note that GitHub Pages is a static site hosting service and doesnβt support server-side code such as, PHP, Ruby, or Python.
To learn more about the different types of GitHub Pages sites, take a look here.
π€¨ Thatβs the theory! Letβs start: π€¨
Copy the name of your project.
The name of my repo is deploy-react-to-gh-pages
.
For React specify the homepage
in package.json
(Docs).
{
...
"homepage": "/name-of-your-project/",
...
}
For Vue create a new file in your project root named vue.config.js
(Docs) and specify the publicPath
(Docs).
module.exports = {
publicPath: '/name-of-your-project/'
}
Now commit and push your changes.
Note: if you don't commit your changes, you will lose them in the next command, so make sure you don't skip this step
Open your terminal in your project and run:
Note: For the following commands, if you are using vue, just copy paste them, if you are using react replace dist
with build
.
npm run build
creates a directory with a production build of your app. In vue, that directory in named dist
, in react is named build
.
-
git checkout --orphan gh-pages
Docs npm run build
-
git --work-tree dist add --all
Docs (for react: replace dist with build) -
git --work-tree dist commit -m 'Deploy'
(for react: replace dist with build) git push origin HEAD:gh-pages --force
-
rm -r dist
(for react: replace dist with build) git checkout -f master
git branch -D gh-pages
- Navigate to your github project and click 'Settings'
- Scroll to find the section 'Github Pages' , select the
gh-pages
branch and click 'Save'
ππ Congrats ππ
Your site is ready to be published.
You might have to wait a bit. Generally it takes 2β10 minutes until this process is done.
π€π€But... wait. You probably want to re-deploy. There must be a simpler solution instead of re-doing over and over again all the commands above.
Create a node.js script
Now, we are gonna create a node.js script so whenever we want to deploy, we just run one command.
Create a
scripts
folder in your project root.Inside
scripts
folder, create agh-pages-deploy.js
file.Copy and paste the code below:
const execa = require("execa");
const fs = require("fs");
(async () => {
try {
await execa("git", ["checkout", "--orphan", "gh-pages"]);
console.log("Building...");
await execa("npm", ["run", "build"]);
// Understand if it's dist or build folder
const folderName = fs.existsSync("dist") ? "dist" : "build";
await execa("git", ["--work-tree", folderName, "add", "--all"]);
await execa("git", ["--work-tree", folderName, "commit", "-m", "gh-pages"]);
console.log("Pushing to gh-pages...");
await execa("git", ["push", "origin", "HEAD:gh-pages", "--force"]);
await execa("rm", ["-r", folderName]);
await execa("git", ["checkout", "-f", "master"]);
await execa("git", ["branch", "-D", "gh-pages"]);
console.log("Successfully deployed");
} catch (e) {
console.log(e.message);
process.exit(1);
}
})();
- Open
package.json
and addexeca
(Docs) to yourdevDependencies
.
"devDependencies": {
...
"execa": "latest"
},
- Also add a new script in
scripts
section:
"scripts": {
...
"gh-pages-deploy": "node scripts/gh-pages-deploy.js"
},
- Finally, run
npm install
.
β¨π And... that's it! πβ¨
You can now deploy as many times as you want by just running npm run gh-pages-deploy
.
Me- But, hey... π€«π€«! Wouldn't be even more exciting if we automate everything ?
Everyone- Do you mean that the app will be deployed itself ? π€¨π€¨
Me- ππ
Everyone- π²π²
Github Pages- π€π€
Create a github action to automate deployment
Wouldn't be great if on every push on master, the app gets deployed without us doing nothing ?? π§ββοΈπ§ββοΈ
We can achieve that by using... ππ Github Actions ππ.
GitHub Actions enables you to create custom software development life cycle (SDLC) workflows directly in your GitHub repository. Docs
Let's start:
Create a
.github
(Don't forget the dot in front) folder in your project rootInside create another folder named
workflows
Inside
workflows
create a file namedgh-pages-deploy.yml
(The name is up to you).Now copy & paste the code below inside that file.
name: Deploy to github pages
on:
push:
branches:
- master
jobs:
gh-pages-deploy:
name: Deploying to gh-pages
runs-on: ubuntu-latest
steps:
- name: Setup Node.js for use with actions
uses: actions/setup-node@v2
with:
version: 12.x
- name: Checkout branch
uses: actions/checkout@v2
- name: Clean install dependencies
run: npm ci
- name: Run deploy script
run: |
git config user.name "Your username" && git config user.email "your email"
npm run gh-pages-deploy
Important: Make sure to change your username and email:
Commit and push your changes
Now, navigate to your github project and first click Actions (1) then Deploy to github pages (2) and last click on the action (3).
- If everything goes well, you will see this:
ππ Taadaaa!!! You successfully automated deployment!!! ππ
Now, whenever you merge a PR or push to master this action will run and will deploy your app automatically. ππ
Things to know
- React & Vue provide their own steps to deploy on github pages:
- For React, See the steps Here.
- For Vue, see the steps Here.
- Also Read the steps to create a github action
- Great libraries to use for deploying to gh-pages:
- It's definitely a good thing to know how to manually deploy to gh-pages. Also, the script is very minimal and easy to understand. This simplicity gives you the power to modify it. (add colors, emojis, promts). So here are some great resources to enrich the script:
- Repositories (feel free to checkout the commits):
ππ Thank you for reading. I would be glad to help you if you face any problem, so don't hesitate to email me at rolanddoda2014@gmail.com ππ
Top comments (39)
Great article, thank you. I had to do some changes to get it working through trial and error. For example if you have a custom domain you need to write a CNAME file to the dist/build directory before the git commands. Indenting was also broken for me on copy paste.
Hi Sam, thank you for your comment.
Yeah those are some valid issues, glad to read you fixed them on your own.
I remember I created this library which does everything automatically if you use vue-cli -> github.com/Rolanddoda/vue-cli-plug....
However, both the article and the repo are old and nowadays it's not recommended to use vue-cli because it's in Maintenance Mode.
Hi!!!, Great post I have been using the
gh-pages-deploy.js script for a while and it worked perfectly, but for some reason now I get an error when using
require`.Error [ERR_REQUIRE_ESM]: Must use import to load ES Module...
...require() of ES modules is not supported...is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Is this happening to anyone?
Hi, thanks.
Probably it's an error coming from upgrading packages. For instance, chalk and other libraries that
gh-pages-deploy
script uses, are now ESM only!If you want me to help you, please drop me a message on Linkedin with a screenshot of the error you are getting.
Thanks Ronald!
Right, I was trying a lot of things for a while and finally found it by installing an older version of the packages.
Glad to see that you fixed it.
I was also getting some errors in the yml file.
I solved it by updating it following the structure of this file :
github.com/Rolanddoda/vue-cli-plug...
... and the name of my npm script also had a different name
I leave it here written down in case someone else finds it helpful.
Thanks for that. Yes
setup-node@v1.1.0
is deprecated andsetup-node@v2
should be used. I will make sure to update the article. Since you are using vue and you found the vue-cli plugin, then I guess you don't have to follow this article anymore. You can just install the plugin and everything that is in that article will automatically be done for you.Thanks, yes I will take a look at the repo, when I have time, it is more updated and I see that there are more automations to get the user's name and email.
Yup. :)
Excellent post! Thank you! If I may make a recommendation, removing the first layer of indentation in the code block would help a lot I think. It took me a few minutes to figure out why my .yml was being rejected, but it was because everything except the
name:
line was indented too much.Still, this got me up and running quickly, with a few minor tweaks to improve things for my workflow! Unfortunately, my user page has to deploy on
master
so I'm doing that. I might move my personal website to a different repo though, because being able to usegh-pages
without pollutingmaster
would definitely be preferable.Thank you for posting this great article. Just a few additional notes you might even want to put in the article.
1) I am fairly sure github pages has no way of implementing
History
mode, so it is important that if you are using the Vue router, it is set like so2) For the script to deploy to github pages from the local machine, I would advise checking if there are uncommitted changes first with something like
3) It might be worth putting the final git commands in a
finally
block so you always end up back on master. Also note below the rm command is replaced by rimraf - rm is platform specific (and certainly will not work on Windows) and rimraf deals with this for us.Hi Brent and thank you for this comment.
As I said in the end of the article, I want to keep the script very minimal so anyone understands it and can modify it. There is so many things to add to that script and to the whole article itself, but I wanted to go with simplicity.
Here are my answers to your notes:
1) There is a way to get the History mode work with github pages. See -> github.com/Rolanddoda/vue-router-g...
However, going with hash mode, is something that you can easily do, but it's out of the scope of this article on automating deployment to github pages by using github actions. (I would had to talk about vue router history mode and hash mode).
2) It's worth noting that the script will run in github actions environment after you have pushed on master. So no need to check for uncommitted changes.
3) For the same reason as on the second note, no need to add a finally block and also the rm command will run in ubuntu as I've defined in the github actions workflow.
Again, there are so many things to add on that article but I want to keep it simple so anyone can easily extend it. I hope I have helped people on how to take advantage of github actions and github pages.
Thanks for taking the time to comment Brent,
With Respect, Roland.
Thank you very much. It helped me very much.
Glad to read that it helped you π.
If you are using vue.js though I have created a vue-cli plugin which automates everything and it's literally a zero-config solution. Check it out -> github.com/Rolanddoda/vue-cli-plug....
I have in mind some improvements to do there but haven't found the time yet.
Small note for those who use
yarn
(like me) and not npm. You will getnpm ERR! cipm can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync.
because obviously
package-lock.json
doesn't exist. You either need to create package-lock bynpm install
or change a bit last lines ofgh-pages-deploy.yml
toThank you Philipp.
Hello, Thank you for the great tutorial.
one problem I have is
rm -r dist
doesn't work! it says that rm is not recognized and I tried replacing it withdel
so it asked me to delete everything insidedist
and I said yes.and nothing is working :(
Can you please help?
I have to see what and where the issue is. Feel free to send me an email at rolanddoda2014@gmail.com so I can help you to fix the issue
Thank you for the article. I've published many websites on gh-pages using this. I was getting an error while deploying using Github actions and it turns out that the setup-node version has been updated and using
setup-node@v1.1.0
will throw an error. I used the updated versionsetup-node@v2
and it worked fine.Excellent post! Thank you, Roland.
As Nathan Snyder pointed out, the .yml block doesn't work if you copy from the first character to the last as there is an indentation on the entire code block that is not immediately apparent. Though this is a minor detail, it might help other less experienced programmers (like myself) to take note of this.
I got mine working after tweaks here and there. Thank you sooo much!
Thanks for the post, Roland,
Especially arrows on the images are helpful as people don't have to scan the image to find out where.
Glad to read that you liked the article and the way it's written Sung. It took me some days (considering I am working full-time) to finish it but I always try to make good articles. So far I have got 3 emails from people thanking me and they are amazed about the automation. Wondering if you have tried it.
I've tried gh pages & actions but only separately.
Should an opportunity comes, then I will try it :)