Skip to content

Commit afdeff5

Browse files
authored
chore: remove fs-extra as a dependency. (#40)
* chore: remove fs-extra as a dependency. Fixes https://linear.app/netlify/issue/FRA-91/remove-fs-extra-dependency * chore: update * chore: updates * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update
1 parent 9c2348a commit afdeff5

File tree

9 files changed

+165
-100
lines changed

9 files changed

+165
-100
lines changed

package-lock.json

+7-41
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"build:debug": "tsc --sourceMap",
1919
"build:watch": "tsc --watch",
2020
"test": "vitest",
21-
"test:ci": "vitest run --reporter=default"
21+
"test:ci": "vitest run --reporter=default --retry=3"
2222
},
2323
"repository": {
2424
"type": "git",
@@ -41,7 +41,6 @@
4141
"@netlify/build": "^29.20.6",
4242
"@netlify/functions": "^2.0.1",
4343
"@vercel/nft": "^0.24.3",
44-
"fs-extra": "^11.1.1",
4544
"globby": "^13.2.2",
4645
"os": "^0.1.2",
4746
"outdent": "^0.8.0",
@@ -51,7 +50,6 @@
5150
"@netlify/eslint-config-node": "^7.0.1",
5251
"@netlify/serverless-functions-api": "^1.10.1",
5352
"@netlify/zip-it-and-ship-it": "^9.25.5",
54-
"@types/fs-extra": "^11.0.1",
5553
"@types/mock-fs": "^4.13.1",
5654
"@types/uuid": "^9.0.6",
5755
"cheerio": "^1.0.0-rc.12",

src/build/cache.ts

+25-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { NetlifyPluginConstants, NetlifyPluginUtils } from '@netlify/build'
2-
import { ensureDir, move, pathExists } from 'fs-extra/esm'
2+
import { existsSync } from 'node:fs'
3+
import { mkdir, rename, rm } from 'node:fs/promises'
4+
import { join } from 'node:path'
35
import { BUILD_DIR } from './constants.js'
46

57
/**
@@ -9,15 +11,32 @@ export const moveBuildOutput = async (
911
{ PUBLISH_DIR }: NetlifyPluginConstants,
1012
utils: NetlifyPluginUtils,
1113
): Promise<void> => {
12-
if (!(await pathExists(PUBLISH_DIR))) {
14+
if (!existsSync(PUBLISH_DIR)) {
1315
utils.build.failBuild(
1416
'Your publish directory does not exist. Please check your netlify.toml file.',
1517
)
1618
}
1719

18-
// move the build output to a temp dir
19-
await move(PUBLISH_DIR, `${BUILD_DIR}/.next`, { overwrite: true })
20+
const tempDir = join(BUILD_DIR, '.next')
2021

21-
// recreate the publish dir so we can move the static content back
22-
await ensureDir(PUBLISH_DIR)
22+
try {
23+
// cleanup any existing directory
24+
await rm(tempDir, { force: true, recursive: true })
25+
await mkdir(tempDir, { recursive: true })
26+
// move the build output to a temp dir
27+
await rename(PUBLISH_DIR, tempDir)
28+
} catch (error) {
29+
if (error instanceof Error) {
30+
utils.build.failBuild(`Error moving the build output to the temp directory`, { error })
31+
}
32+
}
33+
34+
try {
35+
// recreate the publish dir so we can move the static content back
36+
await mkdir(PUBLISH_DIR, { recursive: true })
37+
} catch (error) {
38+
if (error instanceof Error) {
39+
utils.build.failBuild(`Error recreating publish directory`, { error })
40+
}
41+
}
2342
}

src/build/content/server.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,28 @@
1-
import { copy } from 'fs-extra/esm'
21
import { globby } from 'globby'
2+
import { existsSync } from 'node:fs'
3+
import { copyFile, mkdir } from 'node:fs/promises'
4+
import { dirname, join } from 'node:path'
35

46
/**
57
* Copy App/Pages Router Javascript needed by the server handler
68
*/
7-
export const copyServerContent = async (src: string, dest: string): Promise<Promise<void>[]> => {
9+
export const copyServerContent = async (src: string, dest: string): Promise<void> => {
810
const paths = await globby([`*`, `server/*`, `server/chunks/*`, `server/+(app|pages)/**/*.js`], {
911
cwd: src,
1012
extglob: true,
1113
})
1214

13-
return paths.map((path: string) => copy(`${src}/${path}`, `${dest}/${path}`))
15+
await Promise.all(
16+
paths.map(async (path: string) => {
17+
const srcPath = join(src, path)
18+
const destPath = join(dest, path)
19+
20+
if (!existsSync(srcPath)) {
21+
throw new Error(`Source file does not exist: ${srcPath}`)
22+
}
23+
24+
await mkdir(dirname(destPath), { recursive: true })
25+
await copyFile(srcPath, destPath)
26+
}),
27+
)
1428
}

src/build/content/static.ts

+47-13
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,73 @@
11
import { NetlifyPluginConstants } from '@netlify/build'
2-
import { copy, pathExists } from 'fs-extra/esm'
32
import { globby } from 'globby'
4-
import { ParsedPath, parse } from 'node:path'
3+
import { existsSync } from 'node:fs'
4+
import { copyFile, cp, mkdir } from 'node:fs/promises'
5+
import { ParsedPath, dirname, join, parse } from 'node:path'
56
import { BUILD_DIR, WORKING_DIR } from '../constants.js'
67

78
/**
89
* Copy static pages (HTML without associated JSON data)
910
*/
10-
const copyStaticPages = async (src: string, dest: string): Promise<Promise<void>[]> => {
11+
const copyStaticPages = async (src: string, dest: string): Promise<void> => {
1112
const paths = await globby([`server/pages/**/*.+(html|json)`], {
1213
cwd: src,
1314
extglob: true,
1415
})
1516

16-
return (
17+
await Promise.all(
1718
paths
1819
.map(parse)
1920
// keep only static files that do not have JSON data
2021
.filter(({ dir, name }: ParsedPath) => !paths.includes(`${dir}/${name}.json`))
21-
.map(({ dir, base }: ParsedPath) =>
22-
copy(`${src}/${dir}/${base}`, `${dest}/${dir.replace(/^server\/(app|pages)/, '')}/${base}`),
23-
)
22+
.map(async ({ dir, base }: ParsedPath) => {
23+
const srcPath = join(src, dir, base)
24+
const destPath = join(dest, dir.replace(/^server\/(app|pages)/, ''), base)
25+
26+
await mkdir(dirname(destPath), { recursive: true })
27+
await copyFile(srcPath, destPath)
28+
}),
2429
)
2530
}
2631

32+
/**
33+
* Copies static assets
34+
*/
35+
const copyStaticAssets = async ({
36+
PUBLISH_DIR,
37+
}: Pick<NetlifyPluginConstants, 'PUBLISH_DIR'>): Promise<void> => {
38+
try {
39+
const src = join(BUILD_DIR, '.next/static')
40+
const dist = join(PUBLISH_DIR, '_next/static')
41+
await mkdir(dist, { recursive: true })
42+
cp(src, dist, { recursive: true, force: true })
43+
} catch (error) {
44+
throw new Error(`Failed to copy static assets: ${error}`)
45+
}
46+
}
47+
48+
/**
49+
* Copies the public folder over
50+
*/
51+
const copyPublicAssets = async ({
52+
PUBLISH_DIR,
53+
}: Pick<NetlifyPluginConstants, 'PUBLISH_DIR'>): Promise<void> => {
54+
const src = join(WORKING_DIR, 'public')
55+
const dist = join(PUBLISH_DIR, 'public')
56+
if (!existsSync(src)) {
57+
return
58+
}
59+
60+
await mkdir(dist, { recursive: true })
61+
await cp(src, dist)
62+
}
63+
2764
/**
2865
* Move static content to the publish dir so it is uploaded to the CDN
2966
*/
3067
export const copyStaticContent = async ({ PUBLISH_DIR }: NetlifyPluginConstants): Promise<void> => {
3168
await Promise.all([
32-
// static pages
33-
Promise.all(await copyStaticPages(`${BUILD_DIR}/.next`, PUBLISH_DIR)),
34-
// static assets
35-
copy(`${BUILD_DIR}/.next/static/`, `${PUBLISH_DIR}/_next/static`),
36-
// public assets
37-
(await pathExists(`${WORKING_DIR}/public/`)) && copy(`${WORKING_DIR}/public/`, PUBLISH_DIR),
69+
copyStaticPages(`${BUILD_DIR}/.next`, PUBLISH_DIR),
70+
copyStaticAssets({ PUBLISH_DIR }),
71+
copyPublicAssets({ PUBLISH_DIR }),
3872
])
3973
}

src/build/functions/edge.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { emptyDir } from 'fs-extra/esm'
1+
import { mkdir, rm } from 'node:fs/promises'
22
import { EDGE_HANDLER_DIR } from '../constants.js'
33

44
/**
55
* Create a Netlify edge function to run the Next.js server
66
*/
77
export const createEdgeHandler = async () => {
88
// reset the handler directory
9-
await emptyDir(EDGE_HANDLER_DIR)
9+
await rm(EDGE_HANDLER_DIR, { recursive: true, force: true })
10+
await mkdir(EDGE_HANDLER_DIR, { recursive: true })
1011
}

0 commit comments

Comments
 (0)