@netlify/plugin-nextjs 4.0.0-rc.0 → 4.0.0-rc.1

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/lib/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DYNAMIC_PARAMETER_REGEX = exports.OPTIONAL_CATCH_ALL_REGEX = exports.CATCH_ALL_REGEX = exports.DEFAULT_FUNCTIONS_SRC = exports.HANDLER_FUNCTION_PATH = exports.ODB_FUNCTION_PATH = exports.HIDDEN_PATHS = exports.IMAGE_FUNCTION_NAME = exports.ODB_FUNCTION_NAME = exports.HANDLER_FUNCTION_NAME = void 0;
3
+ exports.DIVIDER = exports.MINIMUM_REVALIDATE_SECONDS = exports.DYNAMIC_PARAMETER_REGEX = exports.OPTIONAL_CATCH_ALL_REGEX = exports.CATCH_ALL_REGEX = exports.DEFAULT_FUNCTIONS_SRC = exports.HANDLER_FUNCTION_PATH = exports.ODB_FUNCTION_PATH = exports.HIDDEN_PATHS = exports.IMAGE_FUNCTION_NAME = exports.ODB_FUNCTION_NAME = exports.HANDLER_FUNCTION_NAME = void 0;
4
4
  exports.HANDLER_FUNCTION_NAME = '___netlify-handler';
5
5
  exports.ODB_FUNCTION_NAME = '___netlify-odb-handler';
6
6
  exports.IMAGE_FUNCTION_NAME = '_ipx';
@@ -22,3 +22,7 @@ exports.DEFAULT_FUNCTIONS_SRC = 'netlify/functions';
22
22
  exports.CATCH_ALL_REGEX = /\/\[\.{3}(.*)](.json)?$/;
23
23
  exports.OPTIONAL_CATCH_ALL_REGEX = /\/\[{2}\.{3}(.*)]{2}(.json)?$/;
24
24
  exports.DYNAMIC_PARAMETER_REGEX = /\/\[(.*?)]/g;
25
+ exports.MINIMUM_REVALIDATE_SECONDS = 60;
26
+ exports.DIVIDER = `
27
+ ────────────────────────────────────────────────────────────────
28
+ `;
@@ -13,7 +13,7 @@ const defaultFailBuild = (message, { error }) => {
13
13
  };
14
14
  const getNextConfig = async function getNextConfig({ publish, failBuild = defaultFailBuild, }) {
15
15
  try {
16
- const { config, appDir, ignore } = await (0, fs_extra_1.readJSON)((0, pathe_1.join)(publish, 'required-server-files.json'));
16
+ const { config, appDir, ignore } = await fs_extra_1.readJSON(pathe_1.join(publish, 'required-server-files.json'));
17
17
  if (!config) {
18
18
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
19
19
  // @ts-ignore
@@ -28,7 +28,7 @@ const getNextConfig = async function getNextConfig({ publish, failBuild = defaul
28
28
  exports.getNextConfig = getNextConfig;
29
29
  const resolveModuleRoot = (moduleName) => {
30
30
  try {
31
- return (0, pathe_1.dirname)((0, pathe_1.relative)(process.cwd(), require.resolve(`${moduleName}/package.json`, { paths: [process.cwd()] })));
31
+ return pathe_1.dirname(pathe_1.relative(process.cwd(), require.resolve(`${moduleName}/package.json`, { paths: [process.cwd()] })));
32
32
  }
33
33
  catch (error) {
34
34
  return null;
@@ -45,7 +45,7 @@ const configureHandlerFunctions = ({ netlifyConfig, publish, ignore = [] }) => {
45
45
  (_a = netlifyConfig.functions)[functionName] || (_a[functionName] = { included_files: [], external_node_modules: [] });
46
46
  netlifyConfig.functions[functionName].node_bundler = 'nft';
47
47
  (_b = netlifyConfig.functions[functionName]).included_files || (_b.included_files = []);
48
- netlifyConfig.functions[functionName].included_files.push('.env', '.env.local', '.env.production', '.env.production.local', `${publish}/server/**`, `${publish}/serverless/**`, `${publish}/*.json`, `${publish}/BUILD_ID`, `${publish}/static/chunks/webpack-middleware*.js`, `!${publish}/server/**/*.js.nft.json`, ...ignore.map((path) => `!${(0, slash_1.default)(path)}`));
48
+ netlifyConfig.functions[functionName].included_files.push('.env', '.env.local', '.env.production', '.env.production.local', `${publish}/server/**`, `${publish}/serverless/**`, `${publish}/*.json`, `${publish}/BUILD_ID`, `${publish}/static/chunks/webpack-middleware*.js`, `!${publish}/server/**/*.js.nft.json`, ...ignore.map((path) => `!${slash_1.default(path)}`));
49
49
  const nextRoot = resolveModuleRoot('next');
50
50
  if (nextRoot) {
51
51
  netlifyConfig.functions[functionName].included_files.push(`!${nextRoot}/dist/server/lib/squoosh/**/*.wasm`, `!${nextRoot}/dist/next-server/server/lib/squoosh/**/*.wasm`, `!${nextRoot}/dist/compiled/webpack/bundle4.js`, `!${nextRoot}/dist/compiled/webpack/bundle5.js`, `!${nextRoot}/dist/compiled/terser/bundle.min.js`);
@@ -7,6 +7,7 @@ const { outdent } = require('outdent');
7
7
  const pLimit = require('p-limit');
8
8
  const { join } = require('pathe');
9
9
  const slash = require('slash');
10
+ const { MINIMUM_REVALIDATE_SECONDS, DIVIDER } = require('../constants');
10
11
  const TEST_ROUTE = /(|\/)\[[^/]+?](\/|\.html|$)/;
11
12
  const isDynamicRoute = (route) => TEST_ROUTE.test(route);
12
13
  const stripLocale = (rawPath, locales = []) => {
@@ -64,12 +65,16 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n }) => {
64
65
  const prerenderManifest = await readJson(join(netlifyConfig.build.publish, 'prerender-manifest.json'));
65
66
  const { redirects, rewrites } = await readJson(join(netlifyConfig.build.publish, 'routes-manifest.json'));
66
67
  const isrFiles = new Set();
68
+ const shortRevalidateRoutes = [];
67
69
  Object.entries(prerenderManifest.routes).forEach(([route, { initialRevalidateSeconds }]) => {
68
70
  if (initialRevalidateSeconds) {
69
71
  // Find all files used by ISR routes
70
72
  const trimmedPath = route.slice(1);
71
73
  isrFiles.add(`${trimmedPath}.html`);
72
74
  isrFiles.add(`${trimmedPath}.json`);
75
+ if (initialRevalidateSeconds < MINIMUM_REVALIDATE_SECONDS) {
76
+ shortRevalidateRoutes.push({ Route: route, Revalidate: initialRevalidateSeconds });
77
+ }
73
78
  }
74
79
  });
75
80
  const files = [];
@@ -77,10 +82,10 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n }) => {
77
82
  const moveFile = async (file) => {
78
83
  const isData = file.endsWith('.json');
79
84
  const source = join(root, file);
80
- const target = isData ? join(dataDir, file) : file;
85
+ const targetFile = isData ? join(dataDir, file) : file;
81
86
  files.push(file);
82
- filesManifest[file] = target;
83
- const dest = join(netlifyConfig.build.publish, target);
87
+ filesManifest[file] = targetFile;
88
+ const dest = join(netlifyConfig.build.publish, targetFile);
84
89
  try {
85
90
  await move(source, dest);
86
91
  }
@@ -99,7 +104,7 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n }) => {
99
104
  const matchedRewrites = new Set();
100
105
  // Limit concurrent file moves to number of cpus or 2 if there is only 1
101
106
  const limit = pLimit(Math.max(2, cpus().length));
102
- const promises = pages.map(async (rawPath) => {
107
+ const promises = pages.map((rawPath) => {
103
108
  const filePath = slash(rawPath);
104
109
  // Don't move ISR files, as they're used for the first request
105
110
  if (isrFiles.has(filePath)) {
@@ -138,8 +143,7 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n }) => {
138
143
  The following middleware matched statically-rendered pages:
139
144
 
140
145
  ${yellowBright([...matchingMiddleware].map((mid) => `- /${mid}/_middleware`).join('\n'))}
141
-
142
- ────────────────────────────────────────────────────────────────
146
+ ${DIVIDER}
143
147
  `);
144
148
  // There could potentially be thousands of matching pages, so we don't want to spam the console with this
145
149
  if (matchedPages.size < 50) {
@@ -147,8 +151,7 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n }) => {
147
151
  The following files matched middleware and were not moved to the CDN:
148
152
 
149
153
  ${yellowBright([...matchedPages].map((mid) => `- ${mid}`).join('\n'))}
150
-
151
- ────────────────────────────────────────────────────────────────
154
+ ${DIVIDER}
152
155
  `);
153
156
  }
154
157
  }
@@ -161,8 +164,7 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n }) => {
161
164
  The following files matched redirects and were not moved to the CDN:
162
165
 
163
166
  ${yellowBright([...matchedRedirects].map((mid) => `- ${mid}`).join('\n'))}
164
-
165
- ────────────────────────────────────────────────────────────────
167
+ ${DIVIDER}
166
168
  `);
167
169
  }
168
170
  if (matchedRewrites.size < 50 && matchedRewrites.size !== 0) {
@@ -170,8 +172,7 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n }) => {
170
172
  The following files matched beforeFiles rewrites and were not moved to the CDN:
171
173
 
172
174
  ${yellowBright([...matchedRewrites].map((mid) => `- ${mid}`).join('\n'))}
173
-
174
- ────────────────────────────────────────────────────────────────
175
+ ${DIVIDER}
175
176
  `);
176
177
  }
177
178
  }
@@ -193,6 +194,20 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n }) => {
193
194
  catch { }
194
195
  }
195
196
  }
197
+ if (shortRevalidateRoutes.length !== 0) {
198
+ console.log(outdent `
199
+ The following routes use "revalidate" values of under ${MINIMUM_REVALIDATE_SECONDS} seconds, which is not supported.
200
+ They will use a revalidate time of ${MINIMUM_REVALIDATE_SECONDS} seconds instead.
201
+ `);
202
+ console.table(shortRevalidateRoutes);
203
+ // TODO: add these docs
204
+ // console.log(
205
+ // outdent`
206
+ // For more information, see https://ntl.fyi/next-revalidate-time
207
+ // ${DIVIDER}
208
+ // `,
209
+ // )
210
+ }
196
211
  };
197
212
  const patchFile = async ({ file, from, to }) => {
198
213
  if (!existsSync(file)) {
@@ -9,14 +9,14 @@ const getPageResolver_1 = require("../templates/getPageResolver");
9
9
  const generateFunctions = async ({ FUNCTIONS_SRC = constants_1.DEFAULT_FUNCTIONS_SRC, INTERNAL_FUNCTIONS_SRC, PUBLISH_DIR }, appDir) => {
10
10
  const functionsDir = INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC;
11
11
  const bridgeFile = require.resolve('@vercel/node/dist/bridge');
12
- const functionDir = (0, pathe_1.join)(process.cwd(), functionsDir, constants_1.HANDLER_FUNCTION_NAME);
13
- const publishDir = (0, pathe_1.relative)(functionDir, (0, pathe_1.join)(process.cwd(), PUBLISH_DIR));
12
+ const functionDir = pathe_1.join(process.cwd(), functionsDir, constants_1.HANDLER_FUNCTION_NAME);
13
+ const publishDir = pathe_1.relative(functionDir, pathe_1.join(process.cwd(), PUBLISH_DIR));
14
14
  const writeHandler = async (func, isODB) => {
15
- const handlerSource = await (0, getHandler_1.getHandler)({ isODB, publishDir, appDir: (0, pathe_1.relative)(functionDir, appDir) });
16
- await (0, fs_extra_1.ensureDir)((0, pathe_1.join)(functionsDir, func));
17
- await (0, fs_extra_1.writeFile)((0, pathe_1.join)(functionsDir, func, `${func}.js`), handlerSource);
18
- await (0, fs_extra_1.copyFile)(bridgeFile, (0, pathe_1.join)(functionsDir, func, 'bridge.js'));
19
- await (0, fs_extra_1.copyFile)((0, pathe_1.join)(__dirname, '..', '..', 'lib', 'templates', 'handlerUtils.js'), (0, pathe_1.join)(functionsDir, func, 'handlerUtils.js'));
15
+ const handlerSource = await getHandler_1.getHandler({ isODB, publishDir, appDir: pathe_1.relative(functionDir, appDir) });
16
+ await fs_extra_1.ensureDir(pathe_1.join(functionsDir, func));
17
+ await fs_extra_1.writeFile(pathe_1.join(functionsDir, func, `${func}.js`), handlerSource);
18
+ await fs_extra_1.copyFile(bridgeFile, pathe_1.join(functionsDir, func, 'bridge.js'));
19
+ await fs_extra_1.copyFile(pathe_1.join(__dirname, '..', '..', 'lib', 'templates', 'handlerUtils.js'), pathe_1.join(functionsDir, func, 'handlerUtils.js'));
20
20
  };
21
21
  await writeHandler(constants_1.HANDLER_FUNCTION_NAME, false);
22
22
  await writeHandler(constants_1.ODB_FUNCTION_NAME, true);
@@ -28,25 +28,25 @@ exports.generateFunctions = generateFunctions;
28
28
  */
29
29
  const generatePagesResolver = async ({ constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC = constants_1.DEFAULT_FUNCTIONS_SRC }, netlifyConfig, target, }) => {
30
30
  const functionsPath = INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC;
31
- const jsSource = await (0, getPageResolver_1.getPageResolver)({
31
+ const jsSource = await getPageResolver_1.getPageResolver({
32
32
  netlifyConfig,
33
33
  target,
34
34
  });
35
- await (0, fs_extra_1.writeFile)((0, pathe_1.join)(functionsPath, constants_1.ODB_FUNCTION_NAME, 'pages.js'), jsSource);
36
- await (0, fs_extra_1.writeFile)((0, pathe_1.join)(functionsPath, constants_1.HANDLER_FUNCTION_NAME, 'pages.js'), jsSource);
35
+ await fs_extra_1.writeFile(pathe_1.join(functionsPath, constants_1.ODB_FUNCTION_NAME, 'pages.js'), jsSource);
36
+ await fs_extra_1.writeFile(pathe_1.join(functionsPath, constants_1.HANDLER_FUNCTION_NAME, 'pages.js'), jsSource);
37
37
  };
38
38
  exports.generatePagesResolver = generatePagesResolver;
39
39
  // Move our next/image function into the correct functions directory
40
40
  const setupImageFunction = async ({ constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC = constants_1.DEFAULT_FUNCTIONS_SRC }, imageconfig = {}, netlifyConfig, basePath, }) => {
41
41
  const functionsPath = INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC;
42
42
  const functionName = `${constants_1.IMAGE_FUNCTION_NAME}.js`;
43
- const functionDirectory = (0, pathe_1.join)(functionsPath, constants_1.IMAGE_FUNCTION_NAME);
44
- await (0, fs_extra_1.ensureDir)(functionDirectory);
45
- await (0, fs_extra_1.writeJSON)((0, pathe_1.join)(functionDirectory, 'imageconfig.json'), {
43
+ const functionDirectory = pathe_1.join(functionsPath, constants_1.IMAGE_FUNCTION_NAME);
44
+ await fs_extra_1.ensureDir(functionDirectory);
45
+ await fs_extra_1.writeJSON(pathe_1.join(functionDirectory, 'imageconfig.json'), {
46
46
  ...imageconfig,
47
47
  basePath: [basePath, constants_1.IMAGE_FUNCTION_NAME].join('/'),
48
48
  });
49
- await (0, fs_extra_1.copyFile)((0, pathe_1.join)(__dirname, '..', '..', 'lib', 'templates', 'ipx.js'), (0, pathe_1.join)(functionDirectory, functionName));
49
+ await fs_extra_1.copyFile(pathe_1.join(__dirname, '..', '..', 'lib', 'templates', 'ipx.js'), pathe_1.join(functionDirectory, functionName));
50
50
  const imagePath = imageconfig.path || '/_next/image';
51
51
  netlifyConfig.redirects.push({
52
52
  from: `${imagePath}*`,
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.generateRedirects = void 0;
4
- const chalk_1 = require("chalk");
5
7
  const fs_extra_1 = require("fs-extra");
6
- const outdent_1 = require("outdent");
8
+ const globby_1 = __importDefault(require("globby"));
7
9
  const pathe_1 = require("pathe");
8
10
  const constants_1 = require("../constants");
9
11
  const utils_1 = require("./utils");
@@ -35,8 +37,8 @@ const generateLocaleRedirects = ({ i18n, basePath, trailingSlash, }) => {
35
37
  });
36
38
  return redirects;
37
39
  };
38
- const generateRedirects = async ({ netlifyConfig, nextConfig: { i18n, basePath, trailingSlash }, }) => {
39
- const { dynamicRoutes, routes: staticRoutes } = await (0, fs_extra_1.readJSON)((0, pathe_1.join)(netlifyConfig.build.publish, 'prerender-manifest.json'));
40
+ const generateRedirects = async ({ netlifyConfig, nextConfig: { i18n, basePath, trailingSlash, appDir }, }) => {
41
+ const { dynamicRoutes, routes: staticRoutes } = await fs_extra_1.readJSON(pathe_1.join(netlifyConfig.build.publish, 'prerender-manifest.json'));
40
42
  netlifyConfig.redirects.push(...constants_1.HIDDEN_PATHS.map((path) => ({
41
43
  from: `${basePath}${path}`,
42
44
  to: '/404.html',
@@ -49,7 +51,6 @@ const generateRedirects = async ({ netlifyConfig, nextConfig: { i18n, basePath,
49
51
  const dataRedirects = [];
50
52
  const pageRedirects = [];
51
53
  const isrRedirects = [];
52
- let hasIsr = false;
53
54
  const dynamicRouteEntries = Object.entries(dynamicRoutes);
54
55
  const staticRouteEntries = Object.entries(staticRoutes);
55
56
  staticRouteEntries.forEach(([route, { dataRoute, initialRevalidateSeconds }]) => {
@@ -61,20 +62,20 @@ const generateRedirects = async ({ netlifyConfig, nextConfig: { i18n, basePath,
61
62
  if ((i18n === null || i18n === void 0 ? void 0 : i18n.defaultLocale) && route.startsWith(`/${i18n.defaultLocale}/`)) {
62
63
  route = route.slice(i18n.defaultLocale.length + 1);
63
64
  }
64
- hasIsr = true;
65
- isrRedirects.push(...(0, utils_1.netlifyRoutesForNextRoute)(dataRoute), ...(0, utils_1.netlifyRoutesForNextRoute)(route));
65
+ isrRedirects.push(...utils_1.netlifyRoutesForNextRoute(dataRoute), ...utils_1.netlifyRoutesForNextRoute(route));
66
66
  });
67
67
  dynamicRouteEntries.forEach(([route, { dataRoute, fallback }]) => {
68
68
  // Add redirects if fallback is "null" (aka blocking) or true/a string
69
69
  if (fallback === false) {
70
70
  return;
71
71
  }
72
- pageRedirects.push(...(0, utils_1.netlifyRoutesForNextRoute)(route));
73
- dataRedirects.push(...(0, utils_1.netlifyRoutesForNextRoute)(dataRoute));
72
+ pageRedirects.push(...utils_1.netlifyRoutesForNextRoute(route));
73
+ dataRedirects.push(...utils_1.netlifyRoutesForNextRoute(dataRoute));
74
74
  });
75
75
  if (i18n) {
76
76
  netlifyConfig.redirects.push({ from: `${basePath}/:locale/_next/static/*`, to: `/static/:splat`, status: 200 });
77
77
  }
78
+ const publicFiles = await globby_1.default('**/*', { cwd: pathe_1.join(appDir, 'public') });
78
79
  // This is only used in prod, so dev uses `next dev` directly
79
80
  netlifyConfig.redirects.push(
80
81
  // Static files are in `static`
@@ -89,20 +90,24 @@ const generateRedirects = async ({ netlifyConfig, nextConfig: { i18n, basePath,
89
90
  to: constants_1.HANDLER_FUNCTION_PATH,
90
91
  status: 200,
91
92
  },
92
- // Preview mode gets forced to the function, to bypess pre-rendered pages
93
- {
93
+ // Preview mode gets forced to the function, to bypass pre-rendered pages, but static files need to be skipped
94
+ ...publicFiles.map((file) => ({
95
+ from: `${basePath}/${file}`,
96
+ // This is a no-op, but we do it to stop it matching the following rule
97
+ to: `${basePath}/${file}`,
98
+ conditions: { Cookie: ['__prerender_bypass', '__next_preview_data'] },
99
+ status: 200,
100
+ })), {
94
101
  from: `${basePath}/*`,
95
102
  to: constants_1.HANDLER_FUNCTION_PATH,
96
103
  status: 200,
97
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
98
- // @ts-ignore The conditions type is incorrect
99
104
  conditions: { Cookie: ['__prerender_bypass', '__next_preview_data'] },
100
105
  force: true,
101
106
  },
102
107
  // ISR redirects are handled by the regular function. Forced to avoid pre-rendered pages
103
108
  ...isrRedirects.map((redirect) => ({
104
109
  from: `${basePath}${redirect}`,
105
- to: process.env.EXPERIMENTAL_ODB_TTL ? constants_1.ODB_FUNCTION_PATH : constants_1.HANDLER_FUNCTION_PATH,
110
+ to: constants_1.ODB_FUNCTION_PATH,
106
111
  status: 200,
107
112
  force: true,
108
113
  })),
@@ -121,10 +126,5 @@ const generateRedirects = async ({ netlifyConfig, nextConfig: { i18n, basePath,
121
126
  })),
122
127
  // Everything else is handled by the regular function
123
128
  { from: `${basePath}/*`, to: constants_1.HANDLER_FUNCTION_PATH, status: 200 });
124
- if (hasIsr) {
125
- console.log((0, chalk_1.yellowBright)((0, outdent_1.outdent) `
126
- You have some pages that use ISR (pages that use getStaticProps with revalidate set), which is not currently fully-supported by this plugin. Be aware that results may be unreliable.
127
- `));
128
- }
129
129
  };
130
130
  exports.generateRedirects = generateRedirects;
@@ -63,13 +63,13 @@ exports.checkZipSize = async (file, maxSize = LAMBDA_MAX_SIZE) => {
63
63
  console.warn(`Could not check zip size because ${file} does not exist`);
64
64
  return;
65
65
  }
66
- const size = await promises.stat(file).then(({ size }) => size);
67
- if (size < maxSize) {
66
+ const fileSize = await promises.stat(file).then(({ size }) => size);
67
+ if (fileSize < maxSize) {
68
68
  return;
69
69
  }
70
70
  // We don't fail the build, because the actual hard max size is larger so it might still succeed
71
71
  console.log(redBright(outdent `
72
- The function zip ${yellowBright(relative(process.cwd(), file))} size is ${prettyBytes(size)}, which is larger than the maximum supported size of ${prettyBytes(maxSize)}.
72
+ The function zip ${yellowBright(relative(process.cwd(), file))} size is ${prettyBytes(fileSize)}, which is larger than the maximum supported size of ${prettyBytes(maxSize)}.
73
73
  There are a few reasons this could happen. You may have accidentally bundled a large dependency, or you might have a
74
74
  large number of pre-rendered pages included.
75
75
  `));
package/lib/index.js CHANGED
@@ -42,7 +42,7 @@ module.exports = {
42
42
  await setupImageFunction({ constants, imageconfig: images, netlifyConfig, basePath });
43
43
  await generateRedirects({
44
44
  netlifyConfig,
45
- nextConfig: { basePath, i18n, trailingSlash },
45
+ nextConfig: { basePath, i18n, trailingSlash, appDir },
46
46
  });
47
47
  },
48
48
  async onPostBuild({ netlifyConfig, utils: { cache, functions, failBuild }, constants: { FUNCTIONS_DIST } }) {
@@ -68,7 +68,7 @@ const makeHandler = () =>
68
68
  // Sending SWR headers causes undefined behaviour with the Netlify CDN
69
69
  const cacheHeader = (_c = multiValueHeaders['cache-control']) === null || _c === void 0 ? void 0 : _c[0];
70
70
  if (cacheHeader === null || cacheHeader === void 0 ? void 0 : cacheHeader.includes('stale-while-revalidate')) {
71
- if (requestMode === 'odb' && process.env.EXPERIMENTAL_ODB_TTL) {
71
+ if (requestMode === 'odb') {
72
72
  requestMode = 'isr';
73
73
  const ttl = getMaxAge(cacheHeader);
74
74
  // Long-expiry TTL is basically no TTL
@@ -14,14 +14,14 @@ const constants_1 = require("../constants");
14
14
  const getPageResolver = async ({ netlifyConfig, target }) => {
15
15
  const functionDir = path_1.posix.resolve(path_1.posix.join('.netlify', 'functions', constants_1.HANDLER_FUNCTION_NAME));
16
16
  const root = path_1.posix.join(netlifyConfig.build.publish, target === 'server' ? 'server' : 'serverless', 'pages');
17
- const pages = await (0, tiny_glob_1.default)('**/*.js', {
17
+ const pages = await tiny_glob_1.default('**/*.js', {
18
18
  cwd: root,
19
19
  dot: true,
20
20
  });
21
21
  const pageFiles = pages
22
- .map((page) => `require.resolve('${path_1.posix.relative(functionDir, path_1.posix.join(root, (0, slash_1.default)(page)))}')`)
22
+ .map((page) => `require.resolve('${path_1.posix.relative(functionDir, path_1.posix.join(root, slash_1.default(page)))}')`)
23
23
  .sort();
24
- return (0, outdent_1.outdent) `
24
+ return outdent_1.outdent `
25
25
  // This file is purely to allow nft to know about these pages. It should be temporary.
26
26
  exports.resolvePages = () => {
27
27
  try {
@@ -11,7 +11,7 @@ const os_1 = require("os");
11
11
  const path_1 = __importDefault(require("path"));
12
12
  const stream_1 = require("stream");
13
13
  const util_1 = require("util");
14
- const streamPipeline = (0, util_1.promisify)(stream_1.pipeline);
14
+ const streamPipeline = util_1.promisify(stream_1.pipeline);
15
15
  const downloadFile = async (url, destination) => {
16
16
  console.log(`Downloading ${url} to ${destination}`);
17
17
  const httpx = url.startsWith('https') ? https_1.default : http_1.default;
@@ -21,7 +21,7 @@ const downloadFile = async (url, destination) => {
21
21
  reject(new Error(`Failed to download ${url}: ${response.statusCode} ${response.statusMessage || ''}`));
22
22
  return;
23
23
  }
24
- const fileStream = (0, fs_1.createWriteStream)(destination);
24
+ const fileStream = fs_1.createWriteStream(destination);
25
25
  streamPipeline(response, fileStream)
26
26
  .then(resolve)
27
27
  .catch((error) => {
@@ -78,7 +78,7 @@ const augmentFsModule = ({ promises, staticManifest, pageRoot, getBase, }) => {
78
78
  const staticFiles = new Map(staticManifest);
79
79
  const downloadPromises = new Map();
80
80
  // Yes, you can cache stuff locally in a Lambda
81
- const cacheDir = path_1.default.join((0, os_1.tmpdir)(), 'next-static-cache');
81
+ const cacheDir = path_1.default.join(os_1.tmpdir(), 'next-static-cache');
82
82
  // Grab the real fs.promises.readFile...
83
83
  const readfileOrig = promises.readFile;
84
84
  const statsOrig = promises.stat;
@@ -90,7 +90,7 @@ const augmentFsModule = ({ promises, staticManifest, pageRoot, getBase, }) => {
90
90
  // We only want the part after `pages/`
91
91
  const filePath = file.slice(pageRoot.length + 1);
92
92
  // Is it in the CDN and not local?
93
- if (staticFiles.has(filePath) && !(0, fs_1.existsSync)(file)) {
93
+ if (staticFiles.has(filePath) && !fs_1.existsSync(file)) {
94
94
  // This name is safe to use, because it's one that was already created by Next
95
95
  const cacheFile = path_1.default.join(cacheDir, filePath);
96
96
  const url = `${base}/${staticFiles.get(filePath)}`;
@@ -99,11 +99,11 @@ const augmentFsModule = ({ promises, staticManifest, pageRoot, getBase, }) => {
99
99
  await downloadPromises.get(url);
100
100
  }
101
101
  // Have we already cached it? We download every time if running locally to avoid staleness
102
- if ((!(0, fs_1.existsSync)(cacheFile) || process.env.NETLIFY_DEV) && base) {
102
+ if ((!fs_1.existsSync(cacheFile) || process.env.NETLIFY_DEV) && base) {
103
103
  await promises.mkdir(path_1.default.dirname(cacheFile), { recursive: true });
104
104
  try {
105
105
  // Append the path to our host and we can load it like a regular page
106
- const downloadPromise = (0, exports.downloadFile)(url, cacheFile);
106
+ const downloadPromise = exports.downloadFile(url, cacheFile);
107
107
  downloadPromises.set(url, downloadPromise);
108
108
  await downloadPromise;
109
109
  }
@@ -122,7 +122,7 @@ const augmentFsModule = ({ promises, staticManifest, pageRoot, getBase, }) => {
122
122
  if (file.startsWith(pageRoot)) {
123
123
  // We only want the part after `pages/`
124
124
  const cacheFile = path_1.default.join(cacheDir, file.slice(pageRoot.length + 1));
125
- if ((0, fs_1.existsSync)(cacheFile)) {
125
+ if (fs_1.existsSync(cacheFile)) {
126
126
  return statsOrig(cacheFile, options);
127
127
  }
128
128
  }
@@ -5,7 +5,7 @@ exports.handler = void 0;
5
5
  const ipx_1 = require("@netlify/ipx");
6
6
  // @ts-ignore Injected at build time
7
7
  const imageconfig_json_1 = require("./imageconfig.json");
8
- exports.handler = (0, ipx_1.createIPXHandler)({
8
+ exports.handler = ipx_1.createIPXHandler({
9
9
  basePath: imageconfig_json_1.basePath,
10
10
  domains: imageconfig_json_1.domains,
11
11
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/plugin-nextjs",
3
- "version": "4.0.0-rc.0",
3
+ "version": "4.0.0-rc.1",
4
4
  "description": "Run Next.js seamlessly on Netlify",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -55,7 +55,7 @@
55
55
  "homepage": "https://github.com/netlify/netlify-plugin-nextjs#readme",
56
56
  "dependencies": {
57
57
  "@netlify/functions": "^0.10.0",
58
- "@netlify/ipx": "^0.0.7",
58
+ "@netlify/ipx": "^0.0.8",
59
59
  "@vercel/node": "^1.11.2-canary.4",
60
60
  "chalk": "^4.1.2",
61
61
  "fs-extra": "^10.0.0",
@@ -75,8 +75,8 @@
75
75
  "@babel/core": "^7.15.8",
76
76
  "@babel/preset-env": "^7.15.8",
77
77
  "@babel/preset-typescript": "^7.16.0",
78
- "@netlify/build": "^20.0.4",
79
- "@netlify/eslint-config-node": "^3.3.11",
78
+ "@netlify/build": "^20.1.0",
79
+ "@netlify/eslint-config-node": "^4.0.0",
80
80
  "@testing-library/cypress": "^8.0.1",
81
81
  "@types/fs-extra": "^9.0.13",
82
82
  "@types/jest": "^27.0.2",