@netlify/plugin-nextjs 4.33.1-lazy-server-import.0 → 4.35.0

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.
@@ -23,16 +23,18 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.extractConfigFromFile = exports.validateConfigValue = void 0;
26
+ exports.extractConfigFromFile = exports.validateConfigValue = exports.isEdgeConfig = void 0;
27
27
  const fs_1 = __importStar(require("fs"));
28
28
  const pathe_1 = require("pathe");
29
+ const isEdgeConfig = (config) => ['experimental-edge', 'edge'].includes(config);
30
+ exports.isEdgeConfig = isEdgeConfig;
29
31
  const validateConfigValue = (config, apiFilePath) => {
30
32
  if (config.type === "experimental-scheduled" /* ApiRouteType.SCHEDULED */) {
31
33
  if (!config.schedule) {
32
34
  console.error(`Invalid config value in ${(0, pathe_1.relative)(process.cwd(), apiFilePath)}: schedule is required when type is "${"experimental-scheduled" /* ApiRouteType.SCHEDULED */}"`);
33
35
  return false;
34
36
  }
35
- if (config.runtime === 'experimental-edge') {
37
+ if ((0, exports.isEdgeConfig)(config.runtime)) {
36
38
  console.error(`Invalid config value in ${(0, pathe_1.relative)(process.cwd(), apiFilePath)}: edge runtime is not supported for scheduled functions`);
37
39
  return false;
38
40
  }
@@ -43,7 +45,7 @@ const validateConfigValue = (config, apiFilePath) => {
43
45
  console.error(`Invalid config value in ${(0, pathe_1.relative)(process.cwd(), apiFilePath)}: schedule is not allowed unless type is "${"experimental-scheduled" /* ApiRouteType.SCHEDULED */}"`);
44
46
  return false;
45
47
  }
46
- if (config.type && config.runtime === 'experimental-edge') {
48
+ if (config.type && (0, exports.isEdgeConfig)(config.runtime)) {
47
49
  console.error(`Invalid config value in ${(0, pathe_1.relative)(process.cwd(), apiFilePath)}: edge runtime is not supported for background functions`);
48
50
  return false;
49
51
  }
@@ -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.writeEdgeFunctions = exports.getEdgeFunctionPatternForPage = exports.writeRscDataEdgeFunction = exports.writeDevEdgeFunction = exports.cleanupEdgeFunctions = exports.loadPrerenderManifest = exports.loadAppPathRoutesManifest = exports.loadMiddlewareManifest = exports.isAppDirRoute = void 0;
6
+ exports.writeEdgeFunctions = exports.getEdgeFunctionPatternForPage = exports.generateRscDataEdgeManifest = exports.writeDevEdgeFunction = exports.cleanupEdgeFunctions = exports.loadPrerenderManifest = exports.loadAppPathRoutesManifest = exports.loadMiddlewareManifest = exports.isAppDirRoute = void 0;
7
7
  const fs_1 = require("fs");
8
8
  const path_1 = require("path");
9
9
  const chalk_1 = require("chalk");
@@ -130,19 +130,19 @@ exports.writeDevEdgeFunction = writeDevEdgeFunction;
130
130
  /**
131
131
  * Writes an edge function that routes RSC data requests to the `.rsc` route
132
132
  */
133
- const writeRscDataEdgeFunction = async ({ prerenderManifest, appPathRoutesManifest, }) => {
133
+ const generateRscDataEdgeManifest = async ({ prerenderManifest, appPathRoutesManifest, }) => {
134
134
  if (!prerenderManifest || !appPathRoutesManifest) {
135
135
  return [];
136
136
  }
137
137
  const staticAppdirRoutes = [];
138
138
  for (const [path, route] of Object.entries(prerenderManifest.routes)) {
139
- if ((0, exports.isAppDirRoute)(route.srcRoute, appPathRoutesManifest)) {
139
+ if ((0, exports.isAppDirRoute)(route.srcRoute, appPathRoutesManifest) && route.dataRoute) {
140
140
  staticAppdirRoutes.push(path, route.dataRoute);
141
141
  }
142
142
  }
143
143
  const dynamicAppDirRoutes = [];
144
144
  for (const [path, route] of Object.entries(prerenderManifest.dynamicRoutes)) {
145
- if ((0, exports.isAppDirRoute)(path, appPathRoutesManifest)) {
145
+ if ((0, exports.isAppDirRoute)(path, appPathRoutesManifest) && route.dataRouteRegex) {
146
146
  dynamicAppDirRoutes.push(route.routeRegex, route.dataRouteRegex);
147
147
  }
148
148
  }
@@ -165,7 +165,7 @@ const writeRscDataEdgeFunction = async ({ prerenderManifest, appPathRoutesManife
165
165
  })),
166
166
  ];
167
167
  };
168
- exports.writeRscDataEdgeFunction = writeRscDataEdgeFunction;
168
+ exports.generateRscDataEdgeManifest = generateRscDataEdgeManifest;
169
169
  const getEdgeFunctionPatternForPage = ({ edgeFunctionDefinition, pageRegexMap, appPathRoutesManifest, }) => {
170
170
  // We don't just use the matcher from the edge function definition, because it doesn't handle trailing slashes
171
171
  var _a, _b;
@@ -189,6 +189,7 @@ const writeEdgeFunctions = async ({ netlifyConfig, routesManifest, }) => {
189
189
  var _a;
190
190
  const manifest = {
191
191
  functions: [],
192
+ layers: [],
192
193
  version: 1,
193
194
  };
194
195
  const edgeFunctionRoot = (0, path_1.resolve)('.netlify', 'edge-functions');
@@ -205,7 +206,7 @@ const writeEdgeFunctions = async ({ netlifyConfig, routesManifest, }) => {
205
206
  console.log('Environment variable NEXT_DISABLE_NETLIFY_EDGE has been set, skipping Netlify Edge Function creation.');
206
207
  return;
207
208
  }
208
- const rscFunctions = await (0, exports.writeRscDataEdgeFunction)({
209
+ const rscFunctions = await (0, exports.generateRscDataEdgeManifest)({
209
210
  prerenderManifest: await (0, exports.loadPrerenderManifest)(netlifyConfig),
210
211
  appPathRoutesManifest: await (0, exports.loadAppPathRoutesManifest)(netlifyConfig),
211
212
  });
@@ -291,7 +292,11 @@ const writeEdgeFunctions = async ({ netlifyConfig, routesManifest, }) => {
291
292
  manifest.functions.push({
292
293
  function: 'ipx',
293
294
  name: 'next/image handler',
294
- path: '/_next/image*',
295
+ path: nextConfig.images.path || '/_next/image',
296
+ });
297
+ manifest.layers.push({
298
+ name: 'https://ipx-edge-function-layer.netlify.app/mod.ts',
299
+ flag: 'ipx-edge-function-layer-url',
295
300
  });
296
301
  }
297
302
  else {
@@ -25,7 +25,7 @@ const generateFunctions = async ({ FUNCTIONS_SRC = constants_1.DEFAULT_FUNCTIONS
25
25
  const publishDir = (0, pathe_1.relative)(functionDir, publish);
26
26
  for (const { route, config, compiled } of apiRoutes) {
27
27
  // Don't write a lambda if the runtime is edge
28
- if (config.runtime === 'experimental-edge') {
28
+ if ((0, analysis_1.isEdgeConfig)(config.runtime)) {
29
29
  continue;
30
30
  }
31
31
  const apiHandlerSource = await (0, getApiHandler_1.getApiHandler)({
@@ -11,14 +11,13 @@ const path = require('path');
11
11
  const { URLSearchParams, URL } = require('url');
12
12
  const { Bridge } = require('@vercel/node-bridge/bridge');
13
13
  const { augmentFsModule, getMaxAge, getMultiValueHeaders, getPrefetchResponse, normalizePath, } = require('./handlerUtils');
14
+ const { NetlifyNextServer } = require('./server');
14
15
  // We return a function and then call `toString()` on it to serialise it as the launcher function
15
16
  // eslint-disable-next-line max-params, max-lines-per-function
16
17
  const makeHandler = (conf, app, pageRoot, staticManifest = [], mode = 'ssr') => {
17
18
  var _a;
18
19
  // Change working directory into the site root, unless using Nx, which moves the
19
20
  // dist directory and handles this itself
20
- // eslint-disable-next-line @typescript-eslint/no-var-requires
21
- const { NetlifyNextServer } = require('./server');
22
21
  const dir = path.resolve(__dirname, app);
23
22
  if (pageRoot.startsWith(dir)) {
24
23
  process.chdir(dir);
@@ -146,6 +145,7 @@ const getHandler = ({ isODB = false, publishDir = '../../../.next', appDir = '..
146
145
  // We copy the file here rather than requiring from the node module
147
146
  const { Bridge } = require("./bridge");
148
147
  const { augmentFsModule, getMaxAge, getMultiValueHeaders, getPrefetchResponse, getNextServer, normalizePath } = require('./handlerUtils')
148
+ const { NetlifyNextServer } = require('./server')
149
149
 
150
150
  ${isODB ? `const { builder } = require("@netlify/functions")` : ''}
151
151
  const { config } = require("${publishDir}/required-server-files.json")
@@ -91,7 +91,7 @@ const augmentFsModule = ({ promises, staticManifest, pageRoot, getBase, }) => {
91
91
  // Grab the real fs.promises.readFile...
92
92
  const readfileOrig = promises.readFile;
93
93
  const statsOrig = promises.stat;
94
- // ...then money-patch it to see if it's requesting a CDN file
94
+ // ...then monkey-patch it to see if it's requesting a CDN file
95
95
  promises.readFile = (async (file, options) => {
96
96
  const baseUrl = getBase();
97
97
  // We only care about page files
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/plugin-nextjs",
3
- "version": "4.33.1-lazy-server-import.0",
3
+ "version": "4.35.0",
4
4
  "description": "Run Next.js seamlessly on Netlify",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -13,7 +13,7 @@
13
13
  "dependencies": {
14
14
  "@netlify/esbuild": "0.14.39",
15
15
  "@netlify/functions": "^1.4.0",
16
- "@netlify/ipx": "^1.3.3",
16
+ "@netlify/ipx": "^1.4.0",
17
17
  "@vercel/node-bridge": "^2.1.0",
18
18
  "chalk": "^4.1.2",
19
19
  "chokidar": "^3.5.3",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@delucis/if-env": "^1.1.2",
40
- "@netlify/build": "^29.9.0",
40
+ "@netlify/build": "^29.9.2",
41
41
  "@types/fs-extra": "^9.0.13",
42
42
  "@types/jest": "^27.4.1",
43
43
  "@types/merge-stream": "^1.1.2",
@@ -0,0 +1,3 @@
1
+ {
2
+ "formats": ["webp"]
3
+ }
@@ -1,73 +1,5 @@
1
- import { Accepts } from 'https://deno.land/x/accepts@2.1.1/mod.ts'
2
- import type { Context } from 'https://edge.netlify.com'
3
- // Available at build time
4
- import imageconfig from './imageconfig.json' assert { type: 'json' }
5
-
6
- const defaultFormat = 'webp'
7
-
8
- interface ImageConfig extends Record<string, unknown> {
9
- formats?: string[]
10
- }
11
-
12
- // Checks if a URL param is numeric
13
- const isNumeric = (value: string | null) => Number(value).toString() === value
14
-
15
- /**
16
- * Implement content negotiation for images
17
- */
18
-
19
- // deno-lint-ignore require-await
20
- const handler = async (req: Request, context: Context) => {
21
- const { searchParams } = new URL(req.url)
22
- const accept = new Accepts(req.headers)
23
- const { formats = [defaultFormat] } = imageconfig as ImageConfig
24
- if (formats.length === 0) {
25
- formats.push(defaultFormat)
26
- }
27
- let type = accept.types(formats) || defaultFormat
28
- if (Array.isArray(type)) {
29
- type = type[0]
30
- }
31
-
32
- const source = searchParams.get('url')
33
- const width = searchParams.get('w')
34
- const quality = searchParams.get('q') ?? '75'
1
+ import { getHandler } from 'https://ipx-edge-function-layer.netlify.app/mod.ts'
35
2
 
36
- const errors: Array<string> = []
37
-
38
- if (!source) {
39
- errors.push('Missing "url" parameter')
40
- } else if (!source.startsWith('http') && !source.startsWith('/')) {
41
- errors.push('The "url" parameter must be a valid URL or path')
42
- }
43
-
44
- if (!width) {
45
- errors.push('Missing "w" parameter')
46
- } else if (!isNumeric(width)) {
47
- errors.push('Invalid "w" parameter')
48
- }
49
-
50
- if (!isNumeric(quality)) {
51
- errors.push('Invalid "q" parameter')
52
- }
53
-
54
- if (!source || errors.length > 0) {
55
- return new Response(`Invalid request: \n${errors.join('\n')}`, {
56
- status: 400,
57
- })
58
- }
59
-
60
- const modifiers = [`w_${width}`, `q_${quality}`]
61
-
62
- if (type) {
63
- if (type.includes('/')) {
64
- // If this is a mimetype, strip "image/"
65
- type = type.split('/')[1]
66
- }
67
- modifiers.push(`f_${type}`)
68
- }
69
- const target = `/_ipx/${modifiers.join(',')}/${encodeURIComponent(source)}`
70
- return context.rewrite(target)
71
- }
3
+ import imageconfig from './imageconfig.json' assert { type: 'json' }
72
4
 
73
- export default handler
5
+ export default getHandler({ formats: imageconfig?.formats })
@@ -44,7 +44,7 @@ export const getRscDataRouter = ({ routes: staticRoutes, dynamicRoutes }: Preren
44
44
  )
45
45
 
46
46
  const dynamicRouteMatcher = Object.values(dynamicRoutes)
47
- .filter(({ dataRoute }) => dataRoute.endsWith('.rsc'))
47
+ .filter(({ dataRoute }) => dataRoute?.endsWith('.rsc'))
48
48
  .map(({ routeRegex }) => new RegExp(routeRegex))
49
49
 
50
50
  const matchesDynamicRscDataRoute = (pathname: string) => {