Before we get too deep into the details, I'd like to detail the driving principle behind being able to deploy a website for this cheap. And that is the KISS Principal. KISS stands for "keep it simple, stupid" or "keep it stupid simple" depending on who you ask. Surprisingly, the saying draws its roots from the U.S. Navy, but is applicable to any complicated task. It's particularly applicable while developing software. The millions of ways to develop and deploy applications can be overwhelming when starting out. There's different frameworks, Server-side rendering vs Client-side rendering, different hosting platforms. The amount of options you have is seemingly endless. At the end of the day, if you take your time to honestly exam what you're goals are for a project, and find the smallest tools you can to complete those goals, it often leads to the best outcome both for the creator and for the consumer.
To kick things off, let's get the mile-high view of how the project is built. For starters, the core of my application is React. However, you can easily do this with just plain-old HTML, CSS & JS. Next, we'll go over the AWS side of things. If you're unfamiliar, Amazon Web Services is a cloud computing platform built and maintained by Amazon. It has an extremely wide-range of services, however today we're going to focus in on two. S3 or Amazon's Simple Storage Service is a data-storage service. It's a staple of AWS and where we're going to store our static files for others to access. Secondly, Cloudfront is Amazon's Content Delivery Network. The purpose of CDNs' is to maximize availability to consumers, regardless of geographic location. So even though our site will live in a specific region, we can ensure that everyone has a consistent experience while accessing our product.
Continuous Integration (and it's sibling Continuous Deployment) is the act of automating the process of delivering the production version of an application. CircleCI is a product that provides integrations for deploying applications to common targets. We'll use it to wire our project to AWS.
Let's jump in.
$: npm i -g create-react-app $: create-react-app demo
This will create a React boiler plate project that we can use to setup our deployment process. Next let's build the project locally, to ensure we don't fail our longer process later.
$: npm run build
Once this completes successfully, let's add a repository. If you're new to Github, you can sign up here and follow this guide for how to create a repository with them. Once you've create a repository lets setup our local repo to work with the remote one we've created in Github. As well as add our first commit. If you're unfamiliar with Git or the Git CLI, I have a short tutorial series that covers the basics
$: git remote add origin https://github.com/YOUR_USERNAME/YOUR_REPO.git $: git add . $: git commit -m "Inital Commit" $: git push -u origin master
Now we'll need to setup our AWS architecture before we go too much further with the project itself. If you don't already have an AWS account, you can follow their guide here. Once you've done that head into the console and search for "S3". In the S3 dashboard, you'll be greeted by the sight of your accounts buckets in a table. You'll see a series of buttons to the top-right. Select "Create Bucket" on the far right.
You'll have a form presented to you for creating an S3 Bucket. Buckets in S3 are similar to top-level directories in a file structure. How they are configured determines how the objects inside of them behave. Simply, they are a location for you to store data and configure how the data is accessed. Here you'll want to enter a name that is easy to relate to your project and uncheck the "Block all public access" button. It warns you that this is dangerous, because when you select this setting, any data you put in the bucket can be accessed by anyone. For our use-case, this is required. We're going to be hosting a website for everyone to have access to. After you've created the bucket, select it from your table and then select the "Properties" tab.
In here, we need to configure the Bucket to be a web host. Select "Static Website Hosting" from the first row of buttons. In here you'll enter the index and error HTML file names. And that's it for S3!! Halfway through the architecture setup, lets now turn to Cloudfront.
If you go back to the AWS console, and search for "Cloudfront" instead of "S3" you'll be redirected to CloudFront. In the CloudFront dashboard, select "Create Distribution". Where you'll be greeted by two buttons. One underneath a section titled "Web" and another under "RTMP". Selected the button underneath "Web". You'll be greeted by a long form with a lot of complicated-sounding options. Lucky for us, the only thing we have to do is insert the bucket's site URL, into the "Origin Domain Name" field. After that you can leave everything as default and select "Create Distribution" at the very bottom-right of the page. Congrats!! That's all the scary stuff down. Finally let's connect the project we made earlier with the architecture that we finished setting up.
First, you'll need to create a CircleCI account here and link it with your github account. Then, head back into your create-react-app project and add a root level directory named, ".circleci". In it create a file titled "config.yml". Paste below, into the file, replacing BUCKET_NAME with the name of the bucket you created earlier.
version: 2.1 orbs: node: firstname.lastname@example.org aws-s3: email@example.com jobs: build-and-test: executor: name: node/default working_directory: ~/repo steps: - checkout - node/with-cache: steps: - run: npm install - run: npm test - run: npm run build - aws-s3/sync: from: build to: 's3://YOUR_BUCKET' overwrite: true arguments: | --acl public-read \ --cache-control "max-age=86400" workflows: build-and-test: jobs: - build-and-test: filters: branches: only: master
One other thing to note, is the "filters" object at the very bottom. This is saying that, whenever their is a commit to the master branch, I want to build and deploy the website. Once you push this file to the remote, you should no longer commit directly to master, otherwise you'll trigger a deployment with every commit! This would not only lead to extra charges on your AWS account, but would most likely lead to a poor experience for your user.
In the CircleCI Dashboard, select the "Projects" tab from the sidebar. You should see a list of all the repositories in your Github account. To the right of each repository, you'll see a "Set Up Project" button. Select the button for the repository that houses the create-react-app project. Inside, you'll be greeted by a text-editor with a sample node configuration. Above that you will see this ribbon. Select "Add Manually". At this point, CircleCI should be running and within a few minutes, you should have your first deployment!!
You now have your website hosted on AWS!! How's it feel? I know at first AWS can be super overwhelming, but like most things once you spend time in it, getting things done becomes second nature. If you would like to see how to setup a custom domain, had any issues following this guide, or have questions in general, you can comment below or reach out to me on twitter.