feat: allows overriding import map location (#11532)
By default, Payload only attempts to locate the import map file in the following locations:
- `src/app/(payload)/{adminroute}/importMap.js`
- `app/(payload)/{adminroute}/importMap.js`
This is fine for most projects, but sometimes you may want to place the import map - or the Payload admin directory - somewhere else.
This PR adds a new `importMapFile` property that allows you to override this heuristic and specify your own import map path.
This commit is contained in:
@@ -119,10 +119,32 @@ For details on how to build Custom Components, see [Building Custom Components](
|
||||
|
||||
### Import Map
|
||||
|
||||
In order for Payload to make use of [Component Paths](#component-paths), an "Import Map" is automatically generated at `app/(payload)/admin/importMap.js`. This file contains every Custom Component in your config, keyed to their respective paths. When Payload needs to lookup a component, it uses this file to find the correct import.
|
||||
In order for Payload to make use of [Component Paths](#component-paths), an "Import Map" is automatically generated at either `src/app/(payload)/admin/importMap.js` or `app/(payload)/admin/importMap.js`. This file contains every Custom Component in your config, keyed to their respective paths. When Payload needs to lookup a component, it uses this file to find the correct import.
|
||||
|
||||
The Import Map is automatically regenerated at startup and whenever Hot Module Replacement (HMR) runs, or you can run `payload generate:importmap` to manually regenerate it.
|
||||
|
||||
#### Overriding Import Map Location
|
||||
|
||||
Using the `config.admin.importMap.importMapFile` property, you can override the location of the import map. This is useful if you want to place the import map in a different location, or if you want to use a custom file name.
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import path from 'path'
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
const config = buildConfig({
|
||||
// ...
|
||||
admin: {
|
||||
importMap: {
|
||||
baseDir: path.resolve(dirname, 'src'),
|
||||
importMapFile: path.resolve(dirname, 'app', '(payload)', 'custom-import-map.js'), // highlight-line
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
#### Custom Imports
|
||||
|
||||
If needed, custom items can be appended onto the Import Map. This is mostly only relevant for plugin authors who need to add a custom import that is not referenced in a known location.
|
||||
@@ -146,7 +168,7 @@ export default buildConfig({
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Building Custom Components
|
||||
|
||||
@@ -209,16 +209,29 @@ export async function writeImportMap({
|
||||
log?: boolean
|
||||
rootDir: string
|
||||
}) {
|
||||
let importMapFolderPath = ''
|
||||
if (fs.existsSync(path.resolve(rootDir, `app/(payload)${config.routes.admin}/`))) {
|
||||
importMapFolderPath = path.resolve(rootDir, `app/(payload)${config.routes.admin}/`)
|
||||
} else if (fs.existsSync(path.resolve(rootDir, `src/app/(payload)${config.routes.admin}/`))) {
|
||||
importMapFolderPath = path.resolve(rootDir, `src/app/(payload)${config.routes.admin}/`)
|
||||
let importMapFilePath: string | undefined = undefined
|
||||
|
||||
if (config?.admin?.importMap?.importMapFile?.length) {
|
||||
if (!fs.existsSync(config.admin.importMap.importMapFile)) {
|
||||
throw new Error(
|
||||
`Could not find the import map file at ${config.admin.importMap.importMapFile}`,
|
||||
)
|
||||
}
|
||||
importMapFilePath = config.admin.importMap.importMapFile
|
||||
} else {
|
||||
const appLocation = path.resolve(rootDir, `app/(payload)${config.routes.admin}/`)
|
||||
const srcAppLocation = path.resolve(rootDir, `src/app/(payload)${config.routes.admin}/`)
|
||||
|
||||
if (fs.existsSync(appLocation)) {
|
||||
importMapFilePath = path.resolve(appLocation, fileName)
|
||||
} else if (fs.existsSync(srcAppLocation)) {
|
||||
importMapFilePath = path.resolve(srcAppLocation, fileName)
|
||||
} else {
|
||||
throw new Error(
|
||||
`Could not find the payload admin directory. Looked in ${path.resolve(rootDir, `app/(payload)${config.routes.admin}/`)} and ${path.resolve(rootDir, `src/app/(payload)${config.routes.admin}/`)}`,
|
||||
`Could not find Payload import map folder. Looked in ${appLocation} and ${srcAppLocation}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const imports: string[] = []
|
||||
for (const [identifier, { path, specifier }] of Object.entries(importMap)) {
|
||||
@@ -237,8 +250,6 @@ ${mapKeys.join(',\n')}
|
||||
}
|
||||
`
|
||||
|
||||
const importMapFilePath = path.resolve(importMapFolderPath, fileName)
|
||||
|
||||
if (!force) {
|
||||
// Read current import map and check in the IMPORTS if there are any new imports. If not, don't write the file.
|
||||
const currentImportMap = await fs.promises.readFile(importMapFilePath, 'utf-8')
|
||||
|
||||
@@ -855,9 +855,9 @@ export type Config = {
|
||||
* @default true
|
||||
*/
|
||||
autoGenerate?: boolean
|
||||
/** The base directory for component paths starting with /.
|
||||
*
|
||||
* By default, this is process.cwd()
|
||||
/**
|
||||
* The base directory for component paths starting with /.
|
||||
* @default process.cwd()
|
||||
**/
|
||||
baseDir?: string
|
||||
/**
|
||||
@@ -873,6 +873,11 @@ export type Config = {
|
||||
imports: Imports
|
||||
}) => void
|
||||
>
|
||||
/**
|
||||
* If Payload cannot find the import map file location automatically,
|
||||
* you can manually provide it here.
|
||||
*/
|
||||
importMapFile?: string
|
||||
}
|
||||
livePreview?: {
|
||||
collections?: string[]
|
||||
|
||||
Reference in New Issue
Block a user