From 975b1a2c72a60172b0b373036dfa197980b1c32a Mon Sep 17 00:00:00 2001 From: James Dempster Date: Thu, 22 Apr 2021 19:41:54 +0100 Subject: [PATCH] feat: `staticFilename` option to customize static image filenames (#220) Co-authored-by: Pooya Parsa --- docs/content/en/3.api/1.options.md | 19 +++++++++++++++++++ src/generate.ts | 19 +++++++++++++------ src/module.ts | 3 ++- src/runtime/image.ts | 7 ++----- src/types/module.ts | 1 + 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/docs/content/en/3.api/1.options.md b/docs/content/en/3.api/1.options.md index dd3a9956c..022c6f6d8 100644 --- a/docs/content/en/3.api/1.options.md +++ b/docs/content/en/3.api/1.options.md @@ -148,3 +148,22 @@ export default { } ``` +## `staticFilename` + +You can use this option to change filename and location for the static image generation. + +### Parameters + +- `[name]`: Only filename, without extension or path +- `[hash]`: The hash of url +- `[ext]`: Extension with leading dot `.png` +- `[publicPath]`: Default is `build.publicPath` (`/_nuxt`) + +```ts [nuxt.config.js] +export default { + image: { + // Generate images to `/_nuxt/image/file.png` + staticFilename: '[publicPath]/images/[name]-[hash][ext]' + } +} +``` diff --git a/src/generate.ts b/src/generate.ts index 0f7e18523..2d33bc83c 100644 --- a/src/generate.ts +++ b/src/generate.ts @@ -3,9 +3,9 @@ import { createWriteStream } from 'fs' import { promisify } from 'util' import stream from 'stream' import { mkdirp } from 'fs-extra' -import { dirname, join, relative, resolve, extname } from 'upath' +import { dirname, join, relative, extname, basename, trimExt } from 'upath' import fetch from 'node-fetch' -import { joinURL, hasProtocol, parseURL } from 'ufo' +import { joinURL, hasProtocol, parseURL, withoutTrailingSlash } from 'ufo' import pLimit from 'p-limit' import { ModuleOptions, MapToStatic, ResolvedImage } from './types' import { hash, logger } from './utils' @@ -19,15 +19,22 @@ export function setupStaticGeneration (nuxt: any, options: ModuleOptions) { renderContext.image = renderContext.image || {} renderContext.image.mapToStatic = function ({ url, format }: ResolvedImage) { if (!staticImages[url]) { - const ext = (format && `.${format}`) || extname(parseURL(url).pathname) || '.png' - staticImages[url] = hash(url) + ext + const { pathname } = parseURL(url) + const params: any = { + name: trimExt(basename(pathname)), + ext: (format && `.${format}`) || extname(pathname) || '.png', + hash: hash(url), + // TODO: pass from runtimeConfig to mapStatic as param + publicPath: withoutTrailingSlash(nuxt.options.build.publicPath) + } + + staticImages[url] = options.staticFilename.replace(/\[(\w+)]/g, (match, key) => params[key] || match) } return staticImages[url] } }) nuxt.hook('generate:done', async () => { - const { dir: generateDir } = nuxt.options.generate const limit = pLimit(8) const downloads = Object.entries(staticImages).map(([url, name]) => { if (!hasProtocol(url)) { @@ -36,7 +43,7 @@ export function setupStaticGeneration (nuxt: any, options: ModuleOptions) { return limit(() => downloadImage({ url, name, - outDir: resolve(generateDir, '_nuxt/image' /* TODO: staticImagesBase */) + outDir: nuxt.options.generate.dir })) }) await Promise.all(downloads) diff --git a/src/module.ts b/src/module.ts index cdc548198..9376d5297 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1,4 +1,4 @@ -import { resolve } from 'upath' +import { resolve, join } from 'upath' import type { Module } from '@nuxt/types' import defu from 'defu' @@ -13,6 +13,7 @@ const imageModule: Module = async function imageModule (moduleOpt const { nuxt, addPlugin, addServerMiddleware } = this const defaults: ModuleOptions = { + staticFilename: '[publicPath]/image/[hash][ext]', provider: 'auto', presets: {}, dir: resolve(nuxt.options.srcDir, nuxt.options.dir.static), diff --git a/src/runtime/image.ts b/src/runtime/image.ts index ecf30c2a8..5772eab5f 100644 --- a/src/runtime/image.ts +++ b/src/runtime/image.ts @@ -1,5 +1,4 @@ import defu from 'defu' -import { joinURL } from 'ufo' import type { ImageOptions, ImageSizesOptions, CreateImageOptions, ResolvedImage, MapToStatic, ImageCTX, $Img } from '../types/image' import { imageMeta } from './utils/meta' import { parseSize } from './utils' @@ -33,11 +32,9 @@ export function createImage (globalOptions: CreateImageOptions, nuxtContext: any function handleStaticImage (image: ResolvedImage, input: string) { if (process.static) { - const staticImagesBase = '/_nuxt/image' // TODO - if (process.client && 'fetchPayload' in window.$nuxt) { const mappedURL = staticImageManifest[image.url] - image.url = mappedURL ? joinURL(staticImagesBase, mappedURL) : input + image.url = mappedURL || input return image } @@ -50,7 +47,7 @@ export function createImage (globalOptions: CreateImageOptions, nuxtContext: any const mappedURL = mapToStatic(image) if (mappedURL) { staticImages[image.url] = mappedURL - image.url = joinURL(staticImagesBase, mappedURL) + image.url = mappedURL } } } diff --git a/src/types/module.ts b/src/types/module.ts index 87dfb5c92..8d0df44ab 100644 --- a/src/types/module.ts +++ b/src/types/module.ts @@ -25,6 +25,7 @@ export interface ImageProviders { // TODO: use types from CreateImageOptions export interface ModuleOptions extends ImageProviders { + staticFilename: string, provider: CreateImageOptions['provider'] presets: { [name: string]: ImageOptions } dir: string