My jekyll blog template have links to resources and pages like so:
{{ site.url }}/my-page.html
This works well in deployment, but when I run jekyll serve in development, all of the links point to the live page instead of the development page.
my-site-url/my-page.html
# But I want this in development
localhost:4000/my-page.html
Is there a way to make jekyll use a different {{ site.url }} in development?
This is a common problem between different Jekyll environments.
Some explanations
We need to understand site.url and site.baseurl and in which situation we need them.
Those variables don't serve the same purpose.
site.url
By default, this variable is only used in page head for the canonical header and the RSS link. It's also used in the xml feed to point to site resources as the software that will manage this feed doesn't know resource's urls.
This variable is only necessary for external systems.
site.baseurl
This variable indicates the root folder of your Jekyll site. By default it is set to "" (empty string). That means that your Jekyll site is at the root of http://example.com.
If your Jekyll site lives in http://example.com/blog, you have to set site.baseurl to /blog (note the slash). This will allow assets (css, js) to load correctly.
See how assets are loaded in you head :
<link rel="stylesheet" href="{{ "/css/main.css" | prepend: site.baseurl }}">
that can also be :
<link rel="stylesheet" href="{{ site.baseurl }}/css/main.css">
Working in different environments
Now you have to test your site locally and to deploy it in production. Sometimes, the baseurl is different and the jekyll build may not work out of the box in one of those environment.
Here we have two solutions :
Use jekyll serve
Let's imagine that your site lives in a github repository and is served at https://username.github.io/myProject.
You can setup the baseurl to /myProject. and test your site locally with jekyll serve, your site will be served at http://127.0.0.1:4000/myProject/
Use multiple configuration files
If, for one reason or another, you cannot use jekyll serve, you can set a configuration file for both environment and jekyll build depending on where you are deploying.
Let's say we have the local site served at http://localhost and the production site served at https://username.github.io/myProject.
We leave the _config.yml with url: https://username.github.io and baseurl: /myProject
We create a new _config_dev.yml with only url: https://localhost and baseurl: ""
Now to test locally :
jekyll build --config _config.yml,_config_dev.yml
or
jekyll build --config _config.yml,_config_dev.yml --watch
When pushed on production, the jekyll build command will use the default _config.yml.
The question and the good answer is a bit old, but I think still from need.
I also run in that issue on jekyll v4.2. I have three differnt environments, with differnt url and baseurl in my config-files (see answer from #david-jacquel) can be combined.
Production
Dev
GitLab Page
url
https://company.tld
http://localhost:8017
https://n13org.gitlab.io
baseurl
/
/
/demo/company-tld
config
_config.yml
_config.dev.yml
_config.gitlab.yml
I was not happy with the handling / behavior of url and baseurl together with CSS / JS / images / internal links to posts and pages ... I tried many ways also in combination with the relative_url filter.
I end up, with writting a small ruby plugin for jekyll. The plugin is just ruby code inside the _plugins folder.
The plugin code from file tag_website_url.rb will create a new jekyll tag which can be used in html or markdown (md) files with {% website_url %} or {% website_url noprotocol %}. The second tag will omit the protocol (e.g. http or https).
require 'uri'
module Jekyll
class WebsiteUrlTag < Liquid::Tag
def initialize(tag_name, text, tokens)
super
#text = text.strip
tokens = tokens
end
def render(context)
site = context.registers[:site]
uri = URI.parse("#{site.config["url"]}#{site.config["baseurl"]}")
str_uri_port = uri.port && uri.port != 80 && uri.port != 443 ? ":" + uri.port.to_s : ""
websiteurl = uri.host + str_uri_port + uri.path
websiteurl.prepend(uri.scheme + '://') if #text != "noprotocol"
websiteurl.sub(/(\/)+$/,'')
end
end
end
Liquid::Template.register_tag('website_url', Jekyll::WebsiteUrlTag)
The code can handle also PORTS which are often used for localhost development. The ports 80 (http) and 443 (https) will be removed. The settings from the config files are stored inside the variables site.config
Related
In my Rails (Rails 7) app, I have some small assets (a logo and a favicon), which I want to render in production as well as in development.
I put the assets in /app/assets/images.
Since setting # config.assets.compile = true is not recommended, i run RAILS_ENV=production bundle exec rake assets:precompile. It then builds a whole lot of files (it runs esbuild app/javascript/application.tsx since I have a typescript react app running in this rails app.) and puts them in /public/assets/. But this folder is .gitignored by default. Since the folder is approx 5.5 Mb I can see why. Now, heroku docs tell me to add /public/assets/ to git and then my assets should show, but why then is this directory gitignored by default?
Am I missing something? Should I just remove the dir from my .gitignore file?
Or could I just put the assets in the public folder directly? If so, how do I add an image referencing the public folder in an erb file?
The home for static assets is the /public folder. In a default Rails 7 app you will find some error pages (e.g. /public/404.html) and icons (e.g. /public/favicon.ico) already in that folder. Files in this folder will be available both directly, example.com/favicon.ico, and under the public path, example.com/public/favicon.ico. Serving public files can be disabled, see below.
To answer your sub-question, "how do I add an image referencing the public folder in an erb file?" you need to make sure you tell Rails it's an absolute path, not a relative one somewhere in the asset pipeline. This is done with a leading forward slash.
The following compares including a logo called logo.png when it's stored in app/assets/images vs /public
<%= image_tag "logo.png" %>
<!-- becomes <img src="/assets/logo-1f04fdc3ec379029cee88d56e008774df299be776f88e7a9fe5.png"> or similar -->
<%= image_tag "/logo.png" %>
<!-- note the leading slash. This becomes <img src="/logo.png"> -->
<img src="/logo.png">
<!-- or use plain HTML if you don't need/want to use the helper -->
You can also use sub-directories; /public/images/logo.png would be available at /images/logo.png (or image_tag "/images/logo.png").
The second paragraph of chapter 2 of The Asset Pipeline Rails Guide contians more information. It mentions that this functionality depends on whether config.public_file_server.enabled is set.
In Rails 7 that config defaults to ENV["RAILS_SERVE_STATIC_FILES"].present? in config/production.rb. If you're using Heroku you can check this variable with heroku config:get RAILS_SERVE_STATIC_FILES.
The guide also has more information on how to adjust all this behaviour to have these files served by your upstream web server (e.g. nginx) or from a CDN.
Thanks for the comments, I went with adding the assets to the public folder directly and this works fine. It would be nice though if Heroku would either support a way to generate the assets after deployment by default, or describe an option to do it like I did in their docs.
I'm have following (abstract) project structure:
src/brands
src/admin
src/home
Brands & admin are a pure vue project, home is a nuxt project. I'm trying to get the brands & admin project to run on their own subdomain (brands.website.com & admin.website.com, respectively), and home on the main domain. The deploy to production/staging happens via docker (with an nginx image), and I was thinking to just copy a nginx config file from my project to the docker image to point the files in the dist folder to the correct html file (not sure how yet, I need to research that first).
For development, I used vue.config.js (since I'm using v3 of the vue cli) and I have setup the following:
index: {
entry: 'src/index/main.js',
filename: 'index.html',
},
brands: {
entry: 'src/brands/main.js',
filename: 'brands/index.html',
},
admin: {
entry: 'src/admin/main.js',
filename: 'admin/index.html',
},
I can reach the brands module via localhost:8080/brands, admin module via localhost:8080/admin and the homepage via localhost:8080, but the problem is that on my index page I'm gonna have a route that is /brands, so that would probably overwrite the brands module route with the page from nuxt (or vice versa). Now is my question if there is a better way of doing this (for example to enable subdomains in vue / localhost) and if not, is the way I'm wanting to copy the nginx config to my docker image a good practice? Or not?
Thanks in advance!
I have a similar project architecture. I have a single repo with multiple vue/nuxt projects. Each of my projects is its own npm/webpack project and is accessed by subdomain when developing locally.
Based on your example, this is how I would setup the projects.
Modify your hosts file:
127.0.0.1 website.localhost brands.website.localhost admin.website.localhost
Using localhost as the TLD was my personal decision, feel free to name the domains anyway you like.
Configure webpack dev server to serve each project at the corresponding subdomain + port.
src/brands: https://brands.website.localhost:8080
src/admin: https://admin.website.localhost:8081
src/home: https://website.localhost:8082
Whats nice about this configuration is that your dev URLs match your production URLs. https://brands.website.localhost:8080 -> https://brands.website.com
Each project will have complete control over the domain's subpaths and won't clobber other project's routes, which you alluded to with the /brands route.
prentend that I have a file in .../web/main.dart and when I'm serving the app ( webdev serve web:8080) it will be located in localhost:8080/main.dart.js and the packages in localhost:8080/packages/ is there anyway to move them to localhost:8080/foo/main.dart and localhost/foo/packages/ ?
Basically add /foo/ to all dartdevc generated dictories.
No, that is not supported by the default dev server (and is unlikely ever to be).
The typical way to do this would be to set up a separate server, which delegates all things under the /foo route to the dev server, and strips out /foo from the path.
I have a website that I am developing locally and pushing to RH Openshift with a PHP-5.4 and MySQL cartridge.
Most URL's work, but I am having an issue with some page URL's being recognised locally, but returning a 404 on Openshift.
Example: on development the following URL works: local.development.local/public/reset.php but visiting the Openshift url: example.rhcloud.com/public/reset.php returns a 404. However, example.rhcloud.com/reset.php works, even though reset.php is within the public folder directory.
The folder structure is the exact same on development as it is within Openshift repo folder.
Is there a specific setting I need to set in my Openshift environment to get it to recognize the URL?
The problem was due to the directory structure I had given my website. Since I had placed the majority of my code within a folder named public, Openshift was using that as the DocumentRoot. This wasn't my required functionality, so I renamed the folder to app, updated my URL's and this resolved the issue. Blog post giving the Openshift DocumentRoot logic can be found here: https://blog.openshift.com/openshift-online-march-2014-release-blog/
I want to force my URL to start with www. when it's not present.
I tried the match method, but it seems to ignore the start of the URL, it seems to do something called Route Globbing, that appearently just works with route segments http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments
How do I make my application in RoR always start with www. ?
-> www.foo.com must remain as it is
-> foo.com must be redirected to www.foo.com
It's better to do it in nginx or apache (depends on what you're using). Please see these topics:
For nginx
Nginx no-www to www and www to no-www
For Apache
apache redirect from non www to www
You might consider a rack middleware like rack-www or rack-rewrite. Setup of rack-www is only two steps:
# Add to Gemfile (and run `bundler`)
gem 'rack-www'
# configure middleware via `application.rb` (for all environments)
# or the environment specific configuration file
# `environments/<environment>.rb`
config.middleware.use Rack::WWW, :www => true