Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(middleware): issues warnings when using node.js global APIs in middleware #36980

Merged

Conversation

feugy
Copy link
Member

@feugy feugy commented May 17, 2022

What's in there?

Middleware, since they are ran on edge runtime, do not have access to Node.js globals. While #36434 addressed cases where a middleware would import a node.js module, this PR issues warning when trying to access unsupported globals, such as:
clearImmediate(), process.cwd(), Event or TextDecoderStream (full list in packages/next/shared/lib/constants.ts).

The new behavior is:

  • a warning at build time. Failing the build would be too strict: it's possible for the final bundle to include unsupported calls that would never be reached at run time (despite tree-shaking).
  • a warning on the first access at run time (useful in development)
  • process.env is always allowed
  • other attributes/methods of process are not supported, but could be overridden

How to test?

First, build next: yarn workspace next release

Then, using integration tests:

  1. yarn jest test/integration/middleware-with-node.js-apis (checks both build and run time behavior)
  2. yarn jest test/integration/middleware-overrides-node.js-api (ability to override process.XYZ and use process.env with no warning)

Finally, as an example:

  1. create a middleware file in examples/with-node-api/middleware.js, with this content:
    import { NextResponse } from 'next/server'
    
    export default function middleware() {
      console.log(`this should work:`, process.env, __dirname, __filename)
      console.log(`this should not`, setImmediate(() => {}))
      return NextResponse.next()
    }
  2. creates a plain pages in examples/with-node-api/pages/index.js, with this content:
    export default function Home() {
      return <div>A page</div>
    }
  3. run it in dev mode yarn next dev examples/with-node-api/ and browse to https://localhost:3000:

    it should print this should work: { NEXT_RUNTIME: 'edge' }, issue a warning about using setImmediate(), and fail because setImmediate() is not detined.

  4. build it: yarn next build examples/with-node-api/:

    it should build, and issue a warning about using setImmediate(),

Notes to reviewers

  • build/webpack/plugins/middleware-plugin.ts does the build-time validation.
  • server/web/sandbox/context.ts does the run-time behavior.

To determine unsupported APIs, I compared the list from node.js docs to the our edge-runtime.
Please note that __dirname and __filename are still allowed because webpack uses them.

Feature

  • 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
  • Integration tests added
  • Documentation added
  • Telemetry added. In case of a feature if it's used or not.
  • Errors have helpful link attached, see contributing.md

Documentation / Examples

  • Make sure the linting passes by running yarn lint

@ijjk
Copy link
Member

ijjk commented May 17, 2022

Stats from current PR

Default Build (Decrease detected ✓)
General Overall increase ⚠️
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
buildDuration 20.3s 20.3s ⚠️ +44ms
buildDurationCached 7.8s 7.8s ⚠️ +44ms
nodeModulesSize 479 MB 479 MB ⚠️ +7.88 kB
Page Load Tests Overall decrease ⚠️
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
/ failed reqs 0 0
/ total time (seconds) 5.347 5.234 -0.11
/ avg req/sec 467.58 477.69 +10.11
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 2.07 2.136 ⚠️ +0.07
/error-in-render avg req/sec 1207.54 1170.47 ⚠️ -37.07
Client Bundles (main, webpack)
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
925.HASH.js gzip 179 B 179 B
framework-HASH.js gzip 42 kB 42 kB
main-HASH.js gzip 29 kB 29 kB
webpack-HASH.js gzip 1.44 kB 1.44 kB
Overall change 72.6 kB 72.6 kB
Legacy Client Bundles (polyfills)
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
polyfills-HASH.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
_app-HASH.js gzip 1.36 kB 1.36 kB
_error-HASH.js gzip 193 B 193 B
amp-HASH.js gzip 308 B 308 B
css-HASH.js gzip 327 B 327 B
dynamic-HASH.js gzip 2.71 kB 2.71 kB
head-HASH.js gzip 359 B 359 B
hooks-HASH.js gzip 920 B 920 B
image-HASH.js gzip 5.73 kB 5.73 kB
index-HASH.js gzip 263 B 263 B
link-HASH.js gzip 2.65 kB 2.65 kB
routerDirect..HASH.js gzip 320 B 320 B
script-HASH.js gzip 391 B 391 B
withRouter-HASH.js gzip 318 B 318 B
85e02e95b279..7e3.css gzip 107 B 107 B
Overall change 16 kB 16 kB
Client Build Manifests
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
_buildManifest.js gzip 458 B 458 B
Overall change 458 B 458 B
Rendered Page Sizes
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
index.html gzip 533 B 533 B
link.html gzip 547 B 547 B
withRouter.html gzip 528 B 528 B
Overall change 1.61 kB 1.61 kB

Default Build with SWC (Decrease detected ✓)
General Overall increase ⚠️
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
buildDuration 23.2s 23s -179ms
buildDurationCached 7.9s 7.9s -44ms
nodeModulesSize 479 MB 479 MB ⚠️ +7.88 kB
Page Load Tests Overall decrease ⚠️
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
/ failed reqs 0 0
/ total time (seconds) 5.317 5.474 ⚠️ +0.16
/ avg req/sec 470.17 456.7 ⚠️ -13.47
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 2.126 2.153 ⚠️ +0.03
/error-in-render avg req/sec 1175.92 1161.05 ⚠️ -14.87
Client Bundles (main, webpack)
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
925.HASH.js gzip 178 B 178 B
framework-HASH.js gzip 42.7 kB 42.7 kB
main-HASH.js gzip 29.5 kB 29.5 kB
webpack-HASH.js gzip 1.45 kB 1.45 kB
Overall change 73.8 kB 73.8 kB
Legacy Client Bundles (polyfills)
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
polyfills-HASH.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
_app-HASH.js gzip 1.35 kB 1.35 kB
_error-HASH.js gzip 179 B 179 B
amp-HASH.js gzip 311 B 311 B
css-HASH.js gzip 324 B 324 B
dynamic-HASH.js gzip 2.89 kB 2.89 kB
head-HASH.js gzip 357 B 357 B
hooks-HASH.js gzip 920 B 920 B
image-HASH.js gzip 5.82 kB 5.82 kB
index-HASH.js gzip 261 B 261 B
link-HASH.js gzip 2.78 kB 2.78 kB
routerDirect..HASH.js gzip 322 B 322 B
script-HASH.js gzip 392 B 392 B
withRouter-HASH.js gzip 317 B 317 B
85e02e95b279..7e3.css gzip 107 B 107 B
Overall change 16.3 kB 16.3 kB
Client Build Manifests
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
_buildManifest.js gzip 457 B 457 B
Overall change 457 B 457 B
Rendered Page Sizes
vercel/next.js canary feugy/next.js feat/warn-for-nodejs-global-apis-in-middleware Change
index.html gzip 532 B 532 B
link.html gzip 546 B 546 B
withRouter.html gzip 527 B 527 B
Overall change 1.6 kB 1.6 kB
Commit: 9e2a6d1

@feugy feugy force-pushed the feat/warn-for-nodejs-global-apis-in-middleware branch from 1c40e11 to 7d59361 Compare May 17, 2022 15:47
@feugy feugy marked this pull request as ready for review May 18, 2022 08:51
@feugy feugy force-pushed the feat/warn-for-nodejs-global-apis-in-middleware branch from 7d59361 to 33bda80 Compare May 18, 2022 08:51
@ijjk
Copy link
Member

ijjk commented May 20, 2022

Failing test suites

Commit: 9e2a6d1

yarn testheadless test/integration/cli/test/index.test.js

  • CLI Usage > info > should print output
Expand output

● CLI Usage › info › should print output

expect(received).toBe(expected) // Object.is equality

Expected: ""
Received: "warn  - Latest canary version not detected, detected: \"12.1.7-canary.10\", newest: \"12.1.7-canary.9\".
        Please try the latest canary version (`npm install next@canary`) to confirm the issue still exists before creating a new issue.
        Read more - https://nextjs.org/docs/messages/opening-an-issue
"

  496 |       // warning will show so skip this check for the stable release
  497 |       if (pkg.version.includes('-canary')) {
> 498 |         expect(info.stderr || '').toBe('')
      |                                   ^
  499 |       }
  500 |       expect(info.stdout).toMatch(
  501 |         new RegExp(`

  at Object.<anonymous> (integration/cli/test/index.test.js:498:35)

Read more about building and testing Next.js in contributing.md.

@timneutkens timneutkens merged commit 4e6b6a5 into vercel:canary May 23, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants