Skip to content

Commit

Permalink
Fix extra swc optimizer applied to node_modules in browser layer (#62051
Browse files Browse the repository at this point in the history
)

Disable swc transform optimizer for node_modules in browser layer of app
router bundles

Fixes #61858
Fixes #60644
Fixes #60920
Fixes #61740
Closes NEXT-2418

In browser there could be not only one runtime, it could have both js
worker and browser. In js worker the `typeof window` is not as same as
in browser, so disabling the swc optimizer which will replace the code.
Leave the condition as it as.
  • Loading branch information
huozhi committed Feb 28, 2024
1 parent b747e08 commit 1bee5b6
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 2 deletions.
5 changes: 5 additions & 0 deletions packages/next/src/build/swc/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,11 @@ export function getLoaderSWCOptions({
options.isPageFile = false
options.optimizeServerReact = undefined
options.cjsRequireOptimizer = undefined
// Disable optimizer for node_modules in app browser layer, to avoid unnecessary replacement.
// e.g. typeof window could result differently in js worker or browser.
if (options.jsc.transform.optimizer.globals?.typeofs) {
delete options.jsc.transform.optimizer.globals.typeofs.window
}
}

return options
Expand Down
15 changes: 14 additions & 1 deletion test/e2e/app-dir/app-external/app-external.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createNextDescribe } from 'e2e-utils'
import { check, hasRedbox, shouldRunTurboDevTest } from 'next-test-utils'
import { check, hasRedbox, retry, shouldRunTurboDevTest } from 'next-test-utils'

async function resolveStreamResponse(response: any, onData?: any) {
let result = ''
Expand Down Expand Up @@ -153,6 +153,19 @@ createNextDescribe(
).toMatch(/^__myFont_.{6}, __myFont_Fallback_.{6}$/)
})

it('should not apply swc optimizer transform for external packages in browser layer', async () => {
const browser = await next.browser('/browser')
expect(await browser.elementByCss('#worker-state').text()).toBe('default')

await browser.elementByCss('button').click()

await retry(async () => {
expect(await browser.elementByCss('#worker-state').text()).toBe(
'worker.js:browser-module/other'
)
})
})

describe('react in external esm packages', () => {
it('should use the same react in client app', async () => {
const html = await next.render('/esm/client')
Expand Down
22 changes: 22 additions & 0 deletions test/e2e/app-dir/app-external/app/browser/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use client'
import { useState } from 'react'

export default function Home() {
const [state, setState] = useState('default')
return (
<div>
<button
onClick={() => {
const worker = new Worker(new URL('./worker', import.meta.url))
worker.addEventListener('message', (event) => {
setState(event.data)
})
}}
>
Get web worker data
</button>
<p>Worker state: </p>
<p id="worker-state">{state}</p>
</div>
)
}
3 changes: 3 additions & 0 deletions test/e2e/app-dir/app-external/app/browser/worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { value } from 'browser-module'

self.postMessage('worker.js:' + value)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
'use client'

export const value =
'browser-module/' + (typeof window !== 'undefined' ? 'browser' : 'other')
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const value = 'browser-module/index'
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "module",
"exports": {
"browser": "./browser.js",
"default": "./index.js"
}
}
3 changes: 2 additions & 1 deletion test/turbopack-tests-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2560,7 +2560,8 @@
"failed": [
"app dir - external dependency server actions should compile server actions from node_modules in client components",
"app dir - external dependency should be able to opt-out 3rd party packages being bundled in server components",
"app dir - external dependency should have proper tree-shaking for known modules in CJS"
"app dir - external dependency should have proper tree-shaking for known modules in CJS",
"app dir - external dependency should not apply swc optimizer transform for external packages in browser layer"
],
"pending": [],
"flakey": [],
Expand Down

0 comments on commit 1bee5b6

Please sign in to comment.