2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"routes": [
|
|
|
|
{
|
|
|
|
"title": "Messages",
|
|
|
|
"heading": true,
|
|
|
|
"routes": [
|
2022-06-16 18:46:15 +02:00
|
|
|
{
|
|
|
|
"title": "middleware-upgrade-guide",
|
|
|
|
"path": "/errors/middleware-upgrade-guide.md"
|
|
|
|
},
|
2021-11-23 14:10:56 +01:00
|
|
|
{
|
|
|
|
"title": "react-hydration-error",
|
|
|
|
"path": "/errors/react-hydration-error.md"
|
|
|
|
},
|
2021-10-22 08:40:57 +02:00
|
|
|
{
|
|
|
|
"title": "beta-middleware",
|
|
|
|
"path": "/errors/beta-middleware.md"
|
|
|
|
},
|
2021-10-25 19:23:44 +02:00
|
|
|
{
|
|
|
|
"title": "failed-loading-swc",
|
|
|
|
"path": "/errors/failed-loading-swc.md"
|
|
|
|
},
|
2021-10-24 17:38:24 +02:00
|
|
|
{
|
|
|
|
"title": "deprecated-target-config",
|
|
|
|
"path": "/errors/deprecated-target-config.md"
|
|
|
|
},
|
2021-09-06 13:41:18 +02:00
|
|
|
{
|
|
|
|
"title": "custom-document-image-import",
|
|
|
|
"path": "/errors/custom-document-image-import.md"
|
|
|
|
},
|
2021-10-25 21:07:05 +02:00
|
|
|
{
|
|
|
|
"title": "large-page-data",
|
|
|
|
"path": "/errors/large-page-data.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "404-get-initial-props",
|
|
|
|
"path": "/errors/404-get-initial-props.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "amp-bind-jsx-alt",
|
|
|
|
"path": "/errors/amp-bind-jsx-alt.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "amp-export-validation",
|
|
|
|
"path": "/errors/amp-export-validation.md"
|
|
|
|
},
|
2021-07-02 21:27:33 +02:00
|
|
|
{
|
2022-02-25 20:09:04 +01:00
|
|
|
"path": "/errors/api-routes-body-size-limit.md",
|
|
|
|
"redirect": {
|
|
|
|
"destination": "/docs/messages/api-routes-response-size-limit"
|
|
|
|
}
|
2022-02-25 03:04:02 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "api-routes-response-size-limit",
|
|
|
|
"path": "/errors/api-routes-response-size-limit.md"
|
2021-07-02 21:27:33 +02:00
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "api-routes-static-export",
|
|
|
|
"path": "/errors/api-routes-static-export.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "app-container-deprecated",
|
|
|
|
"path": "/errors/app-container-deprecated.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "build-dir-not-writeable",
|
|
|
|
"path": "/errors/build-dir-not-writeable.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "built-in-css-disabled",
|
|
|
|
"path": "/errors/built-in-css-disabled.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "can-not-output-to-public",
|
|
|
|
"path": "/errors/can-not-output-to-public.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "can-not-output-to-static",
|
|
|
|
"path": "/errors/can-not-output-to-static.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "cant-override-next-props",
|
|
|
|
"path": "/errors/cant-override-next-props.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "circular-structure",
|
|
|
|
"path": "/errors/circular-structure.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "config-resolve-alias",
|
|
|
|
"path": "/errors/config-resolve-alias.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "conflicting-amp-tag",
|
|
|
|
"path": "/errors/conflicting-amp-tag.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "conflicting-public-file-page",
|
|
|
|
"path": "/errors/conflicting-public-file-page.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "conflicting-ssg-paths",
|
|
|
|
"path": "/errors/conflicting-ssg-paths.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "css-global",
|
|
|
|
"path": "/errors/css-global.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "css-modules-npm",
|
|
|
|
"path": "/errors/css-modules-npm.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "css-npm",
|
|
|
|
"path": "/errors/css-npm.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "custom-error-no-custom-404",
|
|
|
|
"path": "/errors/custom-error-no-custom-404.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "doc-crossorigin-deprecated",
|
|
|
|
"path": "/errors/doc-crossorigin-deprecated.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "duplicate-sass",
|
|
|
|
"path": "/errors/duplicate-sass.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "empty-configuration",
|
|
|
|
"path": "/errors/empty-configuration.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "empty-object-getInitialProps",
|
|
|
|
"path": "/errors/empty-object-getInitialProps.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "env-key-not-allowed",
|
|
|
|
"path": "/errors/env-key-not-allowed.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "env-loading-disabled",
|
|
|
|
"path": "/errors/env-loading-disabled.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "export-all-in-page",
|
|
|
|
"path": "/errors/export-all-in-page.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "export-image-api",
|
|
|
|
"path": "/errors/export-image-api.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "export-no-custom-routes",
|
|
|
|
"path": "/errors/export-no-custom-routes.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "export-path-mismatch",
|
|
|
|
"path": "/errors/export-path-mismatch.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "generatebuildid-not-a-string",
|
|
|
|
"path": "/errors/generatebuildid-not-a-string.md"
|
|
|
|
},
|
2021-05-10 10:03:28 +02:00
|
|
|
{
|
|
|
|
"title": "google-font-display",
|
|
|
|
"path": "/errors/google-font-display.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "google-font-preconnect",
|
|
|
|
"path": "/errors/google-font-preconnect.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "get-initial-props-as-an-instance-method",
|
|
|
|
"path": "/errors/get-initial-props-as-an-instance-method.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "gsp-redirect-during-prerender",
|
|
|
|
"path": "/errors/gsp-redirect-during-prerender.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "gssp-component-member",
|
|
|
|
"path": "/errors/gssp-component-member.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "gssp-export",
|
|
|
|
"path": "/errors/gssp-export.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "gssp-mixed-not-found-redirect",
|
|
|
|
"path": "/errors/gssp-mixed-not-found-redirect.md"
|
|
|
|
},
|
2021-09-14 00:10:46 +02:00
|
|
|
{
|
|
|
|
"title": "gssp-no-mutating-res",
|
|
|
|
"path": "/errors/gssp-no-mutating-res.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "head-build-id",
|
|
|
|
"path": "/errors/head-build-id.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "href-interpolation-failed",
|
|
|
|
"path": "/errors/href-interpolation-failed.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "improper-devtool",
|
|
|
|
"path": "/errors/improper-devtool.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "incompatible-href-as",
|
|
|
|
"path": "/errors/incompatible-href-as.md"
|
|
|
|
},
|
2021-08-19 22:08:04 +02:00
|
|
|
{
|
|
|
|
"title": "inline-script-id",
|
|
|
|
"path": "/errors/inline-script-id.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "install-sass",
|
|
|
|
"path": "/errors/install-sass.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "install-sharp",
|
|
|
|
"path": "/errors/install-sharp.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "invalid-assetprefix",
|
|
|
|
"path": "/errors/invalid-assetprefix.md"
|
|
|
|
},
|
2021-08-18 03:21:22 +02:00
|
|
|
{
|
|
|
|
"title": "invalid-dynamic-suspense",
|
|
|
|
"path": "/errors/invalid-dynamic-suspense.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "invalid-external-rewrite",
|
|
|
|
"path": "/errors/invalid-external-rewrite.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-getstaticpaths-value",
|
|
|
|
"path": "/errors/invalid-getstaticpaths-value.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-getstaticprops-value",
|
|
|
|
"path": "/errors/invalid-getstaticprops-value.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-href-passed",
|
|
|
|
"path": "/errors/invalid-href-passed.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-i18n-config",
|
|
|
|
"path": "/errors/invalid-i18n-config.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-images-config",
|
|
|
|
"path": "/errors/invalid-images-config.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-multi-match",
|
|
|
|
"path": "/errors/invalid-multi-match.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-page-config",
|
|
|
|
"path": "/errors/invalid-page-config.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-react-version",
|
|
|
|
"path": "/errors/invalid-react-version.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-redirect-gssp",
|
|
|
|
"path": "/errors/invalid-redirect-gssp.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-relative-url-external-as",
|
|
|
|
"path": "/errors/invalid-relative-url-external-as.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-resolve-alias",
|
|
|
|
"path": "/errors/invalid-resolve-alias.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-route-source",
|
|
|
|
"path": "/errors/invalid-route-source.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-server-options",
|
|
|
|
"path": "/errors/invalid-server-options.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-webpack-5-version",
|
|
|
|
"path": "/errors/invalid-webpack-5-version.md"
|
|
|
|
},
|
2021-05-10 20:35:11 +02:00
|
|
|
{
|
|
|
|
"title": "link-passhref",
|
|
|
|
"path": "/errors/link-passhref.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "manifest.json",
|
|
|
|
"path": "/errors/manifest.json"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "minification-disabled",
|
|
|
|
"path": "/errors/minification-disabled.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "missing-document-component",
|
|
|
|
"path": "/errors/missing-document-component.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "missing-env-value",
|
|
|
|
"path": "/errors/missing-env-value.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "multi-tabs",
|
|
|
|
"path": "/errors/multi-tabs.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "nested-reserved-page",
|
|
|
|
"path": "/errors/nested-reserved-page.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "next-dynamic-modules",
|
|
|
|
"path": "/errors/next-dynamic-modules.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "next-export-no-build-id",
|
|
|
|
"path": "/errors/next-export-no-build-id.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "next-export-serverless",
|
|
|
|
"path": "/errors/next-export-serverless.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "next-head-count-missing",
|
|
|
|
"path": "/errors/next-head-count-missing.md"
|
|
|
|
},
|
2021-07-08 21:35:19 +02:00
|
|
|
{
|
|
|
|
"title": "next-image-missing-loader",
|
|
|
|
"path": "/errors/next-image-missing-loader.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "next-image-missing-loader-width",
|
|
|
|
"path": "/errors/next-image-missing-loader-width.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "next-image-unconfigured-host",
|
|
|
|
"path": "/errors/next-image-unconfigured-host.md"
|
|
|
|
},
|
2021-08-31 09:41:27 +02:00
|
|
|
{
|
|
|
|
"title": "next-script-for-ga",
|
|
|
|
"path": "/errors/next-script-for-ga.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "next-start-serverless",
|
|
|
|
"path": "/errors/next-start-serverless.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "no-cache",
|
|
|
|
"path": "/errors/no-cache.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "no-css-tags",
|
|
|
|
"path": "/errors/no-css-tags.md"
|
|
|
|
},
|
2021-05-10 23:28:06 +02:00
|
|
|
{
|
|
|
|
"title": "no-document-import-in-page",
|
|
|
|
"path": "/errors/no-document-import-in-page.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "no-document-title",
|
|
|
|
"path": "/errors/no-document-title.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "no-document-viewport-meta",
|
|
|
|
"path": "/errors/no-document-viewport-meta.md"
|
|
|
|
},
|
2021-07-15 20:04:17 +02:00
|
|
|
{
|
|
|
|
"title": "no-duplicate-head",
|
|
|
|
"path": "/errors/no-duplicate-head.md"
|
|
|
|
},
|
2021-05-10 23:28:06 +02:00
|
|
|
{
|
|
|
|
"title": "no-head-import-in-document",
|
|
|
|
"path": "/errors/no-head-import-in-document.md"
|
|
|
|
},
|
2021-04-30 13:09:07 +02:00
|
|
|
{
|
|
|
|
"title": "no-html-link-for-pages",
|
|
|
|
"path": "/errors/no-html-link-for-pages.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "no-on-app-updated-hook",
|
|
|
|
"path": "/errors/no-on-app-updated-hook.md"
|
|
|
|
},
|
2021-05-10 21:08:14 +02:00
|
|
|
{
|
|
|
|
"title": "no-page-custom-font",
|
|
|
|
"path": "/errors/no-page-custom-font.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "no-router-instance",
|
|
|
|
"path": "/errors/no-router-instance.md"
|
|
|
|
},
|
2021-11-13 00:44:39 +01:00
|
|
|
{
|
|
|
|
"title": "no-server-import-in-page",
|
|
|
|
"path": "/errors/no-server-import-in-page.md"
|
|
|
|
},
|
2022-05-23 04:32:13 +02:00
|
|
|
{
|
|
|
|
"title": "no-styled-jsx-in-document",
|
|
|
|
"path": "/errors/no-styled-jsx-in-document.md"
|
|
|
|
},
|
2021-04-30 13:09:07 +02:00
|
|
|
{
|
|
|
|
"title": "no-sync-scripts",
|
|
|
|
"path": "/errors/no-sync-scripts.md"
|
|
|
|
},
|
2021-05-07 10:49:37 +02:00
|
|
|
{
|
|
|
|
"title": "no-title-in-document-head",
|
|
|
|
"path": "/errors/no-title-in-document-head.md"
|
|
|
|
},
|
2021-04-30 13:09:07 +02:00
|
|
|
{
|
|
|
|
"title": "no-unwanted-polyfillio",
|
|
|
|
"path": "/errors/no-unwanted-polyfillio.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "non-standard-node-env",
|
|
|
|
"path": "/errors/non-standard-node-env.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "opt-out-auto-static-optimization",
|
|
|
|
"path": "/errors/opt-out-auto-static-optimization.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "opt-out-automatic-prerendering",
|
|
|
|
"path": "/errors/opt-out-automatic-prerendering.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "page-without-valid-component",
|
|
|
|
"path": "/errors/page-without-valid-component.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "popstate-state-empty",
|
|
|
|
"path": "/errors/popstate-state-empty.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "postcss-function",
|
|
|
|
"path": "/errors/postcss-function.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "postcss-ignored-plugin",
|
|
|
|
"path": "/errors/postcss-ignored-plugin.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "postcss-shape",
|
|
|
|
"path": "/errors/postcss-shape.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "prefetch-true-deprecated",
|
|
|
|
"path": "/errors/prefetch-true-deprecated.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "prerender-error",
|
|
|
|
"path": "/errors/prerender-error.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "production-start-no-build-id",
|
|
|
|
"path": "/errors/production-start-no-build-id.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "promise-in-next-config",
|
|
|
|
"path": "/errors/promise-in-next-config.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "public-next-folder-conflict",
|
|
|
|
"path": "/errors/public-next-folder-conflict.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "react-version",
|
|
|
|
"path": "/errors/react-version.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "render-no-starting-slash",
|
|
|
|
"path": "/errors/render-no-starting-slash.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "reserved-page-prop",
|
|
|
|
"path": "/errors/reserved-page-prop.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "rewrite-auto-export-fallback",
|
|
|
|
"path": "/errors/rewrite-auto-export-fallback.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "routes-must-be-array",
|
|
|
|
"path": "/errors/routes-must-be-array.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "ssg-fallback-true-export",
|
|
|
|
"path": "/errors/ssg-fallback-true-export.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "static-dir-deprecated",
|
|
|
|
"path": "/errors/static-dir-deprecated.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "threw-undefined",
|
|
|
|
"path": "/errors/threw-undefined.md"
|
|
|
|
},
|
2021-03-23 13:53:17 +01:00
|
|
|
{
|
|
|
|
"title": "undefined-webpack-config",
|
|
|
|
"path": "/errors/undefined-webpack-config.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "url-deprecated",
|
|
|
|
"path": "/errors/url-deprecated.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "webpack5",
|
|
|
|
"path": "/errors/webpack5.md"
|
|
|
|
},
|
2021-06-15 20:36:25 +02:00
|
|
|
{
|
|
|
|
"title": "client-side-exception-occurred",
|
|
|
|
"path": "/errors/client-side-exception-occurred.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "future-webpack5-moved-to-webpack5",
|
|
|
|
"path": "/errors/future-webpack5-moved-to-webpack5.md"
|
|
|
|
},
|
2022-03-22 19:58:55 +01:00
|
|
|
{
|
|
|
|
"title": "link-no-children",
|
|
|
|
"path": "/errors/link-no-children.md"
|
|
|
|
},
|
2021-06-15 20:36:25 +02:00
|
|
|
{
|
|
|
|
"title": "link-multiple-children",
|
|
|
|
"path": "/errors/link-multiple-children.md"
|
|
|
|
},
|
2022-02-10 02:54:28 +01:00
|
|
|
{
|
|
|
|
"title": "no-img-element",
|
|
|
|
"path": "/errors/no-img-element.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "no-head-element",
|
|
|
|
"path": "/errors/no-head-element.md"
|
|
|
|
},
|
2021-06-15 20:36:25 +02:00
|
|
|
{
|
|
|
|
"title": "non-dynamic-getstaticpaths-usage",
|
|
|
|
"path": "/errors/non-dynamic-getstaticpaths-usage.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "placeholder-blur-data-url",
|
|
|
|
"path": "/errors/placeholder-blur-data-url.md"
|
2021-07-10 18:49:02 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "import-esm-externals",
|
|
|
|
"path": "/errors/import-esm-externals.md"
|
2021-07-16 11:21:44 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "static-page-generation-timeout",
|
|
|
|
"path": "/errors/static-page-generation-timeout.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "page-data-collection-timeout",
|
|
|
|
"path": "/errors/page-data-collection-timeout.md"
|
2021-07-23 01:11:17 +02:00
|
|
|
},
|
|
|
|
{
|
2021-07-23 16:07:09 +02:00
|
|
|
"title": "sharp-missing-in-production",
|
2021-07-23 01:11:17 +02:00
|
|
|
"path": "/errors/sharp-missing-in-production.md"
|
2021-08-11 11:17:57 +02:00
|
|
|
},
|
2021-10-12 01:17:47 +02:00
|
|
|
{
|
|
|
|
"title": "sharp-version-avif",
|
|
|
|
"path": "/errors/sharp-version-avif.md"
|
|
|
|
},
|
2021-08-14 01:16:15 +02:00
|
|
|
{
|
2022-06-14 04:17:42 +02:00
|
|
|
"path": "/errors/no-script-in-document-page.md",
|
|
|
|
"redirect": {
|
2022-06-19 22:26:52 +02:00
|
|
|
"destination": "/docs/messages/no-script-in-document"
|
2022-06-14 04:17:42 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "no-script-in-document",
|
|
|
|
"path": "/errors/no-script-in-document.md"
|
2021-08-14 01:16:15 +02:00
|
|
|
},
|
2022-04-21 23:15:53 +02:00
|
|
|
{
|
|
|
|
"title": "before-interactive-script-outside-document",
|
|
|
|
"path": "/errors/no-before-interactive-script-outside-document.md"
|
|
|
|
},
|
2021-08-14 01:16:15 +02:00
|
|
|
{
|
2022-06-14 04:17:42 +02:00
|
|
|
"path": "/errors/no-script-in-head-component.md",
|
|
|
|
"redirect": {
|
|
|
|
"destination": "/errors/no-script-component-in-head"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"path": "/errors/no-script-component-in-head-component.md",
|
|
|
|
"redirect": {
|
|
|
|
"destination": "/errors/no-script-component-in-head"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "no-script-component-in-head",
|
|
|
|
"path": "/errors/no-script-component-in-head.md"
|
2022-02-04 14:06:55 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "script-tags-in-head-component",
|
|
|
|
"path": "/errors/no-script-tags-in-head-component.md"
|
2021-08-14 01:16:15 +02:00
|
|
|
},
|
2022-02-04 23:48:30 +01:00
|
|
|
{
|
|
|
|
"title": "stylesheets-in-head-component",
|
|
|
|
"path": "/errors/no-stylesheets-in-head-component.md"
|
|
|
|
},
|
2021-08-11 11:17:57 +02:00
|
|
|
{
|
|
|
|
"title": "max-custom-routes-reached",
|
|
|
|
"path": "/errors/max-custom-routes-reached.md"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "module-not-found",
|
|
|
|
"path": "/errors/module-not-found.md"
|
2021-08-14 15:52:18 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "next-config-error",
|
|
|
|
"path": "/errors/next-config-error.md"
|
2021-08-25 17:52:43 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-api-status-body",
|
|
|
|
"path": "/errors/invalid-api-status-body.md"
|
2021-09-22 23:29:27 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-project-dir-casing",
|
|
|
|
"path": "/errors/invalid-project-dir-casing.md"
|
2021-10-23 10:21:44 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "swc-disabled",
|
|
|
|
"path": "/errors/swc-disabled.md"
|
2021-10-25 13:49:11 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "swc-minify-enabled",
|
|
|
|
"path": "/errors/swc-minify-enabled.md"
|
2021-10-26 17:03:39 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "middleware-new-signature",
|
|
|
|
"path": "/errors/middleware-new-signature.md"
|
2021-11-08 17:35:04 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "experimental-jest-transformer",
|
|
|
|
"path": "/errors/experimental-jest-transformer.md"
|
2021-11-26 15:22:28 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-dynamic-options-type",
|
|
|
|
"path": "/errors/invalid-dynamic-options-type.md"
|
2021-12-20 16:17:37 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-styled-jsx-children",
|
|
|
|
"path": "/errors/invalid-styled-jsx-children.md"
|
Enforce absolute URLs in Edge Functions runtime (#33410)
We currently have inconsistencies when working with URLs in the Edge Functions runtime, this PR addresses them introducing a warning for inconsistent usage that will break in the future. Here is the reasoning.
### The Browser
When we are in a browser environment there is a fixed location stored at `globalThis.location`. Then, if one tries to build a request with a relative URL it will work using that location global hostname as _base_ to construct its URL. For example:
```typescript
// https://nextjs.org
new Request('/test').url; // https://nextjs.org/test
Response.redirect('/test').headers.get('Location'); // https://nextjs.org/test
```
However, if we attempt to run the same code from `about:blank` it would not work because the global to use as a base `String(globalThis.location)` is not a valid URL. Therefore a call to `Response.redirect('/test')` or `new Response('/test')` would fail.
### Edge Functions Runtime
In Next.js Edge Functions runtime the situation is slightly different from a browser. Say that we have a root middleware (`pages/_middleware`) that gets invoked for every page. In the middleware file we expose the handler function and also define a global variable that we mutate on every request:
```typescript
// pages/_middleware
let count = 0;
export function middleware(req: NextRequest) {
console.log(req.url);
count += 1;
}
```
Currently we cache the module scope in the runtime so subsequent invocations would hold the same globals and the module would not be evaluated again. This would make the counter to increment for each request that the middleware handles. It is for this reason that we **can't have a global location** that changes across different invocations. Each invocation of the same function uses the same global which also holds primitives like `URL` or `Request` so changing an hypothetical `globalThis.location` per request would affect concurrent requests being handled.
Then, it is not possible to use relative URLs in the same way the browser does because we don't have a global to rely on to use its host to compose a URL from a relative path.
### Why it works today
We are **not** validating what is provided to, for example, `NextResponse.rewrite()` nor `NextResponse.redirect()`. We simply create a `Response` instance that adds the corresponding header for the rewrite or the redirect. Then it is **the consumer** the one that composes the final destination based on the request. Theoretically you can pass any value and it would fail on redirect but won't validate the input.
Of course this is inconsistent because it doesn't make sense that `NextResponse.rewrite('/test')` works but `fetch(new NextRequest('/test'))` does not. Also we should validate what is provided. Finally, we want to be consistent with the way a browser behaves so `new Request('/test')` _should_ not work if there is no global location which we lack.
### What this PR does
We will have to deprecate the usage of relative URLs in the previously mentioned scenarios. In preparation for it, this PR adds a validation function in those places where it will break in the future, printing a warning with a link that points to a Next.js page with an explanation of the issue and ways to fix it.
Although middleware changes are not covered by semver, we will roll this for some time to make people aware that this change is coming. Then after a reasonable period of time we can remove the warning and make the code fail when using relative URLs in the previously exposed scenarios.
2022-01-19 16:10:25 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "middleware-relative-urls",
|
|
|
|
"path": "/errors/middleware-relative-urls.md"
|
2022-01-27 23:06:39 +01:00
|
|
|
},
|
2022-05-19 17:46:21 +02:00
|
|
|
{
|
|
|
|
"title": "nested-middleware",
|
|
|
|
"path": "/errors/nested-middleware.md"
|
|
|
|
},
|
2022-01-27 23:06:39 +01:00
|
|
|
{
|
|
|
|
"title": "deleting-query-params-in-middlewares",
|
|
|
|
"path": "/errors/deleting-query-params-in-middlewares.md"
|
2022-02-10 02:54:28 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "ignored-compiler-options",
|
|
|
|
"path": "/errors/ignored-compiler-options.md"
|
2022-02-16 18:45:01 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "opening-an-issue",
|
|
|
|
"path": "/errors/opening-an-issue.md"
|
2022-02-18 01:18:28 +01:00
|
|
|
},
|
2022-04-05 17:57:45 +02:00
|
|
|
{
|
|
|
|
"title": "import-next",
|
|
|
|
"path": "/errors/import-next.md"
|
2022-04-06 17:25:27 +02:00
|
|
|
},
|
|
|
|
{
|
2022-08-10 04:34:43 +02:00
|
|
|
"path": "/errors/invalid-getserversideprops-return-value.md",
|
|
|
|
"redirect": {
|
|
|
|
"destination": "/docs/messages/invalid-getserversideprops-value"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-getserversideprops-value",
|
|
|
|
"path": "/errors/invalid-getserversideprops-value.md"
|
2022-04-15 14:45:53 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "no-assign-module-variable",
|
|
|
|
"path": "/errors/no-assign-module-variable.md"
|
2022-04-29 17:20:31 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-script",
|
|
|
|
"path": "/errors/invalid-script.md"
|
feat(middleware)!: forbids middleware response body (#36835)
_Hello Next.js team! First PR here, I hope I've followed the right practices._
### What's in there?
It has been decided to only support the following uses cases in Next.js' middleware:
- rewrite the URL (`x-middleware-rewrite` response header)
- redirect to another URL (`Location` response header)
- pass on to the next piece in the request pipeline (`x-middleware-next` response header)
1. during development, a warning on console tells developers when they are returning a response (either with `Response` or `NextResponse`).
2. at build time, this warning becomes an error.
3. at run time, returning a response body will trigger a 500 HTTP error with a JSON payload containing the detailed error.
All returned/thrown errors contain a link to the documentation.
This is a breaking feature compared to the _beta_ middleware implementation, and also removes `NextResponse.json()` which makes no sense any more.
### How to try it?
- runtime behavior: `HEADLESS=true yarn jest test/integration/middleware/core`
- build behavior : `yarn jest test/integration/middleware/build-errors`
- development behavior: `HEADLESS=true yarn jest test/development/middleware-warnings`
### Notes to reviewers
The limitation happens in next's web adapter. ~The initial implementation was to check `response.body` existence, but it turns out [`Response.redirect()`](https://github.com/vercel/next.js/blob/canary/packages/next/server/web/spec-compliant/response.ts#L42-L53) may set the response body (https://github.com/vercel/next.js/pull/31886). Hence why the proposed implementation specifically looks at response headers.~
`Response.redirect()` and `NextResponse.redirect()` do not need to include the final location in their body: it is handled by next server https://github.com/vercel/next.js/blob/canary/packages/next/server/next-server.ts#L1142
Because this is a breaking change, I had to adjust several tests cases, previously returning JSON/stream/text bodies. When relevant, these middlewares are returning data using response headers.
About DevEx: relying on AST analysis to detect forbidden use cases is not as good as running the code.
Such cases are easy to detect:
```js
new Response('a text value')
new Response(JSON.stringify({ /* whatever */ })
```
But these are false-positive cases:
```js
function returnNull() { return null }
new Response(returnNull())
function doesNothing() {}
new Response(doesNothing())
```
However, I see no good reasons to let users ship middleware such as the one above, hence why the build will fail, even if _technically speaking_, they are not setting the response body.
## Feature
- [x] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [x] Integration tests added
- [x] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [x] Errors have helpful link attached, see `contributing.md`
## Documentation / Examples
- [x] Make sure the linting passes by running `yarn lint`
2022-05-20 00:02:20 +02:00
|
|
|
},
|
2022-05-23 00:45:58 +02:00
|
|
|
{
|
|
|
|
"title": "nested-styled-jsx-tags",
|
|
|
|
"path": "/errors/nested-styled-jsx-tags.md"
|
|
|
|
},
|
feat(middleware)!: forbids middleware response body (#36835)
_Hello Next.js team! First PR here, I hope I've followed the right practices._
### What's in there?
It has been decided to only support the following uses cases in Next.js' middleware:
- rewrite the URL (`x-middleware-rewrite` response header)
- redirect to another URL (`Location` response header)
- pass on to the next piece in the request pipeline (`x-middleware-next` response header)
1. during development, a warning on console tells developers when they are returning a response (either with `Response` or `NextResponse`).
2. at build time, this warning becomes an error.
3. at run time, returning a response body will trigger a 500 HTTP error with a JSON payload containing the detailed error.
All returned/thrown errors contain a link to the documentation.
This is a breaking feature compared to the _beta_ middleware implementation, and also removes `NextResponse.json()` which makes no sense any more.
### How to try it?
- runtime behavior: `HEADLESS=true yarn jest test/integration/middleware/core`
- build behavior : `yarn jest test/integration/middleware/build-errors`
- development behavior: `HEADLESS=true yarn jest test/development/middleware-warnings`
### Notes to reviewers
The limitation happens in next's web adapter. ~The initial implementation was to check `response.body` existence, but it turns out [`Response.redirect()`](https://github.com/vercel/next.js/blob/canary/packages/next/server/web/spec-compliant/response.ts#L42-L53) may set the response body (https://github.com/vercel/next.js/pull/31886). Hence why the proposed implementation specifically looks at response headers.~
`Response.redirect()` and `NextResponse.redirect()` do not need to include the final location in their body: it is handled by next server https://github.com/vercel/next.js/blob/canary/packages/next/server/next-server.ts#L1142
Because this is a breaking change, I had to adjust several tests cases, previously returning JSON/stream/text bodies. When relevant, these middlewares are returning data using response headers.
About DevEx: relying on AST analysis to detect forbidden use cases is not as good as running the code.
Such cases are easy to detect:
```js
new Response('a text value')
new Response(JSON.stringify({ /* whatever */ })
```
But these are false-positive cases:
```js
function returnNull() { return null }
new Response(returnNull())
function doesNothing() {}
new Response(doesNothing())
```
However, I see no good reasons to let users ship middleware such as the one above, hence why the build will fail, even if _technically speaking_, they are not setting the response body.
## Feature
- [x] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [x] Integration tests added
- [x] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [x] Errors have helpful link attached, see `contributing.md`
## Documentation / Examples
- [x] Make sure the linting passes by running `yarn lint`
2022-05-20 00:02:20 +02:00
|
|
|
{
|
|
|
|
"title": "returning-response-body-in-middleware",
|
|
|
|
"path": "/errors/returning-response-body-in-middleware.md"
|
2022-06-01 22:06:37 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "middleware-request-page.md",
|
|
|
|
"path": "/errors/middleware-request-page.md"
|
2022-06-09 13:10:21 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "middleware-user-agent.md",
|
|
|
|
"path": "/errors/middleware-user-agent.md"
|
2022-06-13 04:34:23 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "get-initial-props-export",
|
|
|
|
"path": "/errors/get-initial-props-export.md"
|
2022-06-16 16:59:30 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "middleware-dynamic-wasm-compilation",
|
|
|
|
"path": "/errors/middleware-dynamic-wasm-compilation.md"
|
feat: build edge functions with node.js modules and fail at runtime (#38234)
## What's in there?
The Edge runtime [does not support Node.js modules](https://edge-runtime.vercel.app/features/available-apis#unsupported-apis).
When building Next.js application, we currently fail the build when detecting node.js module imported from middleware.
This is an blocker for using code that is conditionally loading node.js modules (based on platform/env detection), as @cramforce reported.
This PR implements a new strategy where:
- we can build such middleware/Edge API route code **with a warning**
- we fail at run time, with graceful errors in dev (console & react-dev-overlay error)
- we fail at run time, with console errors in production
## How to test?
All cases are covered with integration tests.
To try them live, create a simple app with a page, a `middleware.js` file and a `pages/api/route.js`file.
Here are iconic examples:
### node.js modules
```js
// middleware.js
import { NextResponse } from 'next/server'
// static
import { basename } from 'path'
export default async function middleware() {
// dynamic
const { basename } = await import('path')
basename()
return NextResponse.next()
}
export const config = { matcher: '/' }
```
```js
// pags/api/route.js
// static
import { isAbsolute } from 'path'
export default async function handle() {
// dynamic
const { isAbsolute } = await import('path')
return Response.json({ useNodeModule: isAbsolute('/test') })
}
export const config = { runtime: 'experimental-edge' }
```
Desired error (+ source code highlight in dev):
> The edge runtime does not support Node.js 'path' module
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime
Desired warning at build time:
> A Node.js module is loaded ('path' at line 2) which is not supported in the Edge Runtime.
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime
- [x] in dev middleware, static, shows desired error on stderr
- [x] in dev route, static, shows desired error on stderr
- [x] in dev middleware, dynamic, shows desired error on stderr
- [x] in dev route, dynamic, shows desired error on stderr
- [x] in dev middleware, static, shows desired error on react error overlay
- [x] in dev route, static, shows desired error on react error overlay
- [x] in dev middleware, dynamic, shows desired error on react error overlay
- [x] in dev route, dynamic, shows desired error on react error overlay
- [x] builds middleware successfully, shows build warning, shows desired error on stderr on call
- [x] builds route successfully, shows build warning, shows desired error on stderr on call
### 3rd party modules not found
```js
// middleware.js
import { NextResponse } from 'next/server'
// static
import Unknown from 'unknown'
export default async function middleware() {
// dynamic
const Unknown = await import('unknown')
new Unknown()
return NextResponse.next()
}
```
export const config = { matcher: '/' }
```
```js
// pags/api/route.js
// static
import Unknown from 'unknown'
export default async function handle() {
// dynamic
const Unknown = await import('unknown')
return Response.json({ use3rdPartyModule: Unknown() })
}
export const config = { runtime: 'experimental-edge' }
```
Desired error (+ source code highlight in dev):
> Module not found: Can't resolve 'does-not-exist'
Learn More: https://nextjs.org/docs/messages/module-not-found
- [x] in dev middleware, static, shows desired error on stderr
- [x] in dev route, static, shows desired error on stderr
- [x] in dev middleware, dynamic, shows desired error on stderr
- [x] in dev route, dynamic, shows desired error on stderr
- [x] in dev middleware, static, shows desired error on react error overlay
- [x] in dev route, static, shows desired error on react error overlay
- [x] in dev middleware, dynamic, shows desired error on react error overlay
- [x] in dev route, dynamic, shows desired error on react error overlay
- [x] fails to build middleware, with desired error on stderr
- [x] fails to build route, with desired error on stderr
### unused node.js modules
```js
// middleware.js
import { NextResponse } from 'next/server'
export default async function middleware() {
if (process.exit) {
const { basename } = await import('path')
basename()
}
return NextResponse.next()
}
```
```js
// pags/api/route.js
export default async function handle() {
if (process.exit) {
const { basename } = await import('path')
basename()
}
return Response.json({ useNodeModule: false })
}
export const config = { runtime: 'experimental-edge' }
```
Desired warning at build time:
> A Node.js module is loaded ('path' at line 2) which is not supported in the Edge Runtime.
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime
- [x] invoke middleware in dev with no error
- [x] invoke route in dev with no error
- [x] builds successfully, shows build warning, invoke middleware with no error
- [x] builds successfully, shows build warning, invoke api-route with no error
## Notes to reviewers
The strategy to implement this feature is to leverages webpack [externals](https://webpack.js.org/configuration/externals/#externals) and run a global `__unsupported_module()` function when using a node.js module from edge function's code.
For the record, I tried using [webpack resolve.fallback](https://webpack.js.org/configuration/resolve/#resolvefallback) and [Webpack.IgnorePlugin](https://webpack.js.org/plugins/ignore-plugin/) but they do not allow throwing proper errors at runtime that would contain the loaded module name for reporting.
`__unsupported_module()` is defined in `EdgeRuntime`, and returns a proxy that's throw on use (whether it's property access, function call, new operator... synchronous & promise-based styles).
However there's an issue with error reporting: webpack does not includes the import lines in the generated sourcemaps, preventing from displaying useful errors.
I extended our middleware-plugin to supplement the sourcemaps (when analyzing edge function code, it saves which module is imported from which file, together with line/column/source)
The react-dev-overlay was adapted to look for this additional information when the caught error relates to modules, instead of looking at sourcemaps.
I removed the previous mechanism (built by @nkzawa ) which caught webpack errors at built time to change the displayed error message (files `next/build/index.js`, `next/build/utils.ts` and `wellknown-errors-plugin`)
2022-07-06 22:54:44 +02:00
|
|
|
},
|
feat(edge): allows configuring Dynamic code execution guard (#39539)
### 📖 What's in there?
Dynamic code evaluation (`eval()`, `new Function()`, ...) is not
supported on the edge runtime, hence why we fail the build when
detecting such statement in the middleware or `experimental-edge` routes
at build time.
However, there could be false positives, which static analysis and
tree-shaking can not exclude:
- `qs` through these dependencies (get-intrinsic:
[source](https://github.com/ljharb/get-intrinsic/blob/main/index.js#L12))
- `function-bind`
([source](https://github.com/Raynos/function-bind/blob/master/implementation.js#L42))
- `has`
([source](https://github.com/tarruda/has/blob/master/src/index.js#L5))
This PR leverages the existing `config` export to let user allow some of
their files.
it’s meant for allowing users to import 3rd party modules who embed
dynamic code evaluation, but do not use it (because or code paths), and
can't be tree-shaked.
By default, it’s keeping the existing behavior: warn in dev, fails to
build.
If users allow dynamic code, and that code is reached at runtime, their
app stills breaks.
### 🧪 How to test?
- (existing) integration tests for disallowing dynamic code evaluation:
`pnpm testheadless --testPathPattern=runtime-dynamic`
- (new) integration tests for allowing dynamic code evaluation: `pnpm
testheadless --testPathPattern=runtime-configurable`
- (amended) production tests for validating the new configuration keys:
`pnpm testheadless --testPathPattern=config-validations`
To try it live, you could have an application such as:
```js
// lib/index.js
/* eslint-disable no-eval */
export function hasUnusedDynamic() {
if ((() => false)()) {
eval('100')
}
}
export function hasDynamic() {
eval('100')
}
// pages/index.jsx
export default function Page({ edgeRoute }) {
return <p>{edgeRoute}</p>
}
export const getServerSideProps = async (req) => {
const res = await fetch(`http://localhost:3000/api/route`)
const data = await res.json()
return { props: { edgeRoute: data.ok ? `Hi from the edge route` : '' } }
}
// pages/api/route.js
import { hasDynamic } from '../../lib'
export default async function handle() {
hasDynamic()
return Response.json({ ok: true })
}
export const config = {
runtime: 'experimental-edge' ,
allowDynamic: '/lib/**'
}
```
Playing with `config.allowDynamic`, you should be able to:
- build the app even if it uses `eval()` (it will obviously fail at
runtime)
- build the app that _imports but does not use_ `eval()`
- run the app in dev, even if it uses `eval()` with no warning
### 🆙 Notes to reviewers
Before adding documentation and telemetry, I'd like to collect comments
on a couple of points:
- the overall design for this feature: is a list of globs useful and
easy enough?
- should the globs be relative to the application root (current
implementation) to to the edge route/middleware file?
- (especially to @sokra) is the implementation idiomatic enough? I've
leverage loaders to read the _entry point_ configuration once, then the
ModuleGraph to get it back during the parsing phase. I couldn't re-use
the existing `getExtractMetadata()` facility since it's happening late
after the parsing.
- there's a glitch with `import { ServerRuntime } from '../../types'` in
`get-page-static-info.ts`
([here](https://github.com/vercel/next.js/pull/39539/files#diff-cb7ac6392c3dd707c5edab159c3144ec114eafea92dad5d98f4eedfc612174d2L12)).
I had to use `next/types` because it was failing during lint. Any clue
why?
### ☑️ Checklist
- [ ] Implements an existing feature request or RFC. Make sure the
feature request has been accepted for implementation before opening a
PR.
- [ ] Related issues linked using `fixes #number`
- [x] Integration tests added
- [x] Documentation added
- [x] Telemetry added. In case of a feature if it's used or not.
- [x] Errors have helpful link attached, see `contributing.md`
2022-09-13 00:01:00 +02:00
|
|
|
{
|
|
|
|
"title": "edge-dynamic-code-evaluation",
|
|
|
|
"path": "/errors/edge-dynamic-code-evaluation.md"
|
|
|
|
},
|
feat: build edge functions with node.js modules and fail at runtime (#38234)
## What's in there?
The Edge runtime [does not support Node.js modules](https://edge-runtime.vercel.app/features/available-apis#unsupported-apis).
When building Next.js application, we currently fail the build when detecting node.js module imported from middleware.
This is an blocker for using code that is conditionally loading node.js modules (based on platform/env detection), as @cramforce reported.
This PR implements a new strategy where:
- we can build such middleware/Edge API route code **with a warning**
- we fail at run time, with graceful errors in dev (console & react-dev-overlay error)
- we fail at run time, with console errors in production
## How to test?
All cases are covered with integration tests.
To try them live, create a simple app with a page, a `middleware.js` file and a `pages/api/route.js`file.
Here are iconic examples:
### node.js modules
```js
// middleware.js
import { NextResponse } from 'next/server'
// static
import { basename } from 'path'
export default async function middleware() {
// dynamic
const { basename } = await import('path')
basename()
return NextResponse.next()
}
export const config = { matcher: '/' }
```
```js
// pags/api/route.js
// static
import { isAbsolute } from 'path'
export default async function handle() {
// dynamic
const { isAbsolute } = await import('path')
return Response.json({ useNodeModule: isAbsolute('/test') })
}
export const config = { runtime: 'experimental-edge' }
```
Desired error (+ source code highlight in dev):
> The edge runtime does not support Node.js 'path' module
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime
Desired warning at build time:
> A Node.js module is loaded ('path' at line 2) which is not supported in the Edge Runtime.
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime
- [x] in dev middleware, static, shows desired error on stderr
- [x] in dev route, static, shows desired error on stderr
- [x] in dev middleware, dynamic, shows desired error on stderr
- [x] in dev route, dynamic, shows desired error on stderr
- [x] in dev middleware, static, shows desired error on react error overlay
- [x] in dev route, static, shows desired error on react error overlay
- [x] in dev middleware, dynamic, shows desired error on react error overlay
- [x] in dev route, dynamic, shows desired error on react error overlay
- [x] builds middleware successfully, shows build warning, shows desired error on stderr on call
- [x] builds route successfully, shows build warning, shows desired error on stderr on call
### 3rd party modules not found
```js
// middleware.js
import { NextResponse } from 'next/server'
// static
import Unknown from 'unknown'
export default async function middleware() {
// dynamic
const Unknown = await import('unknown')
new Unknown()
return NextResponse.next()
}
```
export const config = { matcher: '/' }
```
```js
// pags/api/route.js
// static
import Unknown from 'unknown'
export default async function handle() {
// dynamic
const Unknown = await import('unknown')
return Response.json({ use3rdPartyModule: Unknown() })
}
export const config = { runtime: 'experimental-edge' }
```
Desired error (+ source code highlight in dev):
> Module not found: Can't resolve 'does-not-exist'
Learn More: https://nextjs.org/docs/messages/module-not-found
- [x] in dev middleware, static, shows desired error on stderr
- [x] in dev route, static, shows desired error on stderr
- [x] in dev middleware, dynamic, shows desired error on stderr
- [x] in dev route, dynamic, shows desired error on stderr
- [x] in dev middleware, static, shows desired error on react error overlay
- [x] in dev route, static, shows desired error on react error overlay
- [x] in dev middleware, dynamic, shows desired error on react error overlay
- [x] in dev route, dynamic, shows desired error on react error overlay
- [x] fails to build middleware, with desired error on stderr
- [x] fails to build route, with desired error on stderr
### unused node.js modules
```js
// middleware.js
import { NextResponse } from 'next/server'
export default async function middleware() {
if (process.exit) {
const { basename } = await import('path')
basename()
}
return NextResponse.next()
}
```
```js
// pags/api/route.js
export default async function handle() {
if (process.exit) {
const { basename } = await import('path')
basename()
}
return Response.json({ useNodeModule: false })
}
export const config = { runtime: 'experimental-edge' }
```
Desired warning at build time:
> A Node.js module is loaded ('path' at line 2) which is not supported in the Edge Runtime.
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime
- [x] invoke middleware in dev with no error
- [x] invoke route in dev with no error
- [x] builds successfully, shows build warning, invoke middleware with no error
- [x] builds successfully, shows build warning, invoke api-route with no error
## Notes to reviewers
The strategy to implement this feature is to leverages webpack [externals](https://webpack.js.org/configuration/externals/#externals) and run a global `__unsupported_module()` function when using a node.js module from edge function's code.
For the record, I tried using [webpack resolve.fallback](https://webpack.js.org/configuration/resolve/#resolvefallback) and [Webpack.IgnorePlugin](https://webpack.js.org/plugins/ignore-plugin/) but they do not allow throwing proper errors at runtime that would contain the loaded module name for reporting.
`__unsupported_module()` is defined in `EdgeRuntime`, and returns a proxy that's throw on use (whether it's property access, function call, new operator... synchronous & promise-based styles).
However there's an issue with error reporting: webpack does not includes the import lines in the generated sourcemaps, preventing from displaying useful errors.
I extended our middleware-plugin to supplement the sourcemaps (when analyzing edge function code, it saves which module is imported from which file, together with line/column/source)
The react-dev-overlay was adapted to look for this additional information when the caught error relates to modules, instead of looking at sourcemaps.
I removed the previous mechanism (built by @nkzawa ) which caught webpack errors at built time to change the displayed error message (files `next/build/index.js`, `next/build/utils.ts` and `wellknown-errors-plugin`)
2022-07-06 22:54:44 +02:00
|
|
|
{
|
|
|
|
"title": "node-module-in-edge-runtime",
|
|
|
|
"path": "/errors/node-module-in-edge-runtime.md"
|
2022-07-13 20:31:55 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "invalid-next-config",
|
|
|
|
"path": "/errors/invalid-next-config.md"
|
2022-08-07 21:36:03 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "failed-to-fetch-devpagesmanifest",
|
|
|
|
"path": "/errors/failed-to-fetch-devpagesmanifest.md"
|
2022-08-08 16:40:44 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "middleware-parse-user-agent",
|
|
|
|
"path": "/errors/middleware-parse-user-agent.md"
|
2022-09-09 00:17:15 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"title": "nonce-contained-invalid-characters",
|
|
|
|
"path": "/errors/nonce-contained-invalid-characters.md"
|
2021-06-15 20:36:25 +02:00
|
|
|
}
|
2021-03-23 13:53:17 +01:00
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|