@netlify/plugin-nextjs 3.9.0 → 4.0.0-beta.10

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.
Files changed (97) hide show
  1. package/README.md +32 -51
  2. package/lib/.DS_Store +0 -0
  3. package/lib/constants.js +21 -0
  4. package/lib/helpers/cache.js +20 -0
  5. package/lib/helpers/config.js +174 -0
  6. package/lib/helpers/files.js +187 -0
  7. package/lib/helpers/functions.js +65 -0
  8. package/lib/helpers/verification.js +93 -0
  9. package/lib/index.js +50 -0
  10. package/lib/templates/getHandler.js +161 -0
  11. package/lib/templates/getPageResolver.js +24 -0
  12. package/lib/templates/handlerUtils.js +36 -0
  13. package/lib/templates/ipx.js +8 -0
  14. package/manifest.yml +1 -1
  15. package/package.json +50 -55
  16. package/LICENSE.md +0 -7
  17. package/helpers/cacheBuild.js +0 -31
  18. package/helpers/checkNxConfig.js +0 -56
  19. package/helpers/copyUnstableIncludedDirs.js +0 -27
  20. package/helpers/doesNotNeedPlugin.js +0 -49
  21. package/helpers/doesSiteUseNextOnNetlify.js +0 -20
  22. package/helpers/getNextConfig.js +0 -46
  23. package/helpers/getNextRoot.js +0 -20
  24. package/helpers/isStaticExportProject.js +0 -20
  25. package/helpers/resolveNextModule.js +0 -30
  26. package/helpers/usesBuildCommand.js +0 -37
  27. package/helpers/validateNextUsage.js +0 -53
  28. package/helpers/verifyBuildTarget.js +0 -69
  29. package/index.js +0 -166
  30. package/src/index.js +0 -94
  31. package/src/lib/config.js +0 -58
  32. package/src/lib/constants/regex.js +0 -9
  33. package/src/lib/helpers/addDefaultLocaleRedirect.js +0 -25
  34. package/src/lib/helpers/addLocaleRedirects.js +0 -19
  35. package/src/lib/helpers/asyncForEach.js +0 -7
  36. package/src/lib/helpers/convertToBasePathRedirects.js +0 -80
  37. package/src/lib/helpers/copyDynamicImportChunks.js +0 -39
  38. package/src/lib/helpers/formatRedirectTarget.js +0 -9
  39. package/src/lib/helpers/getDataRouteForRoute.js +0 -30
  40. package/src/lib/helpers/getFilePathForRoute.js +0 -10
  41. package/src/lib/helpers/getI18n.js +0 -10
  42. package/src/lib/helpers/getNetlifyFunctionName.js +0 -38
  43. package/src/lib/helpers/getNetlifyRoutes.js +0 -45
  44. package/src/lib/helpers/getNextDistDir.js +0 -12
  45. package/src/lib/helpers/getNextSrcDir.js +0 -5
  46. package/src/lib/helpers/getPagesManifest.js +0 -19
  47. package/src/lib/helpers/getPrerenderManifest.js +0 -40
  48. package/src/lib/helpers/getPreviewModeFunctionName.js +0 -5
  49. package/src/lib/helpers/getRoutesManifest.js +0 -12
  50. package/src/lib/helpers/getSortedRedirects.js +0 -37
  51. package/src/lib/helpers/handleFileTracking.js +0 -61
  52. package/src/lib/helpers/isApiRoute.js +0 -4
  53. package/src/lib/helpers/isDynamicRoute.js +0 -6
  54. package/src/lib/helpers/isFrameworkRoute.js +0 -5
  55. package/src/lib/helpers/isHtmlFile.js +0 -4
  56. package/src/lib/helpers/isRootCatchAllRedirect.js +0 -6
  57. package/src/lib/helpers/isRouteInPrerenderManifest.js +0 -23
  58. package/src/lib/helpers/isRouteWithDataRoute.js +0 -13
  59. package/src/lib/helpers/isRouteWithFallback.js +0 -12
  60. package/src/lib/helpers/logger.js +0 -44
  61. package/src/lib/helpers/removeFileExtension.js +0 -4
  62. package/src/lib/helpers/runJobsQueue.js +0 -18
  63. package/src/lib/helpers/setupNetlifyFunctionForPage.js +0 -44
  64. package/src/lib/helpers/setupStaticFileForPage.js +0 -18
  65. package/src/lib/pages/api/pages.js +0 -22
  66. package/src/lib/pages/api/redirects.js +0 -13
  67. package/src/lib/pages/api/setup.js +0 -15
  68. package/src/lib/pages/getInitialProps/pages.js +0 -40
  69. package/src/lib/pages/getInitialProps/redirects.js +0 -26
  70. package/src/lib/pages/getInitialProps/setup.js +0 -15
  71. package/src/lib/pages/getServerSideProps/pages.js +0 -43
  72. package/src/lib/pages/getServerSideProps/redirects.js +0 -44
  73. package/src/lib/pages/getServerSideProps/setup.js +0 -15
  74. package/src/lib/pages/getStaticProps/pages.js +0 -26
  75. package/src/lib/pages/getStaticProps/redirects.js +0 -70
  76. package/src/lib/pages/getStaticProps/setup.js +0 -68
  77. package/src/lib/pages/getStaticPropsWithFallback/pages.js +0 -24
  78. package/src/lib/pages/getStaticPropsWithFallback/redirects.js +0 -51
  79. package/src/lib/pages/getStaticPropsWithFallback/setup.js +0 -29
  80. package/src/lib/pages/getStaticPropsWithRevalidate/pages.js +0 -45
  81. package/src/lib/pages/getStaticPropsWithRevalidate/redirects.js +0 -55
  82. package/src/lib/pages/getStaticPropsWithRevalidate/setup.js +0 -40
  83. package/src/lib/pages/withoutProps/pages.js +0 -27
  84. package/src/lib/pages/withoutProps/redirects.js +0 -51
  85. package/src/lib/pages/withoutProps/setup.js +0 -34
  86. package/src/lib/pages/worker.js +0 -19
  87. package/src/lib/steps/copyNextAssets.js +0 -31
  88. package/src/lib/steps/copyPublicFiles.js +0 -18
  89. package/src/lib/steps/prepareFolders.js +0 -39
  90. package/src/lib/steps/setupHeaders.js +0 -37
  91. package/src/lib/steps/setupImageFunction.js +0 -17
  92. package/src/lib/steps/setupPages.js +0 -25
  93. package/src/lib/steps/setupRedirects.js +0 -105
  94. package/src/lib/templates/getHandlerFunction.js +0 -209
  95. package/src/lib/templates/getTemplate.js +0 -15
  96. package/src/lib/templates/imageFunction.js +0 -135
  97. package/src/next-on-netlify.js +0 -22
@@ -0,0 +1,93 @@
1
+ const { existsSync, promises } = require('fs');
2
+ const path = require('path');
3
+ const { relative } = require('path');
4
+ const { yellowBright, greenBright, blueBright, redBright, reset } = require('chalk');
5
+ const { async: StreamZip } = require('node-stream-zip');
6
+ const outdent = require('outdent');
7
+ const prettyBytes = require('pretty-bytes');
8
+ const { satisfies } = require('semver');
9
+ // This is when nft support was added
10
+ const REQUIRED_BUILD_VERSION = '>=18.16.0';
11
+ exports.verifyNetlifyBuildVersion = ({ IS_LOCAL, NETLIFY_BUILD_VERSION, failBuild }) => {
12
+ // We check for build version because that's what's available to us, but prompt about the cli because that's what they can upgrade
13
+ if (IS_LOCAL && !satisfies(NETLIFY_BUILD_VERSION, REQUIRED_BUILD_VERSION, { includePrerelease: true })) {
14
+ return failBuild(outdent `
15
+ This version of the Essential Next.js plugin requires netlify-cli@6.12.4 or higher. Please upgrade and try again.
16
+ You can do this by running: "npm install -g netlify-cli@latest" or "yarn global add netlify-cli@latest"
17
+ `);
18
+ }
19
+ };
20
+ exports.checkForOldFunctions = async ({ functions }) => {
21
+ const oldFunctions = (await functions.list()).filter(({ name }) => name.startsWith('next_'));
22
+ if (oldFunctions.length !== 0) {
23
+ console.log(yellowBright(outdent `
24
+ We have found the following functions in your site that seem to be left over from the old Next.js plugin (v3). We have guessed this because the name starts with "next_".
25
+
26
+ ${reset(oldFunctions.map(({ name }) => `- ${name}`).join('\n'))}
27
+
28
+ If they were created by the old plugin, these functions are likely to cause errors so should be removed. You can do this by deleting the following directories:
29
+
30
+ ${reset(oldFunctions.map(({ mainFile }) => `- ${path.relative(process.cwd(), path.dirname(mainFile))}`).join('\n'))}
31
+ `));
32
+ }
33
+ };
34
+ exports.checkNextSiteHasBuilt = ({ publish, failBuild }) => {
35
+ if (!existsSync(path.join(publish, 'BUILD_ID'))) {
36
+ return failBuild(outdent `
37
+ The directory "${path.relative(process.cwd(), publish)}" does not contain a Next.js production build. Perhaps the build command was not run, or you specified the wrong publish directory.
38
+ In most cases it should be set to the site's ".next" directory path, unless you have chosen a custom "distDir" in your Next config.
39
+ If you are using "next export" then the Essential Next.js plugin should be removed. See https://ntl.fyi/remove-plugin for details.
40
+ `);
41
+ }
42
+ if (existsSync(path.join(publish, 'export-detail.json'))) {
43
+ failBuild(outdent `
44
+ Detected that "next export" was run, but site is incorrectly publishing the ".next" directory.
45
+ This plugin is not needed for "next export" so should be removed, and publish directory set to "out".
46
+ See https://ntl.fyi/remove-plugin for more details on how to remove this plugin.
47
+ `);
48
+ }
49
+ };
50
+ exports.checkForRootPublish = ({ publish, failBuild }) => {
51
+ if (path.resolve(publish) === path.resolve('.')) {
52
+ failBuild(outdent `
53
+ Your publish directory is pointing to the base directory of your site. This is not supported for Next.js sites, and is probably a mistake.
54
+ In most cases it should be set to ".next", unless you have chosen a custom "distDir" in your Next config, or the Next site is in a subdirectory.
55
+ `);
56
+ }
57
+ };
58
+ // 50MB, which is the documented max, though the hard max seems to be higher
59
+ const LAMBDA_MAX_SIZE = 1024 * 1024 * 50;
60
+ exports.checkZipSize = async (file, maxSize = LAMBDA_MAX_SIZE) => {
61
+ if (!existsSync(file)) {
62
+ console.warn(`Could not check zip size because ${file} does not exist`);
63
+ return;
64
+ }
65
+ const size = await promises.stat(file).then(({ size }) => size);
66
+ if (size < maxSize) {
67
+ return;
68
+ }
69
+ // We don't fail the build, because the actual hard max size is larger so it might still succeed
70
+ console.log(redBright(outdent `
71
+ The function zip ${yellowBright(relative(process.cwd(), file))} size is ${prettyBytes(size)}, which is larger than the maximum supported size of ${prettyBytes(maxSize)}.
72
+ There are a few reasons this could happen. You may have accidentally bundled a large dependency, or you might have a
73
+ large number of pre-rendered pages included.
74
+ `));
75
+ const zip = new StreamZip({ file });
76
+ console.log(`Contains ${await zip.entriesCount} files`);
77
+ const sortedFiles = Object.values(await zip.entries()).sort((a, b) => b.size - a.size);
78
+ const largest = {};
79
+ for (let i = 0; i < 10 && i < sortedFiles.length; i++) {
80
+ largest[`${i + 1}`] = {
81
+ File: sortedFiles[i].name,
82
+ 'Compressed Size': prettyBytes(sortedFiles[i].compressedSize),
83
+ 'Uncompressed Size': prettyBytes(sortedFiles[i].size),
84
+ };
85
+ }
86
+ console.log(yellowBright `\n\nThese are the largest files in the zip:`);
87
+ console.table(largest);
88
+ console.log(greenBright `\n\nFor more information on fixing this, see ${blueBright `https://ntl.fyi/large-next-functions`}`);
89
+ };
90
+ exports.logBetaMessage = () => console.log(greenBright(outdent `
91
+ Thank you for trying the Essential Next.js beta plugin.
92
+ Please share feedback (both good and bad) at ${blueBright `https://ntl.fyi/next-beta-feedback`}
93
+ `));
package/lib/index.js ADDED
@@ -0,0 +1,50 @@
1
+ const { join, relative } = require('path');
2
+ const { ODB_FUNCTION_NAME } = require('./constants');
3
+ const { restoreCache, saveCache } = require('./helpers/cache');
4
+ const { getNextConfig, configureHandlerFunctions, generateRedirects } = require('./helpers/config');
5
+ const { moveStaticPages, movePublicFiles } = require('./helpers/files');
6
+ const { generateFunctions, setupImageFunction, generatePagesResolver } = require('./helpers/functions');
7
+ const { verifyNetlifyBuildVersion, checkNextSiteHasBuilt, checkForRootPublish, logBetaMessage, checkZipSize, checkForOldFunctions, } = require('./helpers/verification');
8
+ /** @type import("@netlify/build").NetlifyPlugin */
9
+ module.exports = {
10
+ async onPreBuild({ constants, netlifyConfig, utils: { build: { failBuild }, cache, }, }) {
11
+ var _a;
12
+ logBetaMessage();
13
+ const { publish } = netlifyConfig.build;
14
+ checkForRootPublish({ publish, failBuild });
15
+ verifyNetlifyBuildVersion({ failBuild, ...constants });
16
+ await restoreCache({ cache, publish });
17
+ (_a = netlifyConfig.build).environment || (_a.environment = {});
18
+ // eslint-disable-next-line unicorn/consistent-destructuring
19
+ netlifyConfig.build.environment.NEXT_PRIVATE_TARGET = 'server';
20
+ },
21
+ async onBuild({ constants, netlifyConfig, utils: { build: { failBuild }, }, }) {
22
+ const { publish } = netlifyConfig.build;
23
+ checkNextSiteHasBuilt({ publish, failBuild });
24
+ const { appDir, basePath, i18n, images, target, ignore } = await getNextConfig({ publish, failBuild });
25
+ configureHandlerFunctions({ netlifyConfig, ignore, publish: relative(process.cwd(), publish) });
26
+ await generateFunctions(constants, appDir);
27
+ await generatePagesResolver({ netlifyConfig, target, constants });
28
+ await movePublicFiles({ appDir, publish });
29
+ if (process.env.EXPERIMENTAL_MOVE_STATIC_PAGES) {
30
+ 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'");
31
+ }
32
+ if (!process.env.SERVE_STATIC_FILES_FROM_ORIGIN) {
33
+ await moveStaticPages({ target, failBuild, netlifyConfig, i18n });
34
+ }
35
+ await setupImageFunction({ constants, imageconfig: images, netlifyConfig, basePath });
36
+ await generateRedirects({
37
+ netlifyConfig,
38
+ basePath,
39
+ i18n,
40
+ });
41
+ },
42
+ async onPostBuild({ netlifyConfig, utils: { cache, functions }, constants: { FUNCTIONS_DIST } }) {
43
+ await saveCache({ cache, publish: netlifyConfig.build.publish });
44
+ await checkForOldFunctions({ functions });
45
+ await checkZipSize(join(FUNCTIONS_DIST, `${ODB_FUNCTION_NAME}.zip`));
46
+ },
47
+ onEnd() {
48
+ logBetaMessage();
49
+ },
50
+ };
@@ -0,0 +1,161 @@
1
+ const { promises, existsSync } = require('fs');
2
+ const { Server } = require('http');
3
+ const { tmpdir } = require('os');
4
+ const path = require('path');
5
+ const { Bridge } = require('@vercel/node/dist/bridge');
6
+ const { downloadFile } = require('./handlerUtils');
7
+ const makeHandler = () =>
8
+ // We return a function and then call `toString()` on it to serialise it as the launcher function
9
+ // eslint-disable-next-line max-params
10
+ (conf, app, pageRoot, staticManifest = [], mode = 'ssr') => {
11
+ // This is just so nft knows about the page entrypoints. It's not actually used
12
+ try {
13
+ // eslint-disable-next-line node/no-missing-require
14
+ require.resolve('./pages.js');
15
+ }
16
+ catch { }
17
+ // We don't want to write ISR files to disk in the lambda environment
18
+ conf.experimental.isrFlushToDisk = false;
19
+ // Set during the request as it needs the host header. Hoisted so we can define the function once
20
+ let base;
21
+ // Only do this if we have some static files moved to the CDN
22
+ if (staticManifest.length !== 0) {
23
+ // These are static page files that have been removed from the function bundle
24
+ // In most cases these are served from the CDN, but for rewrites Next may try to read them
25
+ // from disk. We need to intercept these and load them from the CDN instead
26
+ // Sadly the only way to do this is to monkey-patch fs.promises. Yeah, I know.
27
+ const staticFiles = new Set(staticManifest);
28
+ // Yes, you can cache stuff locally in a Lambda
29
+ const cacheDir = path.join(tmpdir(), 'next-static-cache');
30
+ // Grab the real fs.promises.readFile...
31
+ const readfileOrig = promises.readFile;
32
+ // ...then money-patch it to see if it's requesting a CDN file
33
+ promises.readFile = async (file, options) => {
34
+ // We only care about page files
35
+ if (file.startsWith(pageRoot)) {
36
+ // We only want the part after `pages/`
37
+ const filePath = file.slice(pageRoot.length + 1);
38
+ // Is it in the CDN and not local?
39
+ if (staticFiles.has(filePath) && !existsSync(file)) {
40
+ // This name is safe to use, because it's one that was already created by Next
41
+ const cacheFile = path.join(cacheDir, filePath);
42
+ // Have we already cached it? We ignore the cache if running locally to avoid staleness
43
+ if ((!existsSync(cacheFile) || process.env.NETLIFY_DEV) && base) {
44
+ await promises.mkdir(path.dirname(cacheFile), { recursive: true });
45
+ // Append the path to our host and we can load it like a regular page
46
+ const url = `${base}/${filePath}`;
47
+ await downloadFile(url, cacheFile);
48
+ }
49
+ // Return the cache file
50
+ return readfileOrig(cacheFile, options);
51
+ }
52
+ }
53
+ return readfileOrig(file, options);
54
+ };
55
+ }
56
+ let NextServer;
57
+ try {
58
+ // next >= 11.0.1. Yay breaking changes in patch releases!
59
+ NextServer = require('next/dist/server/next-server').default;
60
+ }
61
+ catch (error) {
62
+ if (!error.message.includes("Cannot find module 'next/dist/server/next-server'")) {
63
+ // A different error, so rethrow it
64
+ throw error;
65
+ }
66
+ // Probably an old version of next
67
+ }
68
+ if (!NextServer) {
69
+ try {
70
+ // next < 11.0.1
71
+ // eslint-disable-next-line node/no-missing-require, import/no-unresolved
72
+ NextServer = require('next/dist/next-server/server/next-server').default;
73
+ }
74
+ catch (error) {
75
+ if (!error.message.includes("Cannot find module 'next/dist/next-server/server/next-server'")) {
76
+ throw error;
77
+ }
78
+ throw new Error('Could not find Next.js server');
79
+ }
80
+ }
81
+ const nextServer = new NextServer({
82
+ conf,
83
+ dir: path.resolve(__dirname, app),
84
+ customServer: false,
85
+ });
86
+ const requestHandler = nextServer.getRequestHandler();
87
+ const server = new Server(async (req, res) => {
88
+ try {
89
+ await requestHandler(req, res);
90
+ }
91
+ catch (error) {
92
+ console.error(error);
93
+ throw new Error('server function error');
94
+ }
95
+ });
96
+ const bridge = new Bridge(server);
97
+ bridge.listen();
98
+ return async (event, context) => {
99
+ var _a, _b, _c;
100
+ // Ensure that paths are encoded - but don't double-encode them
101
+ event.path = new URL(event.path, event.rawUrl).pathname;
102
+ // Next expects to be able to parse the query from the URL
103
+ const query = new URLSearchParams(event.queryStringParameters).toString();
104
+ event.path = query ? `${event.path}?${query}` : event.path;
105
+ // Only needed if we're intercepting static files
106
+ if (staticManifest.length !== 0) {
107
+ const { host } = event.headers;
108
+ const protocol = event.headers['x-forwarded-proto'] || 'http';
109
+ base = `${protocol}://${host}`;
110
+ }
111
+ const { headers, ...result } = await bridge.launcher(event, context);
112
+ /** @type import("@netlify/functions").HandlerResponse */
113
+ // Convert all headers to multiValueHeaders
114
+ const multiValueHeaders = {};
115
+ for (const key of Object.keys(headers)) {
116
+ if (Array.isArray(headers[key])) {
117
+ multiValueHeaders[key] = headers[key];
118
+ }
119
+ else {
120
+ multiValueHeaders[key] = [headers[key]];
121
+ }
122
+ }
123
+ if ((_b = (_a = multiValueHeaders['set-cookie']) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.includes('__prerender_bypass')) {
124
+ delete multiValueHeaders.etag;
125
+ multiValueHeaders['cache-control'] = ['no-cache'];
126
+ }
127
+ // Sending SWR headers causes undefined behaviour with the Netlify CDN
128
+ const cacheHeader = (_c = multiValueHeaders['cache-control']) === null || _c === void 0 ? void 0 : _c[0];
129
+ if (cacheHeader === null || cacheHeader === void 0 ? void 0 : cacheHeader.includes('stale-while-revalidate')) {
130
+ console.log({ cacheHeader });
131
+ multiValueHeaders['cache-control'] = ['public, max-age=0, must-revalidate'];
132
+ }
133
+ multiValueHeaders['x-render-mode'] = [mode];
134
+ return {
135
+ ...result,
136
+ multiValueHeaders,
137
+ isBase64Encoded: result.encoding === 'base64',
138
+ };
139
+ };
140
+ };
141
+ const getHandler = ({ isODB = false, publishDir = '../../../.next', appDir = '../../..' }) => `
142
+ const { Server } = require("http");
143
+ const { tmpdir } = require('os')
144
+ const { promises, existsSync } = require("fs");
145
+ // We copy the file here rather than requiring from the node module
146
+ const { Bridge } = require("./bridge");
147
+ const { downloadFile } = require('./handlerUtils')
148
+
149
+ const { builder } = require("@netlify/functions");
150
+ const { config } = require("${publishDir}/required-server-files.json")
151
+ let staticManifest
152
+ try {
153
+ staticManifest = require("${publishDir}/static-manifest.json")
154
+ } catch {}
155
+ const path = require("path");
156
+ const pageRoot = path.resolve(path.join(__dirname, "${publishDir}", config.target === "server" ? "server" : "serverless", "pages"));
157
+ exports.handler = ${isODB
158
+ ? `builder((${makeHandler().toString()})(config, "${appDir}", pageRoot, staticManifest, 'odb'));`
159
+ : `(${makeHandler().toString()})(config, "${appDir}", pageRoot, staticManifest, 'ssr');`}
160
+ `;
161
+ module.exports = getHandler;
@@ -0,0 +1,24 @@
1
+ const { posix: { resolve, join, relative }, } = require('path');
2
+ const { outdent } = require('outdent');
3
+ const slash = require('slash');
4
+ const glob = require('tiny-glob');
5
+ const { HANDLER_FUNCTION_NAME } = require('../constants');
6
+ // Generate a file full of require.resolve() calls for all the pages in the
7
+ // build. This is used by the nft bundler to find all the pages.
8
+ exports.getPageResolver = async ({ netlifyConfig, target }) => {
9
+ const functionDir = resolve(join('.netlify', 'functions', HANDLER_FUNCTION_NAME));
10
+ const root = join(netlifyConfig.build.publish, target === 'server' ? 'server' : 'serverless', 'pages');
11
+ const pages = await glob('**/*.js', {
12
+ cwd: root,
13
+ dot: true,
14
+ });
15
+ const pageFiles = pages.map((page) => `require.resolve('${relative(functionDir, join(root, slash(page)))}')`).sort();
16
+ return outdent `
17
+ // This file is purely to allow nft to know about these pages. It should be temporary.
18
+ exports.resolvePages = () => {
19
+ try {
20
+ ${pageFiles.join('\n ')}
21
+ } catch {}
22
+ }
23
+ `;
24
+ };
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.downloadFile = void 0;
7
+ const fs_1 = require("fs");
8
+ const http_1 = __importDefault(require("http"));
9
+ const https_1 = __importDefault(require("https"));
10
+ const stream_1 = require("stream");
11
+ const util_1 = require("util");
12
+ const streamPipeline = (0, util_1.promisify)(stream_1.pipeline);
13
+ const downloadFile = async (url, destination) => {
14
+ console.log(`Downloading ${url} to ${destination}`);
15
+ const httpx = url.startsWith('https') ? https_1.default : http_1.default;
16
+ await new Promise((resolve, reject) => {
17
+ const req = httpx.get(url, { timeout: 10000 }, (response) => {
18
+ if (response.statusCode < 200 || response.statusCode > 299) {
19
+ reject(new Error(`Failed to download ${url}: ${response.statusCode} ${response.statusMessage || ''}`));
20
+ return;
21
+ }
22
+ const fileStream = (0, fs_1.createWriteStream)(destination);
23
+ streamPipeline(response, fileStream)
24
+ .then(resolve)
25
+ .catch((error) => {
26
+ console.log(`Error downloading ${url}`, error);
27
+ reject(error);
28
+ });
29
+ });
30
+ req.on('error', (error) => {
31
+ console.log(`Error downloading ${url}`, error);
32
+ reject(error);
33
+ });
34
+ });
35
+ };
36
+ exports.downloadFile = downloadFile;
@@ -0,0 +1,8 @@
1
+ const { createIPXHandler } = require('@netlify/ipx');
2
+ // Injected at build time
3
+ // eslint-disable-next-line import/no-unresolved, node/no-missing-require
4
+ const { basePath, domains } = require('./imageconfig.json');
5
+ exports.handler = createIPXHandler({
6
+ basePath,
7
+ domains,
8
+ });
package/manifest.yml CHANGED
@@ -1 +1 @@
1
- name: netlify-plugin-nextjs
1
+ name: netlify-plugin-nextjs-experimental
package/package.json CHANGED
@@ -1,26 +1,17 @@
1
1
  {
2
2
  "name": "@netlify/plugin-nextjs",
3
- "version": "3.9.0",
3
+ "version": "4.0.0-beta.10",
4
4
  "description": "Run Next.js seamlessly on Netlify",
5
- "main": "index.js",
6
- "bin": {
7
- "netlify-plugin-nextjs": "src/next-on-netlify.js"
8
- },
5
+ "main": "lib/index.js",
9
6
  "files": [
10
- "helpers/**/*.js",
11
- "src",
12
- "manifest.yml",
13
- "!src/cypress",
14
- "!src/tests"
7
+ "lib/**/*",
8
+ "manifest.yml"
15
9
  ],
16
10
  "scripts": {
17
- "build": "next build test/sample",
18
11
  "build:demo": "next build demo",
12
+ "cy:open": "cypress open --config-file cypress/config/all.json",
13
+ "cy:run": "cypress run --config-file ../cypress/config/ci.json",
19
14
  "dev:demo": "next dev demo",
20
- "cypress:local": "env CYPRESS_DEPLOY=local cypress run --project ./src --config-file false --config video=false",
21
- "cypress:netlify": "env CYPRESS_DEPLOY=netlify cypress run --project ./src --config-file false --config video=false",
22
- "cypress:local:testonly": "env CYPRESS_SKIP_DEPLOY=true npm run cypress:local",
23
- "cypress:netlify:testonly": "env CYPRESS_SKIP_DEPLOY=true npm run cypress:netlify",
24
15
  "format": "run-s format:check-fix:*",
25
16
  "format:ci": "run-s format:check:*",
26
17
  "format:check-fix:lint": "run-e format:check:lint format:fix:lint",
@@ -29,14 +20,16 @@
29
20
  "format:check-fix:prettier": "run-e format:check:prettier format:fix:prettier",
30
21
  "format:check:prettier": "cross-env-shell prettier --check $npm_package_config_prettier",
31
22
  "format:fix:prettier": "cross-env-shell prettier --write $npm_package_config_prettier",
32
- "prepublishOnly": "run-s prepublishOnly:*",
33
- "prepublishOnly:checkout": "git checkout main",
34
- "prepublishOnly:pull": "git pull",
35
- "prepublishOnly:install": "npm ci",
36
- "prepublishOnly:test": "npm test",
37
- "test:plugin": "npm run build && jest",
38
- "test:src": "jest --config src/tests/jest.config.js",
39
- "test": "run-s test:plugin test:src"
23
+ "prepublishOnly": "run-s publish:pull publish:install clean build test",
24
+ "publish:pull": "git pull",
25
+ "publish:install": "npm ci",
26
+ "publish:test": "npm test",
27
+ "test": "run-s build build:demo test:jest",
28
+ "test:jest": "jest",
29
+ "prepare": "npm run build",
30
+ "clean": "rimraf lib",
31
+ "build": "tsc",
32
+ "watch": "tsc --watch"
40
33
  },
41
34
  "config": {
42
35
  "eslint": "--cache --format=codeframe --max-warnings=0 \"{src,scripts,tests,.github}/**/*.{js,md,html}\" \"*.{js,md,html}\" \".*.{js,md,html}\"",
@@ -59,48 +52,47 @@
59
52
  },
60
53
  "homepage": "https://github.com/netlify/netlify-plugin-nextjs#readme",
61
54
  "dependencies": {
62
- "@babel/core": "^7.15.0",
63
- "@netlify/functions": "^0.7.2",
64
- "@netlify/parse-npm-script": "^0.1.2",
65
- "adm-zip": "^0.5.4",
66
- "chalk": "^4.1.0",
67
- "chokidar": "^3.5.1",
68
- "commander": "^8.0.0",
69
- "debounce-fn": "^4.0.0",
70
- "etag": "^1.8.1",
71
- "execa": "^5.0.0",
72
- "fastq": "^1.11.0",
73
- "find-cache-dir": "^3.3.1",
74
- "find-up": "^5.0.0",
75
- "fs-extra": "^9.1.0",
76
- "image-size": "^1.0.0",
77
- "image-type": "^4.1.0",
78
- "is-svg": "^4.3.1",
79
- "make-dir": "^3.1.0",
80
- "mime-types": "^2.1.30",
81
- "moize": "^6.0.0",
82
- "node-fetch": "^2.6.1",
55
+ "@netlify/functions": "^0.10.0",
56
+ "@netlify/ipx": "^0.0.7",
57
+ "@vercel/node": "^1.11.2-canary.4",
58
+ "chalk": "^4.1.2",
59
+ "fs-extra": "^10.0.0",
60
+ "globby": "^11.0.4",
61
+ "moize": "^6.1.0",
62
+ "node-fetch": "^2.6.6",
63
+ "node-stream-zip": "^1.15.0",
64
+ "outdent": "^0.8.0",
65
+ "p-limit": "^3.1.0",
66
+ "pathe": "^0.2.0",
67
+ "pretty-bytes": "^5.6.0",
83
68
  "semver": "^7.3.5",
84
- "sharp": "^0.29.0",
85
- "slash": "^2.0.0",
69
+ "slash": "^3.0.0",
86
70
  "tiny-glob": "^0.2.9"
87
71
  },
88
72
  "devDependencies": {
89
- "@netlify/eslint-config-node": "^3.2.4",
90
- "cpy": "^8.1.1",
91
- "cypress": "^7.0.0",
73
+ "@babel/core": "^7.15.8",
74
+ "@babel/preset-env": "^7.15.8",
75
+ "@netlify/build": "^18.25.2",
76
+ "@netlify/eslint-config-node": "^3.3.7",
77
+ "@testing-library/cypress": "^8.0.1",
78
+ "@types/fs-extra": "^9.0.13",
79
+ "@types/jest": "^27.0.2",
80
+ "@types/mocha": "^9.0.0",
81
+ "babel-jest": "^27.2.5",
82
+ "cpy": "^8.1.2",
83
+ "cypress": "^9.0.0",
92
84
  "eslint-config-next": "^11.0.0",
93
- "folder-hash": "^4.0.0",
94
85
  "husky": "^4.3.0",
95
86
  "jest": "^27.0.0",
96
- "netlify-cli": "^5.4.16",
97
- "next": "^11.0.0",
98
- "path-exists": "^4.0.0",
87
+ "netlify-plugin-cypress": "^2.2.0",
88
+ "next": "^12.0.2",
89
+ "npm-run-all": "^4.1.5",
99
90
  "prettier": "^2.1.2",
100
91
  "react": "^17.0.1",
101
92
  "react-dom": "^17.0.1",
93
+ "rimraf": "^3.0.2",
102
94
  "tmp-promise": "^3.0.2",
103
- "wait-on": "^6.0.0"
95
+ "typescript": "^4.3.4"
104
96
  },
105
97
  "husky": {
106
98
  "hooks": {
@@ -109,7 +101,7 @@
109
101
  }
110
102
  },
111
103
  "engines": {
112
- "node": ">=10.13.0"
104
+ "node": ">=12.0.0"
113
105
  },
114
106
  "jest": {
115
107
  "testMatch": [
@@ -117,6 +109,9 @@
117
109
  "!**/test/fixtures/**",
118
110
  "!**/test/sample/**"
119
111
  ],
112
+ "transform": {
113
+ "\\.[jt]sx?$": "babel-jest"
114
+ },
120
115
  "verbose": true,
121
116
  "testTimeout": 60000
122
117
  }
package/LICENSE.md DELETED
@@ -1,7 +0,0 @@
1
- Copyright 2020 Netlify, Inc.
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
-
5
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
-
7
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,31 +0,0 @@
1
- const path = require('path')
2
-
3
- const DEFAULT_DIST_DIR = '.next'
4
-
5
- // Account for possible custom distDir
6
- const getPath = (nextRoot, distDir, source) => path.join(nextRoot, distDir || DEFAULT_DIST_DIR, source)
7
-
8
- const restoreCache = async ({ cache, distDir, nextRoot }) => {
9
- const cacheDir = getPath(nextRoot, distDir, 'cache')
10
- if (await cache.restore(cacheDir)) {
11
- console.log('Next.js cache restored.')
12
- } else {
13
- console.log('No Next.js cache to restore.')
14
- }
15
- }
16
-
17
- const saveCache = async ({ cache, distDir, nextRoot }) => {
18
- const cacheDir = getPath(nextRoot, distDir, 'cache')
19
-
20
- const buildManifest = getPath(nextRoot, distDir, 'build-manifest.json')
21
- if (await cache.save(cacheDir, { digests: [buildManifest] })) {
22
- console.log('Next.js cache saved.')
23
- } else {
24
- console.log('No Next.js cache to save.')
25
- }
26
- }
27
-
28
- module.exports = {
29
- restoreCache,
30
- saveCache,
31
- }
@@ -1,56 +0,0 @@
1
- const { existsSync } = require('fs')
2
- const { EOL } = require('os')
3
- const path = require('path')
4
-
5
- const checkNxConfig = ({ netlifyConfig, nextConfig, failBuild, constants: { PUBLISH_DIR = 'out' } }) => {
6
- const errors = []
7
- if (nextConfig.distDir === '.next') {
8
- errors.push(
9
- "- When using Nx you must set a value for 'distDir' in your next.config.js, and the value cannot be '.next'",
10
- )
11
- }
12
- // The PUBLISH_DIR constant is normalized, so no leading slash is needed
13
- if (!PUBLISH_DIR.startsWith('apps/')) {
14
- errors.push(
15
- "Please set the 'publish' value in your Netlify build config to a folder inside your app directory. e.g. 'apps/myapp/out'",
16
- )
17
- }
18
-
19
- // Look for the config file as a sibling of the publish dir
20
- const expectedConfigFile = path.resolve(netlifyConfig.build.publish || PUBLISH_DIR, '..', 'next.config.js')
21
-
22
- if (expectedConfigFile !== nextConfig.configFile) {
23
- const confName = path.relative(process.cwd(), nextConfig.configFile)
24
- errors.push(
25
- `- Using incorrect config file '${confName}'. Expected to use '${path.relative(
26
- process.cwd(),
27
- expectedConfigFile,
28
- )}'`,
29
- )
30
-
31
- if (existsSync(expectedConfigFile)) {
32
- errors.push(
33
- `Please move or delete '${confName}'${confName === 'next.config.js' ? ' from the root of your site' : ''}.`,
34
- )
35
- } else {
36
- errors.push(
37
- `Please move or delete '${confName}'${
38
- confName === 'next.config.js' ? ' from the root of your site' : ''
39
- }, and create '${path.relative(process.cwd(), expectedConfigFile)}' instead.`,
40
- )
41
- }
42
- }
43
-
44
- if (errors.length !== 0) {
45
- failBuild(
46
- // TODO: Add ntl.fyi link to docs
47
- [
48
- 'Invalid configuration',
49
- ...errors,
50
- 'See the docs on using Nx with Netlify for more information: https://ntl.fyi/nx-next',
51
- ].join(EOL),
52
- )
53
- }
54
- }
55
-
56
- module.exports = checkNxConfig