1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Provide a way to copy files in exportPathMap (#5089)

Related #4659 

Adds the possibility for users to copy files inside of `exportPathMap`. This allows for adding `robots.txt` `sitemap.xml` etc. another use case is for https://github.com/hanford/next-offline, currently it's manually reading the buildId in `exportPathMap`.

To allow users to do this we'll introduce a new parameter holding an object with the following keys:

- `dev` - `true` when `exportPathMap` is being called in development. `false` when running `next export`. In development `exportPathMap` is used to define routes and behavior like copying files is not required.
- `dir` - Absolute path to the project directory
- `outDir` - Absolute path to the `out` directory (configurable with `-o` or `--outdir`). When `dev` is `true` the value of `outDir` will be `null`.
- `distDir` - Absolute path to the `.next` directory (configurable using the `distDir` config key)
- `buildId` - The buildId the export is running for

Example usage:

```js
// next.config.js
const fs = require('fs')
const {join} = require('path')
const {promisify} = require('util')
const copyFile = promisify(fs.copyFile)

module.exports = {
  exportPathMap: async function (defaultPathMap, {dev, dir, outDir, distDir, buildId}) {
    if(dev) {
      return defaultPathMap
    }
    // This will copy robots.txt from your project root into the out directory
    await copyFile(join(dir, 'robots.txt'), join(outDir, 'robots.txt'))
    return defaultPathMap
  }
}
```
This commit is contained in:
Tim Neutkens 2018-09-04 16:01:50 +02:00 committed by GitHub
parent b39b44ac23
commit a8a97b07c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 19 deletions

View file

@ -1479,7 +1479,7 @@ next build
next export next export
``` ```
By default `next export` doesn't require any configuration. It will generate a default `exportPathMap` containing the routes to pages inside the `pages` directory. By default `next export` doesn't require any configuration. It will generate a default `exportPathMap` containing the routes to pages inside the `pages` directory. This default mapping is available as `defaultPathMap` in the example below.
If your application has dynamic routes you can add a dynamic `exportPathMap` in `next.config.js`. If your application has dynamic routes you can add a dynamic `exportPathMap` in `next.config.js`.
This function is asynchronous and gets the default `exportPathMap` as a parameter. This function is asynchronous and gets the default `exportPathMap` as a parameter.
@ -1538,6 +1538,36 @@ For an example, simply visit the `out` directory and run following command to de
now now
``` ```
### Copying custom files
In case you have to copy custom files like a robots.txt or generate a sitemap.xml you can do this inside of `exportPathMap`.
`exportPathMap` gets a few contextual parameter to aid you with creating/copying files:
- `dev` - `true` when `exportPathMap` is being called in development. `false` when running `next export`. In development `exportPathMap` is used to define routes and behavior like copying files is not required.
- `dir` - Absolute path to the project directory
- `outDir` - Absolute path to the `out` directory (configurable with `-o` or `--outdir`). When `dev` is `true` the value of `outDir` will be `null`.
- `distDir` - Absolute path to the `.next` directory (configurable using the `distDir` config key)
- `buildId` - The buildId the export is running for
```js
// next.config.js
const fs = require('fs')
const {join} = require('path')
const {promisify} = require('util')
const copyFile = promisify(fs.copyFile)
module.exports = {
exportPathMap: async function (defaultPathMap, {dev, dir, outDir, distDir, buildId}) {
if (dev) {
return defaultPathMap
}
// This will copy robots.txt from your project root into the out directory
await copyFile(join(dir, 'robots.txt'), join(outDir, 'robots.txt'))
return defaultPathMap
}
}
```
### Limitation ### Limitation
With `next export`, we build a HTML version of your app. At export time we will run `getInitialProps` of your pages. With `next export`, we build a HTML version of your app. At export time we will run `getInitialProps` of your pages.

View file

@ -10,6 +10,11 @@ import { setAssetPrefix } from '../lib/asset'
import * as envConfig from '../lib/runtime-config' import * as envConfig from '../lib/runtime-config'
export default async function (dir, options, configuration) { export default async function (dir, options, configuration) {
function log (message) {
if (options.silent) return
console.log(message)
}
dir = resolve(dir) dir = resolve(dir)
const nextConfig = configuration || loadConfig(PHASE_EXPORT, dir) const nextConfig = configuration || loadConfig(PHASE_EXPORT, dir)
const distDir = join(dir, nextConfig.distDir) const distDir = join(dir, nextConfig.distDir)
@ -64,17 +69,6 @@ export default async function (dir, options, configuration) {
) )
} }
// Copy dynamic import chunks
if (existsSync(join(distDir, 'chunks'))) {
log(' copying dynamic import chunks')
await mkdirp(join(outDir, '_next', 'webpack'))
await cp(
join(distDir, 'chunks'),
join(outDir, '_next', 'webpack', 'chunks')
)
}
// Get the exportPathMap from the config file // Get the exportPathMap from the config file
if (typeof nextConfig.exportPathMap !== 'function') { if (typeof nextConfig.exportPathMap !== 'function') {
console.log(`> No "exportPathMap" found in "${CONFIG_FILE}". Generating map from "./pages"`) console.log(`> No "exportPathMap" found in "${CONFIG_FILE}". Generating map from "./pages"`)
@ -114,7 +108,7 @@ export default async function (dir, options, configuration) {
nextExport: true nextExport: true
} }
const exportPathMap = await nextConfig.exportPathMap(defaultPathMap) const exportPathMap = await nextConfig.exportPathMap(defaultPathMap, {dev: false, dir, outDir, distDir, buildId})
const exportPaths = Object.keys(exportPathMap) const exportPaths = Object.keys(exportPathMap)
for (const path of exportPaths) { for (const path of exportPaths) {
@ -146,9 +140,4 @@ export default async function (dir, options, configuration) {
// Add an empty line to the console for the better readability. // Add an empty line to the console for the better readability.
log('') log('')
function log (message) {
if (options.silent) return
console.log(message)
}
} }

View file

@ -155,7 +155,7 @@ export default class Server {
// So that the user doesn't have to define a custom server reading the exportPathMap // So that the user doesn't have to define a custom server reading the exportPathMap
if (this.dev && this.nextConfig.exportPathMap) { if (this.dev && this.nextConfig.exportPathMap) {
console.log('Defining routes from exportPathMap') console.log('Defining routes from exportPathMap')
const exportPathMap = await this.nextConfig.exportPathMap({}) // In development we can't give a default path mapping const exportPathMap = await this.nextConfig.exportPathMap({}, {dev: true, dir: this.dir, outDir: null, distDir: this.distDir, buildId: this.buildId}) // In development we can't give a default path mapping
for (const path in exportPathMap) { for (const path in exportPathMap) {
const {page, query = {}} = exportPathMap[path] const {page, query = {}} = exportPathMap[path]
routes[path] = async (req, res, params, parsedUrl) => { routes[path] = async (req, res, params, parsedUrl) => {