-
-
Notifications
You must be signed in to change notification settings - Fork 5k
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
feat(builder, router): enforce uniform trailing slash handling #6331
Conversation
Codecov Report
@@ Coverage Diff @@
## dev #6331 +/- ##
========================================
+ Coverage 95.7% 95.7% +<.01%
========================================
Files 79 79
Lines 2652 2656 +4
Branches 683 685 +2
========================================
+ Hits 2538 2542 +4
Misses 98 98
Partials 16 16
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea.
Nice timing, have been struggling with trailing slashes in nuxt/press a bit the last weeks! I'd recommend to include a util method so users can easliy normalize paths they use in their project as well, see eg here for the methods currently used in nuxt/press (but they could be improved on probably). |
Good call! |
What would be the use case when all (named) routes or those resolved programmatically will go in line with the config and fixed routes would be easy to change by appending/removing the |
@atinux Isnt that technically more a workaround then a fix? Due to the nature of a SPA the path resolve behaviour is just different then serving static files with a webserver (ie apache/nginx). How close do we want to stay to that 'original' behaviour? @manniL If your router config lists all routes with a trailing slash, then your nuxt/router-links should point to a link with a trailing slash as well right? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice improvement 👍
packages/utils/src/route.js
Outdated
route.path = route.path.endsWith('/') ? route.path : `${route.path}/` | ||
} | ||
|
||
if (trailingSlashes === false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can make at an else if
? This would save branch check-in cases that trailingSlashes
is true + makes it more readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about ?
if(trailingSlashes !== undefined) {
const trailing = trailingSlashes ? '/' : ''
route.path = route.path.replace(/\/+$/, '') + trailing
}
@@ -136,7 +136,8 @@ export const createRoutes = function createRoutes ({ | |||
srcDir, | |||
pagesDir = '', | |||
routeNameSplitter = '-', | |||
supportedExtensions = ['vue', 'js'] | |||
supportedExtensions = ['vue', 'js'], | |||
trailingSlashes = undefined | |||
}) { | |||
const routes = [] | |||
files.forEach((file) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Not related to this PR) what do you think of refactoring forEach
to ES6 for of
? OR using files.map
to directly assign the result of routes
instead of pushing to the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plus one for using map
instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's do this later and not blocking this PR :)
packages/utils/src/route.js
Outdated
route.path = route.path.endsWith('/') ? route.path : `${route.path}/` | ||
} | ||
|
||
if (trailingSlashes === false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about ?
if(trailingSlashes !== undefined) {
const trailing = trailingSlashes ? '/' : ''
route.path = route.path.replace(/\/+$/, '') + trailing
}
Correct. If you use fixed URLs as in |
Thanks, this is why I recommend a normalization utility. Maybe even within nuxt-link itself, but should also be accessible outside for easy use in eg the sitemap-module. If we support this feature switching between having a trailing slash or not should be as effortless as possible, preferable even with just toggling the setting if you use the normalization utility everywhere. |
Now I got it, that'd be a nice DX improvement and also guarantee that all modules implement the same normalization. A utility directly included in the |
TODO for myself: add multi scope handling for release-notes generator! |
Types of changes
Description
Trailing slash handling is important when it comes to SEO. For every existing Nuxt application, the content provided by /route and /route/ should be the same (opposed to how it sometimes worked back in the days). But when it comes to how the search engine sees our page, we have to be consistent and choose one of the options, either with or without a trailing slash.
With the current setup, it is not entirely possible to enforce trailing slashes (or the removal of them) without substantial effort.
As long as you have simple and fixed URLs, you can always append the slash (or not), but when it comes to resolved named routes (e.g. when using https://github.com/nuxt-community/nuxt-i18n/ ), things become difficult and hard to manage.
Thus, this PR
It introduces a new router option called
trailingSlashes
set toundefined
by default. If it's set totrue
, trailing slashes will be appended on every route. If set tofalse
, they'll be removed.Therefore, we use the
pathToRegexpOptions
settings (per route) provided via vue-router (see vuejs/vue-router#1753 and vuejs/vue-router#1443)This option should not be taken lightly and has to be tested thoroughly. When setting
router.trailingSlashes
to something else than undefined, one of the options (either with or w/o trailing slash) will stop working. 301 redirects should be in place before.Related work:
#3448
#5746
TODO
Checklist: