Skip to content

Commit

Permalink
Merge branch 'canary' into add/manifest-check
Browse files Browse the repository at this point in the history
  • Loading branch information
ijjk authored Aug 11, 2021
2 parents 5ae5a33 + 51a2a02 commit 37b19b4
Show file tree
Hide file tree
Showing 11 changed files with 206 additions and 30 deletions.
16 changes: 16 additions & 0 deletions packages/next/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,22 @@ export default async function build(
return returnValue
})

if (isNextImageImported) {
try {
if (process.env.NEXT_SHARP_PATH) {
require(process.env.NEXT_SHARP_PATH)
} else {
require.resolve('sharp', {
paths: [path.join(dir, 'node_modules')],
})
}
} catch (e) {
Log.warn(
'Detected `next/image` usage without `sharp`. https://nextjs.org/docs/messages/sharp-missing-in-production'
)
}
}

if (customAppGetInitialProps) {
console.warn(
chalk.bold.yellow(`Warning: `) +
Expand Down
13 changes: 4 additions & 9 deletions packages/next/client/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,6 @@ type OnLoadingComplete = (result: {

type ImgElementStyle = NonNullable<JSX.IntrinsicElements['img']['style']>

interface StaticImageData {
src: string
height: number
width: number
blurDataURL?: string
}

interface StaticRequire {
default: StaticImageData
}
Expand Down Expand Up @@ -607,6 +600,7 @@ export default function Image({
loader,
})}
decoding="async"
data-nimg
style={imgStyle}
className={className}
/>
Expand All @@ -616,6 +610,7 @@ export default function Image({
{...rest}
{...imgAttributes}
decoding="async"
data-nimg
className={className}
ref={(img) => {
setRef(img)
Expand All @@ -640,9 +635,9 @@ export default function Image({
rel="preload"
as="image"
href={imgAttributes.srcSet ? undefined : imgAttributes.src}
// @ts-ignore: imagesrcset is not yet in the link element type
// @ts-ignore: imagesrcset is not yet in the link element type.
imagesrcset={imgAttributes.srcSet}
// @ts-ignore: imagesizes is not yet in the link element type
// @ts-ignore: imagesizes is not yet in the link element type.
imagesizes={imgAttributes.sizes}
></link>
</Head>
Expand Down
2 changes: 2 additions & 0 deletions packages/next/server/config-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export type NextConfig = { [key: string]: any } & {
staticPageGenerationTimeout?: number
pageDataCollectionTimeout?: number
isrMemoryCacheSize?: number
concurrentFeatures?: boolean
}
}

Expand Down Expand Up @@ -185,6 +186,7 @@ export const defaultConfig: NextConfig = {
pageDataCollectionTimeout: 60,
// default to 50MB limit
isrMemoryCacheSize: 50 * 1024 * 1024,
concurrentFeatures: false,
},
future: {
strictPostcssConfiguration: false,
Expand Down
2 changes: 2 additions & 0 deletions packages/next/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ export default class Server {
defaultLocale?: string
domainLocales?: DomainLocale[]
distDir: string
concurrentFeatures?: boolean
}
private compression?: Middleware
private incrementalCache: IncrementalCache
Expand Down Expand Up @@ -241,6 +242,7 @@ export default class Server {
.disableOptimizedLoading,
domainLocales: this.nextConfig.i18n?.domains,
distDir: this.distDir,
concurrentFeatures: this.nextConfig.experimental.concurrentFeatures,
}

// Only the `publicRuntimeConfig` key is exposed to the client side
Expand Down
60 changes: 51 additions & 9 deletions packages/next/server/render.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { IncomingMessage, ServerResponse } from 'http'
import { ParsedUrlQuery } from 'querystring'
import { PassThrough } from 'stream'
import React from 'react'
import { renderToStaticMarkup, renderToString } from 'react-dom/server'
import * as ReactDOMServer from 'react-dom/server'
import { warn } from '../build/output/log'
import { UnwrapPromise } from '../lib/coalesced-function'
import {
Expand Down Expand Up @@ -43,6 +44,7 @@ import {
loadGetInitialProps,
NextComponentType,
RenderPage,
RenderPageResult,
} from '../shared/lib/utils'
import {
tryGetPreviewData,
Expand Down Expand Up @@ -190,6 +192,7 @@ export type RenderOptsPartial = {
domainLocales?: DomainLocale[]
disableOptimizedLoading?: boolean
requireStaticHTML?: boolean
concurrentFeatures?: boolean
}

export type RenderOpts = LoadComponentsReturnType & RenderOptsPartial
Expand Down Expand Up @@ -263,7 +266,7 @@ function renderDocument(
): string {
return (
'<!DOCTYPE html>' +
renderToStaticMarkup(
ReactDOMServer.renderToStaticMarkup(
<AmpStateContext.Provider value={ampState}>
{Document.renderDocument(Document, {
__NEXT_DATA__: {
Expand Down Expand Up @@ -408,6 +411,7 @@ export async function renderToHTML(
previewProps,
basePath,
devOnlyCacheBusterQueryString,
concurrentFeatures,
} = renderOpts

const getFontDefinition = (url: string): string => {
Expand Down Expand Up @@ -626,6 +630,8 @@ export async function renderToHTML(
let head: JSX.Element[] = defaultHead(inAmpMode)

let scriptLoader: any = {}
const nextExport =
!isSSG && (renderOpts.nextExport || (dev && (isAutoExport || isFallback)))

const AppContainer = ({ children }: any) => (
<RouterContext.Provider value={router}>
Expand Down Expand Up @@ -991,11 +997,45 @@ export async function renderToHTML(
}
}

// TODO: Support SSR streaming of Suspense.
const renderToString = concurrentFeatures
? (element: React.ReactElement) =>
new Promise<string>((resolve, reject) => {
const stream = new PassThrough()
const buffers: Buffer[] = []
stream.on('data', (chunk) => {
buffers.push(chunk)
})
stream.once('end', () => {
resolve(Buffer.concat(buffers).toString('utf-8'))
})

const {
abort,
startWriting,
} = (ReactDOMServer as any).pipeToNodeWritable(element, stream, {
onError(error: Error) {
abort()
reject(error)
},
onCompleteAll() {
startWriting()
},
})
})
: ReactDOMServer.renderToString

const renderPage: RenderPage = (
options: ComponentsEnhancer = {}
): { html: string; head: any } => {
): RenderPageResult | Promise<RenderPageResult> => {
if (ctx.err && ErrorDebug) {
return { html: renderToString(<ErrorDebug error={ctx.err} />), head }
const htmlOrPromise = renderToString(<ErrorDebug error={ctx.err} />)
return typeof htmlOrPromise === 'string'
? { html: htmlOrPromise, head }
: htmlOrPromise.then((html) => ({
html,
head,
}))
}

if (dev && (props.router || props.Component)) {
Expand All @@ -1009,13 +1049,17 @@ export async function renderToHTML(
Component: EnhancedComponent,
} = enhanceComponents(options, App, Component)

const html = renderToString(
const htmlOrPromise = renderToString(
<AppContainer>
<EnhancedApp Component={EnhancedComponent} router={router} {...props} />
</AppContainer>
)

return { html, head }
return typeof htmlOrPromise === 'string'
? { html: htmlOrPromise, head }
: htmlOrPromise.then((html) => ({
html,
head,
}))
}
const documentCtx = { ...ctx, renderPage }
const docProps: DocumentInitialProps = await loadGetInitialProps(
Expand Down Expand Up @@ -1049,8 +1093,6 @@ export async function renderToHTML(
const hybridAmp = ampState.hybrid

const docComponentsRendered: DocumentProps['docComponentsRendered'] = {}
const nextExport =
!isSSG && (renderOpts.nextExport || (dev && (isAutoExport || isFallback)))

let html = renderDocument(Document, {
...renderOpts,
Expand Down
3 changes: 3 additions & 0 deletions test/integration/hashbang/src/cases/cjs.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/env node

module.exports = 789
3 changes: 3 additions & 0 deletions test/integration/hashbang/src/cases/js.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/env node

module.exports = 123
3 changes: 3 additions & 0 deletions test/integration/hashbang/src/cases/mjs.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/env node

export default 456
20 changes: 20 additions & 0 deletions test/integration/hashbang/src/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Import hashbang modules.
*/
import js from '../cases/js.js'
import cjs from '../cases/cjs.cjs'
import mjs from '../cases/mjs.mjs'

const jsMsg = `JS: ${js}`
const mjsMsg = `MJS: ${mjs}`
const cjsMsg = `CJS: ${cjs}`

const Page = () => (
<div>
<h3>{jsMsg}</h3>
<h3>{mjsMsg}</h3>
<h3>{cjsMsg}</h3>
</div>
)

export default Page
63 changes: 63 additions & 0 deletions test/integration/hashbang/test/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* eslint-env jest */

import { join } from 'path'
import fs from 'fs-extra'
import {
renderViaHTTP,
findPort,
launchApp,
killApp,
nextBuild,
nextStart,
} from 'next-test-utils'

jest.setTimeout(1000 * 60 * 2)

let app
let appPort
const appDir = join(__dirname, '../')

function runTests() {
describe('first-line hashbang (#!) parse', () => {
it('should work for .js files', async () => {
const html = await renderViaHTTP(appPort, '/')
expect(html).toMatch('JS: 123')
})

it('should work for .mjs files', async () => {
const html = await renderViaHTTP(appPort, '/')
expect(html).toMatch('MJS: 456')
})

it('should work for .cjs files', async () => {
const html = await renderViaHTTP(appPort, '/')
expect(html).toMatch('CJS: 789')
})
})
}

const nextConfig = join(appDir, 'next.config.js')

describe('Hashbang', () => {
describe('dev mode', () => {
beforeAll(async () => {
appPort = await findPort()
app = await launchApp(appDir, appPort)
})
afterAll(() => killApp(app))

runTests(true)
})

describe('production mode', () => {
beforeAll(async () => {
await fs.remove(nextConfig)
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))

runTests()
})
})
Loading

0 comments on commit 37b19b4

Please sign in to comment.