pathpida
pathpida copied to clipboard
Provide `asPath`
We need your voice. Please check https://github.com/aspida/pathpida/issues/117#issuecomment-1089730653 and vote your opinion.
Continuation of https://github.com/aspida/pathpida/issues/94
TODO
- [x] check Next.js implementation
- https://github.com/vercel/next.js/blob/175e081e862b503d2daf4c2d07d589f86d037f06/packages/next/shared/lib/router/utils/format-url.ts#L29 (EDIT: not related)
- [x] Must it only be implemented for next.js?
- maybe ok
I'm also interested by having the asPath
returned by the $url()
functions.
In addition, I think it could be handy to directly have an $asPath
property returning the actual pathname.
For example:
pagesPath.post._pid(1).$asPath // returns "/post/1"
memo
Next.js uses window.location
for asPath:
- https://github.com/vercel/next.js/blob/canary/packages/next/client/index.tsx#L203
- https://github.com/vercel/next.js/blob/canary/packages/next/shared/lib/utils.ts#L285-L294
We should parse and replace by hand.
- URL path params are parsed here https://github.com/vercel/next.js/blob/canary/packages/next/shared/lib/router/utils/sorted-routes.ts
- https://github.com/vercel/next.js/blob/canary/packages/next/shared/lib/router/utils/route-regex.ts
const { isDynamicRoute } = require('next/dist/shared/lib/router/utils/is-dynamic')
const { searchParamsToUrlQuery } = require('next/dist/shared/lib/router/utils/querystring')
const { formatUrl } = require('next/dist/shared/lib/router/utils/format-url')
const { interpolateAs } = require('next/dist/shared/lib/router/router.js')
function omitParmsFromQuery(query, params) {
const filteredQuery = {}
Object.keys(query).forEach(key => {
if (!params.includes(key)) {
filteredQuery[key] = query[key]
}
})
return filteredQuery
}
const objToAsPath = finalUrl => {
let interpolatedAs = ''
if (isDynamicRoute(finalUrl.pathname) && finalUrl.searchParams) {
const query = searchParamsToUrlQuery(finalUrl.searchParams)
const { result, params } = interpolateAs(finalUrl.pathname, finalUrl.pathname, query)
if (result) {
interpolatedAs = formatUrl({
pathname: result,
hash: finalUrl.hash,
query: omitParmsFromQuery(query, params)
})
}
}
return interpolatedAs
}
console.log(
objToAsPath({
pathname: '/abc/[id]',
searchParams: new URLSearchParams({
id: 'hello'
})
})
)
This worked! Thanks @IshinoJun
Another idea.
const str = '/[name]/[id]/bar/[[foo...]]'
const f = str
.replace(/\/\[\[/g, '/${')
.replace(/\/\.\.\.\]\]/g, '/}')
.replace(/\/\]\]/g, '/}')
.replace(/\/\[/g, '/${')
.replace(/\.\.\.\]\](\/|$)/g, '}$1')
.replace(/\.\.\.\](\/|$)/g, '}$1')
.replace(/\](\/|$)/g, '}$1')
console.log(`\`${f}\``)
Please read, we need your vote.
We're implemented solution for this as https://github.com/aspida/pathpida/pull/124, but this has disadvantage that this includes approx 40KB bundled parts.
Current $path.ts
takes approx 0.3KB per route, so this change looks huge.
Do you want this even though? YES: 👍 , NO: 👎 Or unacceptable until implementing smaller transformation? YES: 😕
Could you detail a bit the reasons for this size increase please?
@ValentinH It bundles some of next.js utility functions. It is treeshaked but maybe it includes much more than what really needed.
As an other option, we're planning to add option to disable asPath
after that PR.
If this is coming from Next then it should really increase the final size if we are already using Next.js. Or it's more complex than that?
Here is an example implementation on the application side. (Next.js)
import { resolveHref } from 'next/dist/shared/lib/router/router';
import Router from 'next/router';
const asPath = resolveHref(Router, $pagesPath.user.articles.$url(), true)[1]
@ValentinH
If this is coming from Next then it should really increase the final size if we are already using Next.js. Or it's more complex than that?
Next.js has server runtime and client side runtime. Path management is included in server part, so calculating asPath of other pages may result as increasing total size of bundle. Originally, because asPath is calculated by browser's location.href
, it is not so costed much. We can't use location.href
of another page, which means we should calculate the value of this in user land for pathpida.
I am finding this, please add it :D