@netlify/plugin-nextjs 4.29.0 → 4.29.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.
@@ -79,7 +79,7 @@ const configureHandlerFunctions = async ({ netlifyConfig, publish, ignore = [],
79
79
  (_a = netlifyConfig.functions)[functionName] || (_a[functionName] = { included_files: [], external_node_modules: [] });
80
80
  netlifyConfig.functions[functionName].node_bundler = 'nft';
81
81
  (_b = netlifyConfig.functions[functionName]).included_files || (_b.included_files = []);
82
- netlifyConfig.functions[functionName].included_files.push('.env', '.env.local', '.env.production', '.env.production.local', './public/locales/**', './next-i18next.config.js', `${publish}/server/**`, `${publish}/serverless/**`, `${publish}/*.json`, `${publish}/BUILD_ID`, `${publish}/static/chunks/webpack-middleware*.js`, `!${publish}/server/**/*.js.nft.json`, '!**/node_modules/@next/swc*/**/*', ...cssFilesToInclude, ...ignore.map((path) => `!${(0, slash_1.default)(path)}`));
82
+ netlifyConfig.functions[functionName].included_files.push('.env', '.env.local', '.env.production', '.env.production.local', './public/locales/**', './next-i18next.config.js', `${publish}/server/**`, `${publish}/serverless/**`, `${publish}/*.json`, `${publish}/BUILD_ID`, `${publish}/static/chunks/webpack-middleware*.js`, `!${publish}/server/**/*.js.nft.json`, `!${publish}/server/**/*.map`, '!**/node_modules/@next/swc*/**/*', ...cssFilesToInclude, ...ignore.map((path) => `!${(0, slash_1.default)(path)}`));
83
83
  const nextRoot = resolveModuleRoot('next');
84
84
  if (nextRoot) {
85
85
  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`);
@@ -39,6 +39,23 @@ globalThis.process = { env: {...Deno.env.toObject(), NEXT_RUNTIME: 'edge', 'NEXT
39
39
  const self = {}
40
40
  let _ENTRIES = {}
41
41
 
42
+ class Response extends globalThis.Response {
43
+ constructor(body, init) {
44
+ super(body, init);
45
+ // Next.js uses this extension to the Headers API implemented by Cloudflare workerd
46
+ this.headers.getAll = (name) => {
47
+ name = name.toLowerCase();
48
+ if (name !== "set-cookie") {
49
+ throw new Error("Headers.getAll is only supported for Set-Cookie");
50
+ }
51
+ return [...this.headers.entries()]
52
+ .filter(([key]) => key === name)
53
+ .map(([, value]) => value);
54
+ };
55
+ }
56
+ }
57
+
58
+
42
59
  // Next uses blob: urls to refer to local assets, so we need to intercept these
43
60
  const _fetch = globalThis.fetch
44
61
  const fetch = async (url, init) => {
@@ -53,12 +53,12 @@ const matchesRewrite = (file, rewrites) => {
53
53
  return (0, exports.matchesRedirect)(file, rewrites.beforeFiles);
54
54
  };
55
55
  exports.matchesRewrite = matchesRewrite;
56
- const getMiddleware = async (distDir) => {
56
+ const getMiddleware = async (publish) => {
57
57
  var _a;
58
58
  if (process.env.NEXT_DISABLE_NETLIFY_EDGE !== 'true' && process.env.NEXT_DISABLE_NETLIFY_EDGE !== '1') {
59
59
  return [];
60
60
  }
61
- const manifestPath = (0, pathe_1.join)(distDir, 'server', 'middleware-manifest.json');
61
+ const manifestPath = (0, pathe_1.join)(publish, 'server', 'middleware-manifest.json');
62
62
  if ((0, fs_extra_1.existsSync)(manifestPath)) {
63
63
  const manifest = await (0, fs_extra_1.readJson)(manifestPath, { throws: false });
64
64
  return (_a = manifest === null || manifest === void 0 ? void 0 : manifest.sortedMiddleware) !== null && _a !== void 0 ? _a : [];
@@ -67,18 +67,18 @@ const getMiddleware = async (distDir) => {
67
67
  };
68
68
  exports.getMiddleware = getMiddleware;
69
69
  // eslint-disable-next-line max-lines-per-function
70
- const moveStaticPages = async ({ distDir, i18n, basePath, publishDir, }) => {
70
+ const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
71
71
  console.log('Moving static page files to serve from CDN...');
72
- const outputDir = (0, pathe_1.join)(distDir, 'server');
72
+ const outputDir = (0, pathe_1.join)(netlifyConfig.build.publish, target === 'server' ? 'server' : 'serverless');
73
73
  const root = (0, pathe_1.join)(outputDir, 'pages');
74
- const buildId = (0, fs_extra_1.readFileSync)((0, pathe_1.join)(distDir, 'BUILD_ID'), 'utf8').trim();
74
+ const buildId = (0, fs_extra_1.readFileSync)((0, pathe_1.join)(netlifyConfig.build.publish, 'BUILD_ID'), 'utf8').trim();
75
75
  const dataDir = (0, pathe_1.join)('_next', 'data', buildId);
76
- await (0, fs_extra_1.ensureDir)((0, pathe_1.join)(publishDir, dataDir));
76
+ await (0, fs_extra_1.ensureDir)((0, pathe_1.join)(netlifyConfig.build.publish, dataDir));
77
77
  // Load the middleware manifest so we can check if a file matches it before moving
78
- const middlewarePaths = await (0, exports.getMiddleware)(distDir);
78
+ const middlewarePaths = await (0, exports.getMiddleware)(netlifyConfig.build.publish);
79
79
  const middleware = middlewarePaths.map((path) => path.slice(1));
80
- const prerenderManifest = await (0, fs_extra_1.readJson)((0, pathe_1.join)(distDir, 'prerender-manifest.json'));
81
- const { redirects, rewrites } = await (0, fs_extra_1.readJson)((0, pathe_1.join)(distDir, 'routes-manifest.json'));
80
+ const prerenderManifest = await (0, fs_extra_1.readJson)((0, pathe_1.join)(netlifyConfig.build.publish, 'prerender-manifest.json'));
81
+ const { redirects, rewrites } = await (0, fs_extra_1.readJson)((0, pathe_1.join)(netlifyConfig.build.publish, 'routes-manifest.json'));
82
82
  const isrFiles = new Set();
83
83
  const shortRevalidateRoutes = [];
84
84
  Object.entries(prerenderManifest.routes).forEach(([route, { initialRevalidateSeconds }]) => {
@@ -101,7 +101,7 @@ const moveStaticPages = async ({ distDir, i18n, basePath, publishDir, }) => {
101
101
  const targetPath = basePath ? (0, pathe_1.join)(basePath, targetFile) : targetFile;
102
102
  files.push(file);
103
103
  filesManifest[file] = targetPath;
104
- const dest = (0, pathe_1.join)(publishDir, targetPath);
104
+ const dest = (0, pathe_1.join)(netlifyConfig.build.publish, targetPath);
105
105
  try {
106
106
  await (0, fs_extra_1.move)(source, dest);
107
107
  }
@@ -193,9 +193,9 @@ const moveStaticPages = async ({ distDir, i18n, basePath, publishDir, }) => {
193
193
  }
194
194
  }
195
195
  // Write the manifest for use in the serverless functions
196
- await (0, fs_extra_1.writeJson)((0, pathe_1.join)(distDir, 'static-manifest.json'), Object.entries(filesManifest));
196
+ await (0, fs_extra_1.writeJson)((0, pathe_1.join)(netlifyConfig.build.publish, 'static-manifest.json'), Object.entries(filesManifest));
197
197
  if (i18n === null || i18n === void 0 ? void 0 : i18n.defaultLocale) {
198
- const rootPath = basePath ? (0, pathe_1.join)(publishDir, basePath) : publishDir;
198
+ const rootPath = basePath ? (0, pathe_1.join)(netlifyConfig.build.publish, basePath) : netlifyConfig.build.publish;
199
199
  // Copy the default locale into the root
200
200
  const defaultLocaleDir = (0, pathe_1.join)(rootPath, i18n.defaultLocale);
201
201
  if ((0, fs_extra_1.existsSync)(defaultLocaleDir)) {
@@ -358,8 +358,7 @@ const unpatchNextFiles = async (root) => {
358
358
  }
359
359
  };
360
360
  exports.unpatchNextFiles = unpatchNextFiles;
361
- const movePublicFiles = async ({ appDir, outdir, publishDir, }) => {
362
- await (0, fs_extra_1.ensureDir)(publishDir);
361
+ const movePublicFiles = async ({ appDir, outdir, publish, }) => {
363
362
  // `outdir` is a config property added when using Next.js with Nx. It's typically
364
363
  // a relative path outside of the appDir, e.g. '../../dist/apps/<app-name>', and
365
364
  // the parent directory of the .next directory.
@@ -368,7 +367,7 @@ const movePublicFiles = async ({ appDir, outdir, publishDir, }) => {
368
367
  // directory from the original app directory.
369
368
  const publicDir = outdir ? (0, pathe_1.join)(appDir, outdir, 'public') : (0, pathe_1.join)(appDir, 'public');
370
369
  if ((0, fs_extra_1.existsSync)(publicDir)) {
371
- await (0, fs_extra_1.copy)(publicDir, `${publishDir}/`);
370
+ await (0, fs_extra_1.copy)(publicDir, `${publish}/`);
372
371
  }
373
372
  };
374
373
  exports.movePublicFiles = movePublicFiles;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateRedirects = void 0;
3
+ exports.generateRedirects = exports.generateStaticRedirects = void 0;
4
4
  const chalk_1 = require("chalk");
5
5
  const fs_extra_1 = require("fs-extra");
6
6
  const outdent_1 = require("outdent");
@@ -9,6 +9,12 @@ const constants_1 = require("../constants");
9
9
  const files_1 = require("./files");
10
10
  const utils_1 = require("./utils");
11
11
  const matchesMiddleware = (middleware, route) => middleware.some((middlewarePath) => route.startsWith(middlewarePath));
12
+ const generateHiddenPathRedirects = ({ basePath }) => constants_1.HIDDEN_PATHS.map((path) => ({
13
+ from: `${basePath}${path}`,
14
+ to: '/404.html',
15
+ status: 404,
16
+ force: true,
17
+ }));
12
18
  const generateLocaleRedirects = ({ i18n, basePath, trailingSlash, }) => {
13
19
  const redirects = [];
14
20
  // If the cookie is set, we need to redirect at the origin
@@ -37,6 +43,14 @@ const generateLocaleRedirects = ({ i18n, basePath, trailingSlash, }) => {
37
43
  });
38
44
  return redirects;
39
45
  };
46
+ const generateStaticRedirects = ({ netlifyConfig, nextConfig: { i18n, basePath }, }) => {
47
+ // Static files are in `static`
48
+ netlifyConfig.redirects.push({ from: `${basePath}/_next/static/*`, to: `/static/:splat`, status: 200 });
49
+ if (i18n) {
50
+ netlifyConfig.redirects.push({ from: `${basePath}/:locale/_next/static/*`, to: `/static/:splat`, status: 200 });
51
+ }
52
+ };
53
+ exports.generateStaticRedirects = generateStaticRedirects;
40
54
  /**
41
55
  * Routes that match middleware need to always use the SSR function
42
56
  * This generates a rewrite for every middleware in every locale, both with and without a splat
@@ -141,6 +155,7 @@ const generateDynamicRewrites = ({ dynamicRoutes, prerenderedDynamicRoutes, midd
141
155
  const generateRedirects = async ({ netlifyConfig, nextConfig: { i18n, basePath, trailingSlash, appDir }, buildId, apiRoutes, }) => {
142
156
  const { dynamicRoutes: prerenderedDynamicRoutes, routes: prerenderedStaticRoutes } = await (0, fs_extra_1.readJSON)((0, pathe_1.join)(netlifyConfig.build.publish, 'prerender-manifest.json'));
143
157
  const { dynamicRoutes, staticRoutes } = await (0, fs_extra_1.readJSON)((0, pathe_1.join)(netlifyConfig.build.publish, 'routes-manifest.json'));
158
+ netlifyConfig.redirects.push(...generateHiddenPathRedirects({ basePath }));
144
159
  if (i18n && i18n.localeDetection !== false) {
145
160
  netlifyConfig.redirects.push(...generateLocaleRedirects({ i18n, basePath, trailingSlash }));
146
161
  }
package/lib/index.js CHANGED
@@ -44,14 +44,10 @@ const plugin = {
44
44
  }
45
45
  const { publish } = netlifyConfig.build;
46
46
  (0, verification_1.checkNextSiteHasBuilt)({ publish, failBuild });
47
- const { appDir, basePath, i18n, images, target, ignore, trailingSlash, outdir, experimental, distDir } = await (0, config_1.getNextConfig)({
47
+ const { appDir, basePath, i18n, images, target, ignore, trailingSlash, outdir, experimental } = await (0, config_1.getNextConfig)({
48
48
  publish,
49
49
  failBuild,
50
50
  });
51
- const dotNextDir = (0, path_1.join)(appDir, distDir);
52
- // This is the *generated* publish dir. The user specifies .next, be we actually use this subdirectory
53
- const publishDir = (0, path_1.join)(dotNextDir, 'dist');
54
- await (0, fs_extra_1.ensureDir)(publishDir);
55
51
  await (0, edge_1.cleanupEdgeFunctions)(constants);
56
52
  const middlewareManifest = await (0, edge_1.loadMiddlewareManifest)(netlifyConfig);
57
53
  if ((middlewareManifest === null || middlewareManifest === void 0 ? void 0 : middlewareManifest.functions) &&
@@ -73,7 +69,7 @@ const plugin = {
73
69
  `));
74
70
  }
75
71
  if ((0, utils_1.isNextAuthInstalled)()) {
76
- const config = await (0, config_1.getRequiredServerFiles)(dotNextDir);
72
+ const config = await (0, config_1.getRequiredServerFiles)(publish);
77
73
  const userDefinedNextAuthUrl = config.config.env.NEXTAUTH_URL;
78
74
  if (userDefinedNextAuthUrl) {
79
75
  console.log(`NextAuth package detected, NEXTAUTH_URL environment variable set by user in next.config.js to ${userDefinedNextAuthUrl}`);
@@ -83,7 +79,7 @@ const plugin = {
83
79
  const nextAuthUrl = `${process.env.NEXTAUTH_URL}${basePath}`;
84
80
  console.log(`NextAuth package detected, NEXTAUTH_URL environment variable set by user in Netlify configuration to ${nextAuthUrl}`);
85
81
  config.config.env.NEXTAUTH_URL = nextAuthUrl;
86
- await (0, config_1.updateRequiredServerFiles)(dotNextDir, config);
82
+ await (0, config_1.updateRequiredServerFiles)(publish, config);
87
83
  }
88
84
  else {
89
85
  // Using the deploy prime url in production leads to issues because the unique deploy ID is part of the generated URL
@@ -91,20 +87,23 @@ const plugin = {
91
87
  const nextAuthUrl = `${process.env.CONTEXT === 'production' ? process.env.URL : process.env.DEPLOY_PRIME_URL}${basePath}`;
92
88
  console.log(`NextAuth package detected, setting NEXTAUTH_URL environment variable to ${nextAuthUrl}`);
93
89
  config.config.env.NEXTAUTH_URL = nextAuthUrl;
94
- await (0, config_1.updateRequiredServerFiles)(dotNextDir, config);
90
+ await (0, config_1.updateRequiredServerFiles)(publish, config);
95
91
  }
96
92
  }
97
- const buildId = (0, fs_extra_1.readFileSync)((0, path_1.join)(dotNextDir, 'BUILD_ID'), 'utf8').trim();
98
- await (0, config_1.configureHandlerFunctions)({ netlifyConfig, ignore, publish: (0, path_1.relative)(process.cwd(), dotNextDir) });
99
- const apiRoutes = await (0, functions_1.getExtendedApiRouteConfigs)(dotNextDir, appDir);
93
+ const buildId = (0, fs_extra_1.readFileSync)((0, path_1.join)(publish, 'BUILD_ID'), 'utf8').trim();
94
+ await (0, config_1.configureHandlerFunctions)({ netlifyConfig, ignore, publish: (0, path_1.relative)(process.cwd(), publish) });
95
+ const apiRoutes = await (0, functions_1.getExtendedApiRouteConfigs)(publish, appDir);
100
96
  await (0, functions_1.generateFunctions)(constants, appDir, apiRoutes);
101
97
  await (0, functions_1.generatePagesResolver)({ target, constants });
102
- await (0, files_1.movePublicFiles)({ appDir, outdir, publishDir });
98
+ await (0, files_1.movePublicFiles)({ appDir, outdir, publish });
103
99
  await (0, files_1.patchNextFiles)(appDir);
104
100
  if (!(0, destr_1.default)(process.env.SERVE_STATIC_FILES_FROM_ORIGIN)) {
105
- await (0, files_1.moveStaticPages)({ distDir: dotNextDir, i18n, basePath, publishDir });
101
+ await (0, files_1.moveStaticPages)({ target, netlifyConfig, i18n, basePath });
106
102
  }
107
- await (0, fs_extra_1.copy)((0, path_1.join)(dotNextDir, 'static'), (0, path_1.join)(publishDir, '_next', 'static'));
103
+ await (0, redirects_1.generateStaticRedirects)({
104
+ netlifyConfig,
105
+ nextConfig: { basePath, i18n },
106
+ });
108
107
  await (0, functions_1.setupImageFunction)({
109
108
  constants,
110
109
  imageconfig: images,
@@ -121,8 +120,8 @@ const plugin = {
121
120
  });
122
121
  await (0, edge_1.writeEdgeFunctions)(netlifyConfig);
123
122
  },
124
- async onPostBuild({ netlifyConfig, utils: { status, cache, functions, build: { failBuild }, }, constants: { FUNCTIONS_DIST, PUBLISH_DIR }, }) {
125
- await (0, cache_1.saveCache)({ cache, publish: netlifyConfig.build.publish });
123
+ async onPostBuild({ netlifyConfig: { build: { publish }, redirects, headers, }, utils: { status, cache, functions, build: { failBuild }, }, constants: { FUNCTIONS_DIST }, }) {
124
+ await (0, cache_1.saveCache)({ cache, publish });
126
125
  if ((0, utils_1.shouldSkip)()) {
127
126
  status.show({
128
127
  title: 'Next Runtime did not run',
@@ -134,13 +133,12 @@ const plugin = {
134
133
  }
135
134
  await (0, verification_1.checkForOldFunctions)({ functions });
136
135
  await (0, verification_1.checkZipSize)((0, path_1.join)(FUNCTIONS_DIST, `${constants_1.ODB_FUNCTION_NAME}.zip`));
137
- const nextConfig = await (0, config_1.getNextConfig)({ publish: netlifyConfig.build.publish, failBuild });
136
+ const nextConfig = await (0, config_1.getNextConfig)({ publish, failBuild });
138
137
  const { basePath, appDir } = nextConfig;
139
- (0, config_1.generateCustomHeaders)(nextConfig, netlifyConfig.headers);
140
- (0, verification_1.warnForProblematicUserRewrites)({ basePath, redirects: netlifyConfig.redirects });
138
+ (0, config_1.generateCustomHeaders)(nextConfig, headers);
139
+ (0, verification_1.warnForProblematicUserRewrites)({ basePath, redirects });
141
140
  (0, verification_1.warnForRootRedirects)({ appDir });
142
141
  await (0, functions_1.warnOnApiRoutes)({ FUNCTIONS_DIST });
143
- netlifyConfig.build.publish = (0, path_1.join)(PUBLISH_DIR, 'dist');
144
142
  },
145
143
  };
146
144
  // The types haven't been updated yet
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/plugin-nextjs",
3
- "version": "4.29.0",
3
+ "version": "4.29.1",
4
4
  "description": "Run Next.js seamlessly on Netlify",
5
5
  "main": "index.js",
6
6
  "files": [