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

Experimental Minification produces unexpected "??" errors #151

Closed
dario-piotrowicz opened this issue Apr 6, 2023 · 5 comments · Fixed by #188
Closed

Experimental Minification produces unexpected "??" errors #151

dario-piotrowicz opened this issue Apr 6, 2023 · 5 comments · Fixed by #188
Assignees
Labels
bug Something isn't working build error

Comments

@dario-piotrowicz
Copy link
Member

Note Original comment from @Stijn-B, see: #2 (comment)

With our project (which was started from https://github.com/shadowwalker/next-pwa) npx @cloudflare/next-on-pages works without the --experimental-minifynode but when I add it there are 6 errors, all of which are just Unexpected "??"'. Looks like it's the same error as mentioned above: #2 (comment)

However Cloudflare Pages doesn't work, even without the --experimental-minifynode because of Error: Failed to publish your Function. Got error: Error: Script startup exceeded CPU time limit.. I can't figure out how to fix this yet but think it's unrelated to @cloudflare/next-on-pages

Details

package.json

{
  "name": "my-nextjs-pwa",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@chakra-ui/react": "^2.4.4",
    "@emotion/react": "^11.10.5",
    "@emotion/styled": "^11.10.5",
    "@fontsource/poppins": "^4.5.10",
    "@fontsource/roboto": "^4.5.8",
    "@next/font": "13.0.7",
    "@types/node": "18.11.17",
    "@types/react": "18.0.26",
    "@types/react-dom": "18.0.9",
    "eslint": "8.30.0",
    "eslint-config-next": "13.0.7",
    "framer-motion": "^6.5.1",
    "i18next": "^22.4.6",
    "next": "13.0.7",
    "next-pwa": "^5.6.0",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-i18next": "^12.1.1",
    "react-icons": "^4.7.1",
    "sass": "^1.57.1",
    "typescript": "4.9.4"
  },
  "devDependencies": {
    "autoprefixer": "^10.4.13",
    "postcss": "^8.4.20",
    "tailwindcss": "^3.2.4",
    "vercel": "^28.10.1"
  }
}

Error log

▲ 
▲ Traced Next.js server files in: 3.012s
▲ 
▲ Created all serverless functions in: 1.329s
▲ 
▲ Collected static files (public/, static/, .next/static): 4.611ms
▲ 
▲ Build Completed in .vercel/output [53s]
▲ 
⚡️
⚡️
⚡️ Completed 'npx vercel build'.
⚡️
✘ [ERROR] Unexpected "??"

    ../../../../../tmp/8ua1xv070ol/overview/[id].func.js:7139:53:
      7139 │         (null == a || a(e), rh(e.currentTarget) && u ?? v && y());
           ╵                                                      ~~

✘ [ERROR] Unexpected "??"

    ../../../../../tmp/8ua1xv070ol/myData.func.js:6625:53:
      6625 │         (null == a || a(e), rh(e.currentTarget) && u ?? v && y());
           ╵                                                      ~~

✘ [ERROR] Unexpected "??"

    ../../../../../tmp/8ua1xv070ol/index.func.js:6725:53:
      6725 │         (null == a || a(e), rh(e.currentTarget) && u ?? v && y());
           ╵                                                      ~~

✘ [ERROR] Unexpected "??"

    ../../../../../tmp/8ua1xv070ol/profile.func.js:6806:53:
      6806 │         (null == a || a(e), rh(e.currentTarget) && u ?? v && y());
           ╵                                                      ~~

✘ [ERROR] Unexpected "??"

    ../../../../../tmp/8ua1xv070ol/profile/settings.func.js:6757:53:
      6757 │         (null == a || a(e), rh(e.currentTarget) && u ?? v && y());
           ╵                                                      ~~

✘ [ERROR] Unexpected "??"

    ../../../../../tmp/8ua1xv070ol/profile/addCarer.func.js:7058:53:
      7058 │         (null == a || a(e), rh(e.currentTarget) && u ?? v && y());
           ╵                                                      ~~

/home/stijn/.npm/_npx/39e2fd552b408994/node_modules/esbuild/lib/main.js:1575
  let error = new Error(`${text}${summary}`);
              ^

Error: Build failed with 6 errors:
../../../../../tmp/8ua1xv070ol/index.func.js:6725:53: ERROR: Unexpected "??"
../../../../../tmp/8ua1xv070ol/myData.func.js:6625:53: ERROR: Unexpected "??"
../../../../../tmp/8ua1xv070ol/overview/[id].func.js:7139:53: ERROR: Unexpected "??"
../../../../../tmp/8ua1xv070ol/profile.func.js:6806:53: ERROR: Unexpected "??"
../../../../../tmp/8ua1xv070ol/profile/addCarer.func.js:7058:53: ERROR: Unexpected "??"
...
    at failureErrorWithLog (/home/stijn/.npm/_npx/39e2fd552b408994/node_modules/esbuild/lib/main.js:1575:15)
    at /home/stijn/.npm/_npx/39e2fd552b408994/node_modules/esbuild/lib/main.js:1033:28
    at /home/stijn/.npm/_npx/39e2fd552b408994/node_modules/esbuild/lib/main.js:978:67
    at buildResponseToResult (/home/stijn/.npm/_npx/39e2fd552b408994/node_modules/esbuild/lib/main.js:1031:7)
    at /home/stijn/.npm/_npx/39e2fd552b408994/node_modules/esbuild/lib/main.js:1143:14
    at responseCallbacks.<computed> (/home/stijn/.npm/_npx/39e2fd552b408994/node_modules/esbuild/lib/main.js:680:9)
    at handleIncomingPacket (/home/stijn/.npm/_npx/39e2fd552b408994/node_modules/esbuild/lib/main.js:735:9)
    at Socket.readFromStdout (/home/stijn/.npm/_npx/39e2fd552b408994/node_modules/esbuild/lib/main.js:656:7)
    at Socket.emit (node:events:513:28)
    at addChunk (node:internal/streams/readable:315:12) {
  errors: [
    {
      detail: undefined,
      id: '',
      location: {
        column: 53,
        file: '../../../../../tmp/8ua1xv070ol/index.func.js',
        length: 2,
        line: 6725,
        lineText: '        (null == a || a(e), rh(e.currentTarget) && u ?? v && y());',
        namespace: '',
        suggestion: ''
      },
      notes: [],
      pluginName: '',
      text: 'Unexpected "??"'
    },
    {
      detail: undefined,
      id: '',
      location: {
        column: 53,
        file: '../../../../../tmp/8ua1xv070ol/myData.func.js',
        length: 2,
        line: 6625,
        lineText: '        (null == a || a(e), rh(e.currentTarget) && u ?? v && y());',
        namespace: '',
        suggestion: ''
      },
      notes: [],
      pluginName: '',
      text: 'Unexpected "??"'
    },
    {
      detail: undefined,
      id: '',
      location: {
        column: 53,
        file: '../../../../../tmp/8ua1xv070ol/overview/[id].func.js',
        length: 2,
        line: 7139,
        lineText: '        (null == a || a(e), rh(e.currentTarget) && u ?? v && y());',
        namespace: '',
        suggestion: ''
      },
      notes: [],
      pluginName: '',
      text: 'Unexpected "??"'
    },
    {
      detail: undefined,
      id: '',
      location: {
        column: 53,
        file: '../../../../../tmp/8ua1xv070ol/profile.func.js',
        length: 2,
        line: 6806,
        lineText: '        (null == a || a(e), rh(e.currentTarget) && u ?? v && y());',
        namespace: '',
        suggestion: ''
      },
      notes: [],
      pluginName: '',
      text: 'Unexpected "??"'
    },
    {
      detail: undefined,
      id: '',
      location: {
        column: 53,
        file: '../../../../../tmp/8ua1xv070ol/profile/addCarer.func.js',
        length: 2,
        line: 7058,
        lineText: '        (null == a || a(e), rh(e.currentTarget) && u ?? v && y());',
        namespace: '',
        suggestion: ''
      },
      notes: [],
      pluginName: '',
      text: 'Unexpected "??"'
    },
    {
      detail: undefined,
      id: '',
      location: {
        column: 53,
        file: '../../../../../tmp/8ua1xv070ol/profile/settings.func.js',
        length: 2,
        line: 6757,
        lineText: '        (null == a || a(e), rh(e.currentTarget) && u ?? v && y());',
        namespace: '',
        suggestion: ''
      },
      notes: [],
      pluginName: '',
      text: 'Unexpected "??"'
    }
  ],
  warnings: []
}
@dario-piotrowicz dario-piotrowicz added bug Something isn't working build error labels Apr 6, 2023
@dario-piotrowicz
Copy link
Member Author

Note Original comment from @mattddean, see: #2 (comment)

I updated the version of esbuild used by next-on-pages and got a more descriptive error message for the ✘ [ERROR] Unexpected "??" error.

With version 0.17.14 of esbuild, the error message is ✘ [ERROR] Cannot use "??" with "&&" without parentheses.

Full output

❯ ./packages/next-on-pages/bin/index.js --experimental-minify
⚡️ @cloudflare/next-on-pages CLI
⚡️ Preparing project for 'npx vercel build'...
⚡️ Project ready for 'npx vercel build'...
⚡️ 
⚡️ Building project with 'npx vercel build'...
▲ Vercel CLI 28.17.0
▲ Warning: Detected "engines": { "node": ">=v16.0.0" } in your `package.json` that will automatically upgrade when a new major Node.js Version is released. Learn More: http://vercel.link/node-version
▲ Installing dependencies...
▲ Scope: all 2 workspace projects
▲ Lockfile is up to date, resolution step is skipped
▲ Already up to date
▲ 
▲ packages/next-on-pages prepare$ npm run build
▲ packages/next-on-pages prepare: > next-on-pages@0.5.1 build
▲ packages/next-on-pages prepare: > npx esbuild --bundle --platform=node ./src/index.ts --external:esbuild --external:chokidar --outfile=./dist/index.js
▲ packages/next-on-pages prepare:   dist/index.js  229.3kb
▲ packages/next-on-pages prepare: ⚡ Done in 32ms
▲ packages/next-on-pages prepare: Done
▲ Done in 1.7s
▲ Detected Next.js version: 13.2.4
▲ Running "pnpm run build"
▲ > next-pages@0.1.0 build /Users/mattdean/static/org/me/junk/next-pages
▲ > next build
▲ warn  - You have enabled experimental feature (appDir) in next.config.js.
▲ warn  - Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use at your own risk.
▲ info  - Thank you for testing `appDir` please leave your feedback at https://nextjs.link/app-feedback
▲ 
▲ Attention: Next.js now collects completely anonymous telemetry regarding usage.
▲ This information is used to shape Next.js' roadmap and prioritize features.
▲ You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
▲ https://nextjs.org/telemetry
▲ info  - Creating an optimized production build...
▲ info  - Compiled successfully
▲ info  - Skipping validation of types
▲ info  - Linting...
▲ info  - Collecting page data...
▲ info  - Generating static pages (0/2)
▲ info  - Generating static pages (2/2)
▲ info  - Finalizing page optimization...
▲ 
▲ Route (app)                                Size     First Load JS
▲ ┌ ℇ /                                      4.85 kB        73.6 kB
▲ ├ ℇ /api/auth/[...nextauth]                0 B                0 B
▲ └ ℇ /api/hello                             0 B                0 B
▲ + First Load JS shared by all              68.7 kB
▲ ├ chunks/146-b9d697522be104bd.js         66.4 kB
▲ ├ chunks/main-app-641446da91e0e650.js    204 B
▲ └ chunks/webpack-d1fbfc897bd49df7.js     2.1 kB
▲ 
▲ Route (pages)                              Size     First Load JS
▲ ─ ○ /404                                   179 B          84.5 kB
▲ + First Load JS shared by all              84.4 kB
▲ ├ chunks/main-20ca2cf56c1761fa.js        82.1 kB
▲ ├ chunks/pages/_app-86e1665ccabf8221.js  192 B
▲ └ chunks/webpack-d1fbfc897bd49df7.js     2.1 kB
▲ ℇ  (Streaming)  server-side renders with streaming (uses React 18 SSR streaming or Server Components)
▲ ○  (Static)     automatically rendered as static HTML (uses no initial props)
▲ Traced Next.js server files in: 704.714ms
▲ Created all serverless functions in: 735.629ms
▲ Collected static files (public/, static/, .next/static): 3.925ms
▲ Build Completed in .vercel/output [13s]
⚡️ Completed `npx vercel build`.
✘ [ERROR] Cannot use "??" with "&&" without parentheses

    ../../../../../../../private/var/folders/0v/p4ygqt354_59j779mn20vjwr0000gn/T/o0r0ns5bfdf/8160.js:1866:28:
      1866 │     e.issuer && e.wellKnown ?? (e.wellKnown = `${e.issuer}/.well-known/openid-configuration`);
           ╵                             ~~

  Expressions of the form "x && y ?? z" are not allowed in JavaScript. You must disambiguate between
  "(x && y) ?? z" and "x && (y ?? z)" by adding parentheses.

✘ [ERROR] Cannot use "??" with "&&" without parentheses

    ../../../../../../../private/var/folders/0v/p4ygqt354_59j779mn20vjwr0000gn/T/o0r0ns5bfdf/8160.js:2601:37:
      2601 │     let l = o && nc[o.toLowerCase()] ?? nc.default, s = "https://authjs.dev/img/providers";
           ╵                                      ~~

  Expressions of the form "x && y ?? z" are not allowed in JavaScript. You must disambiguate between
  "(x && y) ?? z" and "x && (y ?? z)" by adding parentheses.

/Users/mattdean/static/org/me/junk/next-pages/node_modules/.pnpm/esbuild@0.17.14/node_modules/esbuild/lib/main.js:1636
  let error = new Error(`${text}${summary}`);
              ^

Error: Build failed with 2 errors:
../../../../../../../private/var/folders/0v/p4ygqt354_59j779mn20vjwr0000gn/T/o0r0ns5bfdf/8160.js:1866:28: ERROR: Cannot use "??" with "&&" without parentheses
../../../../../../../private/var/folders/0v/p4ygqt354_59j779mn20vjwr0000gn/T/o0r0ns5bfdf/8160.js:2601:37: ERROR: Cannot use "??" with "&&" without parentheses
    at failureErrorWithLog (/Users/mattdean/static/org/me/junk/next-pages/node_modules/.pnpm/esbuild@0.17.14/node_modules/esbuild/lib/main.js:1636:15)
    at /Users/mattdean/static/org/me/junk/next-pages/node_modules/.pnpm/esbuild@0.17.14/node_modules/esbuild/lib/main.js:1048:25
    at /Users/mattdean/static/org/me/junk/next-pages/node_modules/.pnpm/esbuild@0.17.14/node_modules/esbuild/lib/main.js:993:52
    at buildResponseToResult (/Users/mattdean/static/org/me/junk/next-pages/node_modules/.pnpm/esbuild@0.17.14/node_modules/esbuild/lib/main.js:1046:7)
    at /Users/mattdean/static/org/me/junk/next-pages/node_modules/.pnpm/esbuild@0.17.14/node_modules/esbuild/lib/main.js:1075:16
    at responseCallbacks.<computed> (/Users/mattdean/static/org/me/junk/next-pages/node_modules/.pnpm/esbuild@0.17.14/node_modules/esbuild/lib/main.js:697:9)
    at handleIncomingPacket (/Users/mattdean/static/org/me/junk/next-pages/node_modules/.pnpm/esbuild@0.17.14/node_modules/esbuild/lib/main.js:752:9)
    at Socket.readFromStdout (/Users/mattdean/static/org/me/junk/next-pages/node_modules/.pnpm/esbuild@0.17.14/node_modules/esbuild/lib/main.js:673:7)
    at Socket.emit (node:events:527:28)
    at addChunk (node:internal/streams/readable:315:12) {
  errors: [
    {
      detail: undefined,
      id: '',
      location: {
        column: 28,
        file: '../../../../../../../private/var/folders/0v/p4ygqt354_59j779mn20vjwr0000gn/T/o0r0ns5bfdf/8160.js',
        length: 2,
        line: 1866,
        lineText: '    e.issuer && e.wellKnown ?? (e.wellKnown = `${e.issuer}/.well-known/openid-configuration`);',
        namespace: '',
        suggestion: ''
      },
      notes: [
        {
          location: null,
          text: 'Expressions of the form "x && y ?? z" are not allowed in JavaScript. You must disambiguate between "(x && y) ?? z" and "x && (y ?? z)" by adding parentheses.'
        }
      ],
      pluginName: '',
      text: 'Cannot use "??" with "&&" without parentheses'
    },
    {
      detail: undefined,
      id: '',
      location: {
        column: 37,
        file: '../../../../../../../private/var/folders/0v/p4ygqt354_59j779mn20vjwr0000gn/T/o0r0ns5bfdf/8160.js',
        length: 2,
        line: 2601,
        lineText: '    let l = o && nc[o.toLowerCase()] ?? nc.default, s = "https://authjs.dev/img/providers";',
        namespace: '',
        suggestion: ''
      },
      notes: [
        {
          location: null,
          text: 'Expressions of the form "x && y ?? z" are not allowed in JavaScript. You must disambiguate between "(x && y) ?? z" and "x && (y ?? z)" by adding parentheses.'
        }
      ],
      pluginName: '',
      text: 'Cannot use "??" with "&&" without parentheses'
    }
  ],
  warnings: []
}

I suspect this may something to do with the fact that npx vercel build has already "built" the JavaScript files, seemingly without respecting the ?? and && rule, and so this error comes about trying to run esbuild on already built JS files. I wonder if there is a bug in what npx vercel build uses to build is JS files that produces JS that doesn't follow this ?? and && rule.

The issue can be reproduced by cloning this repo, checking out a commit and running the commands in the readme.

git clone git@github.com:mattddean/next-pages.git
cd next-pages
git checkout e5e8b258164e04053e86932093af77184a77d545

@dario-piotrowicz
Copy link
Member Author

Update

I've found the issue, when we process a js to dedupe its chunks we parse it using acorn and obtain an AST representation of the javascript, we then use astring to convert that into js code that we save it in our chunk files.

The issue is that astring doesn't seem to produce correct outputs for expressions containing both && and ??.

I'm going to open an issue in the astring repo as far as I can tell there isn't much we can do on our side for this (unless we decide to switch the library we use to generate the js code)

Detailed Example

For example if I have the following expression:

const a= x && ( y ?? z );

such generates the following AST tree:

{
  "type": "Program",
  "start": 0,
  "end": 25,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 25,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 6,
          "end": 24,
          "id": {
            "type": "Identifier",
            "start": 6,
            "end": 7,
            "name": "a"
          },
          "init": {
            "type": "LogicalExpression",
            "start": 9,
            "end": 24,
            "left": {
              "type": "Identifier",
              "start": 9,
              "end": 10,
              "name": "x"
            },
            "operator": "&&",
            "right": {
              "type": "LogicalExpression",
              "start": 16,
              "end": 22,
              "left": {
                "type": "Identifier",
                "start": 16,
                "end": 17,
                "name": "y"
              },
              "operator": "??",
              "right": {
                "type": "Identifier",
                "start": 21,
                "end": 22,
                "name": "z"
              }
            }
          }
        }
      ],
      "kind": "const"
    }
  ],
  "sourceType": "module"
}

(as you can check using astexplorer)

If I then pass this to the astring generate method this is what the resulting code looks like:

const a = x && y ?? z;

as you can see from this stackblitz

causing the type of wrong code that causes esbuild to fail:
Screenshot 2023-04-06 at 16 25 15

@dario-piotrowicz
Copy link
Member Author

@mattddean can't thank you enough for your repository, that's been extremely helpful for finding the issue, thanks! ❤️

@dario-piotrowicz
Copy link
Member Author

PS: there is already an issue in the astring repo regarding this (davidbonnet/astring#693)

@dario-piotrowicz
Copy link
Member Author

Update: I've created a PR in the astring repo which should fix this: davidbonnet/astring#694

(although we might need more advanced codemod tools with better typing than acorn/astring so we might actually more away from astring entirely 🤔)

mattddean added a commit to mattddean/next-pages that referenced this issue Apr 7, 2023
@dario-piotrowicz dario-piotrowicz self-assigned this Apr 7, 2023
dario-piotrowicz added a commit to dario-piotrowicz/next-on-pages that referenced this issue Apr 20, 2023
dario-piotrowicz added a commit to dario-piotrowicz/next-on-pages that referenced this issue Apr 20, 2023
dario-piotrowicz added a commit to dario-piotrowicz/next-on-pages that referenced this issue Apr 20, 2023
dario-piotrowicz added a commit to dario-piotrowicz/next-on-pages that referenced this issue Apr 21, 2023
dario-piotrowicz added a commit to dario-piotrowicz/next-on-pages that referenced this issue Apr 24, 2023
dario-piotrowicz added a commit that referenced this issue Apr 25, 2023
* remove use of astring

resolves #151
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working build error
Projects
None yet
1 participant