From cbf87e1ebfbc39db5068efdac91e1296c65beb8a Mon Sep 17 00:00:00 2001 From: LongYinan Date: Tue, 6 Dec 2022 13:17:03 +0800 Subject: [PATCH 1/2] Build test binary in Docker image (#43745) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) --- .github/workflows/build_test_deploy.yml | 29 ++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build_test_deploy.yml b/.github/workflows/build_test_deploy.yml index af7ec8598aa5b6a..917d65de05b192f 100644 --- a/.github/workflows/build_test_deploy.yml +++ b/.github/workflows/build_test_deploy.yml @@ -923,13 +923,6 @@ jobs: node-version: 16 check-latest: true - - name: Install - uses: actions-rs/toolchain@v1 - if: ${{ steps.docs-change.outputs.DOCS_CHANGE == 'nope' }} - with: - profile: minimal - toolchain: ${{ env.RUST_TOOLCHAIN }} - - name: Cache cargo registry uses: actions/cache@v3 if: ${{ steps.docs-change.outputs.DOCS_CHANGE == 'nope' }} @@ -976,14 +969,20 @@ jobs: restore-keys: | next-swc-cargo-cache-dev-ubuntu-latest - # since the repo's dependencies aren't installed we need - # to install napi globally - - run: npm i -g @napi-rs/cli@${{ env.NAPI_CLI_VERSION }} turbo@${{ env.TURBO_VERSION }} pnpm@${PNPM_VERSION} - - name: Build - if: ${{ steps.docs-change.outputs.DOCS_CHANGE == 'nope' }} - run: turbo run build-native --cache-dir=".turbo" -- --release - env: - MACOSX_DEPLOYMENT_TARGET: '10.13' + - name: Build in docker + uses: addnab/docker-run-action@v3 + with: + image: ghcr.io/napi-rs/napi-rs/nodejs-rust:stable-2022-10-24-x64 + options: -e RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} -e NAPI_CLI_VERSION=${{ env.NAPI_CLI_VERSION }} -e TURBO_VERSION=${{ env.TURBO_VERSION }} -e TURBO_TEAM=vercel -e TURBO_TOKEN=${{ secrets.TURBO_TOKEN }} -e TURBO_REMOTE_ONLY=true -v ${{ env.HOME }}/.cargo/git:/root/.cargo/git -v ${{ env.HOME }}/.cargo/registry:/root/.cargo/registry -v ${{ github.workspace }}:/build -w /build + run: | + set -e && + rustup toolchain install "${RUST_TOOLCHAIN}" && + rustup default "${RUST_TOOLCHAIN}" && + rustup target add x86_64-unknown-linux-gnu && + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" && if [ ! -f $(dirname $(which yarn))/pnpm ]; then ln -s $(which yarn) $(dirname $(which yarn))/pnpm;fi && + unset CC_x86_64_unknown_linux_gnu && unset CC && + turbo run build-native --cache-dir=".turbo" -- --release --target x86_64-unknown-linux-gnu && + strip packages/next-swc/native/next-swc.*.node - name: Upload artifact uses: actions/upload-artifact@v3 From 5cff316aee008f01c99d99bd14a290b21cab1a65 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 6 Dec 2022 10:26:37 +0100 Subject: [PATCH 2/2] Remove additional `
` at each segment level in `app` (#43717) --- .../next/client/components/layout-router.tsx | 91 +++++++++++++------ 1 file changed, 62 insertions(+), 29 deletions(-) diff --git a/packages/next/client/components/layout-router.tsx b/packages/next/client/components/layout-router.tsx index 35898fd9dfda6de..050ed4a0271af80 100644 --- a/packages/next/client/components/layout-router.tsx +++ b/packages/next/client/components/layout-router.tsx @@ -1,10 +1,4 @@ 'use client' - -import React, { useContext, useEffect, useRef, use } from 'react' -import type { - ChildProp, - //Segment -} from '../../server/app-render' import type { AppRouterInstance, ChildSegmentMap, @@ -12,9 +6,13 @@ import type { import type { FlightRouterState, FlightSegmentPath, - // FlightDataPath, } from '../../server/app-render' import type { ErrorComponent } from './error-boundary' +import type { FocusAndScrollRef } from './reducer' + +import React, { useContext, useEffect, use } from 'react' +import { findDOMNode as ReactDOMfindDOMNode } from 'react-dom' +import type { ChildProp } from '../../server/app-render' import { CacheStates, LayoutRouterContext, @@ -77,6 +75,31 @@ function walkAddRefetch( return treeToRecreate } +// TODO-APP: Replace with new React API for finding dom nodes without a `ref` when available +/** + * Wraps ReactDOM.findDOMNode with additional logic to hide React Strict Mode warning + */ +function findDOMNode( + instance: Parameters[0] +): ReturnType { + // Only apply strict mode warning when not in production + if (process.env.NODE_ENV !== 'production') { + const originalConsoleError = console.error + try { + console.error = (...messages) => { + // Ignore strict mode warning for the findDomNode call below + if (!messages[0].includes('Warning: %s is deprecated in StrictMode.')) { + originalConsoleError(...messages) + } + } + return ReactDOMfindDOMNode(instance) + } finally { + console.error = originalConsoleError! + } + } + return ReactDOMfindDOMNode(instance) +} + /** * Check if the top of the HTMLElement is in the viewport. */ @@ -85,6 +108,36 @@ function topOfElementInViewport(element: HTMLElement) { return rect.top >= 0 } +class ScrollAndFocusHandler extends React.Component<{ + focusAndScrollRef: FocusAndScrollRef + children: React.ReactNode +}> { + componentDidMount() { + // Handle scroll and focus, it's only applied once in the first useEffect that triggers that changed. + const { focusAndScrollRef } = this.props + const domNode = findDOMNode(this) + + if (focusAndScrollRef.apply && domNode instanceof HTMLElement) { + // State is mutated to ensure that the focus and scroll is applied only once. + focusAndScrollRef.apply = false + // Set focus on the element + domNode.focus() + // Only scroll into viewport when the layout is not visible currently. + if (!topOfElementInViewport(domNode)) { + const htmlElement = document.documentElement + const existing = htmlElement.style.scrollBehavior + htmlElement.style.scrollBehavior = 'auto' + domNode.scrollIntoView() + htmlElement.style.scrollBehavior = existing + } + } + } + + render() { + return this.props.children + } +} + /** * InnerLayoutRouter handles rendering the provided segment based on the cache. */ @@ -117,26 +170,6 @@ export function InnerLayoutRouter({ const { changeByServerResponse, tree: fullTree, focusAndScrollRef } = context - const focusAndScrollElementRef = useRef(null) - - useEffect(() => { - // Handle scroll and focus, it's only applied once in the first useEffect that triggers that changed. - if (focusAndScrollRef.apply && focusAndScrollElementRef.current) { - // State is mutated to ensure that the focus and scroll is applied only once. - focusAndScrollRef.apply = false - // Set focus on the element - focusAndScrollElementRef.current.focus() - // Only scroll into viewport when the layout is not visible currently. - if (!topOfElementInViewport(focusAndScrollElementRef.current)) { - const htmlElement = document.documentElement - const existing = htmlElement.style.scrollBehavior - htmlElement.style.scrollBehavior = 'auto' - focusAndScrollElementRef.current.scrollIntoView() - htmlElement.style.scrollBehavior = existing - } - } - }, [focusAndScrollRef]) - // Read segment path from the parallel router cache node. let childNode = childNodes.get(path) @@ -257,9 +290,9 @@ export function InnerLayoutRouter({ // Ensure root layout is not wrapped in a div as the root layout renders `` return rootLayoutIncluded ? ( -
+ {subtree} -
+ ) : ( subtree )