Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Easier global Support for urls without trailing slashes #213

Closed
edwardhorsford opened this issue Sep 8, 2018 · 18 comments
Closed

Easier global Support for urls without trailing slashes #213

edwardhorsford opened this issue Sep 8, 2018 · 18 comments
Assignees
Labels
enhancement needs-votes A feature request on the backlog that needs upvotes or downvotes. Remove this label when resolved.

Comments

@edwardhorsford
Copy link
Contributor

Is it possible for Eleventy to support sites without trailing slashes? At the moment it looks like it adds them / redirects to the url version with the slash.

My existing site does not use them. Since Eleventy redirects foo to foo/, urls will all still work, but I have a slight preference for the former.

I know some static site generators support this, though not all.

@kleinfreund
Copy link
Contributor

kleinfreund commented Sep 8, 2018

It’s a matter of constructing your links across your page to not include a trailing slash. Eleventy (or any other static site generator for that matter) does not redirect anything on its own, it just helps generating a file structure of documents and resources. That redirecting bit is done by your web server. Checking out my site, I see that my web server seems to opt for a trailing slash at the end even if the requested URL doesn’t contain one. I suppose that could be configured to not display a trailing slash for such requests.

(A little bit more details. Not sure if you know this, but for the sake of documentation, I’ll leave it here.)

One thing that comes into play here is the way most static site generators construct permalinks: For a file slug amazing-permalink, they will often output a directory amazing-permalink and in it, an index.html file. Since most web servers are configured to open a default file like index.html when someone requests a URL to a directory, the address in the URL bar looks like it points to amazing-permalink/ which is the same as amazing-permalink/index.html. Without that little trick, the file would be located under amazing-permalink.html. Since that .html bit doesn’t make a URL for, let’s say a blog post, more useful, a lot of people prefer to don’t have it there; hence, they use that directory plus index.html trick.

@zachleat
Copy link
Member

zachleat commented Sep 8, 2018

Here’s what I found when doing a little more specific research on this:

Relative URLs

Slashes are better if you’re using relative URLs:
https://cdivilly.wordpress.com/2014/03/11/why-trailing-slashes-on-uris-are-important/

Avoid duplicate content

No matter which style you choose, you need to avoid duplicate content (SEO and Canonical URLs):
https://webmasters.googleblog.com/2010/04/to-slash-or-not-to-slash.html

This blog post doesn’t necessarily take a side, however it does espouse that servers should be configured so that a canonical version of the URL is specified and consistency is enforced throughout your site. So if you prefer slashless, this means server configuration to redirect from slash versions to slashless. Or if you prefer slashes, server configuration to redirect from slashless to use slashes.

This does suggest that Eleventy sites may need additional configuration (in our current slash setup) to 301 redirect to slash versions of urls if slashless are requested. For example if

https://example.com/my-post-title

should redirect to:
https://example.com/my-post-title/

While you can use <link rel="canonical" href="https://example.com/my-post-title/"/> to indicate the canonical URL to the search engine, you’d still need redirects for users visiting https://example.com/my-post-title in a web browser (if someone accidentally links to the URL without a slash).

However, that’d be an extra nicety that I’m comfortable not including in the core package. since we don’t redirect—there is no danger of duplicate content out of the box.

Server Configuration

Let’s go through the hypothetical of creating a slash-less resource in Eleventy. What might that look like? For example, you can do this in Eleventy today:

test.md:

---
permalink: /docs/test
---

If I run Eleventy, it generates a resource like this:
image

So it makes a resource at docs/test for this. If I’m using --serve and navigate to this resource url http://localhost:8080/docs/test, Chrome downloads the file. It doesn’t know what to do with it by default because it has no file extension on the file system.

image

It doesn’t have the right Content-type header:
image

Certainly you could setup your server to serve these resources as HTML content-types but that requires server specific configuration (maybe an .htaccess file or some other method of forcing content type for this specific resource).

The current behavior for a test.md without setting a permalink is that it would build to test/index.html in the output directory, with all URLs pointing to /test/. This gives us a “cleaner” URL because most web servers are configured by default to show index.html files when you navigate to a directory. We go into this a little on the permalink documentation: https://www.11ty.io/docs/permalinks/#cool-uris-don%E2%80%99t-change

What would happen if you’d used permalink: /docs/test and then wanted to add a new URL as a descendent of /docs/test?

test2.md:

---
permalink: /docs/test/hi
---

image

Because /docs/test already exists as a file, we can’t use /docs/test as a folder with /docs/test/hi.

So test/index.html gives you a nice middle ground of for-free features in more web servers without configuration. No file downloads, no file extensions on URLs, allows you to use the test/ folder for other resources moving forward.

Hope that helps explain it. I think slashless would create a lot more support tickets and maintenance issues than I’d like. I don’t see very many upsides to it other than cosmetic preferences but I see a lot of downsides.

Does that make sense to you?

@zachleat zachleat self-assigned this Sep 8, 2018
@zachleat
Copy link
Member

zachleat commented Sep 8, 2018

I thought this tweet was good for understanding some of the issue:
https://twitter.com/JohnMu/status/943076424130363392

I do want to weigh in and say that I’m not saying no to this. I’m fine putting it in the enhancement queue and letting people upvote on it as a non-default feature request. I think it’s a fairly common thing that exists in the wild.

I just noticed GitHub gets this wrong though

https://github.com/zachleat
https://github.com/zachleat/

…with no canonical HTML tag or 301 redirect. They both return 200’s. ¯_(ツ)_/¯

@edwardhorsford
Copy link
Contributor Author

Thanks for the detailed response.

It's not a major thing for me - very much a nice to have. Happy to see if others are interested in it.

@zachleat
Copy link
Member

zachleat commented Sep 8, 2018

I think the implementation would probably be closer to using docs/test.html and docs/test/hi.html output and then relying on server configuration to remove the extension. This would alleviate the file/folder conflict issue I mentioned above.

It's probably also worth noting that you can do this yourself today using directory data files to set a permalink for a group of templates in a single place. That might be worth documenting as an example somewhere.

@zachleat zachleat changed the title Support for urls without trailing slashes Easier global Support for urls without trailing slashes Sep 10, 2018
@zachleat
Copy link
Member

This repository is now using lodash style issue management for enhancements. This means enhancement issues will now be closed instead of leaving them open.

The enhancement backlog can be found here: https://github.com/11ty/eleventy/issues?utf8=%E2%9C%93&q=label%3Aneeds-votes+sort%3Areactions-%2B1-desc+

Don’t forget to upvote the top comment with 👍!

@zachleat zachleat added enhancement needs-votes A feature request on the backlog that needs upvotes or downvotes. Remove this label when resolved. and removed education labels Sep 10, 2018
@edwardhorsford
Copy link
Contributor Author

I've had another look at this - you're right it looks like we can rely on the server (eg Netlify) to sort this, and use permalinks. However it's hard to develop as the local server doesn't do this, so in local development my link to foo/bar doesn't work - I need to manually visit foo/bar.html.

@zachleat
Copy link
Member

Hey @edwardhorsford I opened #239 which I think would help with this—what do you think?

If you link to input files then you can avoid hardcoding URLs in your templates.

@edwardhorsford
Copy link
Contributor Author

I think it could work?

FWIW I think if I wanted to keep slashless, I could actually change my internal links to point to foo.html. From reading the Netlify docs it sounds like as well as serving foo.html from foo, they'll rewrite the original links too. I've not tried this though.

For now, I've just moved my site over to using trailing slashes.

@kleinfreund
Copy link
Contributor

What @edwardhorsford said. Users are already able to use or not use trailing slashes by making sure their paths (e.g. in href, etc.) use or don’t use them. If the server is not configured to handle that, we can’t do anything about that.

@matthewjumpsoffbuildings

i would like the option to ensure that page.url is without trailing slashes, instead of manually having to specify permalinks or hrefs for every page.

my servers (both local and live) are set up to not have trailing slashes, so currently its a bit of a pain having to manually set urls or run regex on them in my templates

@Ryuno-Ki
Copy link
Contributor

For what it's worth, the index.html is just a convention. In fact other file extensions are valid Webserver directory index also.

@matthewjumpsoffbuildings
Copy link

matthewjumpsoffbuildings commented Jun 15, 2019

@Ryuno-Ki im not sure how thats related? its not the use of /page-name/index.html directory structure thats the issue, its the fact that 11ty sets page.url to /page-name/ instead of /page-name, which isnt always desired

@Ryuno-Ki
Copy link
Contributor

Ah, my quote wasn't posted >_<

This gives us a “cleaner” URL because most web servers are configured by default to show index.html files when you navigate to a directory.

The „by default” is not strictly correct here.

@justinfagnani
Copy link
Contributor

I've been having a hard time with this issue in general. I'm porting an existing site, with an existing static server in production, that doesn't use trailing slashes. So any opinions on the best URL structure is irrelevant, because I'm only trying to replace Jekyll with Eleventy without other changes.

So far the problem is that I either have to choose a permalink without the .html extension, which causes problems for mimetypes, or I have to figure out how to get a extensionless version of the URL, which none of the properties on the page object seem to offer - they're either the "URL" (which in my case isn't the actual URL, but the URL + an extension), or based on the input path.

I think there should be some separation between the output path and the canonical URL for a file, since servers can handle these in a number of ways, ie /myFile.html, /myFile might be valid URLs for the output path /myFile.html.

@Ryuno-Ki
Copy link
Contributor

Hey @justinfagnani,
would #913 (comment) help you?

@justinfagnani
Copy link
Contributor

@Ryuno-Ki no. I'm not having a problem setting the permalink, I already set it globally. The problem is that permalink and page.url are the same - both have the file extension or not. So when I use page.url in collections I have to run it though a filter to remove the extension, and have to remember to do that any place I want to generate a link.

@Booligoosh
Copy link

If you're using Eleventy 2.x.x, you can create the file _data/eleventyComputed.js with this contents and it will remove trailing slashes:

module.exports = {
  // Remove trailing slashes
  permalink: (data) =>
    data.permalink
      ? data.permalink
      : data.page.outputFileExtension === "html" && data.page.filePathStem
      ? `${data.page.filePathStem}.html`
      : "",
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement needs-votes A feature request on the backlog that needs upvotes or downvotes. Remove this label when resolved.
Projects
None yet
Development

No branches or pull requests

7 participants