Skip to content

Commit

Permalink
feat: Support subpath deployment (#252)
Browse files Browse the repository at this point in the history
* test: subpath deployment

* feat: support subpath deployment

* feat: support base value without trailing slash
  • Loading branch information
berlysia authored Jan 23, 2025
1 parent aed14ea commit e66a876
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 2 deletions.
8 changes: 7 additions & 1 deletion src/server/components/link.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { FC } from 'hono/jsx'
import type { JSX } from 'hono/jsx/jsx-runtime'
import type { Manifest } from 'vite'
import { ensureTrailngSlash } from '../utils/path'

type Options = { manifest?: Manifest; prod?: boolean } & JSX.IntrinsicElements['link']

Expand All @@ -23,7 +24,12 @@ export const Link: FC<Options> = (options) => {
const assetInManifest = manifest[href.replace(/^\//, '')]
if (assetInManifest) {
if (href.startsWith('/')) {
return <link href={`/${assetInManifest.file}`} {...rest}></link>
return (
<link
href={`${ensureTrailngSlash(import.meta.env.BASE_URL)}${assetInManifest.file}`}
{...rest}
></link>
)
}

return <link href={assetInManifest.file} {...rest}></link>
Expand Down
3 changes: 2 additions & 1 deletion src/server/components/script.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Manifest } from 'vite'
import { ensureTrailngSlash } from '../utils/path.js'
import { HasIslands } from './has-islands.js'

type Options = {
Expand Down Expand Up @@ -33,7 +34,7 @@ export const Script = (options: Options): any => {
<script
type='module'
async={!!options.async}
src={`/${scriptInManifest.file}`}
src={`${ensureTrailngSlash(import.meta.env.BASE_URL)}${scriptInManifest.file}`}
nonce={options.nonce}
></script>
</HasIslands>
Expand Down
12 changes: 12 additions & 0 deletions src/server/utils/path.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ensureTrailngSlash } from './path'

describe('ensureTrailngSlash', () => {
it('Should ensure trailing slash', () => {
expect(ensureTrailngSlash('./')).toBe('./')
expect(ensureTrailngSlash('/')).toBe('/')
expect(ensureTrailngSlash('/subdir')).toBe('/subdir/')
expect(ensureTrailngSlash('/subdir/')).toBe('/subdir/')
expect(ensureTrailngSlash('https://example.com')).toBe('https://example.com/')
expect(ensureTrailngSlash('https://example.com/subdir')).toBe('https://example.com/subdir/')
})
})
3 changes: 3 additions & 0 deletions src/server/utils/path.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const ensureTrailngSlash = (path: string) => {
return path.endsWith('/') ? path : path + '/'
}
126 changes: 126 additions & 0 deletions test-integration/apps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,69 @@ describe('<Script /> component', () => {
'<html><head><script type="module" src="/static/client-abc.js"></script></head><body><main><honox-island component-name="/mocks/app-script/islands/Component.tsx" data-serialized-props="{}"><p>Component</p></honox-island></main></body></html>'
)
})

describe('with base path - root relative', () => {
const originalBaseURL = import.meta.env.BASE_URL

beforeAll(() => {
// this means `base: "/base/path/"` in vite.config.ts
import.meta.env.BASE_URL = '/base/path/'
})

afterAll(() => {
import.meta.env.BASE_URL = originalBaseURL
})

it('Should convert the script path correctly', async () => {
const res = await app.request('/')
expect(res.status).toBe(200)
expect(await res.text()).toBe(
'<html><head><script type="module" src="/base/path/static/client-abc.js"></script></head><body><main><honox-island component-name="/mocks/app-script/islands/Component.tsx" data-serialized-props="{}"><p>Component</p></honox-island></main></body></html>'
)
})
})

describe('with base path - root relative, without trailing slash', () => {
const originalBaseURL = import.meta.env.BASE_URL

beforeAll(() => {
// this means `base: "/base/path"` in vite.config.ts
import.meta.env.BASE_URL = '/base/path'
})

afterAll(() => {
import.meta.env.BASE_URL = originalBaseURL
})

it('Should convert the script path correctly', async () => {
const res = await app.request('/')
expect(res.status).toBe(200)
expect(await res.text()).toBe(
'<html><head><script type="module" src="/base/path/static/client-abc.js"></script></head><body><main><honox-island component-name="/mocks/app-script/islands/Component.tsx" data-serialized-props="{}"><p>Component</p></honox-island></main></body></html>'
)
})
})

describe('with base path - absolute url', () => {
const originalBaseURL = import.meta.env.BASE_URL

beforeAll(() => {
// this means `base: "https://example.com/base/path/"` in vite.config.ts
import.meta.env.BASE_URL = 'https://example.com/base/path/'
})

afterAll(() => {
import.meta.env.BASE_URL = originalBaseURL
})

it('Should convert the script path correctly', async () => {
const res = await app.request('/')
expect(res.status).toBe(200)
expect(await res.text()).toBe(
'<html><head><script type="module" src="https://example.com/base/path/static/client-abc.js"></script></head><body><main><honox-island component-name="/mocks/app-script/islands/Component.tsx" data-serialized-props="{}"><p>Component</p></honox-island></main></body></html>'
)
})
})
})

describe('With async', () => {
Expand Down Expand Up @@ -555,6 +618,69 @@ describe('<Link /> component', () => {
'<html><head><link href="/static/globals-abc.css" rel="stylesheet"></link></head><body><main><div></div></main></body></html>'
)
})

describe('with base path - root relative', () => {
const originalBaseURL = import.meta.env.BASE_URL

beforeAll(() => {
// this means `base: "/base/path/"` in vite.config.ts
import.meta.env.BASE_URL = '/base/path/'
})

afterAll(() => {
import.meta.env.BASE_URL = originalBaseURL
})

it('Should convert the link path correctly', async () => {
const res = await app.request('/')
expect(res.status).toBe(200)
expect(await res.text()).toBe(
'<html><head><link href="/base/path/static/globals-abc.css" rel="stylesheet"></link></head><body><main><div></div></main></body></html>'
)
})
})

describe('with base path - root relative, without trailing slash', () => {
const originalBaseURL = import.meta.env.BASE_URL

beforeAll(() => {
// this means `base: "/base/path"` in vite.config.ts
import.meta.env.BASE_URL = '/base/path'
})

afterAll(() => {
import.meta.env.BASE_URL = originalBaseURL
})

it('Should convert the link path correctly', async () => {
const res = await app.request('/')
expect(res.status).toBe(200)
expect(await res.text()).toBe(
'<html><head><link href="/base/path/static/globals-abc.css" rel="stylesheet"></link></head><body><main><div></div></main></body></html>'
)
})
})

describe('with base path - absolute url', () => {
const originalBaseURL = import.meta.env.BASE_URL

beforeAll(() => {
// this means `base: "https://example.com/base/path/"` in vite.config.ts
import.meta.env.BASE_URL = 'https://example.com/base/path/'
})

afterAll(() => {
import.meta.env.BASE_URL = originalBaseURL
})

it('Should convert the link path correctly', async () => {
const res = await app.request('/')
expect(res.status).toBe(200)
expect(await res.text()).toBe(
'<html><head><link href="https://example.com/base/path/static/globals-abc.css" rel="stylesheet"></link></head><body><main><div></div></main></body></html>'
)
})
})
})
})

Expand Down

0 comments on commit e66a876

Please sign in to comment.