@netlify/plugin-nextjs 3.9.2 → 4.0.0-beta.12
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 +32 -51
- package/lib/constants.js +21 -0
- package/lib/helpers/cache.js +20 -0
- package/lib/helpers/config.js +174 -0
- package/lib/helpers/files.js +236 -0
- package/lib/helpers/functions.js +65 -0
- package/lib/helpers/verification.js +94 -0
- package/lib/index.js +55 -0
- package/lib/templates/getHandler.js +165 -0
- package/lib/templates/getPageResolver.js +24 -0
- package/lib/templates/handlerUtils.js +66 -0
- package/lib/templates/ipx.js +8 -0
- package/manifest.yml +1 -1
- package/package.json +56 -58
- 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
package/src/index.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
const { normalize } = require('path')
|
|
2
|
-
|
|
3
|
-
const chokidar = require('chokidar')
|
|
4
|
-
const debounceFn = require('debounce-fn')
|
|
5
|
-
const execa = require('execa')
|
|
6
|
-
|
|
7
|
-
const getNextConfig = require('../helpers/getNextConfig')
|
|
8
|
-
|
|
9
|
-
const { NETLIFY_PUBLISH_PATH, NETLIFY_FUNCTIONS_PATH, SRC_FILES } = require('./lib/config')
|
|
10
|
-
const { logTitle } = require('./lib/helpers/logger')
|
|
11
|
-
const copyNextAssets = require('./lib/steps/copyNextAssets')
|
|
12
|
-
const copyPublicFiles = require('./lib/steps/copyPublicFiles')
|
|
13
|
-
const prepareFolders = require('./lib/steps/prepareFolders')
|
|
14
|
-
const setupHeaders = require('./lib/steps/setupHeaders')
|
|
15
|
-
const setupImageFunction = require('./lib/steps/setupImageFunction')
|
|
16
|
-
const setupPages = require('./lib/steps/setupPages')
|
|
17
|
-
const setupRedirects = require('./lib/steps/setupRedirects')
|
|
18
|
-
|
|
19
|
-
const build = async (functionsPath, publishPath, nextRoot) => {
|
|
20
|
-
const trackNextOnNetlifyFiles = prepareFolders({
|
|
21
|
-
functionsPath,
|
|
22
|
-
publishPath,
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
// If we're in a monorepo we need to move into the Next site root
|
|
26
|
-
const oldCwd = process.cwd()
|
|
27
|
-
if (nextRoot !== oldCwd) {
|
|
28
|
-
process.chdir(nextRoot)
|
|
29
|
-
}
|
|
30
|
-
copyPublicFiles(publishPath)
|
|
31
|
-
|
|
32
|
-
await copyNextAssets(publishPath)
|
|
33
|
-
|
|
34
|
-
await setupPages({ functionsPath, publishPath })
|
|
35
|
-
|
|
36
|
-
const { images } = await getNextConfig()
|
|
37
|
-
|
|
38
|
-
await setupImageFunction(functionsPath, images)
|
|
39
|
-
|
|
40
|
-
await setupRedirects(publishPath)
|
|
41
|
-
|
|
42
|
-
setupHeaders(publishPath)
|
|
43
|
-
|
|
44
|
-
// ...and move back after
|
|
45
|
-
if (nextRoot !== oldCwd) {
|
|
46
|
-
process.chdir(oldCwd)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
trackNextOnNetlifyFiles()
|
|
50
|
-
|
|
51
|
-
logTitle('✅ Success! All done!')
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const watch = (functionsPath, publishPath, nextRoot) => {
|
|
55
|
-
logTitle(`👀 Watching source code for changes`)
|
|
56
|
-
|
|
57
|
-
const runBuild = debounceFn(
|
|
58
|
-
async () => {
|
|
59
|
-
try {
|
|
60
|
-
execa.sync('next', ['build'], { stdio: 'inherit', preferLocal: true, cwd: nextRoot })
|
|
61
|
-
await build(functionsPath, publishPath, nextRoot)
|
|
62
|
-
} catch (error) {
|
|
63
|
-
console.log(error)
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
wait: 3000,
|
|
68
|
-
},
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
chokidar.watch(SRC_FILES).on('all', runBuild)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// options param:
|
|
75
|
-
// {
|
|
76
|
-
// functionsDir: string to path
|
|
77
|
-
// publishDir: string to path
|
|
78
|
-
// watch: { directory: string to path }
|
|
79
|
-
// }
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
const nextOnNetlify = async (options = {}) => {
|
|
83
|
-
const functionsPath = normalize(options.functionsDir || NETLIFY_FUNCTIONS_PATH)
|
|
84
|
-
const publishPath = normalize(options.publishDir || NETLIFY_PUBLISH_PATH)
|
|
85
|
-
const nextRoot = normalize(options.nextRoot || process.cwd())
|
|
86
|
-
|
|
87
|
-
if (options.watch) {
|
|
88
|
-
watch(functionsPath, publishPath, nextRoot)
|
|
89
|
-
} else {
|
|
90
|
-
await build(functionsPath, publishPath, nextRoot)
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
module.exports = nextOnNetlify
|
package/src/lib/config.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
const { join } = require('path')
|
|
2
|
-
|
|
3
|
-
const getNextSrcDirs = require('./helpers/getNextSrcDir')
|
|
4
|
-
|
|
5
|
-
// This is where next-on-netlify will place all static files.
|
|
6
|
-
// The publish key in netlify.toml should point to this folder.
|
|
7
|
-
const NETLIFY_PUBLISH_PATH = join('.', 'out_publish')
|
|
8
|
-
|
|
9
|
-
// This is where next-on-netlify will place all Netlify Functions.
|
|
10
|
-
// The functions key in netlify.toml should point to this folder.
|
|
11
|
-
const NETLIFY_FUNCTIONS_PATH = join('.', 'out_functions')
|
|
12
|
-
|
|
13
|
-
// This is where static assets, such as images, can be placed. They will be
|
|
14
|
-
// copied as-is to the Netlify publish folder.
|
|
15
|
-
const PUBLIC_PATH = join('.', 'public')
|
|
16
|
-
|
|
17
|
-
// This is the file where NextJS can be configured
|
|
18
|
-
const NEXT_CONFIG_PATH = join('.', 'next.config.js')
|
|
19
|
-
|
|
20
|
-
const NEXT_SRC_DIRS = getNextSrcDirs()
|
|
21
|
-
|
|
22
|
-
// This is the folder with templates for Netlify Functions
|
|
23
|
-
const TEMPLATES_DIR = join(__dirname, 'templates')
|
|
24
|
-
|
|
25
|
-
// This is the Netlify Function template that wraps all SSR pages
|
|
26
|
-
const FUNCTION_TEMPLATE_PATH = join(TEMPLATES_DIR, 'netlifyFunction.ts')
|
|
27
|
-
|
|
28
|
-
// This is the Netlify Builder template that wraps ISR pages
|
|
29
|
-
const BUILDER_TEMPLATE_PATH = join(TEMPLATES_DIR, 'netlifyOnDemandBuilder.ts')
|
|
30
|
-
|
|
31
|
-
// This is the file where custom redirects can be configured
|
|
32
|
-
const CUSTOM_REDIRECTS_PATH = join('.', '_redirects')
|
|
33
|
-
|
|
34
|
-
// This is the file where custom headers can be configured
|
|
35
|
-
const CUSTOM_HEADERS_PATH = join('.', '_headers')
|
|
36
|
-
|
|
37
|
-
// This is the name used for copying our imageFunction template and for
|
|
38
|
-
// creating the next/image redirect
|
|
39
|
-
const NEXT_IMAGE_FUNCTION_NAME = 'next_image'
|
|
40
|
-
|
|
41
|
-
const PREVIEW_MODE_COOKIES = ['Cookie=__prerender_bypass,__next_preview_data']
|
|
42
|
-
|
|
43
|
-
const SRC_FILES = [PUBLIC_PATH, NEXT_CONFIG_PATH, CUSTOM_REDIRECTS_PATH, CUSTOM_HEADERS_PATH, ...NEXT_SRC_DIRS]
|
|
44
|
-
|
|
45
|
-
module.exports = {
|
|
46
|
-
NETLIFY_PUBLISH_PATH,
|
|
47
|
-
NETLIFY_FUNCTIONS_PATH,
|
|
48
|
-
PUBLIC_PATH,
|
|
49
|
-
NEXT_CONFIG_PATH,
|
|
50
|
-
TEMPLATES_DIR,
|
|
51
|
-
FUNCTION_TEMPLATE_PATH,
|
|
52
|
-
BUILDER_TEMPLATE_PATH,
|
|
53
|
-
CUSTOM_REDIRECTS_PATH,
|
|
54
|
-
CUSTOM_HEADERS_PATH,
|
|
55
|
-
NEXT_IMAGE_FUNCTION_NAME,
|
|
56
|
-
SRC_FILES,
|
|
57
|
-
PREVIEW_MODE_COOKIES,
|
|
58
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
const CATCH_ALL_REGEX = /\/\[\.{3}(.*)](.json)?$/
|
|
2
|
-
const OPTIONAL_CATCH_ALL_REGEX = /\/\[{2}\.{3}(.*)]{2}(.json)?$/
|
|
3
|
-
const DYNAMIC_PARAMETER_REGEX = /\/\[(.*?)]/g
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
CATCH_ALL_REGEX,
|
|
7
|
-
OPTIONAL_CATCH_ALL_REGEX,
|
|
8
|
-
DYNAMIC_PARAMETER_REGEX,
|
|
9
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
const getI18n = require('./getI18n')
|
|
2
|
-
// In i18n projects, we need to create redirects from the "naked" route
|
|
3
|
-
// to the defaultLocale-prepended route i.e. /static -> /en/static
|
|
4
|
-
// Note: there can only one defaultLocale, but we put it in an array to simplify
|
|
5
|
-
// logic in redirects.js files via concatenation
|
|
6
|
-
const addDefaultLocaleRedirect = async (redirects, route, target, additionalParams) => {
|
|
7
|
-
const i18n = await getI18n()
|
|
8
|
-
const { defaultLocale } = i18n
|
|
9
|
-
|
|
10
|
-
// If no i18n, skip
|
|
11
|
-
if (!defaultLocale) return
|
|
12
|
-
|
|
13
|
-
const routePieces = route.split('/')
|
|
14
|
-
const [, routeLocale] = routePieces
|
|
15
|
-
if (routeLocale === defaultLocale) {
|
|
16
|
-
const nakedRoute = route === `/${routeLocale}` ? '/' : route.replace(`/${routeLocale}`, '')
|
|
17
|
-
redirects.push({
|
|
18
|
-
route: nakedRoute,
|
|
19
|
-
target: target || route,
|
|
20
|
-
...additionalParams,
|
|
21
|
-
})
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
module.exports = addDefaultLocaleRedirect
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
const asyncForEach = require('./asyncForEach')
|
|
2
|
-
const getDataRouteForRoute = require('./getDataRouteForRoute')
|
|
3
|
-
const getI18n = require('./getI18n')
|
|
4
|
-
|
|
5
|
-
const addLocaleRedirects = async (redirects, route, target) => {
|
|
6
|
-
const i18n = await getI18n()
|
|
7
|
-
await asyncForEach(i18n.locales, async (locale) => {
|
|
8
|
-
redirects.push({
|
|
9
|
-
route: `/${locale}${route === '/' ? '' : route}`,
|
|
10
|
-
target,
|
|
11
|
-
})
|
|
12
|
-
redirects.push({
|
|
13
|
-
route: await getDataRouteForRoute(route, locale),
|
|
14
|
-
target,
|
|
15
|
-
})
|
|
16
|
-
})
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
module.exports = addLocaleRedirects
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// This helper converts the collection of redirects for all page types into
|
|
2
|
-
// the necessary redirects for a basePath-generated site
|
|
3
|
-
// NOTE: /withoutProps/redirects.js has some of its own contained basePath logic
|
|
4
|
-
|
|
5
|
-
const getBasePathDefaultRedirects = ({ basePath, nextRedirects }) => {
|
|
6
|
-
if (!basePath) return []
|
|
7
|
-
// In a basePath-configured site, all _next assets are fetched with the prepended basePath
|
|
8
|
-
return [
|
|
9
|
-
{
|
|
10
|
-
route: `${basePath}/_next/*`,
|
|
11
|
-
target: '/_next/:splat',
|
|
12
|
-
statusCode: '301',
|
|
13
|
-
force: true,
|
|
14
|
-
},
|
|
15
|
-
]
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const convertToBasePathRedirects = ({ basePath, nextRedirects }) => {
|
|
19
|
-
if (!basePath) return nextRedirects
|
|
20
|
-
const basePathRedirects = getBasePathDefaultRedirects({ basePath, nextRedirects })
|
|
21
|
-
nextRedirects.forEach((r) => {
|
|
22
|
-
if (r.route === '/') {
|
|
23
|
-
// On Vercel, a basePath configured site 404s on /, but we can ensure it redirects to /basePath
|
|
24
|
-
const indexRedirects = [
|
|
25
|
-
{
|
|
26
|
-
route: '/',
|
|
27
|
-
target: basePath,
|
|
28
|
-
statusCode: '301',
|
|
29
|
-
force: true,
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
route: basePath,
|
|
33
|
-
target: r.target,
|
|
34
|
-
},
|
|
35
|
-
]
|
|
36
|
-
basePathRedirects.push(...indexRedirects)
|
|
37
|
-
} else if (r.specialPreviewMode) {
|
|
38
|
-
basePathRedirects.push({
|
|
39
|
-
route: `${basePath}${r.route}`,
|
|
40
|
-
target: r.target,
|
|
41
|
-
force: true,
|
|
42
|
-
conditions: r.conditions,
|
|
43
|
-
})
|
|
44
|
-
} else if (!r.route.includes('_next/') && r.target.includes('/.netlify/functions') && r.conditions) {
|
|
45
|
-
// If this is a preview mode redirect, we need different behavior than other function targets below
|
|
46
|
-
// because the conditions prevent us from doing a route -> basePath/route force
|
|
47
|
-
basePathRedirects.push({
|
|
48
|
-
route: `${basePath}${r.route}`,
|
|
49
|
-
target: r.target,
|
|
50
|
-
force: true,
|
|
51
|
-
conditions: r.conditions,
|
|
52
|
-
})
|
|
53
|
-
basePathRedirects.push({
|
|
54
|
-
route: `${basePath}${r.route}`,
|
|
55
|
-
target: r.route,
|
|
56
|
-
})
|
|
57
|
-
} else if (!r.route.includes('_next/') && r.target.includes('/.netlify/functions')) {
|
|
58
|
-
// This force redirect is necessary for non-preview mode function targets because the serverless lambdas
|
|
59
|
-
// try to strip basePath and redirect to the plain route per https://github.com/vercel/next.js/blob/5bff9eac084b69affe3560c4f4cfd96724aa5e49/packages/next/next-server/lib/router/router.ts#L974
|
|
60
|
-
const functionRedirects = [
|
|
61
|
-
{
|
|
62
|
-
route: r.route,
|
|
63
|
-
target: `${basePath}${r.route}`,
|
|
64
|
-
statusCode: '301',
|
|
65
|
-
force: true,
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
route: `${basePath}${r.route}`,
|
|
69
|
-
target: r.target,
|
|
70
|
-
},
|
|
71
|
-
]
|
|
72
|
-
basePathRedirects.push(...functionRedirects)
|
|
73
|
-
} else {
|
|
74
|
-
basePathRedirects.push(r)
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
return basePathRedirects
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
module.exports = convertToBasePathRedirects
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
const { join } = require('path')
|
|
2
|
-
|
|
3
|
-
const { copySync, existsSync, readdirSync } = require('fs-extra')
|
|
4
|
-
|
|
5
|
-
const getNextDistDir = require('./getNextDistDir')
|
|
6
|
-
const { logTitle } = require('./logger')
|
|
7
|
-
|
|
8
|
-
// Check if there are dynamic import chunks and copy to the necessary function dir
|
|
9
|
-
const copyDynamicImportChunks = async (functionPath) => {
|
|
10
|
-
const nextDistDir = await getNextDistDir()
|
|
11
|
-
const chunksPathWebpack4 = join(nextDistDir, 'serverless')
|
|
12
|
-
const filesWP4 = readdirSync(chunksPathWebpack4)
|
|
13
|
-
const chunkRegexWP4 = new RegExp(/^(\.?[-$~\w]+)+\.js$/g)
|
|
14
|
-
const excludeFiles = new Set(['init-server.js.js', 'on-error-server.js.js'])
|
|
15
|
-
const copyPathWP4 = join(functionPath, 'nextPage')
|
|
16
|
-
|
|
17
|
-
filesWP4.forEach((file) => {
|
|
18
|
-
if (!excludeFiles.has(file) && chunkRegexWP4.test(file)) {
|
|
19
|
-
copySync(join(chunksPathWebpack4, file), join(copyPathWP4, file), {
|
|
20
|
-
overwrite: false,
|
|
21
|
-
errorOnExist: true,
|
|
22
|
-
})
|
|
23
|
-
}
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
// Chunks are copied into the nextPage directory, as a sibling to "pages" or "api".
|
|
27
|
-
// This matches the Next output, so that imports work correctly
|
|
28
|
-
const chunksPathWebpack5 = join(nextDistDir, 'serverless', 'chunks')
|
|
29
|
-
const filesWP5 = existsSync(chunksPathWebpack5) ? readdirSync(chunksPathWebpack5) : []
|
|
30
|
-
const copyPathWP5 = join(functionPath, 'nextPage', 'chunks')
|
|
31
|
-
|
|
32
|
-
filesWP5.forEach((file) => {
|
|
33
|
-
if (file.endsWith('.js')) {
|
|
34
|
-
copySync(join(chunksPathWebpack5, file), join(copyPathWP5, file))
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
module.exports = copyDynamicImportChunks
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
// Returns formatted redirect target
|
|
2
|
-
const { DYNAMIC_PARAMETER_REGEX } = require('../constants/regex')
|
|
3
|
-
|
|
4
|
-
const formatRedirectTarget = ({ basePath, target }) =>
|
|
5
|
-
basePath && basePath !== '' && target.includes(basePath)
|
|
6
|
-
? target.replace(DYNAMIC_PARAMETER_REGEX, '/:$1').replace('[', '').replace(']', '').replace('...', '')
|
|
7
|
-
: target
|
|
8
|
-
|
|
9
|
-
module.exports = formatRedirectTarget
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const { join } = require('path')
|
|
2
|
-
|
|
3
|
-
const { readFileSync } = require('fs-extra')
|
|
4
|
-
|
|
5
|
-
const getFilePathForRoute = require('./getFilePathForRoute')
|
|
6
|
-
const getNextDistDir = require('./getNextDistDir')
|
|
7
|
-
|
|
8
|
-
const getPlainDataRoute = (route, buildId) => {
|
|
9
|
-
const filePath = getFilePathForRoute(route, 'json')
|
|
10
|
-
return `/_next/data/${buildId}${filePath}`
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const getI18nDataRoute = (route, locale, buildId) => {
|
|
14
|
-
const filePath = getFilePathForRoute(route, 'json')
|
|
15
|
-
return route === '/' ? getPlainDataRoute(`/${locale}`, buildId) : `/_next/data/${buildId}/${locale}${filePath}`
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Return the data route for the given route
|
|
19
|
-
const getDataRouteForRoute = async (route, locale) => {
|
|
20
|
-
const nextDistDir = await getNextDistDir()
|
|
21
|
-
|
|
22
|
-
// Get build ID that is used for data routes, e.g. /_next/data/BUILD_ID/...
|
|
23
|
-
const fileContents = readFileSync(join(nextDistDir, 'BUILD_ID'))
|
|
24
|
-
const buildId = fileContents.toString()
|
|
25
|
-
|
|
26
|
-
if (locale) return getI18nDataRoute(route, locale, buildId)
|
|
27
|
-
return getPlainDataRoute(route, buildId)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
module.exports = getDataRouteForRoute
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// Return the file for the given route
|
|
2
|
-
const getFilePathForRoute = (route, extension, locale) => {
|
|
3
|
-
// Replace / with /index
|
|
4
|
-
const path = route.replace(/^\/$/, '/index')
|
|
5
|
-
|
|
6
|
-
if (locale) return `${locale}${path}.${extension}`
|
|
7
|
-
return `${path}.${extension}`
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
module.exports = getFilePathForRoute
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// Get the i18n details specified in next.config.js, if any
|
|
2
|
-
const getNextConfig = require('../../../helpers/getNextConfig')
|
|
3
|
-
|
|
4
|
-
const getI18n = async () => {
|
|
5
|
-
const nextConfig = await getNextConfig()
|
|
6
|
-
|
|
7
|
-
return nextConfig.i18n || { locales: [] }
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
module.exports = getI18n
|
|
@@ -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
|