Skip to content
This repository has been archived by the owner on Jun 21, 2023. It is now read-only.

Commit

Permalink
Add dangerously-unoptimized loader for next/image (vercel#26847)
Browse files Browse the repository at this point in the history
* add support for static loader

* update existing test

* add test

* add prettier-ignore

* update docs

* apply suggestions from review

* remove un-needed normalize

* Apply suggestions from code review

Co-authored-by: Steven <steven@ceriously.com>

* update test

Co-authored-by: JJ Kasper <jj@jjsweb.site>
Co-authored-by: Steven <steven@ceriously.com>
  • Loading branch information
3 people committed Jul 7, 2021
1 parent 8695cd5 commit ba29234
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 8 deletions.
1 change: 1 addition & 0 deletions docs/basic-features/image-optimization.md
Expand Up @@ -121,6 +121,7 @@ The following Image Optimization cloud providers are included:
- [Imgix](https://www.imgix.com): `loader: 'imgix'`
- [Cloudinary](https://cloudinary.com): `loader: 'cloudinary'`
- [Akamai](https://www.akamai.com): `loader: 'akamai'`
- dangerously-unoptimized: uses image directly from `src` prop without optimization (only needed with `next export` or when the built-in `_next/image` optimizer can not be leveraged) `loader: 'dangerously-unoptimized'`
- Default: Works automatically with `next dev`, `next start`, or a custom server

If you need a different provider, you can use the [`loader`](/docs/api-reference/next/image.md#loader) prop with `next/image`.
Expand Down
5 changes: 5 additions & 0 deletions packages/next/client/image.tsx
Expand Up @@ -36,6 +36,7 @@ const loaders = new Map<
['cloudinary', cloudinaryLoader],
['akamai', akamaiLoader],
['default', defaultLoader],
['dangerously-unoptimized', unoptimizedLoader],
])

const VALID_LAYOUT_VALUES = [
Expand Down Expand Up @@ -684,6 +685,10 @@ function cloudinaryLoader({
return `${root}${paramsString}${normalizeSrc(src)}`
}

function unoptimizedLoader({ src }: DefaultImageLoaderProps): string {
return src
}

function defaultLoader({
root,
src,
Expand Down
1 change: 1 addition & 0 deletions packages/next/server/image-config.ts
Expand Up @@ -3,6 +3,7 @@ export const VALID_LOADERS = [
'imgix',
'cloudinary',
'akamai',
'dangerously-unoptimized',
] as const

export type LoaderValue = typeof VALID_LOADERS[number]
Expand Down
8 changes: 2 additions & 6 deletions test/integration/export-image-loader/next.config.js
@@ -1,6 +1,2 @@
module.exports = {
images: {
loader: 'cloudinary',
path: 'https://example.com/',
},
}
// prettier-ignore
module.exports = { /* replaceme */ }
51 changes: 50 additions & 1 deletion test/integration/export-image-loader/test/index.test.js
Expand Up @@ -3,13 +3,25 @@
import fs from 'fs-extra'
import { join } from 'path'
import cheerio from 'cheerio'
import { nextBuild, nextExport } from 'next-test-utils'
import { nextBuild, nextExport, File } from 'next-test-utils'

jest.setTimeout(1000 * 60 * 5)
const appDir = join(__dirname, '../')
const outdir = join(appDir, 'out')
const nextConfig = new File(join(appDir, 'next.config.js'))

describe('Export with cloudinary loader next/image component', () => {
beforeAll(async () => {
await nextConfig.replace(
'{ /* replaceme */ }',
JSON.stringify({
images: {
loader: 'cloudinary',
path: 'https://example.com/',
},
})
)
})
it('should build successfully', async () => {
await fs.remove(join(appDir, '.next'))
const { code } = await nextBuild(appDir)
Expand All @@ -26,4 +38,41 @@ describe('Export with cloudinary loader next/image component', () => {
const $ = cheerio.load(html)
expect($('img[alt="icon"]').attr('alt')).toBe('icon')
})

afterAll(async () => {
await nextConfig.restore()
})
})

describe('Export with dangerously-unoptimized loader next/image component', () => {
beforeAll(async () => {
await nextConfig.replace(
'{ /* replaceme */ }',
JSON.stringify({
images: {
loader: 'dangerously-unoptimized',
},
})
)
})
it('should build successfully', async () => {
await fs.remove(join(appDir, '.next'))
const { code } = await nextBuild(appDir)
if (code !== 0) throw new Error(`build failed with status ${code}`)
})

it('should export successfully', async () => {
const { code } = await nextExport(appDir, { outdir })
if (code !== 0) throw new Error(`export failed with status ${code}`)
})

it('should contain img element with same src in html output', async () => {
const html = await fs.readFile(join(outdir, 'index.html'))
const $ = cheerio.load(html)
expect($('img[alt="icon"]').attr('src')).toBe('/i.png')
})

afterAll(async () => {
await nextConfig.restore()
})
})
2 changes: 1 addition & 1 deletion test/integration/image-optimizer/test/index.test.js
Expand Up @@ -730,7 +730,7 @@ describe('Image Optimizer', () => {
await nextConfig.restore()

expect(stderr).toContain(
'Specified images.loader should be one of (default, imgix, cloudinary, akamai), received invalid value (notreal)'
'Specified images.loader should be one of (default, imgix, cloudinary, akamai, dangerously-unoptimized), received invalid value (notreal)'
)
})
})
Expand Down

0 comments on commit ba29234

Please sign in to comment.