pathpida icon indicating copy to clipboard operation
pathpida copied to clipboard

Provide `asPath`

Open LumaKernel opened this issue 3 years ago • 11 comments

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

LumaKernel avatar Feb 28 '22 09:02 LumaKernel

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"

ValentinH avatar Mar 08 '22 09:03 ValentinH

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

LumaKernel avatar Mar 10 '22 05:03 LumaKernel

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

LumaKernel avatar Mar 14 '22 05:03 LumaKernel

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}\``)

LumaKernel avatar Mar 14 '22 06:03 LumaKernel

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: 😕

LumaKernel avatar Apr 06 '22 03:04 LumaKernel

Could you detail a bit the reasons for this size increase please?

ValentinH avatar Apr 07 '22 21:04 ValentinH

@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.

LumaKernel avatar Apr 12 '22 10:04 LumaKernel

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?

ValentinH avatar Apr 12 '22 11:04 ValentinH

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]

IshinoJun avatar Apr 18 '22 13:04 IshinoJun

@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.

LumaKernel avatar May 10 '22 09:05 LumaKernel

I am finding this, please add it :D

IRediTOTO avatar Aug 31 '22 21:08 IRediTOTO