[SEO] - Add trailing slash to generated href's that have a query string
guerital opened this issue · comments
Italo Guerrieri commented
🧩 Feature request
Description
When a tag is using the [queryParams] attribute, the generated URL doesn't have the trailing slash at the end:
<a [routerLink]="['/page']" [queryParams]="{ index: 0 }"></a>
.../page?index=0
instead of
.../page/?index=0
The missing trailing slash led to a 301 redirect which is not very good for the SEO
Describe the solution you'd like
I have overridden the seoHrefOptimise plugin:
import { JSDOM } from 'jsdom';
import { HandledRoute } from "@scullyio/scully";
const { registerPlugin, logWarn, yellow, getHandledRoutes } = require('@scullyio/scully');
export const impulsoSeoHref = 'impulsoSeoHrefOptimise';
const impulsoSeoHrefOptimise = async (dom: JSDOM, route: HandledRoute): Promise<JSDOM> => {
try {
const routes = await getHandledRoutes();
const { window } = dom;
const anchors = window.document.querySelectorAll<HTMLAnchorElement>('a[href]');
anchors.forEach((a) => {
const href = a.getAttribute('href');
const isExternal = routes.find((r) => r.route === basePathOnly(href)) === undefined;
/** Add noopener and noreferrer to _blank links */
if ((href && a.getAttribute('target') === '_blank') || isExternal) {
/** get the attribute add the options and filter out duplicates */
if ((!href.includes('?') && !href.includes('#') && href.startsWith('//')) || href.startsWith('http')) {
/** only upgrade links that are not startting with '/' */
const rel = ((a.getAttribute('rel') || '') + ' noreferrer noopener')
.trim()
.split(' ')
.filter((v, i, a) => a.indexOf(v) === i)
.join(' ');
a.setAttribute('rel', rel);
}
}
if (!isExternal && !href.endsWith('/') && !href.includes('#')) {
/** don't handle routes that are not inside our app. */
const splittedHref = href.split('?');
if (splittedHref.length == 1) {
a.setAttribute('href', href + '/');
} else {
a.setAttribute('href', splittedHref[0] + '/?' + splittedHref[1])
}
}
/** add the trailing slash */
});
} catch (e) {
console.log(e);
logWarn(`Error in the seoHrefOptimise plugin, didn't update href's for route: "${yellow(route.route)}"`);
}
return dom;
};
registerPlugin('postProcessByDom', impulsoSeoHref, impulsoSeoHrefOptimise);
/** copied from ng-lib */
function basePathOnly(str: string): string {
if (str.includes('#')) {
str = str.split('#')[0];
}
if (str.includes('?')) {
str = str.split('?')[0];
}
const cleanedUpVersion = str.endsWith('/') ? str.slice(0, -1) : str;
return cleanedUpVersion === '' ? '/' : cleanedUpVersion;
}
It would be nice to have a flag to switch from my version to the original one