Skip to content

Commit

Permalink
feat(next/swc): enable wasm first binding load for the platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
kwonoj committed Jul 21, 2022
1 parent 8af81b4 commit 7eab5e8
Showing 1 changed file with 66 additions and 30 deletions.
96 changes: 66 additions & 30 deletions packages/next/build/swc/index.js
Expand Up @@ -13,6 +13,20 @@ const ArchName = arch()
const PlatformName = platform()
const triples = platformArchTriples[PlatformName][ArchName] || []

// 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 = [
'aarch64-linux-android',
'x86_64-unknown-freebsd',
'aarch64-pc-windows-msvc',
'arm-linux-androideabi',
'armv7-unknown-linux-gnueabihf',
'i686-pc-windows-msvc',
]

let nativeBindings
let wasmBindings
let downloadWasmPromise
Expand All @@ -35,51 +49,73 @@ export async function loadBindings() {
}

let attempts = []
try {
return resolve(loadNative())
} catch (a) {
attempts = attempts.concat(a)
const shouldLoadWasmFallbackFirst = triples.some(
(triple) =>
!!triple?.raw && knownDefaultWasmFallbackTriples.includes(triple.raw)
)

if (shouldLoadWasmFallbackFirst) {
const fallbackBindings = await tryLoadWasmWithFallback(attempts)
if (fallbackBindings) {
return resolve(fallbackBindings)
}
}

try {
let bindings = await loadWasm()
eventSwcLoadFailure({ wasm: 'enabled' })
return resolve(bindings)
return resolve(loadNative())
} catch (a) {
attempts = attempts.concat(a)
}

try {
// if not installed already download wasm package on-demand
// we download to a custom directory instead of to node_modules
// as node_module import attempts are cached and can't be re-attempted
// x-ref: https://github.com/nodejs/modules/issues/307
const wasmDirectory = path.join(
path.dirname(require.resolve('next/package.json')),
'wasm'
)
if (!downloadWasmPromise) {
downloadWasmPromise = downloadWasmSwc(nextVersion, wasmDirectory)
}
await downloadWasmPromise
let bindings = await loadWasm(pathToFileURL(wasmDirectory).href)
eventSwcLoadFailure({ wasm: 'fallback' })

// still log native load attempts so user is
// aware it failed and should be fixed
for (const attempt of attempts) {
Log.warn(attempt)
// For these platforms we already tried to load wasm and failed, skip reattempt
if (!shouldLoadWasmFallbackFirst) {
const fallbackBindings = await tryLoadWasmWithFallback(attempts)
if (fallbackBindings) {
return resolve(fallbackBindings)
}
return resolve(bindings)
} catch (a) {
attempts = attempts.concat(a)
}

logLoadFailure(attempts, true)
})
return pendingBindings
}

async function tryLoadWasmWithFallback(attempts) {
try {
let bindings = await loadWasm()
eventSwcLoadFailure({ wasm: 'enabled' })
return bindings
} catch (a) {
attempts = attempts.concat(a)
}

try {
// if not installed already download wasm package on-demand
// we download to a custom directory instead of to node_modules
// as node_module import attempts are cached and can't be re-attempted
// x-ref: https://github.com/nodejs/modules/issues/307
const wasmDirectory = path.join(
path.dirname(require.resolve('next/package.json')),
'wasm'
)
if (!downloadWasmPromise) {
downloadWasmPromise = downloadWasmSwc(nextVersion, wasmDirectory)
}
await downloadWasmPromise
let bindings = await loadWasm(pathToFileURL(wasmDirectory).href)
eventSwcLoadFailure({ wasm: 'fallback' })

// still log native load attempts so user is
// aware it failed and should be fixed
for (const attempt of attempts) {
Log.warn(attempt)
}
return bindings
} catch (a) {
attempts = attempts.concat(a)
}
}

function loadBindingsSync() {
let attempts = []
try {
Expand Down

0 comments on commit 7eab5e8

Please sign in to comment.