Skip to content

Commit

Permalink
Auto insert manifest into metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi committed Apr 12, 2023
1 parent e97100c commit f854c9b
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 8 deletions.
41 changes: 34 additions & 7 deletions packages/next/src/build/webpack/loaders/metadata/discover.ts
@@ -1,7 +1,7 @@
import type webpack from 'webpack'
import type {
CollectingMetadata,
PossibleImageFileNameConvention,
PossibleStaticMetadataFileNameConvention,
} from './types'
import path from 'path'
import { stringify } from 'querystring'
Expand All @@ -20,17 +20,22 @@ async function enumMetadataFiles(
{
resolvePath,
loaderContext,
// When set to true, possible filename without extension could: icon, icon0, ..., icon9
numericSuffix,
}: {
resolvePath: (pathname: string) => Promise<string>
loaderContext: webpack.LoaderContext<any>
numericSuffix: boolean
}
) {
const collectedFiles: string[] = []
// Possible filename without extension could: icon, icon0, ..., icon9

const possibleFileNames = [filename].concat(
Array(10)
.fill(0)
.map((_, index) => filename + index)
numericSuffix
? Array(10)
.fill(0)
.map((_, index) => filename + index)
: []
)
for (const name of possibleFileNames) {
for (const ext of extensions) {
Expand Down Expand Up @@ -74,6 +79,7 @@ export async function createStaticMetadataFromRoute(
apple: [],
twitter: [],
openGraph: [],
manifest: undefined,
}

const opts = {
Expand All @@ -82,16 +88,35 @@ export async function createStaticMetadataFromRoute(
}

async function collectIconModuleIfExists(
type: PossibleImageFileNameConvention
type: PossibleStaticMetadataFileNameConvention
) {
if (type === 'manifest') {
const staticManifestExtension = ['webmanifest', 'json']
const manifestFile = await enumMetadataFiles(
resolvedDir,
'manifest',
staticManifestExtension.concat(pageExtensions),
{ ...opts, numericSuffix: false }
)
if (manifestFile.length > 0) {
hasStaticMetadataFiles = true
const { name, ext } = path.parse(manifestFile[0])
const extension = staticManifestExtension.includes(ext.slice(1))
? ext.slice(1)
: 'webmanifest'
staticImagesMetadata.manifest = JSON.stringify(`/${name}.${extension}`)
}
return
}

const resolvedMetadataFiles = await enumMetadataFiles(
resolvedDir,
STATIC_METADATA_IMAGES[type].filename,
[
...STATIC_METADATA_IMAGES[type].extensions,
...(type === 'favicon' ? [] : pageExtensions),
],
opts
{ ...opts, numericSuffix: true }
)
resolvedMetadataFiles
.sort((a, b) => a.localeCompare(b))
Expand Down Expand Up @@ -123,6 +148,7 @@ export async function createStaticMetadataFromRoute(
collectIconModuleIfExists('openGraph'),
collectIconModuleIfExists('twitter'),
isRootLayer && collectIconModuleIfExists('favicon'),
isRootLayer && collectIconModuleIfExists('manifest'),
])

return hasStaticMetadataFiles ? staticImagesMetadata : null
Expand All @@ -137,6 +163,7 @@ export function createMetadataExportsCode(
apple: [${metadata.apple.join(',')}],
openGraph: [${metadata.openGraph.join(',')}],
twitter: [${metadata.twitter.join(',')}],
manifest: ${metadata.manifest ? metadata.manifest : 'undefined'}
}`
: ''
}
6 changes: 6 additions & 0 deletions packages/next/src/build/webpack/loaders/metadata/types.ts
Expand Up @@ -11,6 +11,7 @@ export type CollectingMetadata = {
apple: string[]
twitter: string[]
openGraph: string[]
manifest?: string
}

// Contain the collecting evaluated image module
Expand All @@ -19,6 +20,7 @@ export type CollectedMetadata = {
apple: ComponentModule[]
twitter: ComponentModule[] | null
openGraph: ComponentModule[] | null
manifest?: string
}

export type MetadataImageModule = {
Expand All @@ -38,3 +40,7 @@ export type PossibleImageFileNameConvention =
| 'favicon'
| 'twitter'
| 'openGraph'

export type PossibleStaticMetadataFileNameConvention =
| PossibleImageFileNameConvention
| 'manifest'
6 changes: 5 additions & 1 deletion packages/next/src/lib/metadata/resolve-metadata.ts
Expand Up @@ -45,7 +45,7 @@ function mergeStaticMetadata(
staticFilesMetadata: StaticMetadata
) {
if (!staticFilesMetadata) return
const { icon, apple, openGraph, twitter } = staticFilesMetadata
const { icon, apple, openGraph, twitter, manifest } = staticFilesMetadata
if (icon || apple) {
metadata.icons = {
icon: icon || [],
Expand All @@ -67,6 +67,9 @@ function mergeStaticMetadata(
)
metadata.openGraph = resolvedOpenGraph
}
if (manifest) {
metadata.manifest = manifest
}

return metadata
}
Expand Down Expand Up @@ -249,6 +252,7 @@ async function resolveStaticMetadata(components: ComponentsType, props: any) {
apple,
openGraph,
twitter,
manifest: metadata.manifest,
}

return staticMetadata
Expand Down
5 changes: 5 additions & 0 deletions test/e2e/app-dir/metadata-dynamic-routes/index.test.ts
Expand Up @@ -201,6 +201,11 @@ createNextDescribe(

expect($('link[rel="favicon"]')).toHaveLength(0)

// manifest
expect($('link[rel="manifest"]').attr('href')).toBe(
'/manifest.webmanifest'
)

// non absolute urls
expect($icon.attr('href')).toContain('/icon')
expect($icon.attr('href')).toMatch(hashRegex)
Expand Down

0 comments on commit f854c9b

Please sign in to comment.