Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add router basename config all #569

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/platform-shared/src/shared/helper/getAppData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export type IData = {

export type IAppData<Data = {}, appState = any> = {
ssr: boolean;
basename?: string;
runtimeConfig?: Record<string, string>;
appState?: appState;
pageData?: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ export async function renderToHTML({
}): Promise<Response> {
let result: Response;
const renderer = new Renderer({ serverPluginContext });
const {
config: { ssr },
appConfig: {
router: { basename }
}
} = serverPluginContext;
const { serverCreateAppTrace } = req._traces;
const { application } = resources.server;
const app = serverCreateAppTrace
Expand All @@ -23,7 +29,8 @@ export async function renderToHTML({
.traceFn(() =>
application.createApp({
req,
ssr: serverPluginContext.config.ssr
ssr,
basename
})
);

Expand All @@ -37,7 +44,7 @@ export async function renderToHTML({
result = await renderer.renderView({
req,
app: app.getPublicAPI(),
ssr: serverPluginContext.config.ssr
ssr
});
} finally {
await app.dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import { IRenderViewOptions, IHtmlDocument } from './types';
export class SpaRenderer extends BaseRenderer {
renderDocument({ req, app }: IRenderViewOptions) {
const assets = this._getMainAssetTags(req);
const {
router: { basename }
} = this._serverPluginContext.appConfig;
const appData: AppData = {
ssr: false,
pageData: {}
pageData: {},
basename
};
const document: IHtmlDocument = {
htmlAttrs: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ export class SsrRenderer extends BaseRenderer {
...result.appData,
ssr: true,
appState: store.getState(),
pageData
pageData,
basename: router.basename
};
appData.runtimeConfig = getPublicRuntimeConfig() || {};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { matchRoutes } from '@shuvi/router';
import { createLocation, matchRoutes } from '@shuvi/router';
import { normalizeBase } from '@shuvi/router/lib/utils';
import resources from '@shuvi/service/lib/resources';
import { ShuviRequestHandler, IServerPluginContext } from '@shuvi/service';
import { DevMiddleware } from '@shuvi/service/lib/server/middlewares/dev';
Expand Down Expand Up @@ -85,8 +86,14 @@ export default class OnDemandRouteManager {
}

async ensureRoutes(pathname: string): Promise<void> {
const {
router: { basename }
} = this._serverPluginContext.appConfig;
const resolvedPath = createLocation(pathname, {
basename: normalizeBase(basename)
});
const matchedRoutes =
matchRoutes(resources.server.pageRoutes, pathname) || [];
matchRoutes(resources.server.pageRoutes, resolvedPath) || [];

const modulesToActivate = matchedRoutes
.map(({ route: { __componentRawRequest__ } }) => __componentRawRequest__)
Expand Down
6 changes: 5 additions & 1 deletion packages/platform-web/src/shared/appTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ export type InternalApplication = _ApplicationImpl<AppConfig>;
export type Application = _Application<AppConfig>;

export interface CreateAppServer {
(options: { req: ShuviRequest; ssr: boolean }): InternalApplication;
(options: {
req: ShuviRequest;
ssr: boolean;
basename: string;
}): InternalApplication;
}

export interface CreateAppClient {
Expand Down
6 changes: 3 additions & 3 deletions packages/platform-web/src/shuvi-app/app/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ export const createApp: CreateAppClient = ({
return app;
}

const { appState, ssr } = appData;
const { appState, ssr, basename } = appData;
let history: History;
if (historyMode === 'hash') {
history = createHashHistory();
history = createHashHistory({ basename });
} else {
history = createBrowserHistory();
history = createBrowserHistory({ basename });
}

const router = createRouter({
Expand Down
5 changes: 3 additions & 2 deletions packages/platform-web/src/shuvi-app/app/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ import { serializeServerError } from '../helper/serializeServerError';

const { SHUVI_SERVER_RUN_LOADERS } = SERVER_CREATE_APP.events;
export const createApp: CreateAppServer = options => {
const { req, ssr } = options;
const { req, ssr, basename } = options;
const history = createMemoryHistory({
initialEntries: [(req && req.url) || '/'],
initialIndex: 0
initialIndex: 0,
basename
});
const router = createRouter({
history,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class ReactServerView implements IReactServerView {
);
}
// handle router internal redirect
return redirect(pathname);
return redirect(router.resolve(router.current).href);
}

const loadableModules: string[] = [];
Expand Down
3 changes: 1 addition & 2 deletions packages/router-react/src/MemoryRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ export function MemoryRouter({
let routerRef = React.useRef<IRouter>();
if (routerRef.current == null) {
routerRef.current = createRouter({
basename,
routes: routes || [],
history: createMemoryHistory({ initialEntries, initialIndex })
history: createMemoryHistory({ initialEntries, initialIndex, basename })
}).init();
}

Expand Down
16 changes: 8 additions & 8 deletions packages/router-react/src/__tests__/useHref-basename.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ describe('useHref under a <Routes basename>', () => {
</Router>
);

expect(href).toBe('/app/');
expect(href).toBe('/app');
});
});
});
Expand All @@ -250,7 +250,7 @@ describe('useHref under a <Routes basename>', () => {
it('returns the correct href', () => {
let href;
function Admin() {
href = useHref('../../../dashboard');
href = useHref('../../dashboard');
return <h1>Admin</h1>;
}

Expand All @@ -269,7 +269,7 @@ describe('useHref under a <Routes basename>', () => {
</Router>
);

expect(href).toBe('/dashboard');
expect(href).toBe('/app/dashboard');
});

describe('and no additional segments', () => {
Expand All @@ -295,15 +295,15 @@ describe('useHref under a <Routes basename>', () => {
</Router>
);

expect(href).toBe('/');
expect(href).toBe('/app');
});
});

describe('when the URL has a trailing slash', () => {
it('returns the correct href', () => {
let href;
function Admin() {
href = useHref('../../../dashboard');
href = useHref('../../dashboard');
return <h1>Admin</h1>;
}

Expand All @@ -322,15 +322,15 @@ describe('useHref under a <Routes basename>', () => {
</Router>
);

expect(href).toBe('/dashboard');
expect(href).toBe('/app/dashboard');
});
});

describe('when the href has a trailing slash', () => {
it('returns the correct href', () => {
let href;
function Admin() {
href = useHref('../../../dashboard/');
href = useHref('../../dashboard/');
return <h1>Admin</h1>;
}

Expand All @@ -349,7 +349,7 @@ describe('useHref under a <Routes basename>', () => {
</Router>
);

expect(href).toBe('/dashboard/');
expect(href).toBe('/app/dashboard/');
});
});
});
Expand Down
100 changes: 100 additions & 0 deletions packages/router-react/src/__tests__/useHref.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,56 @@ describe('useHref', () => {
expect(href).toBe('/courses/');
});
});

describe('when up to root route, href should always be root /', () => {
it('when href has no trailing slash', () => {
let href;
function AdvancedReact() {
href = useHref('..');
return <h1>Advanced React</h1>;
}

createTestRenderer(
<Router
initialEntries={['/courses']}
routes={[
{
path: 'courses',
component: AdvancedReact
}
]}
>
<RouterView />
</Router>
);

expect(href).toBe('/');
});

it('when href has a trailing slash', () => {
let href;
function AdvancedReact() {
href = useHref('../');
return <h1>Advanced React</h1>;
}

createTestRenderer(
<Router
initialEntries={['/courses']}
routes={[
{
path: 'courses',
component: AdvancedReact
}
]}
>
<RouterView />
</Router>
);

expect(href).toBe('/');
});
});
});

describe('with a to value that has more .. segments than are in the URL', () => {
Expand Down Expand Up @@ -277,6 +327,56 @@ describe('useHref', () => {
expect(href).toBe('/courses');
});

describe('when up to root route, href should always be root /', () => {
it('when href has no trailing slash', () => {
let href;
function AdvancedReact() {
href = useHref('../..');
return <h1>Advanced React</h1>;
}

createTestRenderer(
<Router
initialEntries={['/courses/some-path']}
routes={[
{
path: 'courses/some-path',
component: AdvancedReact
}
]}
>
<RouterView />
</Router>
);

expect(href).toBe('/');
});

it('when href has a trailing slash', () => {
let href;
function AdvancedReact() {
href = useHref('../../');
return <h1>Advanced React</h1>;
}

createTestRenderer(
<Router
initialEntries={['/courses/some-path']}
routes={[
{
path: 'courses/some-path',
component: AdvancedReact
}
]}
>
<RouterView />
</Router>
);

expect(href).toBe('/');
});
});

describe('and no additional segments', () => {
it('links to the root /', () => {
let href;
Expand Down
Loading