Skip to content

Commit f7b0c98

Browse files
feat: basePath support (#18)
* feat: `basePath` support * fix: add basepath to image redirects * feat: image support * fix: server loading * fix: add redirect for root image links * fix: remove `basePath` from demo Co-authored-by: lindsaylevine <57350178+lindsaylevine@users.noreply.github.com> Co-authored-by: lindsaylevine <57350178+lindsaylevine@users.noreply.github.com>
1 parent 2d2c198 commit f7b0c98

File tree

4 files changed

+29
-14
lines changed

4 files changed

+29
-14
lines changed

src/helpers/config.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ const getNetlifyRoutes = (nextRoute) => {
5151
return netlifyRoutes
5252
}
5353

54-
exports.generateRedirects = async ({ netlifyConfig }) => {
54+
exports.generateRedirects = async ({ netlifyConfig, basePath }) => {
5555
const { dynamicRoutes } = await readJSON(join(netlifyConfig.build.publish, 'prerender-manifest.json'))
5656

5757
const redirects = []
5858

5959
netlifyConfig.redirects.push(
6060
...HIDDEN_PATHS.map((path) => ({
61-
from: path,
61+
from: `${basePath}${path}`,
6262
to: '/404.html',
6363
status: 404,
6464
force: true,
@@ -78,20 +78,20 @@ exports.generateRedirects = async ({ netlifyConfig }) => {
7878

7979
// This is only used in prod, so dev uses `next dev` directly
8080
netlifyConfig.redirects.push(
81-
{ from: '/_next/static/*', to: '/static/:splat', status: 200 },
81+
{ from: `${basePath}/_next/static/*`, to: '/static/:splat', status: 200 },
8282
{
83-
from: '/*',
83+
from: `${basePath}/*`,
8484
to: HANDLER_FUNCTION_PATH,
8585
status: 200,
8686
force: true,
8787
conditions: { Cookie: ['__prerender_bypass', '__next_preview_data'] },
8888
},
8989
...redirects.map((redirect) => ({
90-
from: redirect,
90+
from: `${basePath}${redirect}`,
9191
to: ODB_FUNCTION_PATH,
9292
status: 200,
9393
})),
94-
{ from: '/*', to: HANDLER_FUNCTION_PATH, status: 200 },
94+
{ from: `${basePath}/*`, to: HANDLER_FUNCTION_PATH, status: 200 },
9595
)
9696
}
9797

src/helpers/functions.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,17 @@ exports.setupImageFunction = async ({
3333
constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC },
3434
imageconfig = {},
3535
netlifyConfig,
36+
basePath,
3637
}) => {
3738
const functionsPath = INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC
3839
const functionName = `${IMAGE_FUNCTION_NAME}.js`
3940
const functionDirectory = join(functionsPath, IMAGE_FUNCTION_NAME)
4041

4142
await ensureDir(functionDirectory)
42-
await writeJSON(join(functionDirectory, 'imageconfig.json'), imageconfig)
43+
await writeJSON(join(functionDirectory, 'imageconfig.json'), {
44+
...imageconfig,
45+
basePath: [basePath, IMAGE_FUNCTION_NAME].join('/'),
46+
})
4347
await copyFile(join(__dirname, '..', 'templates', 'ipx.js'), join(functionDirectory, functionName))
4448

4549
const imagePath = imageconfig.path || '/_next/image'
@@ -48,13 +52,22 @@ exports.setupImageFunction = async ({
4852
{
4953
from: `${imagePath}*`,
5054
query: { url: ':url', w: ':width', q: ':quality' },
51-
to: `/${IMAGE_FUNCTION_NAME}/w_:width,q_:quality/:url`,
55+
to: `${basePath}/${IMAGE_FUNCTION_NAME}/w_:width,q_:quality/:url`,
5256
status: 301,
5357
},
5458
{
55-
from: `/${IMAGE_FUNCTION_NAME}/*`,
59+
from: `${basePath}/${IMAGE_FUNCTION_NAME}/*`,
5660
to: `/.netlify/functions/${IMAGE_FUNCTION_NAME}`,
5761
status: 200,
5862
},
5963
)
64+
65+
if (basePath) {
66+
// next/image generates image static URLs that still point at the site root
67+
netlifyConfig.redirects.push({
68+
from: '/_next/static/image/*',
69+
to: '/static/image/:splat',
70+
status: 200,
71+
})
72+
}
6073
}

src/index.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ module.exports = {
4242

4343
checkNextSiteHasBuilt({ publish, failBuild })
4444

45-
const { images, target, appDir } = await getNextConfig({ publish, failBuild })
45+
const { images, target, appDir, basePath } = await getNextConfig({ publish, failBuild })
4646

4747
setBundler({ netlifyConfig, target })
4848

@@ -54,18 +54,19 @@ module.exports = {
5454

5555
await copy(`${appDir}/public`, `${publish}/`)
5656

57-
await setupImageFunction({ constants, imageconfig: images, netlifyConfig })
57+
await setupImageFunction({ constants, imageconfig: images, netlifyConfig, basePath })
5858

5959
await generateRedirects({
6060
netlifyConfig,
61+
basePath,
6162
})
6263
},
6364

6465
async onPostBuild({ netlifyConfig, constants: { FUNCTIONS_DIST = '.netlify/functions' }, utils: { run, cache } }) {
6566
// Remove swc binaries from the zipfile if present. Yes, it's a hack, but it drops >10MB from the zipfile when bundling with zip-it-and-ship-it
6667
for (const func of [ODB_FUNCTION_NAME, HANDLER_FUNCTION_NAME]) {
6768
await run(`zip`, [`-d`, join(FUNCTIONS_DIST, `${func}.zip`), '*node_modules/@next/swc-*']).catch(() => {
68-
// This throws if there's none of these in the zipfile
69+
// This throws if there's none of these in the zipfile, so ignore it
6970
})
7071
}
7172

src/templates/ipx.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ const { createIPXHandler } = require('@netlify/ipx')
22

33
// Injected at build time
44
// eslint-disable-next-line import/no-unresolved, node/no-missing-require
5-
const config = require('./imageconfig.json')
5+
const { basePath, domains } = require('./imageconfig.json')
66

77
exports.handler = createIPXHandler({
8-
domains: config.domains || [],
8+
basePath,
9+
domains,
910
})

0 commit comments

Comments
 (0)