@netlify/plugin-nextjs 3.9.1 → 4.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -56
- package/lib/constants.js +21 -0
- package/lib/helpers/cache.js +20 -0
- package/lib/helpers/config.js +115 -0
- package/lib/helpers/files.js +48 -0
- package/lib/helpers/functions.js +64 -0
- package/lib/helpers/verification.js +79 -0
- package/lib/index.js +47 -0
- package/lib/templates/getHandler.js +164 -0
- package/lib/templates/getPageResolver.js +24 -0
- package/lib/templates/ipx.js +8 -0
- package/manifest.yml +1 -1
- package/package.json +46 -53
- package/LICENSE.md +0 -7
- package/helpers/cacheBuild.js +0 -31
- package/helpers/checkNxConfig.js +0 -56
- package/helpers/copyUnstableIncludedDirs.js +0 -27
- package/helpers/doesNotNeedPlugin.js +0 -49
- package/helpers/doesSiteUseNextOnNetlify.js +0 -20
- package/helpers/getNextConfig.js +0 -46
- package/helpers/getNextRoot.js +0 -20
- package/helpers/isStaticExportProject.js +0 -20
- package/helpers/resolveNextModule.js +0 -30
- package/helpers/usesBuildCommand.js +0 -37
- package/helpers/validateNextUsage.js +0 -53
- package/helpers/verifyBuildTarget.js +0 -69
- package/index.js +0 -175
- package/src/index.js +0 -94
- package/src/lib/config.js +0 -58
- package/src/lib/constants/regex.js +0 -9
- package/src/lib/helpers/addDefaultLocaleRedirect.js +0 -25
- package/src/lib/helpers/addLocaleRedirects.js +0 -19
- package/src/lib/helpers/asyncForEach.js +0 -7
- package/src/lib/helpers/convertToBasePathRedirects.js +0 -80
- package/src/lib/helpers/copyDynamicImportChunks.js +0 -39
- package/src/lib/helpers/formatRedirectTarget.js +0 -9
- package/src/lib/helpers/getDataRouteForRoute.js +0 -30
- package/src/lib/helpers/getFilePathForRoute.js +0 -10
- package/src/lib/helpers/getI18n.js +0 -10
- package/src/lib/helpers/getNetlifyFunctionName.js +0 -38
- package/src/lib/helpers/getNetlifyRoutes.js +0 -45
- package/src/lib/helpers/getNextDistDir.js +0 -12
- package/src/lib/helpers/getNextSrcDir.js +0 -5
- package/src/lib/helpers/getPagesManifest.js +0 -19
- package/src/lib/helpers/getPrerenderManifest.js +0 -40
- package/src/lib/helpers/getPreviewModeFunctionName.js +0 -5
- package/src/lib/helpers/getRoutesManifest.js +0 -12
- package/src/lib/helpers/getSortedRedirects.js +0 -37
- package/src/lib/helpers/handleFileTracking.js +0 -61
- package/src/lib/helpers/isApiRoute.js +0 -4
- package/src/lib/helpers/isDynamicRoute.js +0 -6
- package/src/lib/helpers/isFrameworkRoute.js +0 -5
- package/src/lib/helpers/isHtmlFile.js +0 -4
- package/src/lib/helpers/isRootCatchAllRedirect.js +0 -6
- package/src/lib/helpers/isRouteInPrerenderManifest.js +0 -23
- package/src/lib/helpers/isRouteWithDataRoute.js +0 -13
- package/src/lib/helpers/isRouteWithFallback.js +0 -12
- package/src/lib/helpers/logger.js +0 -44
- package/src/lib/helpers/removeFileExtension.js +0 -4
- package/src/lib/helpers/runJobsQueue.js +0 -18
- package/src/lib/helpers/setupNetlifyFunctionForPage.js +0 -44
- package/src/lib/helpers/setupStaticFileForPage.js +0 -18
- package/src/lib/pages/api/pages.js +0 -22
- package/src/lib/pages/api/redirects.js +0 -13
- package/src/lib/pages/api/setup.js +0 -15
- package/src/lib/pages/getInitialProps/pages.js +0 -40
- package/src/lib/pages/getInitialProps/redirects.js +0 -26
- package/src/lib/pages/getInitialProps/setup.js +0 -15
- package/src/lib/pages/getServerSideProps/pages.js +0 -43
- package/src/lib/pages/getServerSideProps/redirects.js +0 -44
- package/src/lib/pages/getServerSideProps/setup.js +0 -15
- package/src/lib/pages/getStaticProps/pages.js +0 -26
- package/src/lib/pages/getStaticProps/redirects.js +0 -70
- package/src/lib/pages/getStaticProps/setup.js +0 -68
- package/src/lib/pages/getStaticPropsWithFallback/pages.js +0 -24
- package/src/lib/pages/getStaticPropsWithFallback/redirects.js +0 -51
- package/src/lib/pages/getStaticPropsWithFallback/setup.js +0 -29
- package/src/lib/pages/getStaticPropsWithRevalidate/pages.js +0 -45
- package/src/lib/pages/getStaticPropsWithRevalidate/redirects.js +0 -55
- package/src/lib/pages/getStaticPropsWithRevalidate/setup.js +0 -40
- package/src/lib/pages/withoutProps/pages.js +0 -27
- package/src/lib/pages/withoutProps/redirects.js +0 -51
- package/src/lib/pages/withoutProps/setup.js +0 -34
- package/src/lib/pages/worker.js +0 -19
- package/src/lib/steps/copyNextAssets.js +0 -31
- package/src/lib/steps/copyPublicFiles.js +0 -18
- package/src/lib/steps/prepareFolders.js +0 -39
- package/src/lib/steps/setupHeaders.js +0 -37
- package/src/lib/steps/setupImageFunction.js +0 -17
- package/src/lib/steps/setupPages.js +0 -25
- package/src/lib/steps/setupRedirects.js +0 -105
- package/src/lib/templates/getHandlerFunction.js +0 -209
- package/src/lib/templates/getTemplate.js +0 -15
- package/src/lib/templates/imageFunction.js +0 -135
- package/src/next-on-netlify.js +0 -22
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
|
-
|
|
3
|
-
// Generate the Netlify Function name for the given file path.
|
|
4
|
-
// The file path will be pages/directory/subdirectory/[id].js
|
|
5
|
-
// The function name will be next_directory_subdirectory_[id]
|
|
6
|
-
// We do this because every function needs to be at the top-level, i.e.
|
|
7
|
-
// nested functions are not allowed.
|
|
8
|
-
const getNetlifyFunctionName = (filePath, isApiPage) => {
|
|
9
|
-
// Remove pages/ from file path:
|
|
10
|
-
// pages/directory/page.js > directory/page.js
|
|
11
|
-
const relativeFilePath = path.relative('pages', filePath)
|
|
12
|
-
|
|
13
|
-
// Extract directory path and file name without extension
|
|
14
|
-
const { dir: directoryPath, name } = path.parse(relativeFilePath)
|
|
15
|
-
|
|
16
|
-
// Combine next, directory path, and file name:
|
|
17
|
-
// next/directory/page
|
|
18
|
-
const filePathWithoutExtension = path.join('next', directoryPath, name)
|
|
19
|
-
|
|
20
|
-
// Replace slashes with underscores:
|
|
21
|
-
// next/directory/page > next_directory_page
|
|
22
|
-
let functionName = filePathWithoutExtension.split(path.sep).join('_')
|
|
23
|
-
|
|
24
|
-
// Netlify Function names may not contain periods or square brackets.
|
|
25
|
-
// To be safe, we keep only alphanumeric characters and underscores.
|
|
26
|
-
// See: https://community.netlify.com/t/failed-to-upload-functions-file-function-too-large/3549/8
|
|
27
|
-
const cleanNameRegex = new RegExp(/[^\w\d]/g)
|
|
28
|
-
// Allow users to use background functions for /api pages *only*
|
|
29
|
-
// Note: this means that there is a chance a Next on Netlify user could
|
|
30
|
-
// unknowingly create a background function if they're not familiar with them
|
|
31
|
-
// and their syntax
|
|
32
|
-
const allowBackgroundRegex = new RegExp(/[^\w\d-]|-(?!background$)/g)
|
|
33
|
-
functionName = functionName.replace(isApiPage ? allowBackgroundRegex : cleanNameRegex, '')
|
|
34
|
-
|
|
35
|
-
return functionName
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
module.exports = getNetlifyFunctionName
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// Adapted from @sls-next/lambda-at-edge (v1.2.0-alpha.3)
|
|
2
|
-
// See: https://github.com/danielcondemarin/serverless-next.js/blob/57142970b08e6bc3faf0fc70749b3b0501ad7869/packages/lambda-at-edge/src/lib/expressifyDynamicRoute.ts#L4
|
|
3
|
-
|
|
4
|
-
const { CATCH_ALL_REGEX, OPTIONAL_CATCH_ALL_REGEX, DYNAMIC_PARAMETER_REGEX } = require('../constants/regex')
|
|
5
|
-
|
|
6
|
-
// Convert dynamic NextJS routes into their Netlify-equivalent
|
|
7
|
-
// Note that file endings (.json) must be removed for catch-all and optional
|
|
8
|
-
// catch-all routes to work. That's why the regexes defined above include
|
|
9
|
-
// the (.json)? option
|
|
10
|
-
const getNetlifyRoutes = (nextRoute) => {
|
|
11
|
-
let netlifyRoutes = [nextRoute]
|
|
12
|
-
|
|
13
|
-
// If the route is an optional catch-all route, we need to add a second
|
|
14
|
-
// Netlify route for the base path (when no parameters are present).
|
|
15
|
-
// The file ending must be present!
|
|
16
|
-
if (OPTIONAL_CATCH_ALL_REGEX.test(nextRoute)) {
|
|
17
|
-
let netlifyRoute = nextRoute.replace(OPTIONAL_CATCH_ALL_REGEX, '$2')
|
|
18
|
-
|
|
19
|
-
// When optional catch-all route is at top-level, the regex on line 19 will
|
|
20
|
-
// create an empty string, but actually needs to be a forward slash
|
|
21
|
-
if (netlifyRoute === '') netlifyRoute = '/'
|
|
22
|
-
|
|
23
|
-
// When optional catch-all route is at top-level, the regex on line 19 will
|
|
24
|
-
// create an incorrect route for the data route. For example, it creates
|
|
25
|
-
// /_next/data/%BUILDID%.json, but NextJS looks for
|
|
26
|
-
// /_next/data/%BUILDID%/index.json
|
|
27
|
-
netlifyRoute = netlifyRoute.replace(/(\/_next\/data\/[^/]+).json/, '$1/index.json')
|
|
28
|
-
|
|
29
|
-
// Add second route to the front of the array
|
|
30
|
-
netlifyRoutes.unshift(netlifyRoute)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Replace catch-all, e.g., [...slug]
|
|
34
|
-
netlifyRoutes = netlifyRoutes.map((route) => route.replace(CATCH_ALL_REGEX, '/:$1/*'))
|
|
35
|
-
|
|
36
|
-
// Replace optional catch-all, e.g., [[...slug]]
|
|
37
|
-
netlifyRoutes = netlifyRoutes.map((route) => route.replace(OPTIONAL_CATCH_ALL_REGEX, '/*'))
|
|
38
|
-
|
|
39
|
-
// Replace dynamic parameters, e.g., [id]
|
|
40
|
-
netlifyRoutes = netlifyRoutes.map((route) => route.replace(DYNAMIC_PARAMETER_REGEX, '/:$1'))
|
|
41
|
-
|
|
42
|
-
return netlifyRoutes
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
module.exports = getNetlifyRoutes
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// Get the NextJS distDir specified in next.config.js
|
|
2
|
-
const { join } = require('path')
|
|
3
|
-
|
|
4
|
-
const getNextConfig = require('../../../helpers/getNextConfig')
|
|
5
|
-
|
|
6
|
-
const getNextDistDir = async () => {
|
|
7
|
-
const nextConfig = await getNextConfig()
|
|
8
|
-
|
|
9
|
-
return join('.', nextConfig.distDir)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
module.exports = getNextDistDir
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
const { join } = require('path')
|
|
2
|
-
|
|
3
|
-
const { existsSync, readJSONSync } = require('fs-extra')
|
|
4
|
-
|
|
5
|
-
const getNextDistDir = require('./getNextDistDir')
|
|
6
|
-
|
|
7
|
-
const getPagesManifest = async () => {
|
|
8
|
-
const nextDistDir = await getNextDistDir()
|
|
9
|
-
const manifestPath = join(nextDistDir, 'serverless', 'pages-manifest.json')
|
|
10
|
-
if (!existsSync(manifestPath)) return {}
|
|
11
|
-
const contents = readJSONSync(manifestPath)
|
|
12
|
-
// Next.js mistakenly puts backslashes in certain paths on Windows, replace
|
|
13
|
-
Object.entries(contents).forEach(([key, value]) => {
|
|
14
|
-
contents[key] = value.replace(/\\/g, '/')
|
|
15
|
-
})
|
|
16
|
-
return contents
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
module.exports = getPagesManifest
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
const { join } = require('path')
|
|
2
|
-
|
|
3
|
-
const { readJSONSync } = require('fs-extra')
|
|
4
|
-
|
|
5
|
-
const getNextConfig = require('../../../helpers/getNextConfig')
|
|
6
|
-
|
|
7
|
-
const asyncForEach = require('./asyncForEach')
|
|
8
|
-
const getDataRouteForRoute = require('./getDataRouteForRoute')
|
|
9
|
-
const getNextDistDir = require('./getNextDistDir')
|
|
10
|
-
|
|
11
|
-
const transformManifestForI18n = async (manifest) => {
|
|
12
|
-
const { routes } = manifest
|
|
13
|
-
const newRoutes = {}
|
|
14
|
-
await asyncForEach(Object.entries(routes), async ([route, { dataRoute, srcRoute, ...params }]) => {
|
|
15
|
-
const isDynamicRoute = Boolean(srcRoute)
|
|
16
|
-
if (isDynamicRoute) {
|
|
17
|
-
newRoutes[route] = routes[route]
|
|
18
|
-
} else {
|
|
19
|
-
const [, locale] = route.split('/')
|
|
20
|
-
const routeWithoutLocale = `/${route.split('/').slice(2, route.split('/').length).join('/')}`
|
|
21
|
-
newRoutes[route] = {
|
|
22
|
-
dataRoute: await getDataRouteForRoute(routeWithoutLocale, locale),
|
|
23
|
-
srcRoute: routeWithoutLocale,
|
|
24
|
-
...params,
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
return { ...manifest, routes: newRoutes }
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const getPrerenderManifest = async () => {
|
|
33
|
-
const nextConfig = await getNextConfig()
|
|
34
|
-
const nextDistDir = await getNextDistDir()
|
|
35
|
-
const manifest = readJSONSync(join(nextDistDir, 'prerender-manifest.json'))
|
|
36
|
-
if (nextConfig.i18n) return await transformManifestForI18n(manifest)
|
|
37
|
-
return manifest
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
module.exports = getPrerenderManifest
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// Some pages (getStaticProps/withFallback) require a separate standard function for preview mode; this provides the name for that function, to be called in several places
|
|
2
|
-
|
|
3
|
-
const getPreviewModeFunctionName = (functionName) => `preview-${functionName}`
|
|
4
|
-
|
|
5
|
-
module.exports = getPreviewModeFunctionName
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
const { join } = require('path')
|
|
2
|
-
|
|
3
|
-
const { readJSONSync } = require('fs-extra')
|
|
4
|
-
|
|
5
|
-
const getNextDistDir = require('./getNextDistDir')
|
|
6
|
-
|
|
7
|
-
const getRoutesManifest = async () => {
|
|
8
|
-
const nextDistDir = await getNextDistDir()
|
|
9
|
-
return readJSONSync(join(nextDistDir, 'routes-manifest.json'))
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
module.exports = getRoutesManifest
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
const resolveNextModule = require('../../../helpers/resolveNextModule')
|
|
2
|
-
|
|
3
|
-
const removeFileExtension = require('./removeFileExtension')
|
|
4
|
-
|
|
5
|
-
// Return an array of redirects sorted in order of specificity, i.e., more generic
|
|
6
|
-
// routes precede more specific ones
|
|
7
|
-
const getSortedRedirects = (redirects) => {
|
|
8
|
-
// The @sls-next getSortedRoutes does not correctly sort routes with file
|
|
9
|
-
// endings (e.g., json), so we remove them before sorting and add them back
|
|
10
|
-
// after sorting
|
|
11
|
-
const routesWithoutExtensions = redirects.map(({ route }) => removeFileExtension(route))
|
|
12
|
-
|
|
13
|
-
// Sort the "naked" routes
|
|
14
|
-
// eslint-disable-next-line import/no-dynamic-require
|
|
15
|
-
const { getSortedRoutes } = require(resolveNextModule(
|
|
16
|
-
[
|
|
17
|
-
// next <= 11.0.1
|
|
18
|
-
'next/dist/next-server/lib/router/utils/sorted-routes',
|
|
19
|
-
// next > 11.0.1
|
|
20
|
-
'next/dist/shared/lib/router/utils/sorted-routes',
|
|
21
|
-
],
|
|
22
|
-
process.cwd(),
|
|
23
|
-
))
|
|
24
|
-
const sortedRoutes = getSortedRoutes(routesWithoutExtensions)
|
|
25
|
-
|
|
26
|
-
// Return original routes in the sorted order
|
|
27
|
-
return redirects.sort((a, b) => {
|
|
28
|
-
// If routes are different, sort according to Next.js' getSortedRoutes
|
|
29
|
-
if (a.route !== b.route) {
|
|
30
|
-
return sortedRoutes.indexOf(removeFileExtension(a.route)) - sortedRoutes.indexOf(removeFileExtension(b.route))
|
|
31
|
-
}
|
|
32
|
-
// Otherwise, put the route with more conditions first
|
|
33
|
-
return (b.conditions || []).length - (a.conditions || []).length
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
module.exports = getSortedRedirects
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
const { join } = require('path')
|
|
2
|
-
|
|
3
|
-
const findCacheDir = require('find-cache-dir')
|
|
4
|
-
const { existsSync, readdirSync, readFileSync, removeSync, writeFileSync } = require('fs-extra')
|
|
5
|
-
|
|
6
|
-
const { NETLIFY_PUBLISH_PATH, NETLIFY_FUNCTIONS_PATH } = require('../config')
|
|
7
|
-
|
|
8
|
-
const TRACKING_FILE_SEPARATOR = '---'
|
|
9
|
-
const getDifference = (before, after) => after.filter((filePath) => !before.includes(filePath))
|
|
10
|
-
|
|
11
|
-
// Clean configured publish and functions folders and track next-on-netlify files
|
|
12
|
-
// for future cleans
|
|
13
|
-
const handleFileTracking = ({ functionsPath, publishPath }) => {
|
|
14
|
-
const isConfiguredFunctionsDir = functionsPath !== NETLIFY_FUNCTIONS_PATH
|
|
15
|
-
const isConfiguredPublishDir = publishPath !== NETLIFY_PUBLISH_PATH
|
|
16
|
-
|
|
17
|
-
const cacheDir = findCacheDir({ name: 'next-on-netlify', create: true })
|
|
18
|
-
if (!cacheDir) return () => {}
|
|
19
|
-
const trackingFilePath = join(cacheDir, '.nonfiletracking')
|
|
20
|
-
|
|
21
|
-
if (existsSync(trackingFilePath)) {
|
|
22
|
-
const trackingFile = readFileSync(trackingFilePath, 'utf8')
|
|
23
|
-
const [trackedFunctions, trackedPublish] = trackingFile.split(TRACKING_FILE_SEPARATOR)
|
|
24
|
-
const cleanConfiguredFiles = (trackedFiles, dirPath) => {
|
|
25
|
-
trackedFiles
|
|
26
|
-
.map((file) => file.trim())
|
|
27
|
-
.filter(Boolean)
|
|
28
|
-
.forEach((file) => {
|
|
29
|
-
const filePath = join(dirPath, file)
|
|
30
|
-
removeSync(filePath)
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (isConfiguredPublishDir) {
|
|
35
|
-
cleanConfiguredFiles(trackedPublish.split('\n'), publishPath)
|
|
36
|
-
}
|
|
37
|
-
if (isConfiguredFunctionsDir) {
|
|
38
|
-
cleanConfiguredFiles(trackedFunctions.split('\n'), functionsPath)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const functionsBeforeRun = existsSync(functionsPath) ? readdirSync(functionsPath) : []
|
|
43
|
-
const publishBeforeRun = existsSync(publishPath) ? readdirSync(publishPath) : []
|
|
44
|
-
|
|
45
|
-
// this callback will run at the end of nextOnNetlify()
|
|
46
|
-
const trackNewFiles = () => {
|
|
47
|
-
const functionsAfterRun =
|
|
48
|
-
isConfiguredFunctionsDir && existsSync(functionsPath) ? readdirSync(functionsPath) : functionsBeforeRun
|
|
49
|
-
const publishAfterRun =
|
|
50
|
-
isConfiguredPublishDir && existsSync(publishPath) ? readdirSync(publishPath) : publishBeforeRun
|
|
51
|
-
const newFunctionsFiles = getDifference(functionsBeforeRun, functionsAfterRun)
|
|
52
|
-
const newPublishFiles = getDifference(publishBeforeRun, publishAfterRun)
|
|
53
|
-
|
|
54
|
-
const allTrackedFiles = [...newFunctionsFiles, TRACKING_FILE_SEPARATOR, ...newPublishFiles]
|
|
55
|
-
writeFileSync(trackingFilePath, allTrackedFiles.join('\n'))
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return trackNewFiles
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
module.exports = handleFileTracking
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// Return true if the redirect is a root level catch-all
|
|
2
|
-
// (e.g., /[[...slug]] or /[...slug])
|
|
3
|
-
const isRootCatchAllRedirect = (redirect) =>
|
|
4
|
-
redirect.startsWith('/*') || (redirect.startsWith('/:') && redirect.includes('/*'))
|
|
5
|
-
|
|
6
|
-
module.exports = isRootCatchAllRedirect
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const getI18n = require('./getI18n')
|
|
2
|
-
const getPrerenderManifest = require('./getPrerenderManifest')
|
|
3
|
-
|
|
4
|
-
// Return true if the route is defined in the prerender manifest
|
|
5
|
-
const isRouteInPrerenderManifest = async (route) => {
|
|
6
|
-
const i18n = await getI18n()
|
|
7
|
-
const { defaultLocale } = i18n
|
|
8
|
-
const { routes, dynamicRoutes } = await getPrerenderManifest()
|
|
9
|
-
|
|
10
|
-
const isRouteInManifestWithI18n = () => {
|
|
11
|
-
let isStaticRoute = false
|
|
12
|
-
Object.entries(routes).forEach(([staticRoute, { srcRoute }]) => {
|
|
13
|
-
// This is because in i18n we set the nakedRoute to be the srcRoute in the manifest
|
|
14
|
-
if (route === srcRoute) isStaticRoute = true
|
|
15
|
-
})
|
|
16
|
-
return isStaticRoute || route in dynamicRoutes
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (defaultLocale) return isRouteInManifestWithI18n(route)
|
|
20
|
-
return route in routes || route in dynamicRoutes
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
module.exports = isRouteInPrerenderManifest
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
const getRoutesManifest = require('./getRoutesManifest')
|
|
2
|
-
|
|
3
|
-
// Return true if the route has a data route in the routes manifest
|
|
4
|
-
const isRouteWithDataRoute = async (route) => {
|
|
5
|
-
const { dataRoutes } = await getRoutesManifest()
|
|
6
|
-
|
|
7
|
-
// If no data routes exist, return false
|
|
8
|
-
if (dataRoutes == null) return false
|
|
9
|
-
|
|
10
|
-
return dataRoutes.find((dataRoute) => dataRoute.page === route)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
module.exports = isRouteWithDataRoute
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
const getPrerenderManifest = require('./getPrerenderManifest')
|
|
2
|
-
|
|
3
|
-
const isRouteWithFallback = async (route) => {
|
|
4
|
-
if (!route) return false
|
|
5
|
-
|
|
6
|
-
const { dynamicRoutes } = await getPrerenderManifest()
|
|
7
|
-
|
|
8
|
-
// Fallback "blocking" routes will have fallback: null in manifest
|
|
9
|
-
return dynamicRoutes[route] && dynamicRoutes[route].fallback !== false
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
module.exports = isRouteWithFallback
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// Helpers for writing info to console.log
|
|
2
|
-
const { program } = require('commander')
|
|
3
|
-
|
|
4
|
-
// Number of items processed in current build step
|
|
5
|
-
let itemsCount = 0
|
|
6
|
-
|
|
7
|
-
// Format in bold
|
|
8
|
-
const logTitle = (...args) => {
|
|
9
|
-
// Finish previous log section
|
|
10
|
-
finishLogForBuildStep()
|
|
11
|
-
|
|
12
|
-
// Print title
|
|
13
|
-
log(`\x1b[1m${args.join(' ')}\x1b[22m`)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Indent by three spaces
|
|
17
|
-
const logItem = (...args) => {
|
|
18
|
-
// Display item if within max log lines
|
|
19
|
-
if (itemsCount < program.maxLogLines) log(' ', ...args)
|
|
20
|
-
|
|
21
|
-
itemsCount += 1
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Just console.log
|
|
25
|
-
const log = (...args) => console.log(...args)
|
|
26
|
-
|
|
27
|
-
// Finish log section: Write a single line for any suppressed/hidden items
|
|
28
|
-
// and reset the item counter
|
|
29
|
-
const finishLogForBuildStep = () => {
|
|
30
|
-
// Display number of suppressed log lines
|
|
31
|
-
if (itemsCount > program.maxLogLines) {
|
|
32
|
-
const hiddenLines = itemsCount - program.maxLogLines
|
|
33
|
-
log(' ', '+', hiddenLines, 'more', '(run next-on-netlify with --max-log-lines XX to', 'show more or fewer lines)')
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Reset counter
|
|
37
|
-
itemsCount = 0
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
module.exports = {
|
|
41
|
-
logTitle,
|
|
42
|
-
logItem,
|
|
43
|
-
log,
|
|
44
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
const os = require('os')
|
|
2
|
-
|
|
3
|
-
const fastq = require('fastq')
|
|
4
|
-
|
|
5
|
-
const { processPage } = require('../pages/worker')
|
|
6
|
-
|
|
7
|
-
// TODO: benchmark a large site to find a good value for this
|
|
8
|
-
const PAGE_CONCURRENCY = 4
|
|
9
|
-
|
|
10
|
-
const runJobsQueue = (jobs) => {
|
|
11
|
-
console.log(`Building ${jobs.length} pages`)
|
|
12
|
-
|
|
13
|
-
const queue = fastq.promise(processPage, PAGE_CONCURRENCY)
|
|
14
|
-
|
|
15
|
-
return Promise.all(jobs.map((job) => queue.push(job)))
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
module.exports = runJobsQueue
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
const { join } = require('path')
|
|
2
|
-
|
|
3
|
-
const { copySync, writeFile, ensureDir, copy } = require('fs-extra')
|
|
4
|
-
|
|
5
|
-
const { TEMPLATES_DIR } = require('../config')
|
|
6
|
-
const getTemplate = require('../templates/getTemplate')
|
|
7
|
-
|
|
8
|
-
const copyDynamicImportChunks = require('./copyDynamicImportChunks')
|
|
9
|
-
const getNetlifyFunctionName = require('./getNetlifyFunctionName')
|
|
10
|
-
const getNextDistDir = require('./getNextDistDir')
|
|
11
|
-
const getPreviewModeFunctionName = require('./getPreviewModeFunctionName')
|
|
12
|
-
const { logItem } = require('./logger')
|
|
13
|
-
|
|
14
|
-
// Create a Netlify Function for the page with the given file path
|
|
15
|
-
const setupNetlifyFunctionForPage = async ({ filePath, functionsPath, isApiPage, isODB, forFallbackPreviewMode }) => {
|
|
16
|
-
// Set function name based on file path
|
|
17
|
-
const defaultFunctionName = getNetlifyFunctionName(filePath, isApiPage)
|
|
18
|
-
const functionName = forFallbackPreviewMode ? getPreviewModeFunctionName(defaultFunctionName) : defaultFunctionName
|
|
19
|
-
const functionDirectory = join(functionsPath, functionName)
|
|
20
|
-
|
|
21
|
-
await ensureDir(functionDirectory)
|
|
22
|
-
|
|
23
|
-
if (isApiPage && functionName.endsWith('-background')) {
|
|
24
|
-
logItem(`👁 Setting up API page ${functionName} as a Netlify background function`)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Write entry point to function directory
|
|
28
|
-
const entryPointPath = join(functionDirectory, `${functionName}.js`)
|
|
29
|
-
await writeFile(entryPointPath, getTemplate({ filePath, isODB }))
|
|
30
|
-
|
|
31
|
-
// Copy function helper
|
|
32
|
-
await copy(join(TEMPLATES_DIR, 'getHandlerFunction.js'), join(functionDirectory, 'getHandlerFunction.js'))
|
|
33
|
-
|
|
34
|
-
// Copy any dynamic import chunks
|
|
35
|
-
await copyDynamicImportChunks(functionDirectory)
|
|
36
|
-
|
|
37
|
-
// Copy page to our custom path
|
|
38
|
-
const nextPageCopyPath = join(functionDirectory, 'nextPage', filePath)
|
|
39
|
-
const nextDistDir = await getNextDistDir()
|
|
40
|
-
|
|
41
|
-
copySync(join(nextDistDir, 'serverless', filePath), nextPageCopyPath)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
module.exports = setupNetlifyFunctionForPage
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
const { join } = require('path')
|
|
2
|
-
|
|
3
|
-
const { copySync } = require('fs-extra')
|
|
4
|
-
|
|
5
|
-
const getNextDistDir = require('./getNextDistDir')
|
|
6
|
-
|
|
7
|
-
// Copy the static asset from pages/inputPath to out_publish/outputPath
|
|
8
|
-
const setupStaticFileForPage = async ({ inputPath, outputPath = null, publishPath }) => {
|
|
9
|
-
const nextDistDir = await getNextDistDir()
|
|
10
|
-
|
|
11
|
-
// Perform copy operation
|
|
12
|
-
copySync(join(nextDistDir, 'serverless', 'pages', inputPath), join(publishPath, outputPath || inputPath), {
|
|
13
|
-
overwrite: false,
|
|
14
|
-
errorOnExist: true,
|
|
15
|
-
})
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
module.exports = setupStaticFileForPage
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
const getPagesManifest = require('../../helpers/getPagesManifest')
|
|
2
|
-
const isApiRoute = require('../../helpers/isApiRoute')
|
|
3
|
-
|
|
4
|
-
const getPages = async () => {
|
|
5
|
-
// Get HTML and SSR pages and API endpoints from the NextJS pages manifest
|
|
6
|
-
const pagesManifest = await getPagesManifest()
|
|
7
|
-
|
|
8
|
-
// Collect pages
|
|
9
|
-
const pages = []
|
|
10
|
-
|
|
11
|
-
// Parse pages
|
|
12
|
-
Object.entries(pagesManifest).forEach(([route, filePath]) => {
|
|
13
|
-
// Skip non-API endpoints
|
|
14
|
-
if (!isApiRoute(route)) return
|
|
15
|
-
|
|
16
|
-
// Add page
|
|
17
|
-
pages.push({ route, filePath })
|
|
18
|
-
})
|
|
19
|
-
return pages
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
module.exports = getPages
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
const getNetlifyFunctionName = require('../../helpers/getNetlifyFunctionName')
|
|
2
|
-
|
|
3
|
-
const getPages = require('./pages')
|
|
4
|
-
|
|
5
|
-
const getRedirects = async () => {
|
|
6
|
-
const pages = await getPages()
|
|
7
|
-
return pages.map(({ route, filePath }) => ({
|
|
8
|
-
route,
|
|
9
|
-
target: `/.netlify/functions/${getNetlifyFunctionName(filePath, true)}`,
|
|
10
|
-
}))
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
module.exports = getRedirects
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const { logTitle } = require('../../helpers/logger')
|
|
2
|
-
|
|
3
|
-
const getPages = require('./pages')
|
|
4
|
-
|
|
5
|
-
// Create a Netlify Function for every API endpoint
|
|
6
|
-
const setup = async (functionsPath) => {
|
|
7
|
-
logTitle('💫 Setting up API endpoints as Netlify Functions in', functionsPath)
|
|
8
|
-
|
|
9
|
-
const pages = await getPages()
|
|
10
|
-
|
|
11
|
-
// Create Netlify Function job for every page
|
|
12
|
-
return pages.map(({ filePath }) => ({ type: 'function', filePath, functionsPath, isApiPage: true }))
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
module.exports = setup
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
const asyncForEach = require('../../helpers/asyncForEach')
|
|
2
|
-
const getPagesManifest = require('../../helpers/getPagesManifest')
|
|
3
|
-
const isApiRoute = require('../../helpers/isApiRoute')
|
|
4
|
-
const isFrameworkRoute = require('../../helpers/isFrameworkRoute')
|
|
5
|
-
const isHtmlFile = require('../../helpers/isHtmlFile')
|
|
6
|
-
const isRouteInPrerenderManifest = require('../../helpers/isRouteInPrerenderManifest')
|
|
7
|
-
const isRouteWithDataRoute = require('../../helpers/isRouteWithDataRoute')
|
|
8
|
-
|
|
9
|
-
const getPages = async () => {
|
|
10
|
-
// Get HTML and SSR pages and API endpoints from the NextJS pages manifest
|
|
11
|
-
const pagesManifest = await getPagesManifest()
|
|
12
|
-
|
|
13
|
-
// Collect pages
|
|
14
|
-
const pages = []
|
|
15
|
-
|
|
16
|
-
// Parse pages
|
|
17
|
-
await asyncForEach(Object.entries(pagesManifest), async ([route, filePath]) => {
|
|
18
|
-
// Ignore HTML files
|
|
19
|
-
if (isHtmlFile(filePath)) return
|
|
20
|
-
|
|
21
|
-
// Skip framework pages, such as _app and _error
|
|
22
|
-
if (isFrameworkRoute(route)) return
|
|
23
|
-
|
|
24
|
-
// Skip API endpoints
|
|
25
|
-
if (isApiRoute(route)) return
|
|
26
|
-
|
|
27
|
-
// Skip page if it is actually used with getStaticProps
|
|
28
|
-
if (await isRouteInPrerenderManifest(route)) return
|
|
29
|
-
|
|
30
|
-
// Skip page if it has a data route (because then it is a page with
|
|
31
|
-
// getServerSideProps)
|
|
32
|
-
if (await isRouteWithDataRoute(route)) return
|
|
33
|
-
|
|
34
|
-
// Add page
|
|
35
|
-
pages.push({ route, filePath })
|
|
36
|
-
})
|
|
37
|
-
return pages
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
module.exports = getPages
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const addLocaleRedirects = require('../../helpers/addLocaleRedirects')
|
|
2
|
-
const asyncForEach = require('../../helpers/asyncForEach')
|
|
3
|
-
const getNetlifyFunctionName = require('../../helpers/getNetlifyFunctionName')
|
|
4
|
-
|
|
5
|
-
const getPages = require('./pages')
|
|
6
|
-
|
|
7
|
-
const getRedirects = async () => {
|
|
8
|
-
const redirects = []
|
|
9
|
-
const pages = await getPages()
|
|
10
|
-
|
|
11
|
-
await asyncForEach(pages, async ({ route, filePath }) => {
|
|
12
|
-
const functionName = getNetlifyFunctionName(filePath)
|
|
13
|
-
const target = `/.netlify/functions/${functionName}`
|
|
14
|
-
|
|
15
|
-
await addLocaleRedirects(redirects, route, target)
|
|
16
|
-
|
|
17
|
-
redirects.push({
|
|
18
|
-
route,
|
|
19
|
-
target,
|
|
20
|
-
})
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
return redirects
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
module.exports = getRedirects
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const { logTitle } = require('../../helpers/logger')
|
|
2
|
-
|
|
3
|
-
const getPages = require('./pages')
|
|
4
|
-
|
|
5
|
-
// Create a Netlify Function for every page with getInitialProps
|
|
6
|
-
const setup = async (functionsPath) => {
|
|
7
|
-
logTitle('💫 Setting up pages with getInitialProps as Netlify Functions in', functionsPath)
|
|
8
|
-
|
|
9
|
-
const pages = await getPages()
|
|
10
|
-
|
|
11
|
-
// Create Netlify Function for every page
|
|
12
|
-
return pages.map(({ filePath }) => ({ type: 'function', filePath, functionsPath }))
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
module.exports = setup
|