Skip to content

Commit 96a7c7d

Browse files
feat: image support (#9)
* feat: image support * fix: redirects * fix: update ipx * fix: redirects * fix: update tests * Update demo/netlify.toml Co-authored-by: lindsaylevine <[email protected]> * refactor: move redirect handling into helper * fix: remove doubel redirects Co-authored-by: lindsaylevine <[email protected]>
1 parent c05e601 commit 96a7c7d

File tree

8 files changed

+1247
-29
lines changed

8 files changed

+1247
-29
lines changed

package-lock.json

Lines changed: 1187 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"dependencies": {
5353
"@babel/core": "^7.15.0",
5454
"@netlify/functions": "^0.7.2",
55+
"@netlify/ipx": "^0.0.5",
5556
"@netlify/parse-npm-script": "^0.1.2",
5657
"@vercel/node": "^1.11.2-canary.4",
5758
"chalk": "^4.1.2",

src/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
const HANDLER_FUNCTION_NAME = '___netlify-handler'
22
const ODB_FUNCTION_NAME = '___netlify-odb-handler'
3+
const IMAGE_FUNCTION_NAME = '_ipx'
34

45
module.exports = {
6+
IMAGE_FUNCTION_NAME,
57
HANDLER_FUNCTION_NAME,
68
ODB_FUNCTION_NAME,
79
}

src/helpers/setupImageFunction.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const { join } = require('path')
2+
3+
const { copyFile, writeJSON, ensureDir } = require('fs-extra')
4+
5+
const { IMAGE_FUNCTION_NAME } = require('../constants')
6+
7+
const DEFAULT_FUNCTIONS_SRC = 'netlify/functions'
8+
9+
// Move our next/image function into the correct functions directory
10+
const setupImageFunction = async ({
11+
constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC },
12+
imageconfig = {},
13+
netlifyConfig,
14+
}) => {
15+
const functionsPath = INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC
16+
const functionName = `${IMAGE_FUNCTION_NAME}.js`
17+
const functionDirectory = join(functionsPath, IMAGE_FUNCTION_NAME)
18+
19+
await ensureDir(functionDirectory)
20+
await writeJSON(join(functionDirectory, 'imageconfig.json'), imageconfig)
21+
await copyFile(join(__dirname, '..', 'templates', 'ipx.js'), join(functionDirectory, functionName))
22+
23+
const imagePath = imageconfig.path || '/_next/image'
24+
25+
netlifyConfig.redirects.push(
26+
{
27+
from: `${imagePath}*`,
28+
query: { url: ':url', w: ':width', q: ':quality' },
29+
to: `/${IMAGE_FUNCTION_NAME}/w_:width,q_:quality/:url`,
30+
status: 301,
31+
},
32+
{
33+
from: `/${IMAGE_FUNCTION_NAME}/*`,
34+
to: `/.netlify/functions/${IMAGE_FUNCTION_NAME}`,
35+
status: 200,
36+
},
37+
)
38+
}
39+
40+
module.exports = setupImageFunction

src/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
// @ts-check
22
const path = require('path')
33

4-
const { satisfies } = require('semver')
5-
64
const copyNextDist = require('./helpers/copyNextDist')
75
const generateFunctions = require('./helpers/generateFunctions')
86
const getNextConfig = require('./helpers/getNextConfig')
97
const getNextRoot = require('./helpers/getNextRoot')
108
const setIncludedFiles = require('./helpers/setIncludedFiles')
9+
const setupImageFunction = require('./helpers/setupImageFunction')
1110
const shouldSkipPlugin = require('./helpers/shouldSkipPlugin')
1211
const verifyBuildTarget = require('./helpers/verifyBuildTarget')
1312
const verifyNetlifyBuildVersion = require('./helpers/verifyNetlifyBuildVersion')
@@ -55,6 +54,10 @@ module.exports = {
5554

5655
const siteRoot = getNextRoot({ netlifyConfig })
5756

57+
const { images } = await getNextConfig(failBuild, siteRoot)
58+
59+
await setupImageFunction({ constants, imageconfig: images, netlifyConfig })
60+
5861
await writeRedirects({
5962
siteRoot,
6063
netlifyConfig,

src/templates/ipx.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const { createIPXHandler } = require('@netlify/ipx')
2+
3+
// Injected at build time
4+
// eslint-disable-next-line import/no-unresolved, node/no-missing-require
5+
const config = require('./imageconfig.json')
6+
7+
exports.handler = createIPXHandler({
8+
domains: config.domains || [],
9+
})

test/__snapshots__/index.js.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

33
exports[`onBuild() writes correct redirects to netlifyConfig 1`] = `
4-
"/_next/static/* /static/:splat 200
5-
/* /.netlify/functions/___netlify-handler 200
4+
"/_next/image* /_ipx/w_:width,q_:quality/:url 301
5+
/_ipx/* /.netlify/functions/_ipx 200
66
/_next/static/* /static/:splat 200
77
/* /.netlify/functions/___netlify-handler 200
88
"

test/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ beforeEach(async () => {
7373
const restoreCwd = changeCwd(tmpPath)
7474
Object.assign(this, { cleanup, restoreCwd })
7575
netlifyConfig.build.publish = path.join(process.cwd(), '.next')
76+
netlifyConfig.redirects = []
7677
await useFixture('serverless_next_config')
7778
})
7879

0 commit comments

Comments
 (0)