Skip to content

Commit

Permalink
Merge branch 'canary' into perf/static-check-avoid-main
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra authored May 12, 2021
2 parents debc895 + 9a0fc42 commit 843c8c8
Show file tree
Hide file tree
Showing 23 changed files with 189 additions and 115 deletions.
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pr:
variables:
YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn
NEXT_TELEMETRY_DISABLED: '1'
node_version: ^10.10.0
node_version: ^12.0.0

stages:
- stage: Build
Expand Down
6 changes: 3 additions & 3 deletions packages/eslint-plugin-next/lib/rules/google-font-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ module.exports = {
}

const hrefValue = attributes.value('href')
const isGoogleFont = hrefValue?.startsWith(
'https://fonts.googleapis.com/css'
)
const isGoogleFont =
typeof hrefValue === 'string' &&
hrefValue.startsWith('https://fonts.googleapis.com/css')

if (isGoogleFont) {
const params = new URLSearchParams(hrefValue.split('?')[1])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ module.exports = {
attributes.value('rel') !== 'preconnect'

if (
hrefValue?.startsWith('https://fonts.gstatic.com') &&
typeof hrefValue === 'string' &&
hrefValue.startsWith('https://fonts.gstatic.com') &&
preconnectMissing
) {
context.report({
Expand Down
6 changes: 3 additions & 3 deletions packages/eslint-plugin-next/lib/rules/no-page-custom-font.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ module.exports = {
}

const hrefValue = attributes.value('href')
const isGoogleFont = hrefValue?.startsWith(
'https://fonts.googleapis.com/css'
)
const isGoogleFont =
typeof hrefValue === 'string' &&
hrefValue.startsWith('https://fonts.googleapis.com/css')

if (isGoogleFont) {
context.report({
Expand Down
9 changes: 7 additions & 2 deletions packages/next/build/webpack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ export default async function getBaseWebpackConfig(
// and all other chunk depend on them so there is no
// duplication that need to be pulled out.
chunks: isWebpack5
? (chunk) => !/^(main|pages\/_app)$/.test(chunk.name)
? (chunk) => !/^(polyfills|main|pages\/_app)$/.test(chunk.name)
: 'all',
cacheGroups: {
framework: {
Expand Down Expand Up @@ -1634,7 +1634,12 @@ export default async function getBaseWebpackConfig(

if (isWebpack5 && !isServer) {
for (const name of Object.keys(entry)) {
if (name === 'main' || name === 'amp' || name === 'react-refresh')
if (
name === 'polyfills' ||
name === 'main' ||
name === 'amp' ||
name === 'react-refresh'
)
continue
const dependOn =
name.startsWith('pages/') && name !== 'pages/_app'
Expand Down
26 changes: 9 additions & 17 deletions packages/next/client/experimental-script.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@ const ScriptCache = new Map()
const LoadCache = new Set()

export interface Props extends ScriptHTMLAttributes<HTMLScriptElement> {
strategy?: 'afterInteraction' | 'lazy' | 'beforeInteraction'
strategy?: 'afterInteractive' | 'lazyOnload' | 'beforeInteractive'
id?: string
onLoad?: () => void
onError?: () => void
children?: React.ReactNode
preload?: boolean
}

const ignoreProps = [
Expand All @@ -22,7 +21,6 @@ const ignoreProps = [
'children',
'onError',
'strategy',
'preload',
]

const loadScript = (props: Props): void => {
Expand Down Expand Up @@ -93,10 +91,10 @@ const loadScript = (props: Props): void => {
}

function handleClientScriptLoad(props: Props) {
const { strategy = 'afterInteraction' } = props
if (strategy === 'afterInteraction') {
const { strategy = 'afterInteractive' } = props
if (strategy === 'afterInteractive') {
loadScript(props)
} else if (strategy === 'lazy') {
} else if (strategy === 'lazyOnload') {
window.addEventListener('load', () => {
requestIdleCallback(() => loadScript(props))
})
Expand All @@ -122,19 +120,18 @@ function Script(props: Props): JSX.Element | null {
src = '',
onLoad = () => {},
dangerouslySetInnerHTML,
strategy = 'afterInteraction',
strategy = 'afterInteractive',
onError,
preload = false,
...restProps
} = props

// Context is available only during SSR
const { updateScripts, scripts } = useContext(HeadManagerContext)

useEffect(() => {
if (strategy === 'afterInteraction') {
if (strategy === 'afterInteractive') {
loadScript(props)
} else if (strategy === 'lazy') {
} else if (strategy === 'lazyOnload') {
loadLazyScript(props)
}
}, [props, strategy])
Expand All @@ -143,14 +140,9 @@ function Script(props: Props): JSX.Element | null {
return null
}

if (strategy === 'afterInteraction') {
if (updateScripts && preload) {
scripts.afterInteraction = (scripts.afterInteraction || []).concat([src])
updateScripts(scripts)
}
} else if (strategy === 'beforeInteraction') {
if (strategy === 'beforeInteractive') {
if (updateScripts) {
scripts.beforeInteraction = (scripts.beforeInteraction || []).concat([
scripts.beforeInteractive = (scripts.beforeInteractive || []).concat([
{
src,
onLoad,
Expand Down
12 changes: 12 additions & 0 deletions packages/next/client/head-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@ export default function initHeadManager(): {
const tags: Record<string, JSX.Element[]> = {}

head.forEach((h) => {
if (
// If the font tag is loaded only on client navigation
// it won't be inlined. In this case revert to the original behavior
h.type === 'link' &&
h.props['data-optimized-fonts'] &&
!document.querySelector(
`style[data-href="${h.props['data-href']}"]`
)
) {
h.props.href = h.props['data-href']
h.props['data-href'] = undefined
}
const components = tags[h.type] || []
components.push(h)
tags[h.type] = components
Expand Down
4 changes: 4 additions & 0 deletions packages/next/next-server/lib/head.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ function reduceComponents(
const newProps = { ...(c.props || {}) }
newProps['data-href'] = newProps['href']
newProps['href'] = undefined

// Add this attribute to make it easy to identify optimized tags
newProps['data-optimized-fonts'] = true

return React.cloneElement(c, newProps)
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/next/next-server/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export type DocumentProps = DocumentInitialProps & {
unstable_runtimeJS?: false
unstable_JsPreload?: false
devOnlyCacheBusterQueryString: string
scriptLoader: { afterInteraction?: string[]; beforeInteraction?: any[] }
scriptLoader: { afterInteractive?: string[]; beforeInteractive?: any[] }
locale?: string
}

Expand Down
24 changes: 6 additions & 18 deletions packages/next/pages/_document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export class Head extends Component<
})

return [
...(scriptLoader.beforeInteraction || []).map((file) => (
...(scriptLoader.beforeInteractive || []).map((file) => (
<link
key={file.src}
nonce={this.props.nonce}
Expand All @@ -282,18 +282,6 @@ export class Head extends Component<
}
/>
)),
...(scriptLoader.afterInteraction || []).map((file: string) => (
<link
key={file}
nonce={this.props.nonce}
rel="preload"
href={file}
as="script"
crossOrigin={
this.props.crossOrigin || process.env.__NEXT_CROSS_ORIGIN
}
/>
)),
]
}

Expand All @@ -304,17 +292,17 @@ export class Head extends Component<

React.Children.forEach(children, (child: any) => {
if (child.type === Script) {
if (child.props.strategy === 'beforeInteraction') {
scriptLoader.beforeInteraction = (
scriptLoader.beforeInteraction || []
if (child.props.strategy === 'beforeInteractive') {
scriptLoader.beforeInteractive = (
scriptLoader.beforeInteractive || []
).concat([
{
...child.props,
},
])
return
} else if (
['lazy', 'afterInteraction'].includes(child.props.strategy)
['lazyOnload', 'afterInteractive'].includes(child.props.strategy)
) {
scriptLoaderItems.push(child.props)
return
Expand Down Expand Up @@ -668,7 +656,7 @@ export class NextScript extends Component<OriginProps> {
getPreNextScripts() {
const { scriptLoader } = this.context

return (scriptLoader.beforeInteraction || []).map(
return (scriptLoader.beforeInteractive || []).map(
(file: ScriptLoaderProps) => {
const { strategy, ...props } = file
return (
Expand Down
4 changes: 2 additions & 2 deletions test/integration/build-output/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ describe('Build Output', () => {
expect(parseFloat(err404FirstLoad)).toBeCloseTo(66.3, 0)
expect(err404FirstLoad.endsWith('kB')).toBe(true)

expect(parseFloat(sharedByAll)).toBeCloseTo(63.3, 1)
expect(parseFloat(sharedByAll)).toBeCloseTo(63.4, 1)
expect(sharedByAll.endsWith('kB')).toBe(true)

if (_appSize.endsWith('kB')) {
Expand All @@ -122,7 +122,7 @@ describe('Build Output', () => {
expect(parseFloat(webpackSize) - 952).toBeLessThanOrEqual(0)
expect(webpackSize.endsWith(' B')).toBe(true)

expect(parseFloat(mainSize) - 19.3).toBeLessThanOrEqual(0)
expect(parseFloat(mainSize) - 19.4).toBeLessThanOrEqual(0)
expect(mainSize.endsWith('kB')).toBe(true)

expect(parseFloat(frameworkSize) - 42.1).toBeLessThanOrEqual(0)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import React from 'react'
import Link from 'next/link'

const Page = () => {
return <div>Hi!</div>
return (
<div>
Hi!
<br />
<br />
<Link href="/with-font">
<a id="with-font">With font</a>
</Link>
</div>
)
}

export default Page
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const WithFont = () => {
/>
</Head>

<div>
<div id="with-font-container">
Page with custom fonts
<br />
<br />
Expand Down
29 changes: 19 additions & 10 deletions test/integration/font-optimization/fixtures/with-google/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,27 @@ const server = http.createServer(async (req, res) => {
}

if (pathname.startsWith('/_next/static/')) {
res.write(
fs.readFileSync(
path.join(
__dirname,
'./.next/static/',
decodeURI(pathname.slice('/_next/static/'.length))
),
'utf8'
let prom = Promise.resolve()
if (pathname.endsWith('.css')) {
prom = new Promise((resolve) => setTimeout(resolve, 20000))
}
prom.then(() => {
res.write(
fs.readFileSync(
path.join(
__dirname,
'./.next/static/',
decodeURI(pathname.slice('/_next/static/'.length))
),
'utf8'
)
)
)
return res.end()
return res.end()
})
} else {
if (pathname === '') {
pathname = '/index'
}
const ext = isDataReq ? 'json' : 'html'
if (
fs.existsSync(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import React from 'react'
import Link from 'next/link'

const Page = () => {
return <div>Hi!</div>
return (
<div>
Hi!
<br />
<br />
<Link href="/with-font">
<a id="with-font">With font</a>
</Link>
</div>
)
}

export default Page
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const WithFont = () => {
<link href="https://use.typekit.net/ucs7mcf.css" rel="stylesheet" />
</Head>

<div>
<div id="with-font-container">
Page with custom fonts
<br />
<br />
Expand Down
29 changes: 19 additions & 10 deletions test/integration/font-optimization/fixtures/with-typekit/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,27 @@ const server = http.createServer(async (req, res) => {
}

if (pathname.startsWith('/_next/static/')) {
res.write(
fs.readFileSync(
path.join(
__dirname,
'./.next/static/',
decodeURI(pathname.slice('/_next/static/'.length))
),
'utf8'
let prom = Promise.resolve()
if (pathname.endsWith('.css')) {
prom = new Promise((resolve) => setTimeout(resolve, 20000))
}
prom.then(() => {
res.write(
fs.readFileSync(
path.join(
__dirname,
'./.next/static/',
decodeURI(pathname.slice('/_next/static/'.length))
),
'utf8'
)
)
)
return res.end()
return res.end()
})
} else {
if (pathname === '') {
pathname = '/index'
}
const ext = isDataReq ? 'json' : 'html'
if (
fs.existsSync(
Expand Down
Loading

0 comments on commit 843c8c8

Please sign in to comment.