Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: use fsp in more cases #12553

Merged
merged 2 commits into from Mar 25, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 4 additions & 3 deletions packages/vite/src/node/config.ts
@@ -1,4 +1,5 @@
import fs from 'node:fs'
import fsp from 'node:fs/promises'
import path from 'node:path'
import { pathToFileURL } from 'node:url'
import { performance } from 'node:perf_hooks'
Expand Down Expand Up @@ -1085,12 +1086,12 @@ async function loadConfigFromBundledFile(
.slice(2)})}`
const fileNameTmp = `${fileBase}.mjs`
const fileUrl = `${pathToFileURL(fileBase)}.mjs`
fs.writeFileSync(fileNameTmp, bundledCode)
await fsp.writeFile(fileNameTmp, bundledCode)
try {
return (await dynamicImport(fileUrl)).default
} finally {
try {
fs.unlinkSync(fileNameTmp)
await fsp.unlink(fileNameTmp)
} catch {
// already removed if this function is called twice simultaneously
}
Expand All @@ -1099,7 +1100,7 @@ async function loadConfigFromBundledFile(
// for cjs, we can register a custom loader via `_require.extensions`
else {
const extension = path.extname(fileName)
const realFileName = fs.realpathSync(fileName)
const realFileName = await fsp.realpath(fileName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: The fsp version of realpath uses .native by default, which would cause file read errors on Windows for network drives. But since we're not doing that here, this change should be safe.

Copy link
Contributor

@fwouts fwouts Apr 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This caused #12923, the async version returns a path with uppercase volume letter C:\... whereas the earlier version returns it lowercase, so the equality check on line 1107 no longer works.

const loaderExt = extension in _require.extensions ? extension : '.js'
const defaultLoader = _require.extensions[loaderExt]!
_require.extensions[loaderExt] = (module: NodeModule, filename: string) => {
Expand Down
14 changes: 7 additions & 7 deletions packages/vite/src/node/http.ts
@@ -1,4 +1,4 @@
import fs from 'node:fs'
import fsp from 'node:fs/promises'
import path from 'node:path'
import type {
Server as HttpServer,
Expand Down Expand Up @@ -129,18 +129,18 @@ export async function resolveHttpsConfig(

const { ca, cert, key, pfx } = httpsOption
Object.assign(httpsOption, {
ca: readFileIfExists(ca),
cert: readFileIfExists(cert),
key: readFileIfExists(key),
pfx: readFileIfExists(pfx),
ca: await readFileIfExists(ca),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Promise.all ??

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, done at vitejs/vite@de5e611 (#12553). Also simplified the logic.

cert: await readFileIfExists(cert),
key: await readFileIfExists(key),
pfx: await readFileIfExists(pfx),
})
return httpsOption
}

function readFileIfExists(value?: string | Buffer | any[]) {
async function readFileIfExists(value?: string | Buffer | any[]) {
if (typeof value === 'string') {
try {
return fs.readFileSync(path.resolve(value))
return fsp.readFile(path.resolve(value))
} catch (e) {
return value
}
Expand Down
20 changes: 12 additions & 8 deletions packages/vite/src/node/optimizer/index.ts
Expand Up @@ -233,7 +233,7 @@ export async function optimizeDeps(

const ssr = config.command === 'build' && !!config.build.ssr

const cachedMetadata = loadCachedDepOptimizationMetadata(
const cachedMetadata = await loadCachedDepOptimizationMetadata(
config,
ssr,
force,
Expand Down Expand Up @@ -263,7 +263,7 @@ export async function optimizeServerSsrDeps(
config: ResolvedConfig,
): Promise<DepOptimizationMetadata> {
const ssr = true
const cachedMetadata = loadCachedDepOptimizationMetadata(
const cachedMetadata = await loadCachedDepOptimizationMetadata(
config,
ssr,
config.optimizeDeps.force,
Expand Down Expand Up @@ -340,12 +340,12 @@ export function addOptimizedDepInfo(
* Creates the initial dep optimization metadata, loading it from the deps cache
* if it exists and pre-bundling isn't forced
*/
export function loadCachedDepOptimizationMetadata(
export async function loadCachedDepOptimizationMetadata(
config: ResolvedConfig,
ssr: boolean,
force = config.optimizeDeps.force,
asCommand = false,
): DepOptimizationMetadata | undefined {
): Promise<DepOptimizationMetadata | undefined> {
const log = asCommand ? config.logger.info : debug

// Before Vite 2.9, dependencies were cached in the root of the cacheDir
Expand All @@ -361,7 +361,7 @@ export function loadCachedDepOptimizationMetadata(
try {
const cachedMetadataPath = path.join(depsCacheDir, '_metadata.json')
cachedMetadata = parseDepsOptimizerMetadata(
fs.readFileSync(cachedMetadataPath, 'utf-8'),
await fsp.readFile(cachedMetadataPath, 'utf-8'),
depsCacheDir,
)
} catch (e) {}
Expand All @@ -377,7 +377,7 @@ export function loadCachedDepOptimizationMetadata(
}

// Start with a fresh cache
fs.rmSync(depsCacheDir, { recursive: true, force: true })
await fsp.rm(depsCacheDir, { recursive: true, force: true })
}

/**
Expand Down Expand Up @@ -508,7 +508,11 @@ export function runOptimizeDeps(
const cleanUp = () => {
if (!cleaned) {
cleaned = true
fs.rmSync(processingCacheDir, { recursive: true, force: true })
// No need to wait, we can clean up in the background because temp folders
// are unique per run
fsp.rm(processingCacheDir, { recursive: true, force: true }).catch(() => {
// Ignore errors
})
}
}
const createProcessingResult = () => ({
Expand Down Expand Up @@ -1114,7 +1118,7 @@ export async function extractExportsData(
let parseResult: ReturnType<typeof parse>
let usedJsxLoader = false

const entryContent = fs.readFileSync(filePath, 'utf-8')
const entryContent = await fsp.readFile(filePath, 'utf-8')
try {
parseResult = parse(entryContent)
} catch {
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/optimizer/optimizer.ts
Expand Up @@ -99,7 +99,7 @@ async function createDepsOptimizer(

const sessionTimestamp = Date.now().toString()

const cachedMetadata = loadCachedDepOptimizationMetadata(config, ssr)
const cachedMetadata = await loadCachedDepOptimizationMetadata(config, ssr)

let handle: NodeJS.Timeout | undefined

Expand Down
5 changes: 3 additions & 2 deletions packages/vite/src/node/optimizer/scan.ts
@@ -1,4 +1,5 @@
import fs from 'node:fs'
import fsp from 'node:fs/promises'
import path from 'node:path'
import { performance } from 'node:perf_hooks'
import glob from 'fast-glob'
Expand Down Expand Up @@ -363,7 +364,7 @@ function esbuildScanPlugin(
build.onLoad(
{ filter: htmlTypesRE, namespace: 'html' },
async ({ path }) => {
let raw = fs.readFileSync(path, 'utf-8')
let raw = await fsp.readFile(path, 'utf-8')
// Avoid matching the content of the comment
raw = raw.replace(commentRE, '<!---->')
const isHtml = path.endsWith('.html')
Expand Down Expand Up @@ -576,7 +577,7 @@ function esbuildScanPlugin(
let ext = path.extname(id).slice(1)
if (ext === 'mjs') ext = 'js'

let contents = fs.readFileSync(id, 'utf-8')
let contents = await fsp.readFile(id, 'utf-8')
if (ext.endsWith('x') && config.esbuild && config.esbuild.jsxInject) {
contents = config.esbuild.jsxInject + `\n` + contents
}
Expand Down
5 changes: 3 additions & 2 deletions packages/vite/src/node/plugins/css.ts
@@ -1,4 +1,5 @@
import fs from 'node:fs'
import fsp from 'node:fs/promises'
import path from 'node:path'
import { createRequire } from 'node:module'
import glob from 'fast-glob'
Expand Down Expand Up @@ -1674,7 +1675,7 @@ async function rebaseUrls(
return { file }
}

const content = fs.readFileSync(file, 'utf-8')
const content = await fsp.readFile(file, 'utf-8')
// no url()
const hasUrls = cssUrlRE.test(content)
// data-uri() calls
Expand Down Expand Up @@ -1833,7 +1834,7 @@ function createViteLessPlugin(
if (result && 'contents' in result) {
contents = result.contents
} else {
contents = fs.readFileSync(resolved, 'utf-8')
contents = await fsp.readFile(resolved, 'utf-8')
}
return {
filename: path.resolve(resolved),
Expand Down
10 changes: 5 additions & 5 deletions packages/vite/src/node/server/hmr.ts
@@ -1,4 +1,4 @@
import fs from 'node:fs'
import fsp from 'node:fs/promises'
import path from 'node:path'
import type { Server } from 'node:http'
import colors from 'picocolors'
Expand Down Expand Up @@ -494,14 +494,14 @@ function error(pos: number) {
// change event and sometimes this can be too early and get an empty buffer.
// Poll until the file's modified time has changed before reading again.
async function readModifiedFile(file: string): Promise<string> {
const content = fs.readFileSync(file, 'utf-8')
const content = await fsp.readFile(file, 'utf-8')
if (!content) {
const mtime = fs.statSync(file).mtimeMs
const mtime = (await fsp.stat(file)).mtimeMs
await new Promise((r) => {
let n = 0
const poll = async () => {
n++
const newMtime = fs.statSync(file).mtimeMs
const newMtime = (await fsp.stat(file)).mtimeMs
if (newMtime !== mtime || n > 10) {
r(0)
} else {
Expand All @@ -510,7 +510,7 @@ async function readModifiedFile(file: string): Promise<string> {
}
setTimeout(poll, 10)
})
return fs.readFileSync(file, 'utf-8')
return await fsp.readFile(file, 'utf-8')
} else {
return content
}
Expand Down
3 changes: 2 additions & 1 deletion packages/vite/src/node/server/middlewares/indexHtml.ts
@@ -1,4 +1,5 @@
import fs from 'node:fs'
import fsp from 'node:fs/promises'
import path from 'node:path'
import MagicString from 'magic-string'
import type { SourceMapInput } from 'rollup'
Expand Down Expand Up @@ -292,7 +293,7 @@ export function indexHtmlMiddleware(
const filename = getHtmlFilename(url, server)
if (fs.existsSync(filename)) {
try {
let html = fs.readFileSync(filename, 'utf-8')
let html = await fsp.readFile(filename, 'utf-8')
html = await server.transformIndexHtml(url, html, req.originalUrl)
return send(req, res, html, 'html', {
headers: server.config.server.headers,
Expand Down