@netlify/plugin-nextjs 4.2.2 → 4.2.6

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.
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.movePublicFiles = exports.unpatchNextFiles = exports.patchNextFiles = exports.moveStaticPages = exports.matchesRewrite = exports.matchesRedirect = exports.matchMiddleware = exports.stripLocale = exports.isDynamicRoute = void 0;
6
+ exports.movePublicFiles = exports.unpatchNextFiles = exports.patchNextFiles = exports.moveStaticPages = exports.getMiddleware = exports.matchesRewrite = exports.matchesRedirect = exports.matchMiddleware = exports.stripLocale = exports.isDynamicRoute = void 0;
7
7
  /* eslint-disable max-lines */
8
8
  const os_1 = require("os");
9
9
  const chalk_1 = require("chalk");
@@ -14,6 +14,7 @@ const p_limit_1 = __importDefault(require("p-limit"));
14
14
  const pathe_1 = require("pathe");
15
15
  const slash_1 = __importDefault(require("slash"));
16
16
  const constants_1 = require("../constants");
17
+ const utils_1 = require("./utils");
17
18
  const TEST_ROUTE = /(|\/)\[[^/]+?](\/|\.html|$)/;
18
19
  const isDynamicRoute = (route) => TEST_ROUTE.test(route);
19
20
  exports.isDynamicRoute = isDynamicRoute;
@@ -51,8 +52,18 @@ const matchesRewrite = (file, rewrites) => {
51
52
  return (0, exports.matchesRedirect)(file, rewrites.beforeFiles);
52
53
  };
53
54
  exports.matchesRewrite = matchesRewrite;
55
+ const getMiddleware = async (publish) => {
56
+ var _a;
57
+ const manifestPath = (0, pathe_1.join)(publish, 'server', 'middleware-manifest.json');
58
+ if ((0, fs_extra_1.existsSync)(manifestPath)) {
59
+ const manifest = await (0, fs_extra_1.readJson)(manifestPath, { throws: false });
60
+ return (_a = manifest === null || manifest === void 0 ? void 0 : manifest.sortedMiddleware) !== null && _a !== void 0 ? _a : [];
61
+ }
62
+ return [];
63
+ };
64
+ exports.getMiddleware = getMiddleware;
54
65
  // eslint-disable-next-line max-lines-per-function
55
- const moveStaticPages = async ({ netlifyConfig, target, i18n, }) => {
66
+ const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
56
67
  console.log('Moving static page files to serve from CDN...');
57
68
  const outputDir = (0, pathe_1.join)(netlifyConfig.build.publish, target === 'server' ? 'server' : 'serverless');
58
69
  const root = (0, pathe_1.join)(outputDir, 'pages');
@@ -60,14 +71,8 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, }) => {
60
71
  const dataDir = (0, pathe_1.join)('_next', 'data', buildId);
61
72
  await (0, fs_extra_1.ensureDir)(dataDir);
62
73
  // Load the middleware manifest so we can check if a file matches it before moving
63
- let middleware;
64
- const manifestPath = (0, pathe_1.join)(outputDir, 'middleware-manifest.json');
65
- if ((0, fs_extra_1.existsSync)(manifestPath)) {
66
- const manifest = await (0, fs_extra_1.readJson)(manifestPath);
67
- if (manifest === null || manifest === void 0 ? void 0 : manifest.middleware) {
68
- middleware = Object.keys(manifest.middleware).map((path) => path.slice(1));
69
- }
70
- }
74
+ const middlewarePaths = await (0, exports.getMiddleware)(netlifyConfig.build.publish);
75
+ const middleware = middlewarePaths.map((path) => path.slice(1));
71
76
  const prerenderManifest = await (0, fs_extra_1.readJson)((0, pathe_1.join)(netlifyConfig.build.publish, 'prerender-manifest.json'));
72
77
  const { redirects, rewrites } = await (0, fs_extra_1.readJson)((0, pathe_1.join)(netlifyConfig.build.publish, 'routes-manifest.json'));
73
78
  const isrFiles = new Set();
@@ -89,9 +94,10 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, }) => {
89
94
  const isData = file.endsWith('.json');
90
95
  const source = (0, pathe_1.join)(root, file);
91
96
  const targetFile = isData ? (0, pathe_1.join)(dataDir, file) : file;
97
+ const targetPath = basePath ? (0, pathe_1.join)(basePath, targetFile) : targetFile;
92
98
  files.push(file);
93
- filesManifest[file] = targetFile;
94
- const dest = (0, pathe_1.join)(netlifyConfig.build.publish, targetFile);
99
+ filesManifest[file] = targetPath;
100
+ const dest = (0, pathe_1.join)(netlifyConfig.build.publish, targetPath);
95
101
  try {
96
102
  await (0, fs_extra_1.move)(source, dest);
97
103
  }
@@ -185,19 +191,23 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, }) => {
185
191
  // Write the manifest for use in the serverless functions
186
192
  await (0, fs_extra_1.writeJson)((0, pathe_1.join)(netlifyConfig.build.publish, 'static-manifest.json'), Object.entries(filesManifest));
187
193
  if (i18n === null || i18n === void 0 ? void 0 : i18n.defaultLocale) {
194
+ const rootPath = basePath ? (0, pathe_1.join)(netlifyConfig.build.publish, basePath) : netlifyConfig.build.publish;
188
195
  // Copy the default locale into the root
189
- const defaultLocaleDir = (0, pathe_1.join)(netlifyConfig.build.publish, i18n.defaultLocale);
196
+ const defaultLocaleDir = (0, pathe_1.join)(rootPath, i18n.defaultLocale);
190
197
  if ((0, fs_extra_1.existsSync)(defaultLocaleDir)) {
191
- await (0, fs_extra_1.copy)(defaultLocaleDir, `${netlifyConfig.build.publish}/`);
198
+ await (0, fs_extra_1.copy)(defaultLocaleDir, `${rootPath}/`);
192
199
  }
193
- const defaultLocaleIndex = (0, pathe_1.join)(netlifyConfig.build.publish, `${i18n.defaultLocale}.html`);
194
- const indexHtml = (0, pathe_1.join)(netlifyConfig.build.publish, 'index.html');
200
+ const defaultLocaleIndex = (0, pathe_1.join)(rootPath, `${i18n.defaultLocale}.html`);
201
+ const indexHtml = (0, pathe_1.join)(rootPath, 'index.html');
195
202
  if ((0, fs_extra_1.existsSync)(defaultLocaleIndex) && !(0, fs_extra_1.existsSync)(indexHtml)) {
196
- try {
197
- await (0, fs_extra_1.copy)(defaultLocaleIndex, indexHtml, { overwrite: false });
198
- await (0, fs_extra_1.copy)((0, pathe_1.join)(netlifyConfig.build.publish, `${i18n.defaultLocale}.json`), (0, pathe_1.join)(netlifyConfig.build.publish, 'index.json'), { overwrite: false });
199
- }
200
- catch { }
203
+ await (0, fs_extra_1.copy)(defaultLocaleIndex, indexHtml, { overwrite: false }).catch(() => {
204
+ /* ignore */
205
+ });
206
+ await (0, fs_extra_1.copy)((0, pathe_1.join)(rootPath, `${i18n.defaultLocale}.json`), (0, pathe_1.join)(rootPath, 'index.json'), {
207
+ overwrite: false,
208
+ }).catch(() => {
209
+ /* ignore */
210
+ });
201
211
  }
202
212
  }
203
213
  if (shortRevalidateRoutes.length !== 0) {
@@ -216,47 +226,52 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, }) => {
216
226
  }
217
227
  };
218
228
  exports.moveStaticPages = moveStaticPages;
229
+ /**
230
+ * Attempt to patch a source file, preserving a backup
231
+ */
219
232
  const patchFile = async ({ file, from, to }) => {
220
233
  if (!(0, fs_extra_1.existsSync)(file)) {
221
- return;
234
+ console.warn('File was not found');
235
+ return false;
222
236
  }
223
237
  const content = await (0, fs_extra_1.readFile)(file, 'utf8');
224
238
  if (content.includes(to)) {
225
- return;
239
+ console.log('File already patched');
240
+ return false;
226
241
  }
227
242
  const newContent = content.replace(from, to);
243
+ if (newContent === content) {
244
+ console.warn('File was not changed');
245
+ return false;
246
+ }
228
247
  await (0, fs_extra_1.writeFile)(`${file}.orig`, content);
229
248
  await (0, fs_extra_1.writeFile)(file, newContent);
249
+ console.log('Done');
250
+ return true;
230
251
  };
252
+ /**
253
+ * The file we need has moved around a bit over the past few versions,
254
+ * so we iterate through the options until we find it
255
+ */
231
256
  const getServerFile = (root) => {
232
- let serverFile;
233
- try {
234
- serverFile = require.resolve('next/dist/server/next-server', { paths: [root] });
235
- }
236
- catch {
237
- // Ignore
238
- }
239
- if (!serverFile) {
240
- try {
241
- // eslint-disable-next-line node/no-missing-require
242
- serverFile = require.resolve('next/dist/next-server/server/next-server', { paths: [root] });
243
- }
244
- catch {
245
- // Ignore
246
- }
247
- }
248
- return serverFile;
257
+ const candidates = [
258
+ 'next/dist/server/base-server',
259
+ 'next/dist/server/next-server',
260
+ 'next/dist/next-server/server/next-server',
261
+ ];
262
+ return (0, utils_1.findModuleFromBase)({ candidates, paths: [root] });
249
263
  };
250
- const patchNextFiles = async (root) => {
264
+ const patchNextFiles = (root) => {
251
265
  const serverFile = getServerFile(root);
252
266
  console.log(`Patching ${serverFile}`);
253
267
  if (serverFile) {
254
- await patchFile({
268
+ return patchFile({
255
269
  file: serverFile,
256
270
  from: `let ssgCacheKey = `,
257
271
  to: `let ssgCacheKey = process.env._BYPASS_SSG || `,
258
272
  });
259
273
  }
274
+ return false;
260
275
  };
261
276
  exports.patchNextFiles = patchNextFiles;
262
277
  const unpatchNextFiles = async (root) => {
@@ -1,10 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateRedirects = exports.generateStaticRedirects = void 0;
4
+ const chalk_1 = require("chalk");
4
5
  const fs_extra_1 = require("fs-extra");
6
+ const outdent_1 = require("outdent");
5
7
  const pathe_1 = require("pathe");
6
8
  const constants_1 = require("../constants");
9
+ const files_1 = require("./files");
7
10
  const utils_1 = require("./utils");
11
+ const matchesMiddleware = (middleware, route) => middleware.some((middlewarePath) => route.startsWith(middlewarePath));
8
12
  const generateLocaleRedirects = ({ i18n, basePath, trailingSlash, }) => {
9
13
  const redirects = [];
10
14
  // If the cookie is set, we need to redirect at the origin
@@ -41,27 +45,38 @@ const generateStaticRedirects = ({ netlifyConfig, nextConfig: { i18n, basePath }
41
45
  }
42
46
  };
43
47
  exports.generateStaticRedirects = generateStaticRedirects;
44
- const generateRedirects = async ({ netlifyConfig, nextConfig: { i18n, basePath, trailingSlash, appDir }, buildId, }) => {
45
- const { dynamicRoutes: prerenderedDynamicRoutes, routes: prerenderedStaticRoutes } = await (0, fs_extra_1.readJSON)((0, pathe_1.join)(netlifyConfig.build.publish, 'prerender-manifest.json'));
46
- const { dynamicRoutes, staticRoutes } = await (0, fs_extra_1.readJSON)((0, pathe_1.join)(netlifyConfig.build.publish, 'routes-manifest.json'));
47
- netlifyConfig.redirects.push(...constants_1.HIDDEN_PATHS.map((path) => ({
48
- from: `${basePath}${path}`,
49
- to: '/404.html',
50
- status: 404,
51
- force: true,
52
- })));
53
- if (i18n && i18n.localeDetection !== false) {
54
- netlifyConfig.redirects.push(...generateLocaleRedirects({ i18n, basePath, trailingSlash }));
55
- }
56
- // This is only used in prod, so dev uses `next dev` directly
57
- netlifyConfig.redirects.push(
58
- // API routes always need to be served from the regular function
59
- ...(0, utils_1.getApiRewrites)(basePath),
60
- // Preview mode gets forced to the function, to bypass pre-rendered pages, but static files need to be skipped
61
- ...(await (0, utils_1.getPreviewRewrites)({ basePath, appDir })));
62
- const staticRouteEntries = Object.entries(prerenderedStaticRoutes);
48
+ /**
49
+ * Routes that match middleware need to always use the SSR function
50
+ * This generates a rewrite for every middleware in every locale, both with and without a splat
51
+ */
52
+ const generateMiddlewareRewrites = ({ basePath, middleware, i18n, buildId }) => {
53
+ const handlerRewrite = (from) => ({
54
+ from: `${basePath}${from}`,
55
+ to: constants_1.HANDLER_FUNCTION_PATH,
56
+ status: 200,
57
+ });
58
+ return (middleware
59
+ .map((route) => {
60
+ var _a;
61
+ const unlocalized = [handlerRewrite(`${route}`), handlerRewrite(`${route}/*`)];
62
+ if (((_a = i18n === null || i18n === void 0 ? void 0 : i18n.locales) === null || _a === void 0 ? void 0 : _a.length) > 0) {
63
+ const localized = i18n.locales.map((locale) => [
64
+ handlerRewrite(`/${locale}${route}`),
65
+ handlerRewrite(`/${locale}${route}/*`),
66
+ handlerRewrite(`/_next/data/${buildId}/${locale}${route}/*`),
67
+ ]);
68
+ // With i18n, all data routes are prefixed with the locale, but the HTML also has the unprefixed default
69
+ return [...unlocalized, ...localized];
70
+ }
71
+ return [...unlocalized, handlerRewrite(`/_next/data/${buildId}${route}/*`)];
72
+ })
73
+ // Flatten the array of arrays. Can't use flatMap as it might be 2 levels deep
74
+ .flat(2));
75
+ };
76
+ const generateStaticIsrRewrites = ({ staticRouteEntries, basePath, i18n, buildId, middleware, }) => {
77
+ const staticIsrRoutesThatMatchMiddleware = [];
63
78
  const staticRoutePaths = new Set();
64
- // First add all static ISR routes
79
+ const staticIsrRewrites = [];
65
80
  staticRouteEntries.forEach(([route, { initialRevalidateSeconds }]) => {
66
81
  if ((0, utils_1.isApiRoute)(route)) {
67
82
  return;
@@ -75,7 +90,10 @@ const generateRedirects = async ({ netlifyConfig, nextConfig: { i18n, basePath,
75
90
  if ((i18n === null || i18n === void 0 ? void 0 : i18n.defaultLocale) && route.startsWith(`/${i18n.defaultLocale}/`)) {
76
91
  route = route.slice(i18n.defaultLocale.length + 1);
77
92
  staticRoutePaths.add(route);
78
- netlifyConfig.redirects.push(...(0, utils_1.redirectsForNextRouteWithData)({
93
+ if (matchesMiddleware(middleware, route)) {
94
+ staticIsrRoutesThatMatchMiddleware.push(route);
95
+ }
96
+ staticIsrRewrites.push(...(0, utils_1.redirectsForNextRouteWithData)({
79
97
  route,
80
98
  dataRoute: (0, utils_1.routeToDataRoute)(route, buildId, i18n.defaultLocale),
81
99
  basePath,
@@ -83,41 +101,116 @@ const generateRedirects = async ({ netlifyConfig, nextConfig: { i18n, basePath,
83
101
  force: true,
84
102
  }));
85
103
  }
104
+ else if (matchesMiddleware(middleware, route)) {
105
+ // Routes that match middleware can't use the ODB
106
+ staticIsrRoutesThatMatchMiddleware.push(route);
107
+ }
86
108
  else {
87
109
  // ISR routes use the ODB handler
88
- netlifyConfig.redirects.push(
110
+ staticIsrRewrites.push(
89
111
  // No i18n, because the route is already localized
90
112
  ...(0, utils_1.redirectsForNextRoute)({ route, basePath, to: constants_1.ODB_FUNCTION_PATH, force: true, buildId, i18n: null }));
91
113
  }
92
114
  });
93
- // Add rewrites for all static SSR routes. This is Next 12+
94
- staticRoutes === null || staticRoutes === void 0 ? void 0 : staticRoutes.forEach((route) => {
95
- if (staticRoutePaths.has(route.page) || (0, utils_1.isApiRoute)(route.page)) {
96
- // Prerendered static routes are either handled by the CDN or are ISR
97
- return;
98
- }
99
- netlifyConfig.redirects.push(...(0, utils_1.redirectsForNextRoute)({ route: route.page, buildId, basePath, to: constants_1.HANDLER_FUNCTION_PATH, i18n }));
100
- });
101
- // Add rewrites for all dynamic routes (both SSR and ISR)
115
+ return {
116
+ staticRoutePaths,
117
+ staticIsrRoutesThatMatchMiddleware,
118
+ staticIsrRewrites,
119
+ };
120
+ };
121
+ /**
122
+ * Generate rewrites for all dynamic routes
123
+ */
124
+ const generateDynamicRewrites = ({ dynamicRoutes, prerenderedDynamicRoutes, middleware, basePath, buildId, i18n, }) => {
125
+ const dynamicRewrites = [];
126
+ const dynamicRoutesThatMatchMiddleware = [];
102
127
  dynamicRoutes.forEach((route) => {
103
128
  if ((0, utils_1.isApiRoute)(route.page)) {
104
129
  return;
105
130
  }
106
131
  if (route.page in prerenderedDynamicRoutes) {
107
- const { fallback } = prerenderedDynamicRoutes[route.page];
108
- const { to, status } = (0, utils_1.targetForFallback)(fallback);
109
- netlifyConfig.redirects.push(...(0, utils_1.redirectsForNextRoute)({ buildId, route: route.page, basePath, to, status, i18n }));
132
+ if (matchesMiddleware(middleware, route.page)) {
133
+ dynamicRoutesThatMatchMiddleware.push(route.page);
134
+ }
135
+ else {
136
+ dynamicRewrites.push(...(0, utils_1.redirectsForNextRoute)({ buildId, route: route.page, basePath, to: constants_1.ODB_FUNCTION_PATH, status: 200, i18n }));
137
+ }
110
138
  }
111
139
  else {
112
140
  // If the route isn't prerendered, it's SSR
113
- netlifyConfig.redirects.push(...(0, utils_1.redirectsForNextRoute)({ route: route.page, buildId, basePath, to: constants_1.HANDLER_FUNCTION_PATH, i18n }));
141
+ dynamicRewrites.push(...(0, utils_1.redirectsForNextRoute)({ route: route.page, buildId, basePath, to: constants_1.HANDLER_FUNCTION_PATH, i18n }));
114
142
  }
115
143
  });
144
+ return {
145
+ dynamicRoutesThatMatchMiddleware,
146
+ dynamicRewrites,
147
+ };
148
+ };
149
+ const generateRedirects = async ({ netlifyConfig, nextConfig: { i18n, basePath, trailingSlash, appDir }, buildId, }) => {
150
+ const { dynamicRoutes: prerenderedDynamicRoutes, routes: prerenderedStaticRoutes } = await (0, fs_extra_1.readJSON)((0, pathe_1.join)(netlifyConfig.build.publish, 'prerender-manifest.json'));
151
+ const { dynamicRoutes, staticRoutes } = await (0, fs_extra_1.readJSON)((0, pathe_1.join)(netlifyConfig.build.publish, 'routes-manifest.json'));
152
+ netlifyConfig.redirects.push(...constants_1.HIDDEN_PATHS.map((path) => ({
153
+ from: `${basePath}${path}`,
154
+ to: '/404.html',
155
+ status: 404,
156
+ force: true,
157
+ })));
158
+ if (i18n && i18n.localeDetection !== false) {
159
+ netlifyConfig.redirects.push(...generateLocaleRedirects({ i18n, basePath, trailingSlash }));
160
+ }
161
+ // This is only used in prod, so dev uses `next dev` directly
162
+ netlifyConfig.redirects.push(
163
+ // API routes always need to be served from the regular function
164
+ ...(0, utils_1.getApiRewrites)(basePath),
165
+ // Preview mode gets forced to the function, to bypass pre-rendered pages, but static files need to be skipped
166
+ ...(await (0, utils_1.getPreviewRewrites)({ basePath, appDir })));
167
+ const middleware = await (0, files_1.getMiddleware)(netlifyConfig.build.publish);
168
+ netlifyConfig.redirects.push(...generateMiddlewareRewrites({ basePath, i18n, middleware, buildId }));
169
+ const staticRouteEntries = Object.entries(prerenderedStaticRoutes);
170
+ const routesThatMatchMiddleware = [];
171
+ const { staticRoutePaths, staticIsrRewrites, staticIsrRoutesThatMatchMiddleware } = generateStaticIsrRewrites({
172
+ staticRouteEntries,
173
+ basePath,
174
+ i18n,
175
+ buildId,
176
+ middleware,
177
+ });
178
+ routesThatMatchMiddleware.push(...staticIsrRoutesThatMatchMiddleware);
179
+ netlifyConfig.redirects.push(...staticIsrRewrites);
180
+ // Add rewrites for all static SSR routes. This is Next 12+
181
+ staticRoutes === null || staticRoutes === void 0 ? void 0 : staticRoutes.forEach((route) => {
182
+ if (staticRoutePaths.has(route.page) || (0, utils_1.isApiRoute)(route.page)) {
183
+ // Prerendered static routes are either handled by the CDN or are ISR
184
+ return;
185
+ }
186
+ netlifyConfig.redirects.push(...(0, utils_1.redirectsForNextRoute)({ route: route.page, buildId, basePath, to: constants_1.HANDLER_FUNCTION_PATH, i18n }));
187
+ });
188
+ // Add rewrites for all dynamic routes (both SSR and ISR)
189
+ const { dynamicRewrites, dynamicRoutesThatMatchMiddleware } = generateDynamicRewrites({
190
+ dynamicRoutes,
191
+ prerenderedDynamicRoutes,
192
+ middleware,
193
+ basePath,
194
+ buildId,
195
+ i18n,
196
+ });
197
+ netlifyConfig.redirects.push(...dynamicRewrites);
198
+ routesThatMatchMiddleware.push(...dynamicRoutesThatMatchMiddleware);
116
199
  // Final fallback
117
200
  netlifyConfig.redirects.push({
118
201
  from: `${basePath}/*`,
119
202
  to: constants_1.HANDLER_FUNCTION_PATH,
120
203
  status: 200,
121
204
  });
205
+ const middlewareMatches = new Set(routesThatMatchMiddleware).size;
206
+ if (middlewareMatches > 0) {
207
+ console.log((0, chalk_1.yellowBright)((0, outdent_1.outdent) `
208
+ There ${middlewareMatches === 1
209
+ ? `is one statically-generated or ISR route that matches`
210
+ : `are ${middlewareMatches} statically-generated or ISR routes that match`} a middleware function. Matched routes will always be served from the SSR function and will not use ISR or be served from the CDN.
211
+ If this was not intended, ensure that your middleware only matches routes that you intend to use SSR.
212
+ `));
213
+ }
122
214
  };
123
215
  exports.generateRedirects = generateRedirects;
216
+ /* eslint-enable max-lines */
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.shouldSkip = exports.getPreviewRewrites = exports.getApiRewrites = exports.redirectsForNextRouteWithData = exports.redirectsForNextRoute = exports.targetForFallback = exports.isApiRoute = exports.routeToDataRoute = exports.netlifyRoutesForNextRouteWithData = exports.toNetlifyRoute = void 0;
6
+ exports.findModuleFromBase = exports.shouldSkip = exports.getPreviewRewrites = exports.getApiRewrites = exports.redirectsForNextRouteWithData = exports.redirectsForNextRoute = exports.isApiRoute = exports.routeToDataRoute = exports.netlifyRoutesForNextRouteWithData = exports.toNetlifyRoute = void 0;
7
7
  const globby_1 = __importDefault(require("globby"));
8
8
  const pathe_1 = require("pathe");
9
9
  const constants_1 = require("../constants");
@@ -63,16 +63,6 @@ const netlifyRoutesForNextRoute = (route, buildId, i18n) => {
63
63
  };
64
64
  const isApiRoute = (route) => route.startsWith('/api/') || route === '/api';
65
65
  exports.isApiRoute = isApiRoute;
66
- const targetForFallback = (fallback) => {
67
- if (fallback === null || fallback === false) {
68
- // fallback = null mean "blocking", which uses ODB. For fallback=false then anything prerendered should 404.
69
- // However i18n pages may not have been prerendered, so we still need to hit the origin
70
- return { to: constants_1.ODB_FUNCTION_PATH, status: 200 };
71
- }
72
- // fallback = true is also ODB
73
- return { to: constants_1.ODB_FUNCTION_PATH, status: 200 };
74
- };
75
- exports.targetForFallback = targetForFallback;
76
66
  const redirectsForNextRoute = ({ route, buildId, basePath, to, i18n, status = 200, force = false, }) => netlifyRoutesForNextRoute(route, buildId, i18n).map((redirect) => ({
77
67
  from: `${basePath}${redirect}`,
78
68
  to,
@@ -126,3 +116,21 @@ const shouldSkip = () => process.env.NEXT_PLUGIN_FORCE_RUN === 'false' ||
126
116
  process.env.NETLIFY_NEXT_PLUGIN_SKIP === 'true' ||
127
117
  process.env.NETLIFY_NEXT_PLUGIN_SKIP === '1';
128
118
  exports.shouldSkip = shouldSkip;
119
+ /**
120
+ * Given an array of base paths and candidate modules, return the first one that exists
121
+ */
122
+ const findModuleFromBase = ({ paths, candidates }) => {
123
+ for (const candidate of candidates) {
124
+ try {
125
+ const modulePath = require.resolve(candidate, { paths });
126
+ if (modulePath) {
127
+ return modulePath;
128
+ }
129
+ }
130
+ catch {
131
+ // Ignore the error
132
+ }
133
+ }
134
+ return null;
135
+ };
136
+ exports.findModuleFromBase = findModuleFromBase;
package/lib/index.js CHANGED
@@ -49,7 +49,7 @@ const plugin = {
49
49
  console.log("The flag 'EXPERIMENTAL_MOVE_STATIC_PAGES' is no longer required, as it is now the default. To disable this behavior, set the env var 'SERVE_STATIC_FILES_FROM_ORIGIN' to 'true'");
50
50
  }
51
51
  if (!process.env.SERVE_STATIC_FILES_FROM_ORIGIN) {
52
- await (0, files_1.moveStaticPages)({ target, netlifyConfig, i18n });
52
+ await (0, files_1.moveStaticPages)({ target, netlifyConfig, i18n, basePath });
53
53
  }
54
54
  await (0, redirects_1.generateStaticRedirects)({
55
55
  netlifyConfig,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/plugin-nextjs",
3
- "version": "4.2.2",
3
+ "version": "4.2.6",
4
4
  "description": "Run Next.js seamlessly on Netlify",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -60,6 +60,7 @@
60
60
  "fs-extra": "^10.0.0",
61
61
  "globby": "^11.0.4",
62
62
  "moize": "^6.1.0",
63
+ "next": "^12.0.10",
63
64
  "node-fetch": "^2.6.6",
64
65
  "node-stream-zip": "^1.15.0",
65
66
  "outdent": "^0.8.0",
@@ -74,13 +75,16 @@
74
75
  "@babel/core": "^7.15.8",
75
76
  "@babel/preset-env": "^7.15.8",
76
77
  "@babel/preset-typescript": "^7.16.0",
77
- "@netlify/build": "^26.2.2",
78
- "@netlify/eslint-config-node": "^4.1.7",
78
+ "@netlify/build": "^26.3.1",
79
+ "@netlify/eslint-config-node": "^5.1.4",
80
+ "@reach/dialog": "^0.16.2",
81
+ "@reach/visually-hidden": "^0.16.0",
79
82
  "@testing-library/cypress": "^8.0.1",
80
83
  "@types/fs-extra": "^9.0.13",
81
84
  "@types/jest": "^27.0.2",
82
85
  "@types/mocha": "^9.0.0",
83
86
  "@types/node": "^17.0.10",
87
+ "@types/react": "^17.0.38",
84
88
  "babel-jest": "^27.2.5",
85
89
  "cpy": "^8.1.2",
86
90
  "cypress": "^9.0.0",
@@ -88,12 +92,12 @@
88
92
  "husky": "^7.0.4",
89
93
  "jest": "^27.0.0",
90
94
  "netlify-plugin-cypress": "^2.2.0",
91
- "next": "^12.0.8",
92
95
  "npm-run-all": "^4.1.5",
93
96
  "prettier": "^2.1.2",
94
97
  "react": "^17.0.1",
95
98
  "react-dom": "^17.0.1",
96
99
  "rimraf": "^3.0.2",
100
+ "sass": "^1.49.0",
97
101
  "tmp-promise": "^3.0.2",
98
102
  "typescript": "^4.3.4"
99
103
  },