Skip to content

Commit

Permalink
fix: buffer is not usable on edge runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
feugy committed Aug 3, 2022
1 parent 213c42f commit 1fe553e
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 42 deletions.
5 changes: 4 additions & 1 deletion packages/next/build/webpack/plugins/middleware-plugin.ts
Expand Up @@ -760,5 +760,8 @@ function isProcessEnvMemberExpression(memberExpression: any): boolean {
}

function isNodeJsModule(moduleName: string) {
return require('module').builtinModules.includes(moduleName)
return (
moduleName !== 'buffer' &&
require('module').builtinModules.includes(moduleName)
)
}
113 changes: 80 additions & 33 deletions test/integration/edge-runtime-module-errors/test/index.test.js
Expand Up @@ -490,26 +490,50 @@ describe('Edge runtime code with imports', () => {
})
})

describe('Edge API importing vanilla 3rd party module', () => {
describe.each([
{
title: 'Edge API',
url: routeUrl,
init(importStatement) {
context.api.write(`
${importStatement}
export default async function handler(request) {
const response = Response.json({ ok: true })
response.headers.set('x-from-runtime', nanoid())
return response
}
export const config = { runtime: 'experimental-edge' }
`)
},
},
{
title: 'Middleware',
url: middlewareUrl,
init(importStatement) {
context.middleware.write(`
import { NextResponse } from 'next/server'
${importStatement}
export async function middleware(request) {
const response = NextResponse.next()
response.headers.set('x-from-runtime', nanoid())
return response
}
`)
},
},
])('$title importing vanilla 3rd party module', ({ init, url }) => {
const moduleName = 'nanoid'
const importStatement = `import { nanoid } from "${moduleName}"`

beforeEach(() => {
context.api.write(`
${importStatement}
export default async function handler(request) {
return Response.json({ ok: nanoid() })
}
export const config = { runtime: 'experimental-edge' }
`)
})
beforeEach(() => init(importStatement))

it('does not throw in dev at runtime', async () => {
context.app = await launchApp(context.appDir, context.appPort, appOption)
const res = await fetchViaHTTP(context.appPort, routeUrl)
const res = await fetchViaHTTP(context.appPort, url)
expect(res.status).toBe(200)
expect(await res.json()).toEqual({ ok: expect.any(String) })
expect(res.headers.get('x-from-runtime')).toBeDefined()
expectNoError(moduleName)
})

Expand All @@ -519,35 +543,58 @@ describe('Edge runtime code with imports', () => {
})
expect(stderr).not.toContain(getUnsupportedModuleWarning(moduleName))
context.app = await nextStart(context.appDir, context.appPort, appOption)
const res = await fetchViaHTTP(context.appPort, routeUrl)
const res = await fetchViaHTTP(context.appPort, url)
expect(res.status).toBe(200)
expect(await res.json()).toEqual({ ok: expect.any(String) })
expect(res.headers.get('x-from-runtime')).toBeDefined()
expectNoError(moduleName)
})
})

describe('Middleware importing vanilla 3rd party module', () => {
const moduleName = 'nanoid'
const importStatement = `import { nanoid } from "${moduleName}"`
describe.each([
{
title: 'Edge API',
url: routeUrl,
init(importStatement) {
context.api.write(`
${importStatement}
export default async function handler(request) {
const response = Response.json({ ok: true })
response.headers.set('x-from-runtime', Buffer.isBuffer('a string'))
return response
}
export const config = { runtime: 'experimental-edge' }
`)
},
},
{
title: 'Middleware',
url: middlewareUrl,
init(importStatement) {
context.middleware.write(`
import { NextResponse } from 'next/server'
${importStatement}
beforeEach(() => {
context.middleware.write(`
import { NextResponse } from 'next/server'
${importStatement}
export async function middleware(request) {
const response = NextResponse.next()
response.headers.set('x-from-runtime', Buffer.isBuffer('a string'))
return response
}
`)
},
},
])('$title using Buffer polyfill', ({ init, url }) => {
const moduleName = 'buffer'
const importStatement = `import { Buffer } from "${moduleName}"`

export async function middleware(request) {
const response = NextResponse.next()
response.headers.set('x-from-middleware', nanoid())
return response
}
`)
})
beforeEach(() => init(importStatement))

it('does not throw in dev at runtime', async () => {
context.app = await launchApp(context.appDir, context.appPort, appOption)
const res = await fetchViaHTTP(context.appPort, middlewareUrl)
const res = await fetchViaHTTP(context.appPort, url)
expect(res.status).toBe(200)
expect(res.headers.get('x-from-middleware')).toBeDefined()
expect(res.headers.get('x-from-runtime')).toBe('false')
expectNoError(moduleName)
})

Expand All @@ -557,9 +604,9 @@ describe('Edge runtime code with imports', () => {
})
expect(stderr).not.toContain(getUnsupportedModuleWarning(moduleName))
context.app = await nextStart(context.appDir, context.appPort, appOption)
const res = await fetchViaHTTP(context.appPort, middlewareUrl)
const res = await fetchViaHTTP(context.appPort, url)
expect(res.status).toBe(200)
expect(res.headers.get('x-from-middleware')).toBeDefined()
expect(res.headers.get('x-from-runtime')).toBe('false')
expectNoError(moduleName)
})
})
Expand Down
Expand Up @@ -22,7 +22,7 @@ const unsupportedFunctions = [
'process.cpuUsage',
'process.getuid',
]
const undefinedPropertoes = [
const undefinedProperties = [
// no need to test all of the process properties
'process.arch',
'process.version',
Expand Down Expand Up @@ -83,7 +83,7 @@ describe.each([

afterAll(() => killApp(app))

it.each(undefinedPropertoes.map((api) => ({ api })))(
it.each(undefinedProperties.map((api) => ({ api })))(
'does not throw on using $api',
async ({ api }) => {
const res = await fetchViaHTTP(appPort, computeRoute(api))
Expand Down Expand Up @@ -125,16 +125,14 @@ Learn more: https://nextjs.org/docs/api-reference/edge-runtime`)
})

it.each(
['Buffer', ...unsupportedFunctions, ...unsupportedClasses].map(
(api, index) => ({
api,
})
)
[...unsupportedFunctions, ...unsupportedClasses].map((api, index) => ({
api,
}))
)(`warns for $api during build`, ({ api }) => {
expect(buildResult.stderr).toContain(`A Node.js API is used (${api}`)
})

it.each(undefinedPropertoes.map((api) => ({ api })))(
it.each(['Buffer', ...undefinedProperties].map((api) => ({ api })))(
'does not warn on using $api',
({ api }) => {
expect(buildResult.stderr).toContain(`A Node.js API is used (${api}`)
Expand Down

0 comments on commit 1fe553e

Please sign in to comment.