From 54e8bd0e7e5ba78108a846d717ddfd1f39ea6fbc Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 24 Jun 2024 10:39:38 +0100 Subject: [PATCH] perf(nuxt,vite): use native fs utils rather than `fs-extra` (#27787) --- package.json | 2 -- packages/nuxt/package.json | 2 -- packages/nuxt/src/core/nitro.ts | 2 -- packages/nuxt/src/core/nuxt.ts | 7 ++-- packages/vite/package.json | 2 -- packages/vite/src/manifest.ts | 14 ++++---- packages/vite/src/utils/index.ts | 10 ------ packages/vite/src/utils/wpfs.ts | 7 ---- packages/vite/src/vite-node.ts | 6 ++-- packages/webpack/package.json | 2 -- packages/webpack/src/plugins/vue/client.ts | 10 +++--- pnpm-lock.yaml | 39 ---------------------- test/prepare.ts | 8 +++-- test/setup.ts | 15 +++++---- 14 files changed, 35 insertions(+), 91 deletions(-) delete mode 100644 packages/vite/src/utils/wpfs.ts diff --git a/package.json b/package.json index 931e5aeace..e6a52fa401 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,6 @@ "@nuxt/webpack-builder": "workspace:*", "@testing-library/vue": "8.1.0", "@types/eslint__js": "8.42.3", - "@types/fs-extra": "11.0.4", "@types/node": "20.14.7", "@types/semver": "7.5.8", "@unhead/schema": "1.9.14", @@ -69,7 +68,6 @@ "eslint-plugin-perfectionist": "2.11.0", "eslint-typegen": "0.2.4", "execa": "9.2.0", - "fs-extra": "11.2.0", "globby": "14.0.1", "h3": "1.12.0", "happy-dom": "14.12.3", diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 27a9330c23..dcf6d24318 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -79,7 +79,6 @@ "esbuild": "^0.21.5", "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", - "fs-extra": "^11.2.0", "globby": "^14.0.1", "h3": "^1.12.0", "hookable": "^5.5.3", @@ -122,7 +121,6 @@ "@nuxt/ui-templates": "1.3.4", "@parcel/watcher": "2.4.1", "@types/estree": "1.0.5", - "@types/fs-extra": "11.0.4", "@vitejs/plugin-vue": "5.0.4", "@vue/compiler-sfc": "3.4.29", "unbuild": "latest", diff --git a/packages/nuxt/src/core/nitro.ts b/packages/nuxt/src/core/nitro.ts index 639072ba0d..37b18e278c 100644 --- a/packages/nuxt/src/core/nitro.ts +++ b/packages/nuxt/src/core/nitro.ts @@ -9,7 +9,6 @@ import type { Nitro, NitroConfig, NitroOptions } from 'nitropack' import { findPath, logger, resolveAlias, resolveIgnorePatterns, resolveNuxtModule, resolvePath } from '@nuxt/kit' import escapeRE from 'escape-string-regexp' import { defu } from 'defu' -import fsExtra from 'fs-extra' import { dynamicEventHandler } from 'h3' import { isWindows } from 'std-env' import type { Nuxt, NuxtOptions } from 'nuxt/schema' @@ -534,7 +533,6 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { // nuxt dev if (nuxt.options.dev) { - nuxt.hook('webpack:compile', ({ compiler }) => { compiler.outputFileSystem = { ...fsExtra, join } as any }) nuxt.hook('webpack:compiled', () => { nuxt.server.reload() }) nuxt.hook('vite:compiled', () => { nuxt.server.reload() }) diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index d5fe6f8740..4987fb3d98 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -1,3 +1,5 @@ +import { existsSync } from 'node:fs' +import { rm } from 'node:fs/promises' import { dirname, join, normalize, relative, resolve } from 'pathe' import { createDebugger, createHooks } from 'hookable' import ignore from 'ignore' @@ -10,7 +12,6 @@ import { readPackageJSON, resolvePackageJSON } from 'pkg-types' import { hash } from 'ohash' import escapeRE from 'escape-string-regexp' -import fse from 'fs-extra' import { withTrailingSlash, withoutLeadingSlash } from 'ufo' import defu from 'defu' @@ -159,7 +160,7 @@ async function initNuxt (nuxt: Nuxt) { for (const layer of nuxt.options._layers) { const declaration = join(layer.cwd, 'index.d.ts') - if (fse.existsSync(declaration)) { + if (existsSync(declaration)) { opts.references.push({ path: declaration }) } } @@ -277,7 +278,7 @@ async function initNuxt (nuxt: Nuxt) { nuxt.hook('build:manifest', async (manifest) => { for (const file in manifest) { if (manifest[file].resourceType === 'script') { - await fse.rm(resolve(nuxt.options.buildDir, 'dist/client', withoutLeadingSlash(nuxt.options.app.buildAssetsDir), manifest[file].file), { force: true }) + await rm(resolve(nuxt.options.buildDir, 'dist/client', withoutLeadingSlash(nuxt.options.app.buildAssetsDir), manifest[file].file), { force: true }) manifest[file].file = '' } } diff --git a/packages/vite/package.json b/packages/vite/package.json index d48970a161..2b628b0e77 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -27,7 +27,6 @@ "@nuxt/schema": "workspace:*", "@types/clear": "0.1.4", "@types/estree": "1.0.5", - "@types/fs-extra": "11.0.4", "rollup": "4.18.0", "unbuild": "latest", "vue": "3.4.29" @@ -46,7 +45,6 @@ "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", "externality": "^1.0.2", - "fs-extra": "^11.2.0", "get-port-please": "^3.1.2", "h3": "^1.12.0", "knitwork": "^1.1.0", diff --git a/packages/vite/src/manifest.ts b/packages/vite/src/manifest.ts index 54471633ec..9d4490f36b 100644 --- a/packages/vite/src/manifest.ts +++ b/packages/vite/src/manifest.ts @@ -1,4 +1,6 @@ -import fse from 'fs-extra' +import { readFileSync } from 'node:fs' +import { mkdir, rm, writeFile } from 'node:fs/promises' + import { relative, resolve } from 'pathe' import { withTrailingSlash, withoutLeadingSlash } from 'ufo' import escapeRE from 'escape-string-regexp' @@ -30,7 +32,7 @@ export async function writeManifest (ctx: ViteBuildContext, css: string[] = []) const manifestFile = resolve(clientDist, 'manifest.json') const clientManifest = ctx.nuxt.options.dev ? devClientManifest - : await fse.readJSON(manifestFile) + : JSON.parse(readFileSync(manifestFile, 'utf-8')) const buildAssetsDir = withTrailingSlash(withoutLeadingSlash(ctx.nuxt.options.app.buildAssetsDir)) const BASE_RE = new RegExp(`^${escapeRE(buildAssetsDir)}`) @@ -47,7 +49,7 @@ export async function writeManifest (ctx: ViteBuildContext, css: string[] = []) } } - await fse.mkdirp(serverDist) + await mkdir(serverDist, { recursive: true }) if (ctx.config.build?.cssCodeSplit === false) { for (const key in clientManifest as Record) { @@ -64,10 +66,10 @@ export async function writeManifest (ctx: ViteBuildContext, css: string[] = []) const manifest = normalizeViteManifest(clientManifest) await ctx.nuxt.callHook('build:manifest', manifest) const stringifiedManifest = JSON.stringify(manifest, null, 2) - await fse.writeFile(resolve(serverDist, 'client.manifest.json'), stringifiedManifest, 'utf8') - await fse.writeFile(resolve(serverDist, 'client.manifest.mjs'), 'export default ' + stringifiedManifest, 'utf8') + await writeFile(resolve(serverDist, 'client.manifest.json'), stringifiedManifest, 'utf8') + await writeFile(resolve(serverDist, 'client.manifest.mjs'), 'export default ' + stringifiedManifest, 'utf8') if (!ctx.nuxt.options.dev) { - await fse.rm(manifestFile, { force: true }) + await rm(manifestFile, { force: true }) } } diff --git a/packages/vite/src/utils/index.ts b/packages/vite/src/utils/index.ts index c667b96b20..9221d70278 100644 --- a/packages/vite/src/utils/index.ts +++ b/packages/vite/src/utils/index.ts @@ -1,11 +1,5 @@ -import { hash } from 'ohash' - export { isVue } from '../../../nuxt/src/core/utils/plugins' -export function uniq (arr: T[]): T[] { - return Array.from(new Set(arr)) -} - // Copied from vue-bundle-renderer utils const IS_CSS_RE = /\.(?:css|scss|sass|postcss|pcss|less|stylus|styl)(?:\?[^.]+)?$/ @@ -13,10 +7,6 @@ export function isCSS (file: string) { return IS_CSS_RE.test(file) } -export function hashId (id: string) { - return '$id_' + hash(id) -} - export function matchWithStringOrRegex (value: string, matcher: string | RegExp) { if (typeof matcher === 'string') { return value === matcher diff --git a/packages/vite/src/utils/wpfs.ts b/packages/vite/src/utils/wpfs.ts deleted file mode 100644 index 5538f0bf7e..0000000000 --- a/packages/vite/src/utils/wpfs.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { join } from 'pathe' -import fse from 'fs-extra' - -export const wpfs = { - ...fse, - join, -} as typeof fse & { join: typeof join } diff --git a/packages/vite/src/vite-node.ts b/packages/vite/src/vite-node.ts index 8bbbe98ed0..b4af79e8b0 100644 --- a/packages/vite/src/vite-node.ts +++ b/packages/vite/src/vite-node.ts @@ -1,7 +1,7 @@ +import { writeFile } from 'node:fs/promises' import { pathToFileURL } from 'node:url' import { createApp, createError, defineEventHandler, defineLazyEventHandler, eventHandler, toNodeListener } from 'h3' import { ViteNodeServer } from 'vite-node/server' -import fse from 'fs-extra' import { isAbsolute, normalize, resolve } from 'pathe' import { addDevServerHandler } from '@nuxt/kit' import { isFileServingAllowed } from 'vite' @@ -181,11 +181,11 @@ export async function initViteNodeServer (ctx: ViteBuildContext) { const serverResolvedPath = resolve(distDir, 'runtime/vite-node.mjs') const manifestResolvedPath = resolve(distDir, 'runtime/client.manifest.mjs') - await fse.writeFile( + await writeFile( resolve(ctx.nuxt.options.buildDir, 'dist/server/server.mjs'), `export { default } from ${JSON.stringify(pathToFileURL(serverResolvedPath).href)}`, ) - await fse.writeFile( + await writeFile( resolve(ctx.nuxt.options.buildDir, 'dist/server/client.manifest.mjs'), `export { default } from ${JSON.stringify(pathToFileURL(manifestResolvedPath).href)}`, ) diff --git a/packages/webpack/package.json b/packages/webpack/package.json index e8c3846459..6a4e03a8bd 100644 --- a/packages/webpack/package.json +++ b/packages/webpack/package.json @@ -37,7 +37,6 @@ "estree-walker": "^3.0.3", "file-loader": "^6.2.0", "fork-ts-checker-webpack-plugin": "^9.0.2", - "fs-extra": "^11.2.0", "h3": "^1.12.0", "hash-sum": "^2.0.0", "lodash-es": "4.17.21", @@ -71,7 +70,6 @@ }, "devDependencies": { "@nuxt/schema": "workspace:*", - "@types/fs-extra": "11.0.4", "@types/hash-sum": "1.0.2", "@types/lodash-es": "4.17.12", "@types/pify": "5.0.4", diff --git a/packages/webpack/src/plugins/vue/client.ts b/packages/webpack/src/plugins/vue/client.ts index 10127fcace..23259c6cba 100644 --- a/packages/webpack/src/plugins/vue/client.ts +++ b/packages/webpack/src/plugins/vue/client.ts @@ -3,13 +3,15 @@ * https://github.com/vuejs/vue/blob/dev/src/server/webpack-plugin/client.js */ +import { mkdir, writeFile } from 'node:fs/promises' + import { normalizeWebpackManifest } from 'vue-bundle-renderer' import { dirname } from 'pathe' import hash from 'hash-sum' -import fse from 'fs-extra' import type { Nuxt } from '@nuxt/schema' import type { Compilation, Compiler } from 'webpack' + import { isCSS, isHotUpdate, isJS } from './util' interface PluginOptions { @@ -121,11 +123,11 @@ export default class VueSSRClientPlugin { const src = JSON.stringify(manifest, null, 2) - await fse.mkdirp(dirname(this.options.filename)) - await fse.writeFile(this.options.filename, src) + await mkdir(dirname(this.options.filename), { recursive: true }) + await writeFile(this.options.filename, src) const mjsSrc = 'export default ' + src - await fse.writeFile(this.options.filename.replace('.json', '.mjs'), mjsSrc) + await writeFile(this.options.filename.replace('.json', '.mjs'), mjsSrc) // assets[this.options.filename] = { // source: () => src, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ca42f491c4..4244e351ff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,9 +41,6 @@ importers: '@types/eslint__js': specifier: 8.42.3 version: 8.42.3 - '@types/fs-extra': - specifier: 11.0.4 - version: 11.0.4 '@types/node': specifier: 20.14.7 version: 20.14.7 @@ -89,9 +86,6 @@ importers: execa: specifier: 9.2.0 version: 9.2.0 - fs-extra: - specifier: 11.2.0 - version: 11.2.0 globby: specifier: 14.0.1 version: 14.0.1 @@ -306,9 +300,6 @@ importers: estree-walker: specifier: ^3.0.3 version: 3.0.3 - fs-extra: - specifier: ^11.2.0 - version: 11.2.0 globby: specifier: ^14.0.1 version: 14.0.1 @@ -430,9 +421,6 @@ importers: '@types/estree': specifier: 1.0.5 version: 1.0.5 - '@types/fs-extra': - specifier: 11.0.4 - version: 11.0.4 '@vitejs/plugin-vue': specifier: 5.0.4 version: 5.0.4(vite@5.3.1(@types/node@20.14.7)(sass@1.69.4)(terser@5.27.0))(vue@3.4.29(typescript@5.5.2)) @@ -653,9 +641,6 @@ importers: externality: specifier: ^1.0.2 version: 1.0.2 - fs-extra: - specifier: ^11.2.0 - version: 11.2.0 get-port-please: specifier: ^3.1.2 version: 3.1.2 @@ -726,9 +711,6 @@ importers: '@types/estree': specifier: 1.0.5 version: 1.0.5 - '@types/fs-extra': - specifier: 11.0.4 - version: 11.0.4 rollup: specifier: ^4.18.0 version: 4.18.0 @@ -777,9 +759,6 @@ importers: fork-ts-checker-webpack-plugin: specifier: ^9.0.2 version: 9.0.2(typescript@5.5.2)(webpack@5.92.1) - fs-extra: - specifier: ^11.2.0 - version: 11.2.0 h3: specifier: ^1.12.0 version: 1.12.0 @@ -874,9 +853,6 @@ importers: '@nuxt/schema': specifier: workspace:* version: link:../schema - '@types/fs-extra': - specifier: 11.0.4 - version: 11.0.4 '@types/hash-sum': specifier: 1.0.2 version: 1.0.2 @@ -2496,9 +2472,6 @@ packages: '@types/file-loader@5.0.4': resolution: {integrity: sha512-aB4X92oi5D2nIGI8/kolnJ47btRM2MQjQS4eJgA/VnCD12x0+kP5v7b5beVQWKHLOcquwUXvv6aMt8PmMy9uug==} - '@types/fs-extra@11.0.4': - resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} - '@types/google.maps@3.55.9': resolution: {integrity: sha512-phaOMtezbT3NaXPKiI3m0OosUS7Nly0auw3Be5s/CgMWLVoDAUP1Yb/Ld0TRoRp8ibrlT4VqM5kmzfvUA0UNLQ==} @@ -2526,9 +2499,6 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/jsonfile@6.1.2': - resolution: {integrity: sha512-8t92P+oeW4d/CRQfJaSqEwXujrhH4OEeHRjGU3v1Q8mUS8GPF3yiX26sw4svv6faL2HfBtGTe2xWIoVgN3dy9w==} - '@types/lodash-es@4.17.12': resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} @@ -9164,11 +9134,6 @@ snapshots: dependencies: '@types/webpack': 4.41.34 - '@types/fs-extra@11.0.4': - dependencies: - '@types/jsonfile': 6.1.2 - '@types/node': 20.14.7 - '@types/google.maps@3.55.9': {} '@types/hash-sum@1.0.2': {} @@ -9199,10 +9164,6 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/jsonfile@6.1.2': - dependencies: - '@types/node': 20.14.7 - '@types/lodash-es@4.17.12': dependencies: '@types/lodash': 4.14.200 diff --git a/test/prepare.ts b/test/prepare.ts index 83c2acac2b..e4442a18ac 100644 --- a/test/prepare.ts +++ b/test/prepare.ts @@ -1,6 +1,8 @@ import { fileURLToPath } from 'node:url' +import { rm } from 'node:fs/promises' + import { globby } from 'globby' -import fs from 'fs-extra' + import { execa } from 'execa' async function initTesting () { @@ -12,9 +14,9 @@ async function initTesting () { await Promise.all([ // clear nuxt build files - ...dirs.map(dir => fs.remove(`${dir}/.nuxt`)), + ...dirs.map(dir => rm(`${dir}/.nuxt`, { force: true, recursive: true })), // clear vite cache - ...dirs.map(dir => fs.remove(`${dir}/node_modules/.cache`), { force: true }), + ...dirs.map(dir => rm(`${dir}/node_modules/.cache`, { force: true, recursive: true })), ]) await Promise.all( diff --git a/test/setup.ts b/test/setup.ts index 2655f41fb3..09d429bde6 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -1,22 +1,25 @@ +import { existsSync } from 'node:fs' +import { cp, rm } from 'node:fs/promises' import { fileURLToPath } from 'node:url' + import { dirname, join } from 'pathe' -import fs from 'fs-extra' const dir = dirname(fileURLToPath(import.meta.url)) const fixtureDir = join(dir, 'fixtures') const tempDir = join(dir, 'fixtures-temp') export async function setup () { - if (fs.existsSync(tempDir)) { - await fs.remove(tempDir) + if (existsSync(tempDir)) { + await rm(tempDir, { force: true, recursive: true }) } - await fs.copy(fixtureDir, tempDir, { + await cp(fixtureDir, tempDir, { + recursive: true, filter: src => !src.includes('.cache'), }) } export async function teardown () { - if (fs.existsSync(tempDir)) { - await fs.remove(tempDir) + if (existsSync(tempDir)) { + await rm(tempDir, { force: true, recursive: true }) } }