Creating a website is easy. Depending on what you are trying to do, there are plenty of tutorials available on the web to help you. I even have one for you. The part that is not talked about a lot is how to maintain them. If there is anything I learned through out the years is that no matter how confident I am with my own code, I cannot say I have it memorized. So I had to developed a system organize it in a fashion I can easily update, revert, and keep my sanity in check.
How I started
My first dynamic website was created inside Godaddy text editor. It was slow, painful to debug, and simply not a good way to develop. Plus when I left the page open for too long, I was logged out and my changes were not saved. This method falls short quickly. If there are any problems you have to go through Godaddy and work in browser. This could be good for writing, but not for writing code.
My next process was to install all the environment on my machine. I installed MAMP and created a duplicate of my website locally. It was a mess to use
http://localhost/ locally because a large section of my code depended on the domain name. So my local code had to be a little different then the production one. I would add new features locally and it would fail on production. I would have to go back to Godaddy to manually fix things in the browser.
It was still better then coding everything in browser. I could use an editor like BBedit that had code highlighting; that was a huge advantage. It worked for the most part. I'd transfer my files using ftp and life was good.
The problem came up when I deployed something to production, it failed, and I didn't know how to fix it. That meant my website would be down until I figured out a solution. Even if it was a small
.htaccess error. Getting your error log from Godaddy shared services was a nightmare.
Sometimes the problem would just be that I have a different settings on my local, and no control on what Godaddy set for me on production. If I had to get any control I'd have to move to a different service.
I know many people that still work with a single copy of their project. I don't think I have a healthy enough heart to ever consider this again. Even if you don't use source control, you still need to have back up copies of everything you deploy to production.
However, I recommend source control. I use subversion but there is nothing wrong with using other services. Git is a popular choice these days. We will get back to the exact folder structure in a minute.
The first thing I started doing was to create a release folder for all my deployments:
/var/www/releases/ . .. 2015-01-01.rel1 2015-01-01.rel2 2015-01-02.rel1 2015-01-04.rel1 2015-01-09.rel1 ...
Every time I deploy my code to the server, I add it to a new folder with the current date and the release number. If I deploy more than once on a particular day, I simply increment the release number.
I have a symlink folder that represent the current version of the website that the web server points to.
Created using this command:
ln -s /var/www/releases/2015-01-25.rel1 current;
When I make a new deployment, I delete current, and recreate it pointing a the newest release. If my website fails in anyway, I can simply delete the folder and point back to the previous working release. Now my down-time is counted in seconds instead of being stuck until I find a new solution.
Making changes in production.
There are times I don't have access to my development machine but I still need to make changes. I log in with SSH on my laptop and if I was to make any changes, I still make a backup copy of the file before touching it.
cp index.php index.php.2015.01.05.bak
Then I can modify index.php. This way if I was to make a change that ruins the website, I can always revert back.
If you use another source control, you can still follow the same philosophy. I started using Assembla.com as my SVN server and so far it has been very reliable. A lot of developers don't see the need for using version control if you are working alone on a project. But for me, it goes a long way. The simple fact that I can revert my code is mind boggling.
Imagine this. You have a large function that does too many things. You delete the function to refactor it. You save the file and start writing the new ones. You close the file by mistake then reopen it. You have the names of the new functions but you don't remember exactly all the things the old function was doing. What do you do? You revert back your changes or check the latest version available in source control where you can copy the essential part back to your code. Wait you don't have source control you say?
That is the advantage of source control.
Here is how I like to set up my svn structure
website |- branches | |- 2013-juneredesign | |- 2013-commentsystem | |- ... |- releases | |- 2014-01-01.rel1 | |- 2014-01-02.rel1 | |- 2014-01-05.rel1 | |- ... | |- current |- trunk | |- app | |- src | |- ...
The main code is inside the
trunk folder. This is where I work from. If I find bugs or have to work on a small feature, I work directly from there.
When I have to add a major feature that may take a while to finish, I make a copy of trunk in a new
branch. In the
branch folder I can work on a complete site redesign or feature that would otherwise block any other work on the website. At the same time, I can do bug fixes on
trunk. I will eventually merge the two.
When I have changes stable enough and am ready to deploy, I make a new copy of trunk inside the
release folder. I use the date and release number to name new folder, then I make another copy with the name
current. current is the copy that goes onto my server.
By now you must have noticed that the process is very manual. But you also notice that this can be automated easily. Let's finish this deployment manually first.
There are two ways to deploy your code. You can simply export
current from svn on your local machine then do a ftp transfer. (But I don't like FTP, future post on that). Or you can use
scp -r current firstname.lastname@example.org:/var/www/releases/2014-06-01.rel1
The second way to deploy your code, is to have svn on your server and do a simple export:
svn export https://subversion.assembla.com/svn/mywebsite/releases/current /var/www/releases/2014-06-01.rel1;
Now that your code is in, you can simply create the symlink to point to it:
rm /var/www/current; ln -s /var/www/releases/2014-06-01.rel1 current;
That in a nutshell is the process I use to maintain my websites.
I use a simple bash script to deploy my code.
releasever="$1" username="myuser" rpath="/var/www/releases" currentpath="$rpath/$releasever" cd $rpath echo "Importing Files $1" svn export --username $username https://subversion.assembla.com/svn/mywebsite/releases/current $releasever # Run extra commands to initialize my framework php app/terminal Generate:Sitemap php app/terminal Minify assets ... # change the current dep folder rm /var/www/current ln -s $currentpath /var/www/current
All it does is export the latest code, create the correct folders and run any initialization scripts needed for my framework. I can run it with this command:
I am no expert in creating complex bash files but this should do the trick. The same can be done to create a more robust deployment system. You can use PHP for example to create a more dynamic web facing service to handle deployments. You can even automate the part of SVN that moves the new code to the release folder.
Handling image assets with deployment.
If you have a website were you serve images, you might run into problems. Every time you deploy, you re-export the same images over and over, creating useless copies taking a lot of storage space. I have a few thousand images in my asset folder and if I had to redeploy them every time it would be a mess.
First of all, if you are on the LAMP stack, I highly recommend you use Nginx to serve your static files. But I will show you how to set it up with Apache too.
Your images are not your code.
It is a good idea to not include your images with your code. This mean, you can have a separate folder for your images. For example:
/var/www/current; # latest code /var/www/releases; # all releases /var/www/images; # home for your images
Your images can have their own process for uploading. I use sftp to upload my images, but I can also add a web interface if I have to. The trick is it either add a symlink generated by your deployment process to make the folder accessible through your webroot:
ln -s /var/www/current/html/images /var/www/images;
Or you can set up Apache to point a virtual folder to
# Your website Apache config <VirtualHost:80> ... Alias /images/ /var/www/images <Directory /var/www/images> Options -Indexes AllowOverride All </Directory> </VirtualHost>
Now you have a well organized process to deal with your images.
It is important to organize your code. It is easy to fall in the trap of, "I am the sole developer". You have to remember that even your own code is not very readable a month after. There are a lot of sections of my website that I have no recollection of how it works. "What the hell am I using the Reflection class for?" But if I go to the particular file, there is a nice documentation that reminds me exactly why.
After using the same process for multiple websites, I don't have to think much about this process anymore. I know that if I add new code that fails, I can simply revert to a previous code where everything was fine and dandy. Using SVN source control and making copies of each deployment goes a very long way.
Automating your deployment makes your website easier to maintain, especially when your code base grows. It doesn't hurt to create a solid system that do more automation then the simple script I showed you above.
It is a good idea to separate uploaded image assets out of your code, this not only saves you storage space but it makes your deployment faster. The full framework that run this website was around 70 kilobytes when I started. I'm sure it didn't grow that much in 2 years.
That's it folks. You now have an idea on how to organize your code to make it easier to maintain. If you are just getting started and want to know how to set up your website from scratch I have a How to create a website from scratch series. Feel free to ask questions in the comment section or email me.
Thank you for reading and I hope you found this post useful.