rsnext/packages/next/lib/download-wasm-swc.ts
JJ Kasper 6f698405dd
Update matched path params priority (#37646)
This ensures we use the correct dynamic route params favoring params from the URL/matched-path over route-matches. This also ensures we properly cache `_next/data` requests client side when the page is not a `getServerSideProps` page. 

x-ref: https://github.com/vercel/next.js/pull/37574

## Bug

- [ ] Related issues linked using `fixes #number`
- [x] Integration tests added
- [ ] Errors have helpful link attached, see `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`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The examples guidelines are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples)
2022-06-13 13:34:08 +00:00

122 lines
4 KiB
TypeScript

import os from 'os'
import fs from 'fs'
import path from 'path'
import * as Log from '../build/output/log'
import { execSync } from 'child_process'
import tar from 'next/dist/compiled/tar'
import fetch from 'next/dist/compiled/node-fetch'
import { fileExists } from './file-exists'
const MAX_VERSIONS_TO_CACHE = 5
export async function downloadWasmSwc(
version: string,
wasmDirectory: string,
variant: 'nodejs' | 'web' = 'nodejs'
) {
const pkgName = `@next/swc-wasm-${variant}`
const tarFileName = `${pkgName.substring(6)}-${version}.tgz`
const outputDirectory = path.join(wasmDirectory, pkgName)
if (await fileExists(outputDirectory)) {
// if the package is already downloaded a different
// failure occurred than not being present
return
}
// get platform specific cache directory adapted from playwright's handling
// https://github.com/microsoft/playwright/blob/7d924470d397975a74a19184c136b3573a974e13/packages/playwright-core/src/utils/registry.ts#L141
const cacheDirectory = (() => {
let result
const envDefined = process.env['NEXT_SWC_PATH']
if (envDefined) {
result = envDefined
} else {
let systemCacheDirectory
if (process.platform === 'linux') {
systemCacheDirectory =
process.env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache')
} else if (process.platform === 'darwin') {
systemCacheDirectory = path.join(os.homedir(), 'Library', 'Caches')
} else if (process.platform === 'win32') {
systemCacheDirectory =
process.env.LOCALAPPDATA ||
path.join(os.homedir(), 'AppData', 'Local')
} else {
console.error(new Error('Unsupported platform: ' + process.platform))
process.exit(0)
}
result = path.join(systemCacheDirectory, 'next-swc')
}
if (!path.isAbsolute(result)) {
// It is important to resolve to the absolute path:
// - for unzipping to work correctly;
// - so that registry directory matches between installation and execution.
// INIT_CWD points to the root of `npm/yarn install` and is probably what
// the user meant when typing the relative path.
result = path.resolve(process.env['INIT_CWD'] || process.cwd(), result)
}
return result
})()
await fs.promises.mkdir(outputDirectory, { recursive: true })
const extractFromTar = async () => {
await tar.x({
file: path.join(cacheDirectory, tarFileName),
cwd: outputDirectory,
strip: 1,
})
}
if (!(await fileExists(path.join(cacheDirectory, tarFileName)))) {
Log.info('Downloading WASM swc package...')
await fs.promises.mkdir(cacheDirectory, { recursive: true })
const tempFile = path.join(
cacheDirectory,
`${tarFileName}.temp-${Date.now()}`
)
let registry = `https://registry.npmjs.org/`
try {
const output = execSync('npm config get registry').toString().trim()
if (output.startsWith('http')) {
registry = output
}
} catch (_) {}
await fetch(`${registry}${pkgName}/-/${tarFileName}`).then((res) => {
if (!res.ok) {
throw new Error(`request failed with status ${res.status}`)
}
const cacheWriteStream = fs.createWriteStream(tempFile)
return new Promise<void>((resolve, reject) => {
res.body
.pipe(cacheWriteStream)
.on('error', (err) => reject(err))
.on('finish', () => resolve())
}).finally(() => cacheWriteStream.close())
})
await fs.promises.rename(tempFile, path.join(cacheDirectory, tarFileName))
}
await extractFromTar()
const cacheFiles = await fs.promises.readdir(cacheDirectory)
if (cacheFiles.length > MAX_VERSIONS_TO_CACHE) {
cacheFiles.sort((a, b) => {
if (a.length < b.length) return -1
return a.localeCompare(b)
})
// prune oldest versions in cache
for (let i = 0; i++; i < cacheFiles.length - MAX_VERSIONS_TO_CACHE) {
await fs.promises
.unlink(path.join(cacheDirectory, cacheFiles[i]))
.catch(() => {})
}
}
}