Skip to content

Commit

Permalink
refactor: route id
Browse files Browse the repository at this point in the history
  • Loading branch information
luhc228 committed Apr 23, 2023
1 parent 2cd568d commit fb07169
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 176 deletions.
3 changes: 0 additions & 3 deletions examples/with-nested-routes/src/pages/about/#a.tsx

This file was deleted.

4 changes: 2 additions & 2 deletions packages/ice/src/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default {

export function getRoutesDefinition(nestRouteManifest: NestedRouteManifest[], lazy = false, depth = 0) {
const routeImports: string[] = [];
const routeDefinition = nestRouteManifest.reduce((prev, route, currentIndex) => {
const routeDefinition = nestRouteManifest.reduce((prev, route) => {
const { children, path: routePath, index, componentName, file, id, layout, exports } = route;

const componentPath = id.startsWith('__') ? file : `@/pages/${file}`.replace(new RegExp(`${path.extname(file)}$`), '');
Expand All @@ -66,7 +66,7 @@ export function getRoutesDefinition(nestRouteManifest: NestedRouteManifest[], la
if (lazy) {
loadStatement = `import(/* webpackChunkName: "p_${componentName}" */ '${formatPath(componentPath)}')`;
} else {
const routeSpecifier = `route_${depth}_${currentIndex}`;
const routeSpecifier = id.replace(/[./-]/g, '_').replace(/[:*]/, '$');
routeImports.push(`import * as ${routeSpecifier} from '${formatPath(componentPath)}';`);
loadStatement = routeSpecifier;
}
Expand Down
7 changes: 2 additions & 5 deletions packages/plugin-i18n/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ const plugin: Plugin<I18nConfig> = (i18nConfig) => ({
const defineRoutes: Parameters<typeof addRoutesDefinition>[0] = (defineRoute, options) => {
function defineChildrenRoutes(children: any[], prefixedLocale: string) {
children.forEach(child => {
const newChildRouteId = `${prefixedLocale}/${child.id}`;
defineRoute(
child.path,
child.file,
{ index: child.index, id: newChildRouteId },
{ index: child.index },
() => {
if (child.children) {
defineChildrenRoutes(child.children, prefixedLocale);
Expand All @@ -37,9 +36,7 @@ const plugin: Plugin<I18nConfig> = (i18nConfig) => ({
prefixedLocales.forEach(prefixedLocale => {
options.nestedRouteManifest.forEach(route => {
const newRoutePath = `${prefixedLocale}${route.path ? `/${route.path}` : ''}`;
const newRouteId = `${prefixedLocale}/${route.id}`;

defineRoute(newRoutePath, route.file, { index: route.index, id: newRouteId }, () => {
defineRoute(newRoutePath, route.file, { index: route.index }, () => {
route.children && defineChildrenRoutes(route.children, prefixedLocale);
});
});
Expand Down
64 changes: 29 additions & 35 deletions packages/route-manifest/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
import fs from 'fs';
import path from 'path';
import minimatch from 'minimatch';
import { createComponentName, createRouteId, defineRoutes, normalizeSlashes } from './routes.js';
import {
createComponentName,
removeLastLayoutStrFromId,
createRouteId,
defineRoutes,
normalizeSlashes,
createFileId,
} from './routes.js';
import type {
RouteManifest,
DefineRouteFunction,
Expand Down Expand Up @@ -109,7 +116,7 @@ export function generateRouteManifest(
export function parseRoute(routeItem: RouteItem, parentId?: string, parentPath?: string) {
const routes = [];
const { path: routePath, component, children } = routeItem;
const id = createRouteId(component);
const id = createRouteId(component, routePath, parentPath);
let index;
const currentPath = path.join(parentPath || '/', routePath).split(path.sep).join('/');
const isRootPath = currentPath === '/';
Expand All @@ -124,7 +131,7 @@ export function parseRoute(routeItem: RouteItem, parentId?: string, parentPath?:
id,
parentId,
file: component,
componentName: createComponentName(id),
componentName: createComponentName(component),
layout: !!children,
};
routes.push(route);
Expand Down Expand Up @@ -167,14 +174,14 @@ function defineConventionalRoutes(
}

if (isRouteModuleFile(file)) {
let routeId = createRouteId(file);
files[routeId] = file;
let fileId = createFileId(file);
files[fileId] = file;
return;
}
},
);

const routeIds = Object.keys(files).sort(byLongestFirst);
const fileIds = Object.keys(files).sort(byLongestFirst);

const uniqueRoutes = new Map<string, string>();

Expand All @@ -184,24 +191,24 @@ function defineConventionalRoutes(
options: DefineRoutesOptions,
parentId?: string,
): void {
const childRouteIds = routeIds.filter((id) => {
const parentRouteId = findParentRouteId(routeIds, id);
return parentRouteId === parentId;
const childFileIds = fileIds.filter((id) => {
const parentFileId = findParentFileId(fileIds, id);
return parentFileId === parentId;
});

for (let routeId of childRouteIds) {
for (let fileId of childFileIds) {
const parentRoutePath = removeLastLayoutStrFromId(parentId) || '';
const routePath: string | undefined = createRoutePath(
// parentRoutePath = 'home', routeId = 'home/me', the new routeId is 'me'
// in order to escape the child route path is absolute path
routeId.slice(parentRoutePath.length + (parentRoutePath ? 1 : 0)),
fileId.slice(parentRoutePath.length + (parentRoutePath ? 1 : 0)),
);
const routeFilePath = normalizeSlashes(path.join('src', 'pages', files[routeId]));
const routeFilePath = normalizeSlashes(path.join('src', 'pages', files[fileId]));
if (RegExp(`[^${validRouteChar.join('')}]+`).test(routePath)) {
throw new Error(`invalid character in '${routeFilePath}'. Only support char: ${validRouteChar.join(', ')}`);
}
const isIndexRoute = routeId === 'index' || routeId.endsWith('/index');
const fullPath = createRoutePath(routeId);
const isIndexRoute = fileId === 'index' || fileId.endsWith('/index');
const fullPath = createRoutePath(fileId);
const uniqueRouteId = (fullPath || '') + (isIndexRoute ? '?index' : '');

if (uniqueRouteId) {
Expand All @@ -211,27 +218,27 @@ function defineConventionalRoutes(
conflicts with route ${JSON.stringify(uniqueRoutes.get(uniqueRouteId))}`,
);
} else {
uniqueRoutes.set(uniqueRouteId, routeId);
uniqueRoutes.set(uniqueRouteId, fileId);
}
}

if (isIndexRoute) {
let invalidChildRoutes = routeIds.filter(
(id) => findParentRouteId(routeIds, id) === routeId,
let invalidChildRoutes = fileIds.filter(
(id) => findParentFileId(fileIds, id) === fileId,
);

if (invalidChildRoutes.length > 0) {
throw new Error(
`Child routes are not allowed in index routes. Please remove child routes of ${routeId}`,
`Child routes are not allowed in index routes. Please remove child routes of ${fileId}`,
);
}

defineRoute(routePath, files[routeId], {
defineRoute(routePath, files[fileId], {
index: true,
});
} else {
defineRoute(routePath, files[routeId], () => {
defineNestedRoutes(defineRoute, options, routeId);
defineRoute(routePath, files[fileId], () => {
defineNestedRoutes(defineRoute, options, fileId);
});
}
}
Expand Down Expand Up @@ -309,7 +316,7 @@ export function createRoutePath(routeId: string): string | undefined {
return result || undefined;
}

function findParentRouteId(
function findParentFileId(
routeIds: string[],
childRouteId: string,
): string | undefined {
Expand Down Expand Up @@ -340,16 +347,3 @@ function visitFiles(
}
}
}

/**
* remove `/layout` str if the routeId has it
*
* 'layout' -> ''
* 'About/layout' -> 'About'
* 'About/layout/index' -> 'About/layout/index'
*/
function removeLastLayoutStrFromId(id?: string) {
const layoutStrs = ['/layout', 'layout'];
const currentLayoutStr = layoutStrs.find(layoutStr => id?.endsWith(layoutStr));
return currentLayoutStr ? id.slice(0, id.length - currentLayoutStr.length) : id;
}
55 changes: 41 additions & 14 deletions packages/route-manifest/src/routes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// based on https://github.com/remix-run/remix/blob/main/packages/remix-dev/config/routes.ts

import { win32 } from 'path';
import { win32, join } from 'path';

export interface ConfigRoute {
/**
Expand Down Expand Up @@ -44,10 +44,6 @@ export interface DefineRouteOptions {
* Should be `true` if this is an index route that does not allow child routes.
*/
index?: boolean;
/**
* Support custom route id.
*/
id?: string;
}

interface DefineRouteChildren {
Expand Down Expand Up @@ -123,18 +119,23 @@ export function defineRoutes(
// route(path, file, options)
options = optionsOrChildren || {};
}
const parentRoute = parentRoutes.length > 0
? parentRoutes[parentRoutes.length - 1]
: undefined;

const id = join(
parentRoute?.path || '',
path || (options.index ? '/' : ''),
stripFileExtension(file).endsWith('layout') ? 'layout' : '',
);

const id = options.id || createRouteId(file);
const route: ConfigRoute = {
path,
index: options.index ? true : undefined,
id,
parentId:
parentRoutes.length > 0
? parentRoutes[parentRoutes.length - 1].id
: undefined,
parentId: parentRoute ? parentRoute.id : undefined,
file,
componentName: createComponentName(id),
componentName: createComponentName(file),
layout: id.endsWith('layout'),
};

Expand All @@ -154,7 +155,20 @@ export function defineRoutes(
return routes;
}

export function createRouteId(file: string) {
export function createRouteId(
file: string,
path?: string,
parentPath?: string,
index?: boolean,
) {
return normalizeSlashes(join(
parentPath || '',
path || (index ? '/' : ''),
stripFileExtension(file).endsWith('layout') ? 'layout' : '',
));
}

export function createFileId(file: string) {
return normalizeSlashes(stripFileExtension(file));
}

Expand All @@ -166,8 +180,21 @@ function stripFileExtension(file: string) {
return file.replace(/\.[a-z0-9]+$/i, '');
}

export function createComponentName(id: string) {
return id.split('/')
export function createComponentName(file: string) {
return createFileId(file).split('/')
.map((item: string) => item.toLowerCase())
.join('-');
}

/**
* remove `/layout` str if the routeId has it
*
* 'layout' -> ''
* 'About/layout' -> 'About'
* 'About/layout/index' -> 'About/layout/index'
*/
export function removeLastLayoutStrFromId(id?: string) {
const layoutStrs = ['/layout', 'layout'];
const currentLayoutStr = layoutStrs.find(layoutStr => id?.endsWith(layoutStr));
return currentLayoutStr ? id.slice(0, id.length - currentLayoutStr.length) : id;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ exports[`generateRouteManifest function > layout-routes 1`] = `
{
"componentName": "blog-index",
"file": "blog/index.tsx",
"id": "blog/index",
"id": "blog",
"index": true,
"layout": false,
"parentId": undefined,
Expand All @@ -14,7 +14,7 @@ exports[`generateRouteManifest function > layout-routes 1`] = `
{
"componentName": "blog-$id",
"file": "blog/$id.tsx",
"id": "blog/$id",
"id": "blog/:id",
"index": undefined,
"layout": false,
"parentId": undefined,
Expand All @@ -32,7 +32,7 @@ exports[`generateRouteManifest function > layout-routes 1`] = `
{
"componentName": "index",
"file": "index.tsx",
"id": "index",
"id": "/",
"index": true,
"layout": false,
"parentId": undefined,
Expand Down
Loading

0 comments on commit fb07169

Please sign in to comment.