From f412c8a9918143850b21fc16322e7113e2f0bfaa Mon Sep 17 00:00:00 2001 From: Maia Teegarden Date: Wed, 25 Oct 2023 19:29:07 -0700 Subject: [PATCH] Remove wasm target (#57437) This PR removes the wasm target for the next-swc build for the next major version. The main motivation is that Turbopack does not support targeting wasm yet, and it would be a significant amount of work to add. We plan to make Turbopack the default zero-config experience in a minor version, possibly before we are able to support a wasm target, so we need to make this breaking change now. We also plan to make more improvements to the webpack experience with shared Rust code, which we have so far been blocked from implementing because of the current wasm restrictions. We would like to support a wasm target again in the future, but cannot say at this time when that would be. Closes WEB-1865 --- .github/workflows/build_and_deploy.yml | 58 --------------------- .github/workflows/build_and_test.yml | 17 +++--- contributing/core/building.md | 2 - docs/04-architecture/nextjs-compiler.mdx | 1 - packages/next/src/build/swc/index.ts | 66 +++--------------------- 5 files changed, 14 insertions(+), 130 deletions(-) diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml index 599ba653c36c1..0ffbf16bc2d6a 100644 --- a/.github/workflows/build_and_deploy.yml +++ b/.github/workflows/build_and_deploy.yml @@ -340,65 +340,12 @@ jobs: name: turbo run summary path: .turbo/runs - build-wasm: - strategy: - matrix: - target: [web, nodejs] - - runs-on: - - 'self-hosted' - - 'linux' - - 'x64' - - 'metal' - - steps: - - uses: actions/checkout@v3 - - - name: Setup node - uses: actions/setup-node@v3 - with: - node-version: ${{ env.NODE_LTS_VERSION }} - check-latest: true - - run: corepack enable - - - name: Install Rust - uses: ./.github/actions/setup-rust - with: - targets: wasm32-unknown-unknown - - - run: npm i -g turbo@${{ env.TURBO_VERSION }} - - - name: Install wasm-pack - run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - - - name: normalize versions - run: node scripts/normalize-version-bump.js - - - name: Build - run: turbo run build-wasm -vvv --remote-cache-timeout 90 --summarize -- --target ${{ matrix.target }} --features tracing/release_max_level_info - - - name: Add target to folder name - 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 turbo summary artifact - uses: actions/upload-artifact@v3 - with: - name: turbo run summary - path: .turbo/runs - - - name: Upload swc artifact - uses: actions/upload-artifact@v3 - with: - name: wasm-binaries - path: packages/next-swc/crates/wasm/pkg-* - publishRelease: if: ${{ needs.build.outputs.isRelease == 'true' }} name: Potentially publish release runs-on: ubuntu-latest needs: - build - - build-wasm - build-native permissions: contents: write @@ -429,11 +376,6 @@ jobs: name: next-swc-binaries path: packages/next-swc/native - - uses: actions/download-artifact@v3 - with: - name: wasm-binaries - path: packages/next-swc/crates/wasm - - run: npm i -g npm@9.6.7 # need latest version for provenance (pinning to avoid bugs) - run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc - run: ./scripts/publish-native.js diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index bbf278fd673f6..059ed7160216d 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -151,14 +151,14 @@ jobs: afterBuild: RUST_BACKTRACE=0 NEXT_EXTERNAL_TESTS_FILTERS="$(pwd)/test/turbopack-tests-manifest.json" TURBOPACK=1 node run-tests.js --timings -g ${{ matrix.group }}/5 -c ${TEST_CONCURRENCY} --type integration secrets: inherit - test-next-swc-wasm: - name: test next-swc wasm - needs: ['build-native', 'build-next'] - uses: ./.github/workflows/build_reusable.yml - with: - skipForDocsOnly: 'yes' - afterBuild: rustup target add wasm32-unknown-unknown && curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh && node ./scripts/normalize-version-bump.js && turbo run build-wasm -- --target nodejs --features tracing/release_max_level_info && git checkout . && mv packages/next-swc/crates/wasm/pkg packages/next-swc/crates/wasm/pkg-nodejs && node ./scripts/setup-wasm.mjs && NEXT_TEST_MODE=start TEST_WASM=true node run-tests.js test/production/pages-dir/production/test/index.test.ts test/e2e/streaming-ssr/index.test.ts - secrets: inherit + # test-next-swc-wasm: + # name: test next-swc wasm + # needs: ['build-native', 'build-next'] + # uses: ./.github/workflows/build_reusable.yml + # with: + # skipForDocsOnly: 'yes' + # afterBuild: rustup target add wasm32-unknown-unknown && curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh && node ./scripts/normalize-version-bump.js && turbo run build-wasm -- --target nodejs --features tracing/release_max_level_info && git checkout . && mv packages/next-swc/crates/wasm/pkg packages/next-swc/crates/wasm/pkg-nodejs && node ./scripts/setup-wasm.mjs && NEXT_TEST_MODE=start TEST_WASM=true node run-tests.js test/production/pages-dir/production/test/index.test.ts test/e2e/streaming-ssr/index.test.ts + # secrets: inherit test-unit: name: test unit @@ -258,7 +258,6 @@ jobs: 'test-cargo-integration', 'test-cargo-bench', 'rust-check', - 'test-next-swc-wasm', 'test-turbopack-dev', 'test-turbopack-integration', ] diff --git a/contributing/core/building.md b/contributing/core/building.md index bce370380cbc8..1fe88f8c6b8f8 100644 --- a/contributing/core/building.md +++ b/contributing/core/building.md @@ -8,6 +8,4 @@ pnpm build By default, the latest canary of the `next-swc` binaries will be installed and used. If you are actively working on Rust code or you need to test out the most recent Rust code that hasn't been published as a canary yet, you can [install Rust](https://www.rust-lang.org/tools/install) and run `pnpm --filter=@next/swc build-native`. -If you want to test out the wasm build locally, you will need to [install wasm-pack](https://rustwasm.github.io/wasm-pack/installer/). Run `pnpm --filter=@next/swc build-wasm --target ` to build and `node ./scripts/setup-wasm.mjs` to copy it into your `node_modules`. Run next with `NODE_OPTIONS='--no-addons'` to force it to use the wasm binary. - If you need to clean the project for any reason, use `pnpm clean`. diff --git a/docs/04-architecture/nextjs-compiler.mdx b/docs/04-architecture/nextjs-compiler.mdx index ceb891c95b260..1ba6663c08f49 100644 --- a/docs/04-architecture/nextjs-compiler.mdx +++ b/docs/04-architecture/nextjs-compiler.mdx @@ -17,7 +17,6 @@ We chose to build on SWC for a few reasons: - **Extensibility:** SWC can be used as a Crate inside Next.js, without having to fork the library or workaround design constraints. - **Performance:** We were able to achieve ~3x faster Fast Refresh and ~5x faster builds in Next.js by switching to SWC, with more room for optimization still in progress. -- **WebAssembly:** Rust's support for WASM is essential for supporting all possible platforms and taking Next.js development everywhere. - **Community:** The Rust community and ecosystem are amazing and still growing. ## Supported Features diff --git a/packages/next/src/build/swc/index.ts b/packages/next/src/build/swc/index.ts index 543895eee6670..c723b57b48fac 100644 --- a/packages/next/src/build/swc/index.ts +++ b/packages/next/src/build/swc/index.ts @@ -31,7 +31,7 @@ const infoLog = (...args: any[]) => { * Based on napi-rs's target triples, returns triples that have corresponding next-swc binaries. */ export const getSupportedArchTriples: () => Record = () => { - const { darwin, win32, linux, freebsd, android } = platformArchTriples + const { darwin, win32, linux } = platformArchTriples return { darwin, @@ -48,16 +48,6 @@ export const getSupportedArchTriples: () => Record = () => { (triple: { abi: string }) => triple.abi !== 'gnux32' ), arm64: linux.arm64, - // This target is being deprecated, however we keep it in `knownDefaultWasmFallbackTriples` for now - arm: linux.arm, - }, - // Below targets are being deprecated, however we keep it in `knownDefaultWasmFallbackTriples` for now - freebsd: { - x64: freebsd.x64, - }, - android: { - arm64: android.arm64, - arm: android.arm, }, } } @@ -77,7 +67,7 @@ const triples = (() => { if (rawTargetTriple) { Log.warn( - `Trying to load next-swc for target triple ${rawTargetTriple}, but there next-swc does not have native bindings support` + `Trying to load next-swc for target triple ${rawTargetTriple}, but this target is not supported` ) } else { Log.warn( @@ -107,21 +97,6 @@ function checkVersionMismatch(pkgData: any) { } } -// These are the platforms we'll try to load wasm bindings first, -// only try to load native bindings if loading wasm binding somehow fails. -// Fallback to native binding is for migration period only, -// once we can verify loading-wasm-first won't cause visible regressions, -// we'll not include native bindings for these platform at all. -const knownDefaultWasmFallbackTriples = [ - 'x86_64-unknown-freebsd', - 'aarch64-linux-android', - 'arm-linux-androideabi', - 'armv7-unknown-linux-gnueabihf', - 'i686-pc-windows-msvc', - // WOA targets are TBD, while current userbase is small we may support it in the future - //'aarch64-pc-windows-msvc', -] - // The last attempt's error code returned when cjs require to native bindings fails. // If node.js throws an error without error code, this should be `unknown` instead of undefined. // For the wasm-first targets (`knownDefaultWasmFallbackTriples`) this will be `unsupported_target`. @@ -201,21 +176,6 @@ export async function loadBindings(): Promise { } let attempts: any[] = [] - const disableWasmFallback = process.env.NEXT_DISABLE_SWC_WASM - const shouldLoadWasmFallbackFirst = - !disableWasmFallback && - triples.some( - (triple: any) => - !!triple?.raw && knownDefaultWasmFallbackTriples.includes(triple.raw) - ) - - if (shouldLoadWasmFallbackFirst) { - lastNativeBindingsLoadErrorCode = 'unsupported_target' - const fallbackBindings = await tryLoadWasmWithFallback(attempts) - if (fallbackBindings) { - return resolve(fallbackBindings) - } - } // Trickle down loading `fallback` bindings: // @@ -224,7 +184,6 @@ export async function loadBindings(): Promise { // that host system where generated package lock is not matching to the guest system running on, try to manually // download corresponding target triple and load it. This won't be triggered if native bindings are failed to load // with other reasons than `ERR_MODULE_NOT_FOUND`. - // - Lastly, falls back to wasm binding where possible. try { return resolve(loadNative()) } catch (a) { @@ -242,15 +201,7 @@ export async function loadBindings(): Promise { attempts = attempts.concat(a) } - // For these platforms we already tried to load wasm and failed, skip reattempt - if (!shouldLoadWasmFallbackFirst && !disableWasmFallback) { - const fallbackBindings = await tryLoadWasmWithFallback(attempts) - if (fallbackBindings) { - return resolve(fallbackBindings) - } - } - - logLoadFailure(attempts, true) + logLoadFailure(attempts) }) return pendingBindings } @@ -279,6 +230,8 @@ async function tryLoadNativeWithFallback(attempts: Array) { return undefined } +// We may end up using this function in the future if/when we support wasm builds again +// eslint-disable-next-line @typescript-eslint/no-unused-vars async function tryLoadWasmWithFallback(attempts: any) { try { let bindings = await loadWasm('') @@ -331,18 +284,12 @@ function loadBindingsSync() { attempts = attempts.concat(a) } - // we can leverage the wasm bindings if they are already - // loaded - if (wasmBindings) { - return wasmBindings - } - logLoadFailure(attempts) } let loggingLoadFailure = false -function logLoadFailure(attempts: any, triedWasm = false) { +function logLoadFailure(attempts: any) { // make sure we only emit the event and log the failure once if (loggingLoadFailure) return loggingLoadFailure = true @@ -353,7 +300,6 @@ function logLoadFailure(attempts: any, triedWasm = false) { // @ts-expect-error TODO: this event has a wrong type. eventSwcLoadFailure({ - wasm: triedWasm ? 'failed' : undefined, nativeBindingsErrorCode: lastNativeBindingsLoadErrorCode, }) .then(() => lockfilePatchPromise.cur || Promise.resolve())