diff --git a/.github/actions/next-stats-action/package.json b/.github/actions/next-stats-action/package.json index 4d2e88dae3e3e6..c4f4c4c1d10233 100644 --- a/.github/actions/next-stats-action/package.json +++ b/.github/actions/next-stats-action/package.json @@ -3,6 +3,7 @@ "main": "src/index.js", "dependencies": { "async-sema": "^3.1.0", + "execa": "2.0.3", "fs-extra": "^8.1.0", "get-port": "^5.0.0", "glob": "^7.1.4", diff --git a/.github/actions/next-stats-action/src/constants.js b/.github/actions/next-stats-action/src/constants.js index 625624a18986d3..2bac325eeea77c 100644 --- a/.github/actions/next-stats-action/src/constants.js +++ b/.github/actions/next-stats-action/src/constants.js @@ -5,8 +5,8 @@ const benchTitle = 'Page Load Tests' const workDir = path.join(os.tmpdir(), 'next-stats') const mainRepoName = 'main-repo' const diffRepoName = 'diff-repo' -const mainRepoDir = path.join(workDir, mainRepoName) -const diffRepoDir = path.join(workDir, diffRepoName) +const mainRepoDir = path.join(os.tmpdir(), mainRepoName) +const diffRepoDir = path.join(os.tmpdir(), diffRepoName) const statsAppDir = path.join(workDir, 'stats-app') const diffingDir = path.join(workDir, 'diff') const yarnEnvValues = { diff --git a/.github/actions/next-stats-action/src/index.js b/.github/actions/next-stats-action/src/index.js index 8e2e9f48610879..23ea3882c5a465 100644 --- a/.github/actions/next-stats-action/src/index.js +++ b/.github/actions/next-stats-action/src/index.js @@ -78,9 +78,7 @@ if (!allowedActions.has(actionInfo.actionName) && !actionInfo.isRelease) { if (actionInfo.isRelease) { logger('Release detected, resetting mainRepo to last stable tag') const lastStableTag = await getLastStable(mainRepoDir, actionInfo.prRef) - mainNextSwcVersion = { - '@next/swc-linux-x64-gnu': lastStableTag, - } + mainNextSwcVersion = lastStableTag if (!lastStableTag) throw new Error('failed to get last stable tag') console.log('using latestStable', lastStableTag) await checkoutRef(lastStableTag, mainRepoDir) @@ -140,7 +138,7 @@ if (!allowedActions.has(actionInfo.actionName) && !actionInfo.isRelease) { const isMainRepo = dir === mainRepoDir const pkgPaths = await linkPackages({ repoDir: dir, - nextSwcPkg: isMainRepo ? mainNextSwcVersion : undefined, + nextSwcVersion: isMainRepo ? mainNextSwcVersion : undefined, }) if (isMainRepo) mainRepoPkgPaths = pkgPaths diff --git a/.github/actions/next-stats-action/src/prepare/repo-setup.js b/.github/actions/next-stats-action/src/prepare/repo-setup.js index f490a48ba3daa1..15f1abf8147252 100644 --- a/.github/actions/next-stats-action/src/prepare/repo-setup.js +++ b/.github/actions/next-stats-action/src/prepare/repo-setup.js @@ -4,11 +4,7 @@ const exec = require('../util/exec') const { remove } = require('fs-extra') const logger = require('../util/logger') const semver = require('semver') - -const mockTrace = () => ({ - traceAsyncFn: (fn) => fn(mockTrace()), - traceChild: () => mockTrace(), -}) +const execa = require('execa') module.exports = (actionInfo) => { return { @@ -58,117 +54,28 @@ module.exports = (actionInfo) => { } } }, - async linkPackages({ repoDir = '', nextSwcPkg, parentSpan }) { - const rootSpan = parentSpan - ? parentSpan.traceChild('linkPackages') - : mockTrace() - - return await rootSpan.traceAsyncFn(async () => { - const pkgPaths = new Map() - const pkgDatas = new Map() - let pkgs - - try { - pkgs = await fs.readdir(path.join(repoDir, 'packages')) - } catch (err) { - if (err.code === 'ENOENT') { - require('console').log('no packages to link') - return pkgPaths - } - throw err - } - - await rootSpan - .traceChild('prepare packages for packing') - .traceAsyncFn(async () => { - for (const pkg of pkgs) { - const pkgPath = path.join(repoDir, 'packages', pkg) - const packedPkgPath = path.join(pkgPath, `${pkg}-packed.tgz`) - - const pkgDataPath = path.join(pkgPath, 'package.json') - if (!fs.existsSync(pkgDataPath)) { - require('console').log(`Skipping ${pkgDataPath}`) - continue - } - const pkgData = require(pkgDataPath) - const { name } = pkgData - pkgDatas.set(name, { - pkgDataPath, - pkg, - pkgPath, - pkgData, - packedPkgPath, - }) - pkgPaths.set(name, packedPkgPath) - } - - for (const pkg of pkgDatas.keys()) { - const { pkgDataPath, pkgData } = pkgDatas.get(pkg) - - for (const pkg of pkgDatas.keys()) { - const { packedPkgPath } = pkgDatas.get(pkg) - if (!pkgData.dependencies || !pkgData.dependencies[pkg]) - continue - pkgData.dependencies[pkg] = packedPkgPath - } - - // make sure native binaries are included in local linking - if (pkg === '@next/swc') { - if (!pkgData.files) { - pkgData.files = [] - } - pkgData.files.push('native') - require('console').log( - 'using swc binaries: ', - await exec( - `ls ${path.join(path.dirname(pkgDataPath), 'native')}` - ) - ) - } - - if (pkg === 'next') { - if (nextSwcPkg) { - Object.assign(pkgData.dependencies, nextSwcPkg) - } else { - if (pkgDatas.get('@next/swc')) { - pkgData.dependencies['@next/swc'] = - pkgDatas.get('@next/swc').packedPkgPath - } else { - pkgData.files.push('native') - } - } - } - - await fs.writeFile( - pkgDataPath, - JSON.stringify(pkgData, null, 2), - 'utf8' - ) - } - }) - - // wait to pack packages until after dependency paths have been updated - // to the correct versions - await rootSpan - .traceChild('packing packages') - .traceAsyncFn(async (packingSpan) => { - await Promise.all( - Array.from(pkgDatas.keys()).map(async (pkgName) => { - await packingSpan - .traceChild(`pack ${pkgName}`) - .traceAsyncFn(async () => { - const { pkg, pkgPath } = pkgDatas.get(pkgName) - await exec( - `cd ${pkgPath} && yarn pack -f '${pkg}-packed.tgz'`, - true - ) - }) - }) - ) - }) + async linkPackages({ repoDir, nextSwcVersion }) { + execa.sync('pnpm', ['turbo', 'run', 'test-pack'], { + cwd: repoDir, + env: { NEXT_SWC_VERSION: nextSwcVersion }, + }) - return pkgPaths + const pkgPaths = new Map() + const pkgs = await fs.readdir(path.join(repoDir, 'packages')) + + pkgs.forEach((pkgDirname) => { + const { name } = require(path.join( + repoDir, + 'packages', + pkgDirname, + 'package.json' + )) + pkgPaths.set( + name, + path.join(repoDir, 'packages', pkgDirname, `packed-${pkgDirname}.tgz`) + ) }) + return pkgPaths }, } } diff --git a/.gitignore b/.gitignore index 6bbbba1173fd1c..d5f0273c3fbc83 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ dist .next target packages/next/wasm/@next +packages/*/packed-*.tgz # dependencies node_modules @@ -29,6 +30,7 @@ test/**/tsconfig.json /e2e-tests test/tmp/** test/.trace +test/traces # Editors **/.idea @@ -49,3 +51,4 @@ test-timings.json # Cache *.tsbuildinfo .swc/ +.turbo diff --git a/package.json b/package.json index 1add35dd218c03..75d042c7c5de84 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "test": "pnpm testheadless", "testonly": "pnpm jest --runInBand", "testheadless": "cross-env HEADLESS=true pnpm testonly", + "test-pack": "TS_NODE_TRANSPILE_ONLY=1 node --loader ts-node/esm scripts/test-pack-package.mts", "genstats": "cross-env LOCAL_STATS=true node .github/actions/next-stats-action/src/index.js", "git-reset": "git reset --hard HEAD", "git-clean": "git clean -d -x -e node_modules -e packages -f", @@ -216,6 +217,7 @@ "tailwindcss": "1.1.3", "taskr": "1.1.0", "tree-kill": "1.2.2", + "ts-node": "10.9.1", "tsec": "0.2.1", "turbo": "1.6.3", "typescript": "4.8.2", diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 19a863a58b6db3..02a479e160e3a2 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -25,7 +25,8 @@ "prerelease": "rimraf ./dist/", "release": "ncc build ./index.ts -o ./dist/ --minify --no-cache --no-source-map-register", "prepublishOnly": "cd ../../ && turbo run build", - "build": "pnpm release" + "build": "pnpm release", + "test-pack": "cd ../../ && pnpm test-pack create-next-app" }, "devDependencies": { "@types/async-retry": "1.4.2", diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index c55e73664c2813..52a3802194830c 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -8,6 +8,9 @@ "url": "vercel/next.js", "directory": "packages/eslint-config-next" }, + "scripts": { + "test-pack": "cd ../../ && pnpm test-pack eslint-config-next" + }, "dependencies": { "@next/eslint-plugin-next": "13.1.3-canary.4", "@rushstack/eslint-patch": "^1.1.3", diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index 2b2804d426bdb8..4f006f4f37b024 100644 --- a/packages/eslint-plugin-next/package.json +++ b/packages/eslint-plugin-next/package.json @@ -20,6 +20,7 @@ }, "scripts": { "build": "swc -d dist src", - "prepublishOnly": "cd ../../ && turbo run build" + "prepublishOnly": "cd ../../ && turbo run build", + "test-pack": "cd ../../ && pnpm test-pack eslint-plugin-next" } } diff --git a/packages/font/package.json b/packages/font/package.json index 1acbb788fba7b3..6d57e8c6edb2c1 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -17,7 +17,8 @@ "prepublishOnly": "cd ../../ && turbo run build", "dev": "pnpm ncc-fontkit && tsc -d -w -p tsconfig.json", "typescript": "tsec --noEmit -p tsconfig.json", - "ncc-fontkit": "ncc build ./fontkit.js -o dist/fontkit" + "ncc-fontkit": "ncc build ./fontkit.js -o dist/fontkit", + "test-pack": "cd ../../ && pnpm test-pack font" }, "devDependencies": { "@types/fontkit": "2.0.0", diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index 041f81aff4de35..c207b513b298e1 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -10,5 +10,8 @@ }, "dependencies": { "webpack-bundle-analyzer": "4.7.0" + }, + "scripts": { + "test-pack": "cd ../../ && pnpm test-pack next-bundle-analyzer" } } diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index 2cbc8ced16d032..028ebeb256c4a7 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -22,7 +22,8 @@ "build": "pnpm tsc -d -p tsconfig.json", "prepublishOnly": "cd ../../ && turbo run build", "dev": "pnpm tsc -d -w -p tsconfig.json", - "test": "jest" + "test": "jest", + "test-pack": "cd ../../ && pnpm test-pack next-codemod" }, "bin": "./bin/next-codemod.js", "devDependencies": { diff --git a/packages/next-env/package.json b/packages/next-env/package.json index b09c8a8187d7a1..e8dd37a133b2a7 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -27,7 +27,8 @@ "types": "tsc index.ts --declaration --emitDeclarationOnly --declarationDir types --esModuleInterop", "release": "ncc build ./index.ts -o ./dist/ --minify --no-cache --no-source-map-register", "build": "pnpm release && pnpm types", - "prepublishOnly": "cd ../../ && turbo run build" + "prepublishOnly": "cd ../../ && turbo run build", + "test-pack": "cd ../../ && pnpm test-pack next-env" }, "devDependencies": { "@vercel/ncc": "0.34.0", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index f3614ee27caef6..f8171120642a6d 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -7,6 +7,9 @@ "url": "vercel/next.js", "directory": "packages/next-mdx" }, + "scripts": { + "test-pack": "cd ../../ && pnpm test-pack next-mdx" + }, "peerDependencies": { "@mdx-js/loader": ">=0.15.0", "@mdx-js/react": "*" diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index f5fb8a627884c2..c5a26ddeb2e6e6 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -5,6 +5,9 @@ "url": "vercel/next.js", "directory": "packages/next-plugin-storybook" }, + "scripts": { + "test-pack": "cd ../../ && pnpm test-pack next-plugin-storybook" + }, "peerDependencies": { "next": "*" } diff --git a/packages/next-polyfill-module/package.json b/packages/next-polyfill-module/package.json index d1094dff0dc07c..d891aabfdca1c5 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -11,7 +11,8 @@ "scripts": { "build": "microbundle -i src/index.js -o dist/polyfill-module.js -f iife --no-sourcemap --external none --no-pkg-main", "dev": "pnpm build", - "prepublishOnly": "cd ../../ && turbo run build" + "prepublishOnly": "cd ../../ && turbo run build", + "test-pack": "cd ../../ && pnpm test-pack next-polyfill-module" }, "devDependencies": { "microbundle": "0.15.0" diff --git a/packages/next-polyfill-nomodule/package.json b/packages/next-polyfill-nomodule/package.json index bb14be3821fb65..c5fffe7d538075 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -11,7 +11,8 @@ "scripts": { "build": "microbundle -i src/index.js -o dist/polyfill-nomodule.js -f iife --no-sourcemap --external none --no-pkg-main", "dev": "pnpm build", - "prepublishOnly": "cd ../../ && turbo run build" + "prepublishOnly": "cd ../../ && turbo run build", + "test-pack": "cd ../../ && pnpm test-pack next-polyfill-nomodule" }, "devDependencies": { "core-js": "3.6.5", diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index dd1668610a54d8..ff7ce92602eef3 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -8,7 +8,8 @@ "build-native-no-plugin": "napi build --platform -p next-swc-napi --cargo-name next_swc_napi --js false native", "build-native-no-plugin-woa": "napi build --platform -p next-swc-napi --cargo-name next_swc_napi --cargo-flags=--no-default-features --features native-tls --js false native", "build-wasm": "wasm-pack build crates/wasm --scope=next", - "cache-build-native": "echo $(ls native)" + "cache-build-native": "echo $(ls native)", + "test-pack": "cd ../../ && pnpm test-pack next-swc" }, "napi": { "name": "next-swc", diff --git a/packages/next/package.json b/packages/next/package.json index bc8b2afd43c600..b3e0a08650b35f 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -66,7 +66,8 @@ "prepublishOnly": "cd ../../ && turbo run build", "types": "tsc --declaration --emitDeclarationOnly --declarationDir dist", "typescript": "tsec --noEmit", - "ncc-compiled": "ncc cache clean && taskr ncc" + "ncc-compiled": "ncc cache clean && taskr ncc", + "test-pack": "cd ../../ && pnpm test-pack next" }, "taskr": { "requires": [ diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index 5cb91f8a15cba8..0e6db061fa0b5a 100644 --- a/packages/react-dev-overlay/package.json +++ b/packages/react-dev-overlay/package.json @@ -15,7 +15,8 @@ "build": "rimraf dist && tsc -d -p tsconfig.json", "prepublishOnly": "cd ../../ && turbo run build", "dev": "tsc -d -w -p tsconfig.json", - "typescript": "tsec --noEmit -p tsconfig.json" + "typescript": "tsec --noEmit -p tsconfig.json", + "test-pack": "cd ../../ && pnpm test-pack react-dev-overlay" }, "dependencies": { "@babel/code-frame": "7.12.11", diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json index aa086ab890f796..146207451d65f4 100644 --- a/packages/react-refresh-utils/package.json +++ b/packages/react-refresh-utils/package.json @@ -14,7 +14,8 @@ "scripts": { "build": "rimraf dist && tsc -d -p tsconfig.json", "prepublishOnly": "cd ../../ && turbo run build", - "dev": "tsc -d -w -p tsconfig.json" + "dev": "tsc -d -w -p tsconfig.json", + "test-pack": "cd ../../ && pnpm test-pack react-refresh-utils" }, "peerDependencies": { "react-refresh": "0.12.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dc05cf40f05863..16f4881fb2534a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -178,6 +178,7 @@ importers: tailwindcss: 1.1.3 taskr: 1.1.0 tree-kill: 1.2.2 + ts-node: 10.9.1 tsec: 0.2.1 turbo: 1.6.3 typescript: 4.8.2 @@ -299,7 +300,7 @@ importers: image-size: 0.9.3 is-animated: 2.0.2 isomorphic-unfetch: 3.0.0 - jest: 27.0.6 + jest: 27.0.6_ts-node@10.9.1 jest-extended: 1.2.1 json5: 2.2.3 ky: 0.19.1 @@ -354,6 +355,7 @@ importers: tailwindcss: 1.1.3 taskr: 1.1.0 tree-kill: 1.2.2 + ts-node: 10.9.1_cx2odcp7q42yre3tu7le55sjlu tsec: 0.2.1_sbe2uaqno6akssxfwbhgeg7v2q turbo: 1.6.3 typescript: 4.8.2 @@ -4350,6 +4352,13 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true + /@cspotcode/source-map-support/0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + dev: true + /@csstools/postcss-color-function/1.1.0_postcss@8.4.14: resolution: {integrity: sha512-5D5ND/mZWcQoSfYnSPsXtuiFxhzmhxt6pcjrFLJyldj+p0ZN2vvRpYNX+lahFTtMhAYOa2WmkdGINr0yP0CvGA==} engines: {node: ^12 || ^14 || >=16} @@ -4931,7 +4940,7 @@ packages: slash: 3.0.0 dev: true - /@jest/core/27.0.6: + /@jest/core/27.0.6_ts-node@10.9.1: resolution: {integrity: sha512-SsYBm3yhqOn5ZLJCtccaBcvD/ccTLCeuDv8U41WJH/V1MW5eKUkeMHT9U+Pw/v1m1AIWlnIW/eM2XzQr0rEmow==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: @@ -4952,7 +4961,7 @@ packages: exit: 0.1.2 graceful-fs: 4.2.10 jest-changed-files: 27.0.6 - jest-config: 27.0.6 + jest-config: 27.0.6_ts-node@10.9.1 jest-haste-map: 27.0.6 jest-message-util: 27.5.1 jest-regex-util: 27.0.6 @@ -5226,6 +5235,13 @@ packages: '@jridgewell/resolve-uri': 3.0.5 '@jridgewell/sourcemap-codec': 1.4.11 + /@jridgewell/trace-mapping/0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.0.5 + '@jridgewell/sourcemap-codec': 1.4.11 + dev: true + /@lerna/add/4.0.0: resolution: {integrity: sha512-cpmAH1iS3k8JBxNvnMqrGTTjbY/ZAiKa1ChJzFevMYY3eeqbvhsBKnBcxjRXtdrJ6bd3dCQM+ZtK+0i682Fhng==} engines: {node: '>= 10.18.0'} @@ -6956,6 +6972,22 @@ packages: resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} engines: {node: '>= 6'} + /@tsconfig/node10/1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + dev: true + + /@tsconfig/node12/1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: true + + /@tsconfig/node14/1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: true + + /@tsconfig/node16/1.0.3: + resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} + dev: true + /@types/amphtml-validator/1.0.0: resolution: {integrity: sha512-CJOi00fReT1JehItkgTZDI47v9WJxUH/OLX0XzkDgyEed7dGdeUQfXk5CTRM7N9FkHdv3klSjsZxo5sH1oTIGg==} dependencies: @@ -7983,6 +8015,11 @@ packages: resolution: {integrity: sha512-oZRad/3SMOI/pxbbmqyurIx7jHw1wZDcR9G44L8pUVFEomX/0dH89SrM1KaDXuv1NpzAXz6Op/Xu/Qd5XXzdEA==} engines: {node: '>=0.4.0'} + /acorn-walk/8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + dev: true + /acorn/6.4.2: resolution: {integrity: sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==} engines: {node: '>=0.4.0'} @@ -10335,6 +10372,10 @@ packages: sha.js: 2.4.11 dev: true + /create-require/1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + /critters/0.0.6: resolution: {integrity: sha512-NUB3Om7tkf+XWi9+2kJ2A3l4/tHORDI1UT+nHxUqay2B/tJvMpiXcklDDLBH3fPn9Pe23uu0we/08Ukjy4cLCQ==} dependencies: @@ -11147,6 +11188,11 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dev: true + /diff/4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + /diffie-hellman/5.0.3: resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} dependencies: @@ -13953,7 +13999,7 @@ packages: dependencies: '@babel/code-frame': 7.18.6 '@sidvind/better-ajv-errors': 0.6.10_ajv@6.12.6 - acorn-walk: 8.0.0 + acorn-walk: 8.2.0 ajv: 6.12.6 chalk: 4.1.2 deepmerge: 4.2.2 @@ -15107,7 +15153,7 @@ packages: - supports-color dev: true - /jest-cli/27.0.6: + /jest-cli/27.0.6_ts-node@10.9.1: resolution: {integrity: sha512-qUUVlGb9fdKir3RDE+B10ULI+LQrz+MCflEH2UJyoUjoHHCbxDrMxSzjQAPUMsic4SncI62ofYCcAvW6+6rhhg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} hasBin: true @@ -15117,14 +15163,14 @@ packages: node-notifier: optional: true dependencies: - '@jest/core': 27.0.6 + '@jest/core': 27.0.6_ts-node@10.9.1 '@jest/test-result': 27.0.6 '@jest/types': 27.5.1 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.10 import-local: 3.0.2 - jest-config: 27.0.6 + jest-config: 27.0.6_ts-node@10.9.1 jest-util: 27.5.1 jest-validate: 27.0.6 prompts: 2.3.0 @@ -15137,7 +15183,7 @@ packages: - utf-8-validate dev: true - /jest-config/27.0.6: + /jest-config/27.0.6_ts-node@10.9.1: resolution: {integrity: sha512-JZRR3I1Plr2YxPBhgqRspDE2S5zprbga3swYNrvY3HfQGu7p/GjyLOqwrYad97tX3U3mzT53TPHVmozacfP/3w==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: @@ -15167,6 +15213,7 @@ packages: jest-validate: 27.5.1 micromatch: 4.0.4 pretty-format: 27.5.1 + ts-node: 10.9.1_cx2odcp7q42yre3tu7le55sjlu transitivePeerDependencies: - bufferutil - canvas @@ -15777,7 +15824,7 @@ packages: merge-stream: 2.0.0 supports-color: 8.1.1 - /jest/27.0.6: + /jest/27.0.6_ts-node@10.9.1: resolution: {integrity: sha512-EjV8aETrsD0wHl7CKMibKwQNQc3gIRBXlTikBmmHUeVMKaPFxdcUIBfoDqTSXDoGJIivAYGqCWVlzCSaVjPQsA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} hasBin: true @@ -15787,9 +15834,9 @@ packages: node-notifier: optional: true dependencies: - '@jest/core': 27.0.6 + '@jest/core': 27.0.6_ts-node@10.9.1 import-local: 3.0.2 - jest-cli: 27.0.6 + jest-cli: 27.0.6_ts-node@10.9.1 transitivePeerDependencies: - bufferutil - canvas @@ -16757,6 +16804,10 @@ packages: semver: 6.3.0 dev: true + /make-error/1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + /make-fetch-happen/8.0.13: resolution: {integrity: sha512-rQ5NijwwdU8tIaBrpTtSVrNCcAJfyDRcKBC76vOQlyJX588/88+TE+UpjWl4BgG7gCkp29wER7xcRqkeg+x64Q==} engines: {node: '>= 10'} @@ -22980,6 +23031,38 @@ packages: dependencies: glob: 7.2.0 + /ts-node/10.9.1_cx2odcp7q42yre3tu7le55sjlu: + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@swc/core': 1.2.203 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.3 + '@types/node': 14.14.31 + acorn: 8.8.0 + acorn-walk: 8.2.0 + arg: 4.1.0 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.8.2 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + /tsconfig-paths/3.14.1: resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} dependencies: @@ -23651,6 +23734,10 @@ packages: hasBin: true dev: true + /v8-compile-cache-lib/3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + dev: true + /v8-compile-cache/2.1.0: resolution: {integrity: sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==} dev: true @@ -24319,6 +24406,11 @@ packages: buffer-crc32: 0.2.13 dev: true + /yn/3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: true + /yocto-queue/0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} diff --git a/scripts/test-pack-package.mts b/scripts/test-pack-package.mts new file mode 100755 index 00000000000000..36399fe001c25e --- /dev/null +++ b/scripts/test-pack-package.mts @@ -0,0 +1,105 @@ +import path from 'path' +import fs from 'fs-extra' +import os from 'os' +import execa from 'execa' +import { randomBytes } from 'crypto' +import { fileURLToPath } from 'url' + +const main = async () => { + const __dirname = fileURLToPath(new URL('.', import.meta.url)) + const repoRoot = path.dirname(__dirname) + const pkgsDir = path.join(repoRoot, 'packages') + const currentPkgDirname = process.argv[2] + + const getPackedPkgPath = (pkgDirname: string) => + path.join(pkgsDir, pkgDirname, `packed-${pkgDirname}.tgz`) + const getPackageJsonPath = (pkgDirname: string) => + path.join(pkgsDir, pkgDirname, `package.json`) + + const allPkgDirnames = await fs.readdir(pkgsDir) + if (!allPkgDirnames.includes(currentPkgDirname)) { + throw new Error(`Unknown package '${currentPkgDirname}'`) + } + + const currentPkgDir = path.join(pkgsDir, currentPkgDirname) + + const tmpPkgPath = path.join( + os.tmpdir(), + `${currentPkgDirname}-${randomBytes(32).toString('hex')}` + ) + console.log(`Packing '${currentPkgDirname}' in '${tmpPkgPath}'.`) + + const packageJsonPath = getPackageJsonPath(currentPkgDirname) + const packageJson = await fs.readJson(packageJsonPath) + const dependencies = packageJson.dependencies + + if (packageJson?.scripts?.prepublishOnly) { + // There's a bug in `pnpm pack` where it will run + // the prepublishOnly script and that will fail. + // See https://github.com/pnpm/pnpm/issues/2941 + delete packageJson.scripts.prepublishOnly + } + + // @next/swc is devDependency in next, but we want to include it anyway + if (currentPkgDirname === 'next') { + dependencies['@next/swc'] = '*' + } + + // Modify dependencies to point to packed packages + if (dependencies) { + await Promise.all( + allPkgDirnames.map(async (depPkgDirname) => { + const { name: depPkgName } = await fs.readJson( + getPackageJsonPath(depPkgDirname) + ) + if (depPkgName in dependencies) { + dependencies[depPkgName] = getPackedPkgPath(depPkgDirname) + } + }) + ) + } + + // Ensure that we bundle binaries with swc + if (currentPkgDirname === 'next-swc') { + packageJson.files = packageJson.files ?? [] + packageJson.files.push('native') + + console.log('using swc binaries:') + await execa('ls', [ + path.join(path.dirname(packageJsonPath), 'native'), + ]).stdout?.pipe(process.stdout) + } + + // Allow overriding nateve swc version in next + if (currentPkgDirname === 'next' && process.env.NEXT_SWC_VERSION) { + dependencies['@next/swc-linux-x64-gnu'] = process.env.NEXT_SWC_VERSION + } + + try { + await fs.copy(currentPkgDir, tmpPkgPath, { + filter: (item) => + !item.includes('node_modules') && + !item.includes('.DS_Store') && + // Exclude Rust compilation files + (currentPkgDirname !== 'next' || + !/build[\\/]swc[\\/]target/.test(item)) && + (currentPkgDirname !== 'next-swc' || !/target/.test(item)), + }) + await fs.writeJson(path.join(tmpPkgPath, 'package.json'), packageJson) + // Copied from pnpm source: https://github.com/pnpm/pnpm/blob/5a5512f14c47f4778b8d2b6d957fb12c7ef40127/releasing/plugin-commands-publishing/src/pack.ts#L96 + const tmpTarball = path.join( + tmpPkgPath, + `${packageJson.name.replace('@', '').replace('/', '-')}-${ + packageJson.version + }.tgz` + ) + await execa('yarn', ['pack', '-f', tmpTarball], { + cwd: tmpPkgPath, + }) + await fs.copyFile(tmpTarball, getPackedPkgPath(currentPkgDirname)) + } finally { + await fs.remove(tmpPkgPath).catch() + } +} + +main() diff --git a/scripts/trace-next-server.js b/scripts/trace-next-server.js index e2d8659e9a0724..ca1db9cdd574f8 100644 --- a/scripts/trace-next-server.js +++ b/scripts/trace-next-server.js @@ -38,7 +38,7 @@ async function main() { console.log('using repodir', repoDir) await fs.ensureDir(workDir) - const pkgPaths = await linkPackages({ repoDir }) + const pkgPaths = await linkPackages({ repoDir: origRepoDir }) await fs.writeFile( path.join(workDir, 'package.json'), diff --git a/test/lib/create-next-install.js b/test/lib/create-next-install.js index 7e8060310ecdbf..0f22bf60e207f7 100644 --- a/test/lib/create-next-install.js +++ b/test/lib/create-next-install.js @@ -7,30 +7,11 @@ const { randomBytes } = require('crypto') const { linkPackages } = require('../../.github/actions/next-stats-action/src/prepare/repo-setup')() -/** - * These are simple dependencies provided by default. We want to optimize this special case. - */ -const areGenericDependencies = (dependencies) => - Object.keys(dependencies).length === 6 && - Object.entries(dependencies).every(([dep, version]) => { - if (dep === 'next') return true - return ( - [ - 'react', - 'react-dom', - 'typescript', - '@types/react', - '@types/node', - ].includes(dep) && version === 'latest' - ) - }) - async function createNextInstall({ parentSpan, dependencies, installCommand, packageJson = {}, - packageLockPath = '', dirSuffix = '', }) { return await parentSpan @@ -42,14 +23,9 @@ async function createNextInstall({ tmpDir, `next-install-${randomBytes(32).toString('hex')}${dirSuffix}` ) - const tmpRepoDir = path.join( - tmpDir, - `next-repo-${randomBytes(32).toString('hex')}${dirSuffix}` - ) - require('console').log('Using following temporary directories:') + require('console').log('Creating next instance in:') require('console').log(installDir) - require('console').log(tmpRepoDir) await rootSpan.traceChild(' enruse swc binary').traceAsyncFn(async () => { // ensure swc binary is present in the native folder if @@ -82,35 +58,16 @@ async function createNextInstall({ } }) - for (const item of ['package.json', 'packages']) { - await rootSpan - .traceChild(`copy ${item} to temp dir`) - .traceAsyncFn(async () => { - await fs.copy( - path.join(origRepoDir, item), - path.join(tmpRepoDir, item), - { - filter: (item) => { - return ( - !item.includes('node_modules') && - !item.includes('.DS_Store') && - // Exclude Rust compilation files - !/next[\\/]build[\\/]swc[\\/]target/.test(item) && - !/next-swc[\\/]target/.test(item) - ) - }, - } - ) - }) - } - let combinedDependencies = dependencies if (!(packageJson && packageJson.nextPrivateSkipLocalDeps)) { - const pkgPaths = await linkPackages({ - repoDir: tmpRepoDir, - parentSpan: rootSpan, - }) + const pkgPaths = await rootSpan + .traceChild('linkPackages') + .traceAsyncFn(() => + linkPackages({ + repoDir: origRepoDir, + }) + ) combinedDependencies = { next: pkgPaths.get('next'), ...Object.keys(dependencies).reduce((prev, pkg) => { @@ -135,13 +92,6 @@ async function createNextInstall({ ) ) - if (packageLockPath) { - await fs.copy( - packageLockPath, - path.join(installDir, path.basename(packageLockPath)) - ) - } - if (installCommand) { const installString = typeof installCommand === 'function' @@ -159,65 +109,20 @@ async function createNextInstall({ await rootSpan .traceChild('run generic install command') .traceAsyncFn(async () => { - const runInstall = async () => { - const args = ['install', '--strict-peer-dependencies=false'] + const args = ['install', '--strict-peer-dependencies=false'] - if (process.env.NEXT_TEST_PREFER_OFFLINE === '1') { - args.push('--prefer-offline') - } - - return await execa('pnpm', args, { - cwd: installDir, - stdio: ['ignore', 'inherit', 'inherit'], - env: process.env, - }) + if (process.env.NEXT_TEST_PREFER_OFFLINE === '1') { + args.push('--prefer-offline') } - if (!areGenericDependencies(combinedDependencies)) { - await runInstall() - } else { - const cacheDir = path.join( - origRepoDir, - 'test', - 'tmp', - 'genericInstallCache' - ) - - const cachedFiles = [ - // We can't cache node-modules because .pnpm store must be on the same mount - we can't move it between mountpoints - // 'node_modules', - // FIXME: caching lock file caused itssues and It's not possible when we don't use turbo which we had to disable temporarily - // 'pnpm-lock.yaml', - ] - - if ( - await fs - .access(cacheDir) - .then(() => true) - .catch(() => false) - ) { - require('console').log( - 'We are able to prepopulate pnpm install from cache' - ) - cachedFiles.forEach((file) => { - fs.copy( - path.join(cacheDir, file), - path.join(installDir, file) - ) - }) - } - - await runInstall() - - await fs.ensureDir(cacheDir) - cachedFiles.forEach((file) => { - fs.copy(path.join(installDir, file), path.join(cacheDir, file)) - }) - } + await execa('pnpm', args, { + cwd: installDir, + stdio: ['ignore', 'inherit', 'inherit'], + env: process.env, + }) }) } - await fs.remove(tmpRepoDir) return installDir }) } diff --git a/test/lib/next-modes/base.ts b/test/lib/next-modes/base.ts index 12433a429c652b..714969ff463114 100644 --- a/test/lib/next-modes/base.ts +++ b/test/lib/next-modes/base.ts @@ -24,7 +24,6 @@ export interface NextInstanceOpts { files: FileRef | string | { [filename: string]: string | FileRef } dependencies?: { [name: string]: string } packageJson?: PackageJson - packageLockPath?: string nextConfig?: NextConfig installCommand?: InstallCommand buildCommand?: string @@ -59,7 +58,6 @@ export class NextInstance { protected _url: string protected _parsedUrl: URL protected packageJson?: PackageJson = {} - protected packageLockPath?: string protected basePath?: string protected env?: Record public forcedPort?: string @@ -179,7 +177,6 @@ export class NextInstance { dependencies: finalDependencies, installCommand: this.installCommand, packageJson: this.packageJson, - packageLockPath: this.packageLockPath, dirSuffix: this.dirSuffix, }) } @@ -266,7 +263,6 @@ export class NextInstance { ` ) } - require('console').log(`Test directory created at ${this.testDir}`) }) } diff --git a/turbo.json b/turbo.json index 21c50734074eed..e5ddd1a816a543 100644 --- a/turbo.json +++ b/turbo.json @@ -29,6 +29,16 @@ "dependsOn": ["^dev"], "outputs": ["dist/**"] }, - "typescript": {} + "typescript": {}, + "test-pack": { + "dependsOn": ["^test-pack"], + "inputs": [ + "*", + "../../scripts/test-pack-package.mts", + "../../package.json" + ], + "outputs": ["packed-*.tgz"], + "env": ["NEXT_SWC_VERSION"] + } } }