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

refactor: move ipx to runtime servermiddleware #264

Closed
wants to merge 9 commits into from
50 changes: 50 additions & 0 deletions docs/pages/en/4.providers/ipx.md
Expand Up @@ -21,3 +21,53 @@ that are stored locally within your repo.
```

This will load the image in as `/static/logo.png` and apply the IPX optimizations if applicable.


### Using `ipx` in production

#### Add `ipx` dependency

You'll need to ensure that `ipx` is in your production dependencies.

<d-code-group>
<d-code-block label="Yarn" active>

```bash
yarn add ipx
```

</d-code-block>
<d-code-block label="NPM">

```bash
npm install ipx
```

</d-code-block>
</d-code-group>

#### Add `serverMiddleware` handler

You will also need to add `@nuxt/image` to your _modules_ (instead of buildModules) or add the following code to your `nuxt.config`:

```js [nuxt.config.js]
import path from 'path'
import { createIPX, createIPXMiddleware } from 'ipx'

const ipx = createIPX({
dir: path.join(__dirname, 'static'),
// https://image.nuxtjs.org/api/options#domains
domains: [],
// Any options you need to pass to sharp
sharp: {}
})

export default {
serverMiddleware: [
{
path: '/_ipx',
handler: createIPXMiddleware(ipx)
}
]
}
```
7 changes: 0 additions & 7 deletions src/ipx.ts

This file was deleted.

46 changes: 36 additions & 10 deletions src/module.ts
@@ -1,13 +1,12 @@
import { resolve } from 'upath'

import defu from 'defu'
import { existsSync, mkdirp, readFile, writeFile } from 'fs-extra'
import { relative, resolve } from 'upath'

import type { Module } from '@nuxt/types'
import { setupStaticGeneration } from './generate'
import { createIPXMiddleware } from './ipx'
import { resolveProviders, detectProvider } from './provider'
import { pick, pkg } from './utils'
import type { ModuleOptions, CreateImageOptions } from './types'
import type { Module } from '@nuxt/types'

const imageModule: Module<ModuleOptions> = async function imageModule (moduleOptions) {
const { nuxt, addPlugin, addServerMiddleware } = this
Expand Down Expand Up @@ -73,14 +72,41 @@ const imageModule: Module<ModuleOptions> = async function imageModule (moduleOpt
}
})

addServerMiddleware({
path: '/_ipx',
handle: createIPXMiddleware({
dir: options.dir,
// Check if IPX middleware is required
const ipxEnabled = ('ipx' in options.providers) || (options.provider === 'static' && nuxt.options.dev)

if (ipxEnabled) {
const ipxOptions = {
dir: relative(nuxt.options.rootDir, options.dir),
domains: options.domains,
sharp: options.sharp
})
})
}

// In development, add IPX middleware directly

const hasUserProvidedMiddleware = !!nuxt.options.serverMiddleware
.find((mw: { path: string }) => mw.path && mw.path.startsWith('/_ipx'))

if (!hasUserProvidedMiddleware) {
const handlerContents = await readFile(resolve(runtimeDir, 'ipx.js'), 'utf-8')
const imageDir = resolve(nuxt.options.buildDir, 'image')
const handlerFile = resolve(imageDir, 'ipx.js')

addServerMiddleware({ path: '/_ipx', handler: handlerFile })
const writeServerMiddleware = async () => {
if (!existsSync(handlerFile)) {
await mkdirp(imageDir)
await writeFile(handlerFile, handlerContents.replace(/.__IPX_OPTIONS__./, JSON.stringify(ipxOptions, null, 2)))
}
}
nuxt.hook('build:templates', writeServerMiddleware)
nuxt.hook('render:setupMiddleware', writeServerMiddleware)

if (nuxt.options.dev && options.provider === 'ipx') {
console.warn('If you would like to use the `ipx` provider at runtime, make sure to follow the instructions at https://image.nuxtjs.org/providers/ipx.')
}
}
}

// transform asset urls that pass to `src` attribute on image components
nuxt.options.build.loaders = defu({
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/components/nuxt-img.vue
Expand Up @@ -7,9 +7,9 @@
</template>

<script lang="ts">
import { imageMixin } from './image.mixin'
import type { DefineComponentWithMixin } from '../../types/vue'
import type { ImageSizes } from '../../types'
import { imageMixin } from './image.mixin'

import { parseSize } from '~image'

Expand Down
2 changes: 1 addition & 1 deletion src/runtime/components/nuxt-picture.vue
Expand Up @@ -16,8 +16,8 @@
</template>

<script lang="ts">
import { imageMixin } from './image.mixin'
import type { DefineComponentWithMixin } from '../../types/vue'
import { imageMixin } from './image.mixin'

import { getFileExtension } from '~image'

Expand Down
2 changes: 1 addition & 1 deletion src/runtime/image.ts
@@ -1,8 +1,8 @@
import defu from 'defu'
import type { ImageOptions, ImageSizesOptions, CreateImageOptions, ResolvedImage, MapToStatic, ImageCTX, $Img } from '../types/image'
import { imageMeta } from './utils/meta'
import { parseSize } from './utils'
import { useStaticImageMap } from './utils/static-map'
import type { ImageOptions, ImageSizesOptions, CreateImageOptions, ResolvedImage, MapToStatic, ImageCTX, $Img } from '../types/image'

export function createImage (globalOptions: CreateImageOptions, nuxtContext: any) {
const staticImageManifest: Record<string, string> = (process.client && process.static) ? useStaticImageMap(nuxtContext) : {}
Expand Down
5 changes: 5 additions & 0 deletions src/runtime/ipx.js
@@ -0,0 +1,5 @@
import { createIPX, createIPXMiddleware } from 'ipx'

const ipx = createIPX('__IPX_OPTIONS__')

export default createIPXMiddleware(ipx)
2 changes: 1 addition & 1 deletion src/runtime/providers/prismic.ts
@@ -1,6 +1,6 @@
import { joinURL, parseQuery, parseURL, stringifyQuery } from 'ufo'
import { operationsGenerator } from './imgix'
import type { ProviderGetImage } from 'src'
import { operationsGenerator } from './imgix'

const PRISMIC_IMGIX_BUCKET = 'https://images.prismic.io'

Expand Down
2 changes: 1 addition & 1 deletion test/unit/image.test.ts
Expand Up @@ -4,8 +4,8 @@

import { Wrapper } from '@vue/test-utils'

import { getSrc, mountWithImg } from './utils/mount'
import type Vue from 'vue'
import { getSrc, mountWithImg } from './utils/mount'

import NuxtImg from '~/runtime/components/nuxt-img.vue'

Expand Down
2 changes: 1 addition & 1 deletion test/unit/picture.test.ts
Expand Up @@ -4,9 +4,9 @@

import { Wrapper } from '@vue/test-utils'

import type Vue from 'vue'
import { getSrc, mountWithImg } from './utils/mount'
import { nextTick } from './utils/tick'
import type Vue from 'vue'

import NuxtPicture from '~/runtime/components/nuxt-picture.vue'

Expand Down