diff --git a/.github/workflows/build_test_deploy.yml b/.github/workflows/build_test_deploy.yml index 1b91c3fb11ab..59b4e71bce5b 100644 --- a/.github/workflows/build_test_deploy.yml +++ b/.github/workflows/build_test_deploy.yml @@ -6,12 +6,17 @@ on: name: Build, test, and deploy +env: + NAPI_CLI_VERSION: 2.7.0 + TURBO_VERSION: 1.2.6 + RUST_TOOLCHAIN: nightly-2022-02-23 + jobs: check-examples: name: Check examples runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install moreutils run: sudo apt install moreutils - name: Check examples @@ -30,12 +35,13 @@ jobs: weekNum: ${{ steps.get-week.outputs.WEEK }} steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{ steps.docs-change.outputs.docsChange != 'docs only change' }} with: - node-version: 14 + node-version: 16 + check-latest: true - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 25 @@ -64,7 +70,7 @@ jobs: - id: get-week run: echo ::set-output name=WEEK::$(date +%U) - - uses: actions/cache@v2 + - uses: actions/cache@v3 id: cache-build with: path: ./* @@ -75,12 +81,13 @@ jobs: needs: build steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{ steps.docs-change.outputs.docsChange != 'docs only change' }} with: - node-version: 14 + node-version: 16 + check-latest: true - - uses: actions/cache@v2 + - uses: actions/cache@v3 id: restore-build with: path: ./* @@ -97,24 +104,24 @@ jobs: if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: profile: minimal - toolchain: nightly-2022-02-23 + toolchain: ${{ env.RUST_TOOLCHAIN }} components: rustfmt, clippy - name: Cache cargo registry - uses: actions/cache@v2 + uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: path: ~/.cargo/registry key: stable-ubuntu-clippy-cargo-registry - name: Cache cargo index - uses: actions/cache@v2 + uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: path: ~/.cargo/git key: stable-ubuntu-clippy-cargo-index - - uses: actions/cache@v2 + - uses: actions/cache@v3 id: restore-build if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: @@ -136,23 +143,24 @@ jobs: NEXT_TELEMETRY_DISABLED: 1 steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: - node-version: 14 + node-version: 16 + check-latest: true # https://github.com/actions/virtual-environments/issues/1187 - name: tune linux network if: ${{needs.build.outputs.docsChange != 'docs only change'}} run: sudo ethtool -K eth0 tx off rx off - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} - run: mv .git .git-bak if: ${{needs.build.outputs.docsChange != 'docs only change'}} - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: @@ -180,19 +188,20 @@ jobs: NEXT_TEST_JOB: 1 steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: - node-version: 14 + node-version: 16 + check-latest: true - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -211,13 +220,14 @@ jobs: strategy: fail-fast: false matrix: - node: [16, 17] + node: [16, 18] steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: node-version: ${{ matrix.node }} + check-latest: true - run: echo ${{needs.build.outputs.docsChange}} @@ -225,14 +235,14 @@ jobs: - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -247,7 +257,7 @@ jobs: - name: Upload test trace if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: test-trace if-no-files-found: ignore @@ -265,10 +275,11 @@ jobs: NEXT_TEST_REACT_VERSION: ^17 steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: node-version: 16 + check-latest: true - run: echo ${{needs.build.outputs.docsChange}} @@ -276,14 +287,14 @@ jobs: - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -298,7 +309,7 @@ jobs: - name: Upload test trace if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: test-trace if-no-files-found: ignore @@ -316,13 +327,14 @@ jobs: strategy: fail-fast: false matrix: - node: [16, 17] + node: [16, 18] steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: node-version: ${{ matrix.node }} + check-latest: true - run: echo ${{needs.build.outputs.docsChange}} @@ -330,14 +342,14 @@ jobs: - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -352,7 +364,7 @@ jobs: - name: Upload test trace if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: test-trace if-no-files-found: ignore @@ -370,10 +382,11 @@ jobs: NEXT_TEST_REACT_VERSION: ^17 steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: node-version: 16 + check-latest: true - run: echo ${{needs.build.outputs.docsChange}} @@ -381,14 +394,14 @@ jobs: - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -403,7 +416,7 @@ jobs: - name: Upload test trace if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: test-trace if-no-files-found: ignore @@ -421,13 +434,14 @@ jobs: strategy: fail-fast: false matrix: - node: [16, 17] + node: [16, 18] steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: node-version: ${{ matrix.node }} + check-latest: true - run: echo ${{needs.build.outputs.docsChange}} @@ -435,14 +449,14 @@ jobs: - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -465,10 +479,11 @@ jobs: NEXT_TEST_REACT_VERSION: ^17 steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: node-version: 16 + check-latest: true - run: echo ${{needs.build.outputs.docsChange}} @@ -476,14 +491,14 @@ jobs: - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -506,13 +521,14 @@ jobs: strategy: fail-fast: false matrix: - node: [16, 17] + node: [16, 18] steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: node-version: ${{ matrix.node }} + check-latest: true - run: echo ${{needs.build.outputs.docsChange}} @@ -520,14 +536,14 @@ jobs: - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -548,12 +564,17 @@ jobs: NEXT_TELEMETRY_DISABLED: 1 NEXT_TEST_JOB: 1 NEXT_TEST_REACT_VERSION: ^17 + strategy: + fail-fast: false + matrix: + node: [16, 18] steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: node-version: ${{ matrix.node }} + check-latest: true - run: echo ${{needs.build.outputs.docsChange}} @@ -561,14 +582,14 @@ jobs: - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -595,10 +616,11 @@ jobs: group: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18] steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: - node-version: 14 + node-version: 16 + check-latest: true - run: echo ${{needs.build.outputs.docsChange}} @@ -606,7 +628,7 @@ jobs: - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: @@ -617,7 +639,7 @@ jobs: with: version: 6.32.2 - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -631,7 +653,7 @@ jobs: - name: Upload test trace if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: test-trace if-no-files-found: ignore @@ -649,19 +671,20 @@ jobs: TEST_ELECTRON: 1 steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: - node-version: 14 + node-version: 16 + check-latest: true - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -699,18 +722,19 @@ jobs: NEXT_TELEMETRY_DISABLED: 1 steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: - node-version: 14 + node-version: 16 + check-latest: true - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -737,23 +761,24 @@ jobs: BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: - node-version: 14 + node-version: 16 + check-latest: true # https://github.com/actions/virtual-environments/issues/1187 - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -781,23 +806,24 @@ jobs: BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: - node-version: 14 + node-version: 16 + check-latest: true # https://github.com/actions/virtual-environments/issues/1187 - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -809,8 +835,8 @@ jobs: - run: '[[ -z "$BROWSERSTACK_ACCESS_KEY" ]] && echo "Skipping for PR" || node run-tests.js test/integration/production-nav/test/index.test.js' if: ${{needs.build.outputs.docsChange != 'docs only change'}} - testFirefoxNode17: - name: Test Firefox Node.js 17 + testFirefoxNode18: + name: Test Firefox Node.js 18 runs-on: ubuntu-latest needs: [build, testFirefox, build-native-test] env: @@ -818,18 +844,18 @@ jobs: NEXT_TELEMETRY_DISABLED: 1 steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: - node-version: 17 + node-version: 18 check-latest: true - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -851,27 +877,28 @@ jobs: NPM_TOKEN: ${{ secrets.NPM_TOKEN_ELEVATED }} steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: - node-version: 14 + node-version: 16 + check-latest: true # https://github.com/actions/virtual-environments/issues/1187 - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/cache@v2 + - uses: actions/cache@v3 id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 with: name: next-swc-binaries path: packages/next-swc/native - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 with: name: wasm-binaries path: packages/next-swc/crates/wasm @@ -886,17 +913,18 @@ jobs: needs: [publishRelease, build-native-test] steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 16 + check-latest: true - - uses: actions/cache@v2 + - uses: actions/cache@v3 id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 with: name: next-swc-test-binary path: packages/next-swc/native @@ -916,7 +944,7 @@ jobs: - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 25 @@ -924,7 +952,7 @@ jobs: id: docs-change - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} with: node-version: 16 @@ -935,17 +963,17 @@ jobs: if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} with: profile: minimal - toolchain: nightly-2022-02-23 + toolchain: ${{ env.RUST_TOOLCHAIN }} - name: Cache cargo registry - uses: actions/cache@v2 + uses: actions/cache@v3 if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} with: path: ~/.cargo/registry key: stable-ubuntu-18.04-cargo-registry - name: Cache cargo index - uses: actions/cache@v2 + uses: actions/cache@v3 if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} with: path: ~/.cargo/git @@ -957,7 +985,7 @@ jobs: - name: Turbo Cache id: turbo-cache - uses: actions/cache@v2 + uses: actions/cache@v3 if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} with: path: .turbo @@ -972,7 +1000,7 @@ jobs: # "If there are multiple partial matches for a restore key, the action returns the most recently created cache." # So we get latest cache - name: Cache built files - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ./packages/next-swc/target key: next-swc-cargo-cache-dev-ubuntu-18.04-${{ hashFiles('**/Cargo.lock') }} @@ -981,7 +1009,7 @@ jobs: # since the repo's dependencies aren't installed we need # to install napi globally - - run: npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 + - run: npm i -g @napi-rs/cli@${{ env.NAPI_CLI_VERSION }} turbo@${{ env.TURBO_VERSION }} - name: Build if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} run: turbo run build-native --cache-dir=".turbo" -- --release @@ -989,7 +1017,7 @@ jobs: MACOSX_DEPLOYMENT_TARGET: '10.13' - name: Upload artifact - uses: actions/upload-artifact@v2.2.4 + uses: actions/upload-artifact@v3 with: name: next-swc-test-binary path: packages/next-swc/native/next-swc.linux-x64-gnu.node @@ -1005,7 +1033,7 @@ jobs: runs-on: ubuntu-18.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 25 - run: echo ::set-output name=DOCS_CHANGE::$(node skip-docs-change.js echo 'not-docs-only-change') @@ -1014,7 +1042,7 @@ jobs: if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} uses: actions-rs/toolchain@v1 with: - toolchain: nightly-2022-02-23 + toolchain: ${{ env.RUST_TOOLCHAIN }} profile: minimal - run: cd packages/next-swc && cargo test if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} @@ -1025,14 +1053,14 @@ jobs: needs: [build, build-native-test, build-wasm-dev] steps: - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: path: ./* key: ${{ github.sha }} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: wasm-dev-binary @@ -1041,7 +1069,7 @@ jobs: - run: ls packages/next-swc/crates/wasm if: ${{needs.build.outputs.docsChange != 'docs only change'}} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary @@ -1050,7 +1078,7 @@ jobs: # node version needs to be 16+ to use --no-addons option - name: Setup node if: ${{needs.build.outputs.docsChange != 'docs only change'}} - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: 16 check-latest: true @@ -1076,17 +1104,17 @@ jobs: - host: macos-latest target: 'x86_64-apple-darwin' build: | - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" turbo run build-native --cache-dir=".turbo" -- --release strip -x packages/next-swc/native/next-swc.*.node - host: windows-latest build: | - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" turbo run build-native --cache-dir=".turbo" -- --release target: 'x86_64-pc-windows-msvc' - host: windows-latest build: | - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" turbo run build-native --cache-dir=".turbo" -- --release --target i686-pc-windows-msvc target: 'i686-pc-windows-msvc' - host: ubuntu-latest @@ -1095,10 +1123,10 @@ jobs: # Node.js in Baidu need to compatible with `GLIBC_2.12` build: >- set -e && - rustup toolchain install nightly-2022-02-23 && - rustup default nightly-2022-02-23 && + rustup toolchain install "${RUST_TOOLCHAIN}" && + rustup default "${RUST_TOOLCHAIN}" && rustup target add x86_64-unknown-linux-gnu && - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 && + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" && turbo run build-native --cache-dir=".turbo" -- --release --target x86_64-unknown-linux-gnu --zig --zig-abi-suffix 2.12 && llvm-strip -x packages/next-swc/native/next-swc.*.node - host: ubuntu-latest @@ -1106,10 +1134,10 @@ jobs: docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine build: >- set -e && - rustup toolchain install nightly-2022-02-23 && - rustup default nightly-2022-02-23 && + rustup toolchain install "${RUST_TOOLCHAIN}" && + rustup default "${RUST_TOOLCHAIN}" && rustup target add x86_64-unknown-linux-musl && - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 && + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" && turbo run build-native --cache-dir=".turbo" -- --release --target x86_64-unknown-linux-musl && strip packages/next-swc/native/next-swc.*.node - host: macos-latest @@ -1120,7 +1148,7 @@ jobs: export CXX=$(xcrun -f clang++); SYSROOT=$(xcrun --sdk macosx --show-sdk-path); export CFLAGS="-isysroot $SYSROOT -isystem $SYSROOT"; - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" turbo run build-native --cache-dir=".turbo" -- --release --target aarch64-apple-darwin strip -x packages/next-swc/native/next-swc.*.node - host: ubuntu-latest @@ -1128,10 +1156,10 @@ jobs: docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine-zig build: >- set -e && - rustup toolchain install nightly-2022-02-23 && - rustup default nightly-2022-02-23 && + rustup toolchain install "${RUST_TOOLCHAIN}" && + rustup default "${RUST_TOOLCHAIN}" && rustup target add aarch64-unknown-linux-gnu && - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 && + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" && turbo run build-native --cache-dir=".turbo" -- --release --target aarch64-unknown-linux-gnu --zig --zig-abi-suffix 2.12 && llvm-strip -x packages/next-swc/native/next-swc.*.node - host: ubuntu-18.04 @@ -1140,7 +1168,7 @@ jobs: sudo apt-get update sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf -y build: | - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" turbo run build-native --cache-dir=".turbo" -- --release --target armv7-unknown-linux-gnueabihf arm-linux-gnueabihf-strip packages/next-swc/native/next-swc.*.node - host: ubuntu-latest @@ -1150,7 +1178,7 @@ jobs: export CC="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang" export CXX="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang++" export PATH="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin:${PATH}" - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" turbo run build-native --cache-dir=".turbo" -- --release --target aarch64-linux-android ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip packages/next-swc/native/next-swc.*.node - host: ubuntu-latest @@ -1160,7 +1188,7 @@ jobs: export CC="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang" export CXX="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang++" export PATH="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin:${PATH}" - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" turbo run build-native --cache-dir=".turbo" -- --release --target armv7-linux-androideabi ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip packages/next-swc/native/next-swc.*.node - host: ubuntu-latest @@ -1168,16 +1196,16 @@ jobs: docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine build: >- set -e && - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 && - rustup toolchain install nightly-2022-02-23 && - rustup default nightly-2022-02-23 && + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" && + rustup toolchain install "${RUST_TOOLCHAIN}" && + rustup default "${RUST_TOOLCHAIN}" && rustup target add aarch64-unknown-linux-musl && turbo run build-native --cache-dir=".turbo" -- --release --target aarch64-unknown-linux-musl && llvm-strip -x packages/next-swc/native/next-swc.*.node - host: windows-latest target: 'aarch64-pc-windows-msvc' build: | - npm i -g @napi-rs/cli@2.4.4 turbo@1.0.28 + npm i -g "@napi-rs/cli@${NAPI_CLI_VERSION}" "turbo@${TURBO_VERSION}" turbo run build-native --cache-dir=".turbo" -- --release --target aarch64-pc-windows-msvc if: ${{ needs.build.outputs.isRelease == 'true' }} needs: build @@ -1199,13 +1227,13 @@ jobs: if: ${{ matrix.settings.host == 'macos-latest' }} # we use checkout here instead of the build cache since # it can fail to restore in different OS' - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # We use restore-key to pick latest cache. # We will not get exact match, but doc says # "If there are multiple partial matches for a restore key, the action returns the most recently created cache." # So we get latest cache - name: Cache built files - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ./packages/next-swc/target key: next-swc-cargo-cache-${{ matrix.settings.target }}--${{ hashFiles('**/Cargo.lock') }} @@ -1213,7 +1241,7 @@ jobs: next-swc-cargo-cache-${{ matrix.settings.target }} - name: Turbo Cache id: turbo-cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: .turbo key: turbo-${{ github.job }}-${{ github.ref_name }}-${{ matrix.settings.target }}-${{ needs.build.outputs.weekNum }}-${{ github.sha }} @@ -1223,7 +1251,7 @@ jobs: turbo-${{ github.job }}-canary-${{ matrix.settings.target }}-${{ needs.build.outputs.weekNum }}- - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{ !matrix.settings.docker }} with: node-version: 16 @@ -1236,17 +1264,17 @@ jobs: with: profile: minimal override: true - toolchain: nightly-2022-02-23 + toolchain: ${{ env.RUST_TOOLCHAIN }} target: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.cargo/registry key: ${{ matrix.settings.target }}-cargo-registry - name: Cache cargo index - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.cargo/git key: ${{ matrix.settings.target }}-cargo-index @@ -1261,7 +1289,7 @@ jobs: if: ${{ matrix.settings.docker }} with: image: ${{ matrix.settings.docker }} - options: -v ${{ env.HOME }}/.cargo/git:/root/.cargo/git -v ${{ env.HOME }}/.cargo/registry:/root/.cargo/registry -v ${{ github.workspace }}:/build -w /build + options: -e RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} -e NAPI_CLI_VERSION=${{ env.NAPI_CLI_VERSION }} -e TURBO_VERSION=${{ env.TURBO_VERSION }} -v ${{ env.HOME }}/.cargo/git:/root/.cargo/git -v ${{ env.HOME }}/.cargo/registry:/root/.cargo/registry -v ${{ github.workspace }}:/build -w /build run: ${{ matrix.settings.build }} - name: 'Build' @@ -1270,7 +1298,7 @@ jobs: shell: bash - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: next-swc-binaries path: packages/next-swc/native/next-swc.*.node @@ -1283,30 +1311,31 @@ jobs: target: [web, nodejs] runs-on: ubuntu-latest steps: - - uses: actions/cache@v2 + - uses: actions/cache@v3 id: restore-build with: path: ./* key: ${{ github.sha }}-${{ github.run_number }} - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 16 + check-latest: true - name: Install Rust uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly-2022-02-23 + toolchain: ${{ env.RUST_TOOLCHAIN }} override: true target: wasm32-unknown-unknown - - run: npm i -g turbo@1.0.28 + - run: npm i -g turbo@${{ env.TURBO_VERSION }} - name: Turbo cache id: turbo-cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: .turbo key: turbo-${{ github.job }}-${{ matrix.target }}-${{ github.ref_name }}-${{ needs.build.outputs.weekNum }}-${{ github.sha }} @@ -1325,7 +1354,7 @@ jobs: run: '[[ -d "packages/next-swc/crates/wasm/pkg" ]] && mv packages/next-swc/crates/wasm/pkg packages/next-swc/crates/wasm/pkg-${{ matrix.target }} || ls packages/next-swc/crates/wasm' - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: wasm-binaries path: packages/next-swc/crates/wasm/pkg-* @@ -1334,7 +1363,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/cache@v2 + - uses: actions/cache@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} id: restore-build with: @@ -1343,24 +1372,25 @@ jobs: - name: Setup node if: ${{needs.build.outputs.docsChange != 'docs only change'}} - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 16 + check-latest: true - - run: npm i -g turbo@1.0.28 + - run: npm i -g turbo@${{ env.TURBO_VERSION }} - name: Install Rust if: ${{needs.build.outputs.docsChange != 'docs only change'}} uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly-2022-02-23 + toolchain: ${{ env.RUST_TOOLCHAIN }} override: true target: wasm32-unknown-unknown - name: Turbo Cache id: turbo-cache - uses: actions/cache@v2 + uses: actions/cache@v3 if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} with: path: .turbo @@ -1384,7 +1414,7 @@ jobs: - name: Upload artifact if: ${{needs.build.outputs.docsChange != 'docs only change'}} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: wasm-dev-binary path: packages/next-swc/crates/wasm/pkg-nodejs @@ -1406,12 +1436,13 @@ jobs: if: needs.check-trace-secrests.outputs.trace-api-key == 'true' steps: - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: - node-version: 14 + node-version: 16 + check-latest: true - - uses: actions/cache@v2 + - uses: actions/cache@v3 id: restore-build if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: @@ -1426,7 +1457,7 @@ jobs: if: ${{needs.build.outputs.docsChange != 'docs only change'}} run: echo ${GIT_SHORT_SHA} - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{needs.build.outputs.docsChange != 'docs only change'}} with: name: next-swc-test-binary diff --git a/.github/workflows/pull_request_stats.yml b/.github/workflows/pull_request_stats.yml index 0d1e32362409..26e43bfe2a7e 100644 --- a/.github/workflows/pull_request_stats.yml +++ b/.github/workflows/pull_request_stats.yml @@ -13,7 +13,7 @@ jobs: - name: tune linux network run: sudo ethtool -K eth0 tx off rx off - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 25 @@ -21,10 +21,10 @@ jobs: id: docs-change - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} with: - node-version: 14 + node-version: 16 check-latest: true - name: Install @@ -54,7 +54,7 @@ jobs: - name: Turbo Cache id: turbo-cache - uses: actions/cache@v2 + uses: actions/cache@v3 if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} with: path: .turbo @@ -68,7 +68,7 @@ jobs: # "If there are multiple partial matches for a restore key, the action returns the most recently created cache." # So we get latest cache - name: Cache built files - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ./packages/next-target key: next-swc-cargo-cache-ubuntu-18.04--${{ hashFiles('**/Cargo.lock') }} @@ -77,8 +77,8 @@ jobs: # since the repo's dependencies aren't installed we need # to install napi globally - - run: npm i -g @napi-rs/cli@1.2.1 - - run: npm i -g turbo@1.0.28 + - run: npm i -g @napi-rs/cli@2.7.0 + - run: npm i -g turbo@1.2.6 - name: Build if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} @@ -90,7 +90,7 @@ jobs: TURBO_PROJECT: nextjs - name: Upload artifact - uses: actions/upload-artifact@v2.2.4 + uses: actions/upload-artifact@v3 with: name: next-swc-dev-binary path: packages/next-swc/native/next-swc.linux-x64-gnu.node @@ -106,14 +106,14 @@ jobs: needs: build-native-dev runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 25 - run: echo ::set-output name=DOCS_CHANGE::$(node skip-docs-change.js echo 'not-docs-only-change') id: docs-change - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} with: name: next-swc-dev-binary diff --git a/.github/workflows/test_react_experimental.yml b/.github/workflows/test_react_experimental.yml index 8b56f79f4d9b..79b3381bcdd0 100644 --- a/.github/workflows/test_react_experimental.yml +++ b/.github/workflows/test_react_experimental.yml @@ -9,7 +9,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: yarn install --frozen-lockfile --check-files env: @@ -19,7 +19,7 @@ jobs: - run: node run-tests.js --timings --write-timings -g 1/1 - - uses: actions/cache@v2 + - uses: actions/cache@v3 id: cache-build with: path: ./* @@ -38,7 +38,7 @@ jobs: matrix: group: [1, 2, 3, 4, 5, 6] steps: - - uses: actions/cache@v2 + - uses: actions/cache@v3 id: restore-build with: path: ./* diff --git a/.github/workflows/test_react_next.yml b/.github/workflows/test_react_next.yml index 4411c0a521a5..e44f28170e73 100644 --- a/.github/workflows/test_react_next.yml +++ b/.github/workflows/test_react_next.yml @@ -9,7 +9,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: yarn install --frozen-lockfile --check-files env: @@ -19,7 +19,7 @@ jobs: - run: node run-tests.js --timings --write-timings -g 1/1 - - uses: actions/cache@v2 + - uses: actions/cache@v3 id: cache-build with: path: ./* @@ -38,7 +38,7 @@ jobs: matrix: group: [1, 2, 3, 4, 5, 6] steps: - - uses: actions/cache@v2 + - uses: actions/cache@v3 id: restore-build with: path: ./* diff --git a/docs/api-reference/data-fetching/get-server-side-props.md b/docs/api-reference/data-fetching/get-server-side-props.md index d7e7c1ee6ef5..8eed5bffa2e3 100644 --- a/docs/api-reference/data-fetching/get-server-side-props.md +++ b/docs/api-reference/data-fetching/get-server-side-props.md @@ -31,7 +31,7 @@ You can import modules in top-level scope for use in `getServerSideProps`. Impor The `context` parameter is an object containing the following keys: - `params`: If this page uses a [dynamic route](/docs/routing/dynamic-routes.md), `params` contains the route parameters. If the page name is `[id].js` , then `params` will look like `{ id: ... }`. -- `req`: [The `HTTP` IncomingMessage object](https://nodejs.org/api/http.html#http_class_http_incomingmessage). +- `req`: [The `HTTP` IncomingMessage object](https://nodejs.org/api/http.html#http_class_http_incomingmessage), with an additional `cookies` prop, which is an object with string keys mapping to string values of cookies. - `res`: [The `HTTP` response object](https://nodejs.org/api/http.html#http_class_http_serverresponse). - `query`: An object representing the query string. - `preview`: `preview` is `true` if the page is in the [Preview Mode](/docs/advanced-features/preview-mode.md) and `false` otherwise. diff --git a/docs/api-reference/next.config.js/custom-webpack-config.md b/docs/api-reference/next.config.js/custom-webpack-config.md index 6b4535c7e80f..b58065f3b46f 100644 --- a/docs/api-reference/next.config.js/custom-webpack-config.md +++ b/docs/api-reference/next.config.js/custom-webpack-config.md @@ -36,6 +36,7 @@ The second argument to the `webpack` function is an object with the following pr - `buildId`: `String` - The build id, used as a unique identifier between builds - `dev`: `Boolean` - Indicates if the compilation will be done in development - `isServer`: `Boolean` - It's `true` for server-side compilation, and `false` for client-side compilation +- `nextRuntime`: `String` - The target runtime for server-side compilation; either `"edge"` or `"nodejs"` - `defaultLoaders`: `Object` - Default loaders used internally by Next.js: - `babel`: `Object` - Default `babel-loader` configuration diff --git a/docs/api-reference/next/image.md b/docs/api-reference/next/image.md index dedee45bfb57..043f2487963f 100644 --- a/docs/api-reference/next/image.md +++ b/docs/api-reference/next/image.md @@ -16,6 +16,7 @@ description: Enable Image Optimization with the built-in Image component. | Version | Changes | | --------- | ----------------------------------------------------------------------------------------------------- | +| `v12.1.7` | Experimental `remotePatterns` configuration added. | | `v12.1.1` | `style` prop added. Experimental[\*](#experimental-raw-layout-mode) support for `layout="raw"` added. | | `v12.1.0` | `dangerouslyAllowSVG` and `contentSecurityPolicy` configuration added. | | `v12.0.9` | `lazyRoot` prop added. | @@ -313,9 +314,64 @@ Other properties on the `` component will be passed to the underlying ## Configuration Options +### Remote Patterns + +> Note: The `remotePatterns` configuration is currently **experimental** and subject to change. Please use [`domains`](#domains) for production use cases. + +To protect your application from malicious users, configuration is required in order to use external images. This ensures that only external images from your account can be served from the Next.js Image Optimization API. These external images can be configured with the `remotePatterns` property in your `next.config.js` file, as shown below: + +```js +module.exports = { + experimental: { + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 'example.com', + port: '', + pathname: '/account123/**', + }, + ], + }, + }, +} +``` + +> Note: The example above will ensure the `src` property of `next/image` must start with `https://example.com/account123/`. Any other protocol, hostname, port, or unmatched path will respond with 400 Bad Request. + +Below is another example of the `remotePatterns` property in the `next.config.js` file: + +```js +module.exports = { + experimental: { + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: '**.example.com', + }, + ], + }, + }, +} +``` + +> Note: The example above will ensure the `src` property of `next/image` must start with `https://img1.example.com` or `https://me.avatar.example.com` or any number of subdomains. Any other protocol or unmatched hostname will respond with 400 Bad Request. + +Wildcard patterns can be used for both `pathname` and `hostname` and have the following syntax: + +- `*` match a single path segment or subdomain +- `**` match any number of path segments at the end or subdomains at the beginning + +The `**` syntax does not work in the middle of the pattern. + ### Domains -To protect your application from malicious users, you must define a list of image provider domains that you want to be served from the Next.js Image Optimization API. This is configured in with the `domains` property in your `next.config.js` file, as shown below: +Similar to [`remotePatterns`](#remote-patterns), the `domains` configuration can be used to provide a list of allowed hostnames for external images. + +However, the `domains` configuration does not support wildcard pattern matching and it cannot restrict protocol, port, or pathname. + +Below is an example of the `domains` property in the `next.config.js` file: ```js module.exports = { diff --git a/docs/basic-features/image-optimization.md b/docs/basic-features/image-optimization.md index 0c55837410ec..16c75ffe5533 100644 --- a/docs/basic-features/image-optimization.md +++ b/docs/basic-features/image-optimization.md @@ -66,7 +66,7 @@ function Home() { ### Remote Images -To use a remote image, the `src` property should be a URL string, which can be [relative](#loaders) or [absolute](#domains). Because Next.js does not have access to remote files during the build process, you'll need to provide the [`width`](/docs/api-reference/next/image.md#width), [`height`](/docs/api-reference/next/image.md#height) and optional [`blurDataURL`](/docs/api-reference/next/image.md#blurdataurl) props manually: +To use a remote image, the `src` property should be a URL string, which can be [relative](#loaders) or [absolute](/docs/api-reference/next/image.md#domains). Because Next.js does not have access to remote files during the build process, you'll need to provide the [`width`](/docs/api-reference/next/image.md#width), [`height`](/docs/api-reference/next/image.md#height) and optional [`blurDataURL`](/docs/api-reference/next/image.md#blurdataurl) props manually: ```jsx import Image from 'next/image' @@ -93,15 +93,9 @@ export default function Home() { Sometimes you may want to access a remote image, but still use the built-in Next.js Image Optimization API. To do this, leave the `loader` at its default setting and enter an absolute URL for the Image `src`. -To protect your application from malicious users, you must define a list of remote domains that you intend to access this way. This is configured in your `next.config.js` file, as shown below: +To protect your application from malicious users, you must define a list of remote hostnames you intend to allow remote access. -```js -module.exports = { - images: { - domains: ['example.com', 'example2.com'], - }, -} -``` +> Learn more about [`domains`](/docs/api-reference/next/image.md#domains) configuration. ### Loaders @@ -207,7 +201,7 @@ For examples of the Image component used with the various fill modes, see the [I ## Configuration -The `next/image` component and Next.js Image Optimization API can be configured in the [`next.config.js` file](/docs/api-reference/next.config.js/introduction.md). These configurations allow you to [enable remote domains](/docs/api-reference/next/image.md#domains), [define custom image breakpoints](/docs/api-reference/next/image.md#device-sizes), [change caching behavior](/docs/api-reference/next/image.md#caching-behavior) and more. +The `next/image` component and Next.js Image Optimization API can be configured in the [`next.config.js` file](/docs/api-reference/next.config.js/introduction.md). These configurations allow you to [enable remote images](/docs/api-reference/next/image.md#domains), [define custom image breakpoints](/docs/api-reference/next/image.md#device-sizes), [change caching behavior](/docs/api-reference/next/image.md#caching-behavior) and more. [**Read the full image configuration documentation for more information.**](/docs/api-reference/next/image.md#configuration-options) diff --git a/docs/basic-features/layouts.md b/docs/basic-features/layouts.md index 1bc5c1aa9250..9d4894db0a94 100644 --- a/docs/basic-features/layouts.md +++ b/docs/basic-features/layouts.md @@ -102,11 +102,10 @@ When using TypeScript, you must first create a new type for your pages which inc import type { ReactElement } from 'react' import Layout from '../components/layout' import NestedLayout from '../components/nested-layout' +import type { NextPageWithLayout } from './_app' -export default function Page() { - return { - /** Your content */ - } +const Page: NextPageWithLayout = () => { + return

hello world

} Page.getLayout = function getLayout(page: ReactElement) { @@ -116,6 +115,8 @@ Page.getLayout = function getLayout(page: ReactElement) { ) } + +export default Page ``` ```tsx @@ -125,7 +126,7 @@ import type { ReactElement, ReactNode } from 'react' import type { NextPage } from 'next' import type { AppProps } from 'next/app' -type NextPageWithLayout = NextPage & { +export type NextPageWithLayout = NextPage & { getLayout?: (page: ReactElement) => ReactNode } diff --git a/docs/basic-features/script.md b/docs/basic-features/script.md index cb3905ce4800..4491d251f3a4 100644 --- a/docs/basic-features/script.md +++ b/docs/basic-features/script.md @@ -247,7 +247,7 @@ The `id` property is required for **inline scripts** in order for Next.js to tra ### Executing Code After Loading (`onLoad`) -> **Note: Both `onLoad` and `onError` can't be used with the `beforeInteractive` loading strategy.** +> **Note: `onLoad` and `onError` cannot be used with the `beforeInteractive` loading strategy.** Some third-party scripts require users to run JavaScript code after the script has finished loading in order to instantiate content or call a function. If you are loading a script with either `afterInteractive` or `lazyOnload` as a loading strategy, you can execute code after it has loaded using the `onLoad` property: diff --git a/docs/testing.md b/docs/testing.md index 551933ad4d7d..11163588bbc5 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -263,10 +263,10 @@ npx create-next-app@latest --example with-jest with-jest-app Since the release of [Next.js 12](https://nextjs.org/blog/next-12), Next.js now has built-in configuration for Jest. -To set up Jest, install `jest` , `@testing-library/react`, `@testing-library/jest-dom`: +To set up Jest, install `jest`, `jest-environment-jsdom`, `@testing-library/react`, `@testing-library/jest-dom`: ```bash -npm install --save-dev jest @testing-library/react @testing-library/jest-dom +npm install --save-dev jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom ``` Create a `jest.config.js` file in your project's root directory and add the following: diff --git a/errors/invalid-images-config.md b/errors/invalid-images-config.md index b409f6056830..8a03674a31df 100644 --- a/errors/invalid-images-config.md +++ b/errors/invalid-images-config.md @@ -17,6 +17,8 @@ module.exports = { imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], // limit of 50 domains values domains: [], + // limit of 50 objects + remotePatterns: [], // path prefix for Image Optimization API, useful with `loader` path: '/_next/image', // loader can be 'default', 'imgix', 'cloudinary', 'akamai', or 'custom' diff --git a/errors/no-cache.md b/errors/no-cache.md index b3b0214ca31f..3ef035538512 100644 --- a/errors/no-cache.md +++ b/errors/no-cache.md @@ -78,7 +78,7 @@ cache: Using GitHub's [actions/cache](https://github.com/actions/cache), add the following step in your workflow file: ```yaml -uses: actions/cache@v2 +uses: actions/cache@v3 with: # See here for caching with `yarn` https://github.com/actions/cache/blob/main/examples.md#node---yarn or you can leverage caching with actions/setup-node https://github.com/actions/setup-node path: | diff --git a/examples/cms-buttercms/.env.local.example b/examples/cms-buttercms/.env.local.example index ea6dea901406..07198f69da10 100644 --- a/examples/cms-buttercms/.env.local.example +++ b/examples/cms-buttercms/.env.local.example @@ -1,3 +1 @@ -# Copy this file as .env.local -BUTTERCMS_API_KEY= -BUTTERCMS_PREVIEW_SECRET= \ No newline at end of file +NEXT_PUBLIC_BUTTER_CMS_API_KEY=your_auth_token \ No newline at end of file diff --git a/examples/cms-buttercms/README.md b/examples/cms-buttercms/README.md index bf57965882e9..8e1ed65bdd2d 100644 --- a/examples/cms-buttercms/README.md +++ b/examples/cms-buttercms/README.md @@ -1,16 +1,20 @@ -# A statically generated blog example using Next.js and ButterCMS +# A fully-functional, drop-in proof-of-concept Next.js app using ButterCMS + +This Next.js starter project fully integrates with dynamic sample content from your ButterCMS account, including main menu, pages, blog posts, categories, and tags, all with a beautiful, custom theme with already-implemented search functionality. All of the included sample content is automatically created in your account dashboard when you sign up for a free trial of ButterCMS. + +A copy of this starter project can be easily and quickly deployed to Vercel with the click of a button. This example showcases Next.js's [Static Generation](https://nextjs.org/docs/basic-features/pages) feature using [ButterCMS](https://buttercms.com/) as the data source. ## Demo -[https://next-blog-buttercms.vercel.app/](https://next-blog-buttercms.vercel.app/) +Check out our live demo: [https://nextjs-starter-buttercms.vercel.app/](https://nextjs-starter-buttercms.vercel.app/) ## Deploy your own -Once you have access to [the environment variables you'll need](#step-2-set-up-environment-variables), deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): +Once you have access to your Butter API token, you can deploy your Butterized proof-of-concept app to Vercel, the creators of Next.js, and spread your love of Butter. By clicking the button below, you'll create a copy of our starter project in your Git provider account, instantly deploy it, and institute a full content workflow connected to your ButterCMS account. Smooth. -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/cms-buttercms&project-name=cms-buttercms&repository-name=cms-buttercms&env=BUTTERCMS_API_KEY,BUTTERCMS_PREVIEW_SECRET&envDescription=Required%20to%20connect%20the%20app%20with%20ButterCMS&envLink=https://vercel.link/buttercms-env) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FButterCMS%2Fnextjs-starter-buttercms&env=NEXT_PUBLIC_BUTTER_CMS_API_KEY&envDescription=Your%20ButterCMS%20API%20Token&envLink=https%3A%2F%2Fbuttercms.com%2Fsettings%2F&project-name=nextjs-starter-buttercms&repo-name=nextjs-starter-buttercms&redirect-url=https%3A%2F%2Fbuttercms.com%2Fonboarding%2Fvercel-starter-deploy-callback%2F&production-deploy-hook=Deploy%20Triggered%20from%20ButterCMS&demo-title=ButterCMS%20Next.js%20Starter&demo-description=Fully%20integrated%20with%20your%20ButterCMS%20account&demo-url=https%3A%2F%2Fnextjs-starter-buttercms.vercel.app%2F&demo-image=https://cdn.buttercms.com/r0tGK8xFRti2iRKBJ0eY&repository-name=nextjs-starter-buttercms) ### Related examples @@ -33,6 +37,18 @@ Once you have access to [the environment variables you'll need](#step-2-set-up-e ## How to use +### Option 1. Install via Github and NPM or Yarn + +First, install the dependencies by cloning the repo and running one of the following commands, depending on your current setup: + +```bash +git clone https://github.com/ButterCMS/nextjs-starter-buttercms.git +cd nextjs-starter-buttercms +npm install # or yarn install +``` + +### Option 2. Install via Create-Next-App + Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: ```bash @@ -49,7 +65,7 @@ pnpm create next-app -- --example cms-buttercms cms-buttercms-app First, [create an account on ButterCMS](https://buttercms.com/). -After signing up, you’ll be presented with the API key. We’ll use this in the next step. +After signing up, you’ll be presented with your free API token. We’ll use this in the next step. ### Step 2. Set up environment variables @@ -61,12 +77,12 @@ cp .env.local.example .env.local Then set each variable on `.env.local`: -- `BUTTERCMS_API_KEY` should be set as the API key. -- `BUTTERCMS_PREVIEW_SECRET` can be any random string (but avoid spaces), like `MY_SECRET` - this is used for [Preview Mode](https://nextjs.org/docs/advanced-features/preview-mode). +- `NEXT_PUBLIC_BUTTER_CMS_API_KEY` should be set as the API key. ### Step 3. Run Next.js in development mode -When you sign up to ButterCMS, it creates an example blog post automatically. You can run Next.js in development mode to view a blog containing this example post. +When you sign up for ButterCMS, it creates all of the example content used by this starter project. You can run Next.js in development mode to view your fully-functional starter project, including landing page with +API-based components, API-based menu, and a blog. ```bash npm install @@ -78,44 +94,39 @@ yarn install yarn dev ``` -Your blog should be up and running on [http://localhost:3000](http://localhost:3000)! If it doesn't work, post on [GitHub discussions](https://github.com/vercel/next.js/discussions). +Your starter project should be up and running on [http://localhost:3000](http://localhost:3000)! If it doesn't work, post on [GitHub discussions](https://github.com/vercel/next.js/discussions). ### Step 4. Try preview mode +Your starter project is automatically configured to show draft changes saved in your Butter account when run locally or deploy to a hosting provider. To disable this behavior, set the following value in your `.env.local` file: `PREVIEW=false`. + To try preview mode, [create a blog post](https://buttercms.com/post/): - Set the **Title** as `Draft Post Test`. - Fill the content and summary with dummy text. -- Set the **Featured Image** by downloading some image from [Unsplash](https://unsplash.com/). Most importantly, **do not publish** the blog post. Instead, click **Save Draft**. -Now, if you go to the post page on localhost, you won't see this post because it’s not published. However, if you use the **Preview Mode**, you'll be able to see the change ([Documentation](https://nextjs.org/docs/advanced-features/preview-mode)). - -To enable the Preview Mode, go to this URL: - -``` -http://localhost:3000/api/preview?secret=&slug=draft-post-test -``` - -- `` should be the string you entered for `BUTTERCMS_PREVIEW_SECRET`. +If you have not already, set `PREVIEW=false` in your `.env.local` file and restart your local +development server. -You should now be able to see the draft post. To exit the preview mode, you can click **Click here to exit preview mode** at the top. +Now, if you go to the your blog list view page on localhost: [http://localhost:3000/#blog](http://localhost:3000/#blog), you won't see this post, as its status has not yet been updated to `published`. However, if you use **Preview Mode** by deleting `PREVIEW=false` from your `.env.local` file, your new post will appear ([Documentation](https://nextjs.org/docs/advanced-features/preview-mode)). -**Tip**: [You can set the preview URL on ButterCMS](https://buttercms.com/kb/preview-urls). +**Tip**: [You can set a preview URL on ButterCMS](https://buttercms.com/kb/preview-urls) for pages +deployed to Vercel, allowing you to live-preview changes on the web from within your Butter account! Sweet! ### Step 5. Deploy on Vercel You can deploy this app to the cloud with [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). -#### Deploy Your Local Project +#### Deploy from our template -To deploy your local project to Vercel, push it to GitHub/GitLab/Bitbucket and [import to Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example). +If you want to deploy a copy of our starter to Vercel without any changes, you can just click this button: -**Important**: When you import your project on Vercel, make sure to click on **Environment Variables** and set them to match your `.env.local` file. +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FButterCMS%2Fnextjs-starter-buttercms&env=NEXT_PUBLIC_BUTTER_CMS_API_KEY&envDescription=Your%20ButterCMS%20API%20Token&envLink=https%3A%2F%2Fbuttercms.com%2Fsettings%2F&project-name=nextjs-starter-buttercms&repo-name=nextjs-starter-buttercms&redirect-url=https%3A%2F%2Fbuttercms.com%2Fonboarding%2Fvercel-starter-deploy-callback%2F&production-deploy-hook=Deploy%20Triggered%20from%20ButterCMS&demo-title=ButterCMS%20Next.js%20Starter&demo-description=Fully%20integrated%20with%20your%20ButterCMS%20account&demo-url=https%3A%2F%2Fnextjs-starter-buttercms.vercel.app%2F&demo-image=https://cdn.buttercms.com/r0tGK8xFRti2iRKBJ0eY&repository-name=nextjs-starter-buttercms) -#### Deploy from Our Template +#### Deploy your local project -Alternatively, you can deploy using our template by clicking on the Deploy button below. +To deploy your local project to Vercel (one in which you've made changes), push it to GitHub/GitLab/Bitbucket and [import to Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example). -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/cms-buttercms&project-name=cms-buttercms&repository-name=cms-buttercms&env=BUTTERCMS_API_KEY,BUTTERCMS_PREVIEW_SECRET&envDescription=Required%20to%20connect%20the%20app%20with%20ButterCMS&envLink=https://vercel.link/buttercms-env) +**Important**: When you import your project on Vercel, make sure to click on **Environment Variables** and set them to match your `.env.local` file. diff --git a/examples/cms-buttercms/app.json b/examples/cms-buttercms/app.json new file mode 100644 index 000000000000..4d4c60d77be7 --- /dev/null +++ b/examples/cms-buttercms/app.json @@ -0,0 +1,18 @@ +{ + "name": "ButterCMS NextJS Starter Project ", + "description": "Drop-in proof-of-concept NextJs app, fully integrated with your ButterCMS account.", + "repository": "https://github.com/ButterCMS/nextjs-starter-buttercms", + "logo": "https://cdn.buttercms.com/R3fbtvoRT2CqEQSmk8hb", + "keywords": ["Next.js", "buttercms", "cms", "blog"], + "buildpacks": [ + { + "url": "heroku/nodejs" + } + ], + "env": { + "NEXT_PUBLIC_BUTTER_CMS_API_KEY": { + "description": "The API token of your ButterCMS account", + "value": "" + } + } +} diff --git a/examples/cms-buttercms/components/alert.js b/examples/cms-buttercms/components/alert.js deleted file mode 100644 index 051f3319649e..000000000000 --- a/examples/cms-buttercms/components/alert.js +++ /dev/null @@ -1,42 +0,0 @@ -import Container from './container' -import cn from 'classnames' -import { EXAMPLE_PATH } from '@/lib/constants' - -export default function Alert({ preview }) { - return ( -
- -
- {preview ? ( - <> - This is page is a preview.{' '} - - Click here - {' '} - to exit preview mode. - - ) : ( - <> - The source code for this blog is{' '} - - available on GitHub - - . - - )} -
-
-
- ) -} diff --git a/examples/cms-buttercms/components/author-card.js b/examples/cms-buttercms/components/author-card.js new file mode 100644 index 000000000000..da25b5e222d6 --- /dev/null +++ b/examples/cms-buttercms/components/author-card.js @@ -0,0 +1,7 @@ +export default function AuthorCard({ author }) { + return ( + + {author.first_name} {author.last_name} + + ) +} diff --git a/examples/cms-buttercms/components/avatar.js b/examples/cms-buttercms/components/avatar.js deleted file mode 100644 index 6777f5031359..000000000000 --- a/examples/cms-buttercms/components/avatar.js +++ /dev/null @@ -1,17 +0,0 @@ -import Image from 'next/image' - -export default function Avatar({ name, picture }) { - return ( -
-
- {name} -
-
{name}
-
- ) -} diff --git a/examples/cms-buttercms/components/blog/blog.js b/examples/cms-buttercms/components/blog/blog.js new file mode 100644 index 000000000000..3f2706685192 --- /dev/null +++ b/examples/cms-buttercms/components/blog/blog.js @@ -0,0 +1,42 @@ +import Link from 'next/link' + +import PostPreviewCondensed from './post-preview-condensed' + +export default function Blog({ posts }) { + return ( +
+
+
+
+
+

Latest Blog Posts

+

+ Butter also has a built in blog engine which makes it dead + simple to launch a new company blog. +

+

+ + View All Blog Posts + +

+
+
+
+
+ {posts.map((post) => ( + + ))} +
+
+
+ ) +} diff --git a/examples/cms-buttercms/components/blog/categories-widget.js b/examples/cms-buttercms/components/blog/categories-widget.js new file mode 100644 index 000000000000..4b409eebc9b1 --- /dev/null +++ b/examples/cms-buttercms/components/blog/categories-widget.js @@ -0,0 +1,18 @@ +import Link from 'next/link' + +export default function CategoriesWidget({ categories }) { + return ( +
+
Categories
+ +
+ ) +} diff --git a/examples/cms-buttercms/components/blog/post-preview-condensed.js b/examples/cms-buttercms/components/blog/post-preview-condensed.js new file mode 100644 index 000000000000..a788c7df6f3b --- /dev/null +++ b/examples/cms-buttercms/components/blog/post-preview-condensed.js @@ -0,0 +1,40 @@ +import Link from 'next/link' +import Image from 'next/image' + +export default function PostPreviewCondensed({ + title, + coverImage, + coverImageAlt, + excerpt, + slug, +}) { + return ( +
+
+ {coverImage && ( +
+ {coverImageAlt} +
+ )} +
+
+ + {title} + +
+

{excerpt}

+
+
+ + Read More + +
+
+
+ ) +} diff --git a/examples/cms-buttercms/components/blog/post-preview.js b/examples/cms-buttercms/components/blog/post-preview.js new file mode 100644 index 000000000000..24cd6e9d9143 --- /dev/null +++ b/examples/cms-buttercms/components/blog/post-preview.js @@ -0,0 +1,67 @@ +import Image from 'next/image' +import Link from 'next/link' + +import HumanDate from '@/components/human-date' +import AuthorCard from '@/components/author-card' + +export default function PostsPreview({ + title, + coverImage, + coverImageAlt, + date, + author, + tags, + excerpt, + slug, +}) { + return ( +
+
+
+

+ + {title} + +

+ +
+ {coverImage && ( +
+ {coverImageAlt} +
+ )} +
+
+ + Read More + +
+
+
+ ) +} diff --git a/examples/cms-buttercms/components/blog/posts-list.js b/examples/cms-buttercms/components/blog/posts-list.js new file mode 100644 index 000000000000..59a8245ba31e --- /dev/null +++ b/examples/cms-buttercms/components/blog/posts-list.js @@ -0,0 +1,24 @@ +import PostsPreview from './post-preview' + +export default function PostsList({ posts }) { + return ( +
+
+ {posts.map((post) => ( + + ))} + {!posts.length &&
No blog posts found.
} +
+
+ ) +} diff --git a/examples/cms-buttercms/components/blog/search-widget.js b/examples/cms-buttercms/components/blog/search-widget.js new file mode 100644 index 000000000000..da498214b278 --- /dev/null +++ b/examples/cms-buttercms/components/blog/search-widget.js @@ -0,0 +1,15 @@ +export default function SearchWidget() { + return ( +
+
+
Search This Site
+
+ + +
+
+
+ ) +} diff --git a/examples/cms-buttercms/components/container.js b/examples/cms-buttercms/components/container.js deleted file mode 100644 index fc1c29dfb074..000000000000 --- a/examples/cms-buttercms/components/container.js +++ /dev/null @@ -1,3 +0,0 @@ -export default function Container({ children }) { - return
{children}
-} diff --git a/examples/cms-buttercms/components/cover-image.js b/examples/cms-buttercms/components/cover-image.js deleted file mode 100644 index 0acaa9c23b99..000000000000 --- a/examples/cms-buttercms/components/cover-image.js +++ /dev/null @@ -1,29 +0,0 @@ -import Image from 'next/image' -import Link from 'next/link' -import cn from 'classnames' - -export default function CoverImage({ title, url, slug }) { - const image = ( - {`Cover - ) - - return ( -
- {slug ? ( - - {image} - - ) : ( - image - )} -
- ) -} diff --git a/examples/cms-buttercms/components/date.js b/examples/cms-buttercms/components/date.js deleted file mode 100644 index eac5681378bf..000000000000 --- a/examples/cms-buttercms/components/date.js +++ /dev/null @@ -1,6 +0,0 @@ -import { parseISO, format } from 'date-fns' - -export default function Date({ dateString }) { - const date = parseISO(dateString) - return -} diff --git a/examples/cms-buttercms/components/footer-section.js b/examples/cms-buttercms/components/footer-section.js new file mode 100644 index 000000000000..e421538f0b6a --- /dev/null +++ b/examples/cms-buttercms/components/footer-section.js @@ -0,0 +1,78 @@ +import Image from 'next/image' + +export default function FooterSection({ mainMenu }) { + const links = mainMenu.map((link) => ({ + ...link, + url: link.url[0] === '#' ? `/${link.url}` : link.url, + })) + + return ( +
+
+
+
+
+
+ + logo + +
+

+ ButterCMS is your content backend. Build better with Butter. +

+ +
+
+
+
+

About Us

+ +
+
+ +
+
+

Subscribe Newsletter

+
+ + +
+
+
+
+
+
+ ) +} diff --git a/examples/cms-buttercms/components/footer.js b/examples/cms-buttercms/components/footer.js deleted file mode 100644 index b305c3eb40b0..000000000000 --- a/examples/cms-buttercms/components/footer.js +++ /dev/null @@ -1,30 +0,0 @@ -import Container from './container' -import { EXAMPLE_PATH } from '@/lib/constants' - -export default function Footer() { - return ( - - ) -} diff --git a/examples/cms-buttercms/components/header-section.js b/examples/cms-buttercms/components/header-section.js new file mode 100644 index 000000000000..1a88a8b4e142 --- /dev/null +++ b/examples/cms-buttercms/components/header-section.js @@ -0,0 +1,51 @@ +import { useEffect, useState, useRef } from 'react' + +import Image from 'next/image' + +import MainMenu from './main-menu/main-menu' + +export default function HeaderSection({ mainMenu }) { + const [isNavbarSticky, setIsNavbarSticky] = useState(false) + const navbarAreaEl = useRef(null) + + function fixNavBar() { + if (navbarAreaEl.current) { + setIsNavbarSticky(window.pageYOffset > navbarAreaEl.current.offsetTop) + } + } + + useEffect(() => { + window.addEventListener('scroll', fixNavBar) + + return () => { + window.removeEventListener('scroll', fixNavBar) + } + }, []) + + return ( +
+
+
+
+
+ +
+
+
+
+
+ ) +} diff --git a/examples/cms-buttercms/components/header.js b/examples/cms-buttercms/components/header.js deleted file mode 100644 index 562e7e3eebb6..000000000000 --- a/examples/cms-buttercms/components/header.js +++ /dev/null @@ -1,12 +0,0 @@ -import Link from 'next/link' - -export default function Header() { - return ( -

- - Blog - - . -

- ) -} diff --git a/examples/cms-buttercms/components/hero-post.js b/examples/cms-buttercms/components/hero-post.js deleted file mode 100644 index f45ed8853b12..000000000000 --- a/examples/cms-buttercms/components/hero-post.js +++ /dev/null @@ -1,40 +0,0 @@ -import Avatar from './avatar' -import Date from './date' -import CoverImage from './cover-image' -import Link from 'next/link' - -export default function HeroPost({ - title, - coverImage, - date, - excerpt, - author, - slug, -}) { - return ( -
-
- -
-
-
-

- - {title} - -

-
- -
-
-
-

{excerpt}

- -
-
-
- ) -} diff --git a/examples/cms-buttercms/components/human-date.js b/examples/cms-buttercms/components/human-date.js new file mode 100644 index 000000000000..59a52989ad3d --- /dev/null +++ b/examples/cms-buttercms/components/human-date.js @@ -0,0 +1,6 @@ +import { parseISO, format } from 'date-fns' + +export default function HumanDate({ dateString }) { + const date = parseISO(dateString) + return +} diff --git a/examples/cms-buttercms/components/intro.js b/examples/cms-buttercms/components/intro.js deleted file mode 100644 index c3003c619664..000000000000 --- a/examples/cms-buttercms/components/intro.js +++ /dev/null @@ -1,28 +0,0 @@ -import { CMS_NAME, CMS_URL } from '@/lib/constants' - -export default function Intro() { - return ( -
-

- Blog. -

-

- A statically generated blog example using{' '} - - Next.js - {' '} - and{' '} - - {CMS_NAME} - - . -

-
- ) -} diff --git a/examples/cms-buttercms/components/landing-page-sections/feature.js b/examples/cms-buttercms/components/landing-page-sections/feature.js new file mode 100644 index 000000000000..68ce10e56d13 --- /dev/null +++ b/examples/cms-buttercms/components/landing-page-sections/feature.js @@ -0,0 +1,17 @@ +import Image from 'next/image' + +export default function Feature({ headline, description, icon }) { + return ( +
+
+
+ {icon && } +
+
+

{headline}

+

{description}

+
+
+
+ ) +} diff --git a/examples/cms-buttercms/components/landing-page-sections/features.js b/examples/cms-buttercms/components/landing-page-sections/features.js new file mode 100644 index 000000000000..fa70e7f05273 --- /dev/null +++ b/examples/cms-buttercms/components/landing-page-sections/features.js @@ -0,0 +1,36 @@ +import Feature from './feature' + +export default function Features({ + headline, + subheadline, + features, + scrollAnchorId, +}) { + return ( +
+
+
+
+
+

{headline}

+

{subheadline}

+
+
+ +
+
+ {features.map((feature, index) => ( + + ))} +
+
+
+
+
+ ) +} diff --git a/examples/cms-buttercms/components/landing-page-sections/hero.js b/examples/cms-buttercms/components/landing-page-sections/hero.js new file mode 100644 index 000000000000..f9d267be2ee7 --- /dev/null +++ b/examples/cms-buttercms/components/landing-page-sections/hero.js @@ -0,0 +1,43 @@ +import Image from 'next/image' + +export default function Hero({ + headline, + subheadline, + image, + buttonLabel, + buttonUrl, + scrollAnchorId, +}) { + return ( +
+
+
+
+
+

{headline}

+

{subheadline}

+ + + {buttonLabel} + + Need an account? +
+
+ {image && ( +
+
+ +
+
+ )} +
+
+
+ ) +} diff --git a/examples/cms-buttercms/components/landing-page-sections/landing-page-section.js b/examples/cms-buttercms/components/landing-page-sections/landing-page-section.js new file mode 100644 index 000000000000..fa9ed572086b --- /dev/null +++ b/examples/cms-buttercms/components/landing-page-sections/landing-page-section.js @@ -0,0 +1,50 @@ +import dynamic from 'next/dynamic' + +import camelcaseKeys from 'camelcase-keys' + +import Preloader from '@/components/preloader' +import MissingSection from './missing-section' + +export default function LandingPageSection({ type, sectionData }) { + const sectionsComponentPaths = () => ({ + hero: dynamic( + () => + import('@/components/landing-page-sections/hero').catch( + () => () => MissingSection + ), + { + loading: Preloader, + } + ), + two_column_with_image: dynamic( + () => + import( + '@/components/landing-page-sections/two-column-with-image' + ).catch(() => () => MissingSection), + { + loading: Preloader, + } + ), + features: dynamic( + () => + import('@/components/landing-page-sections/features').catch( + () => () => MissingSection + ), + { + loading: Preloader, + } + ), + testimonials: dynamic( + () => + import('@/components/landing-page-sections/testimonials').catch( + () => () => MissingSection + ), + { + loading: Preloader, + } + ), + }) + const SectionComponent = sectionsComponentPaths()[type] || MissingSection + + return +} diff --git a/examples/cms-buttercms/components/landing-page-sections/missing-section.js b/examples/cms-buttercms/components/landing-page-sections/missing-section.js new file mode 100644 index 000000000000..0feed8dd83f1 --- /dev/null +++ b/examples/cms-buttercms/components/landing-page-sections/missing-section.js @@ -0,0 +1,10 @@ +export default function MissingSection({ type, ...sectionData }) { + console.log(`Missing section ${type} data ${sectionData}`) + + return ( +
+

Missing a template for {type}

+

Check console for component details

+
+ ) +} diff --git a/examples/cms-buttercms/components/landing-page-sections/testimonial.js b/examples/cms-buttercms/components/landing-page-sections/testimonial.js new file mode 100644 index 000000000000..602551243f5c --- /dev/null +++ b/examples/cms-buttercms/components/landing-page-sections/testimonial.js @@ -0,0 +1,16 @@ +export default function Testimonial({ quote, name, title }) { + return ( +
+
+ +
+
+

{quote}

+
+
+
{name}
+

{title}

+
+
+ ) +} diff --git a/examples/cms-buttercms/components/landing-page-sections/testimonials.js b/examples/cms-buttercms/components/landing-page-sections/testimonials.js new file mode 100644 index 000000000000..fe163ae7cba4 --- /dev/null +++ b/examples/cms-buttercms/components/landing-page-sections/testimonials.js @@ -0,0 +1,57 @@ +import { useEffect } from 'react' + +import { tns } from 'tiny-slider' + +import Testimonial from './testimonial' + +export default function Testimonials({ + headline, + testimonial: testimonials, + scrollAnchorId, +}) { + useEffect(() => { + tns({ + container: '.testimonial-active', + autoplay: true, + autoplayTimeout: 5000, + autoplayButtonOutput: false, + mouseDrag: true, + gutter: 0, + nav: false, + navPosition: 'bottom', + controls: true, + controlsText: [ + '', + '', + ], + items: 1, + }) + }) + + return ( +
+
+
+
+
+
+

{headline}

+
+ +
+ {testimonials.map((testimonial, index) => ( + + ))} +
+
+
+
+
+
+ ) +} diff --git a/examples/cms-buttercms/components/landing-page-sections/two-column-with-image.js b/examples/cms-buttercms/components/landing-page-sections/two-column-with-image.js new file mode 100644 index 000000000000..87e3a7943551 --- /dev/null +++ b/examples/cms-buttercms/components/landing-page-sections/two-column-with-image.js @@ -0,0 +1,60 @@ +import Image from 'next/image' + +export default function TwoColumnWithImage({ + headline, + subheadline, + buttonLabel, + buttonUrl, + image, + imagePosition, + scrollAnchorId, +}) { + return ( +
+
+
+ {image && imagePosition === 'left' && ( +
+
+ +
+
+ )} +
+
+
+

{headline}

+
+
+ + {buttonLabel} + +
+
+ {image && imagePosition === 'right' && ( +
+
+ +
+
+ )} +
+
+
+ ) +} diff --git a/examples/cms-buttercms/components/layout.js b/examples/cms-buttercms/components/layout.js deleted file mode 100644 index 399802b095aa..000000000000 --- a/examples/cms-buttercms/components/layout.js +++ /dev/null @@ -1,16 +0,0 @@ -import Alert from './alert' -import Footer from './footer' -import Meta from './meta' - -export default function Layout({ preview, children }) { - return ( - <> - -
- -
{children}
-
-