Making a hybrid static + dynamic site can be quite a useful combination. This
might sound like an oxymoron, but it simply means serving static pages from a
site that also runs a dynamic web application. You can get some of the best of
both worlds with this approach.
My Chinese-learning site ChineseBoost uses this
combination – a lot of the content pages, e.g. for Chinese
grammar, are statically generated with
Hugo, while dynamic parts of the site are served by a Laravel application.
Similarly on our pop out cards shop, we have
a static blog and an ecommerce application on the same server.
This is easy to achieve when you’re using a webserver like nginx. Your nginx
installation is probably set up by default to serve static files that it finds
in the public directory with directives like this:
index index.html index.htm index.php;
location / {
try_files $uri $uri/ /index.html /index.php?$query_string;
}
The config file is usually at e.g. /etc/nginx/sites-available/foo.conf .
This means that if you have a file at public/foobar-static-slug/index.html ,
nginx will serve that at www.yourdomain.com/foobar-static-slug/ . Nginx is fast
at everything, and especially fast at serving static files, so this will perform
nicely with minimal load.
Read more about serving static content with nginx.
Set up Hugo inside Laravel
You can have Hugo output your static content straight to the public directory
where nginx will then serve it.
I would suggest having a separate (non-public) directory for your static
content, e.g. blog at the top-level of your repo, which your static source
files live in. You could have a separate repo for this and pull it in to do the
static generation, but I prefer keeping related things in the same repo as much
as possible.
You have a standard Hugo set-up inside your blog directory, with the important
config.yaml file which controls how the site gets generated. There is nothing
different or special about how you set up this Hugo site, despite it being
inside a repo that is primarily for a Laravel application.
The approach I take is to use a symbolic link to the static files that Hugo
generates, at the path I want the static content to appear in the public
directory. For example, if you want your static content on /blog/ , you’d do
something like:
cd /home/whoever/yoursite.com/blog
yarn install # etc for blog setup...
if [ ! -f ./hugo ]; then
wget https://github.com/gohugoio/hugo/releases/download/v0.62.2/hugo_0.62.2_Linux-64bit.tar.gz
tar -vxzf hugo_0.62.2_Linux-64bit.tar.gz
fi
./hugo
ln -sf /home/whoever/yoursite.com/blog/publish /home/whoever/yoursite.com/public/blog
That can be run on a server during your deployment process.
Now the blog content is served on /blog/ .
Because of how nginx checks for the existence of static files, you can still
have Laravel routes that start with /blog/ , so long as there isn’t a real
index.html at that location on disk.
Automatically regenerating on deploy with Forge
This works quite nicely with Laravel Forge, as you
can put the above script in the deploy script for a site, and Forge will then
regenerate your static content each time you merge to master as part of its
deployment process.
Your homepage can be static
Just a note that it can be beneficial to have a static HTML file as your
homepage by putting an index.html file inside public . The homepage often
gets a large proportion of traffic, and serving it statically reduces the load
to minimal levels. It also means your homepage is likely to stay up even if
something goes wrong with your Laravel application, which looks better than the
whole site going down.
If you’re regenerating the static content on each deploy (or more regularly, see
below), you can still have regularly updating “live” content on the homepage
even when it’s a static file.
If you don’t want to generate that file with Hugo, it’s quite easy to get
Laravel to write the content of your homepage Blade view file to
public/index.html , so you can control that page from Laravel using your full
application, but have the benefits of it being static.
Scheduled Hugo regeneration with Laravel console command
Laravel makes it easy to run application commands and bash scripts on a
schedule (one of my
favourite features of Laravel), and you can utilise this to automatically
regenerate your static content regularly, e.g. once an hour or whatever cadence
suits your content:
<?php
$schedule->exec('(cd /home/whoever/yoursite.com/blog && ./hugo)')->hourly();
Note that that assumes the Hugo binary is present there and that the output files
are linked from the public directory as described above.
Now the static content is kept up-to-date at all times. If your Laravel
application or scheduler goes down, you will at least have the most recently
generated static content being served, so the whole site won’t be down.
Laravel + Hugo data files is fun
One final thing that is quite useful is combining this with Hugo’s data
templates.
Hugo can read from JSON or CSV files while it is generating the site, and it’s
easy to have Laravel write these files in a scheduled command using your site’s
dynamic data.
For example, Pop Robin Cards has product catalogue data from Laravel written
into JSON files for Hugo to use when generating the static content. Because both
get refreshed regularly, this stays up to date but keeps the benefits of
managing static content.
View post:
Setting up a Hugo static site inside Laravel on Forge
|