Skip to content

Commit

Permalink
feat: support remove router even if route count is greater than 1 (#6382
Browse files Browse the repository at this point in the history
)

* feat: support remove router even if route count is greater than 1

* fix: add test case

* Update createService.ts

* Update createService.ts
  • Loading branch information
ClarkXia authored Jul 18, 2023
1 parent 018238f commit b691b9e
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 18 deletions.
6 changes: 6 additions & 0 deletions .changeset/tidy-tomatoes-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@ice/runtime': patch
'@ice/app': patch
---

feat: support remove router even if route count is greater than 1
2 changes: 1 addition & 1 deletion examples/single-route/optimization.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import { defineConfig } from '@ice/app';
export default defineConfig(() => ({
publicPath: '/',
optimization: {
router: true,
disableRouter: true,
},
}));
7 changes: 7 additions & 0 deletions examples/single-route/src/pages/home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const home = () => {
return (
<>home</>
);
};

export default home;
5 changes: 3 additions & 2 deletions packages/ice/src/createService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,10 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt
const hasExportAppData = (await getFileExports({ rootDir, file: 'src/app' })).includes('dataLoader');
const csr = !userConfig.ssr && !userConfig.ssg;

const disableRouter = userConfig?.optimization?.router && routesInfo.routesCount <= 1;
const disableRouter = (userConfig?.optimization?.router && routesInfo.routesCount <= 1) ||
userConfig?.optimization?.disableRouter;
if (disableRouter) {
logger.info('`optimization.router` is enabled and only have one route, ice build will remove react-router and history which is unnecessary.');
logger.info('`optimization.router` is enabled, ice build will remove react-router and history which is unnecessary.');
taskConfigs = mergeTaskConfig(taskConfigs, {
alias: {
'@ice/runtime/router': '@ice/runtime/single-router',
Expand Down
8 changes: 7 additions & 1 deletion packages/ice/src/types/userConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ interface SyntaxFeatures {

interface Optimization {
/**
* Optimize code by remove react-router dependencies when set to true.
* Optimize code by remove react-router dependencies when set to true,
* it only works when route count is 1.
*/
router?: boolean;
/**
* @private
* Remove react-router dependencies by force, even if route count is greater than 1.
*/
disableRouter?: boolean;
}

interface MinifyOptions {
Expand Down
10 changes: 6 additions & 4 deletions packages/runtime/src/runClientApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ interface RenderOptions {

async function render({ history, runtime, needHydrate }: RenderOptions) {
const appContext = runtime.getAppContext();
const { appConfig, loaderData, routes, basename } = appContext;
const { appConfig, loaderData, routes, basename, routePath } = appContext;
const appRender = runtime.getRender();
const AppRuntimeProvider = runtime.composeAppProvider() || React.Fragment;
const AppRouter = runtime.getAppRouter<ClientAppRouterProps>();
Expand All @@ -154,8 +154,9 @@ async function render({ history, runtime, needHydrate }: RenderOptions) {
}
const hydrationData = needHydrate ? { loaderData } : undefined;
const routeModuleCache = {};
const location = history.location ? history.location : { pathname: routePath || window.location.pathname };
if (needHydrate) {
const lazyMatches = matchRoutes(routes, history.location, basename).filter((m) => m.route.lazy);
const lazyMatches = matchRoutes(routes, location, basename).filter((m) => m.route.lazy);
if (lazyMatches?.length > 0) {
// Load the lazy matches and update the routes before creating your router
// so we can hydrate the SSR-rendered content synchronously.
Expand All @@ -182,8 +183,9 @@ async function render({ history, runtime, needHydrate }: RenderOptions) {
let singleComponent = null;
let routeData = null;
if (process.env.ICE_CORE_ROUTER !== 'true') {
const { Component, loader } = await loadRouteModule(routes[0], routeModuleCache);
singleComponent = Component || routes[0].Component;
const singleRoute = matchRoutes(routes, location, basename)[0];
const { Component, loader } = await loadRouteModule(singleRoute.route, routeModuleCache);
singleComponent = Component || singleRoute.route.Component;
routeData = loader && await loader();
}
const renderRoot = appRender(
Expand Down
31 changes: 23 additions & 8 deletions packages/runtime/src/singleRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,30 @@ export const createHistory = (): History => {
};
};

export const matchRoutes = (routes: any[]) => {
return routes.map(item => {
return {
params: {},
pathname: '',
pathnameBase: '',
route: item,
};
const stripString = (str: string) => {
const regexForSlash = /^\/|\/$/g;
return str.replace(regexForSlash, '');
};

export const matchRoutes = (routes: any[], location: Partial<Location> | string, basename: string) => {
const stripedBasename = stripString(basename);
const pathname = typeof location === 'string' ? location : location.pathname;
let stripedPathname = stripString(pathname);
if (stripedBasename) {
stripedPathname = stripedPathname.replace(new RegExp(`^${stripedBasename}/`), '');
}
const route = routes.length === 1 ? routes[0] : routes.find(item => {
return stripString(item.path || '') === stripedPathname;
});
if (!route) {
throw new Error(`No route matched pathname: ${pathname}`);
}
return [{
route,
params: {},
pathname,
pathnameBase: '',
}];
};

export const Link = () => null;
Expand Down
50 changes: 48 additions & 2 deletions packages/runtime/tests/singleRoute.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,54 @@ describe('single route api', () => {
expect(createHistory().location).toBe('');
});

it('matchRoutes', () => {
expect(matchRoutes([{}])[0].pathname).toBe('');
it('matchRoutes - single route', () => {
const routes = [
{
path: 'users',
element: <div>user</div>,
},
];
const location = {
pathname: '/test',
};
const matchedRoutes = matchRoutes(routes, location, '/');
expect(matchedRoutes).toHaveLength(1);
expect(matchedRoutes[0].route.path).toBe('users');
});

it('matchRoutes - mutiple route', () => {
const routes = [
{
path: 'users',
element: <div>user</div>,
},
{
path: 'posts',
element: <div>post</div>,
},
];
const location = {
pathname: '/posts',
};
const matchedRoutes = matchRoutes(routes, location, '/');
expect(matchedRoutes).toHaveLength(1);
expect(matchedRoutes[0].route.path).toBe('posts');
});

it('matchRoutes - basename', () => {
const routes = [
{
path: 'users',
element: <div>user</div>,
},
{
path: 'posts',
element: <div>post</div>,
},
];
const matchedRoutes = matchRoutes(routes, '/basename/posts', '/basename');
expect(matchedRoutes).toHaveLength(1);
expect(matchedRoutes[0].route.path).toBe('posts');
});

it('Link', () => {
Expand Down

0 comments on commit b691b9e

Please sign in to comment.