Skip to content

Commit

Permalink
refactor(cna): make create-next-app even smaller (#53241)
Browse files Browse the repository at this point in the history
The PR follows #53146 and #53115.

The PR does 3 things:

- Replaces a [very heavy dependency `cpy`](#53146 (comment)) with a more lightweight copy helper.
  - The `fs.cp(src, dest, {recursive: true})` API is not used, as it is still experimental:
  <img width="1630" alt="image" src="https://github.com/vercel/next.js/assets/40715044/c61a454a-3a96-4658-a389-fbb68c241f18">
- Update `cross-spawn` to the latest version `7.0.3`
  - The only breaking change introduced in `cross-spawn@7.x` is dropping Node.js 8 supports, which allows `cross-spawn` to drop a dependency. Since `create-next-app` requires Node.js 16.8.0, I assume bumping `cross-spawn` would be safe.
- Update `fast-glob` to the latest version `3.3.1` to remove more KiBs (pointed out by @imranbarbhuiya)
  - The breaking change introduced in `fast-glob@3.x` is dropping Node.js 8 supports and some options changes.

Together the PR removes another 202 KiB from the `create-next-app/dist/index.js`. The size of `create-next-app/dist/index.js` is now 616 KiB.

<img width="583" alt="image" src="https://github.com/vercel/next.js/assets/40715044/4deb5e36-a63b-4501-b67c-29ea06e30578">
  • Loading branch information
SukkaW committed Jul 28, 2023
1 parent 6046819 commit 127e30e
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 144 deletions.
50 changes: 50 additions & 0 deletions packages/create-next-app/helpers/copy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* eslint-disable import/no-extraneous-dependencies */
import { async as glob } from 'fast-glob'
import path from 'path'
import fs from 'fs'

interface CopyOption {
cwd?: string
rename?: (basename: string) => string
parents?: boolean
}

const identity = (x: string) => x

export const copy = async (
src: string | string[],
dest: string,
{ cwd, rename = identity, parents = true }: CopyOption = {}
) => {
const source = typeof src === 'string' ? [src] : src

if (source.length === 0 || !dest) {
throw new TypeError('`src` and `dest` are required')
}

const sourceFiles = await glob(source, {
cwd,
dot: true,
absolute: false,
stats: false,
})

const destRelativeToCwd = cwd ? path.resolve(cwd, dest) : dest

return Promise.all(
sourceFiles.map(async (p) => {
const dirname = path.dirname(p)
const basename = rename(path.basename(p))

const from = cwd ? path.resolve(cwd, p) : p
const to = parents
? path.join(destRelativeToCwd, dirname, basename)
: path.join(destRelativeToCwd, basename)

// Ensure the destination directory exists
await fs.promises.mkdir(path.dirname(to), { recursive: true })

return fs.promises.copyFile(from, to)
})
)
}
6 changes: 2 additions & 4 deletions packages/create-next-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
"@types/async-retry": "1.4.2",
"@types/ci-info": "2.0.0",
"@types/cross-spawn": "6.0.0",
"@types/glob": "7.1.1",
"@types/node": "^20.2.5",
"@types/prompts": "2.0.1",
"@types/tar": "6.1.5",
Expand All @@ -42,9 +41,8 @@
"ci-info": "watson/ci-info#f43f6a1cefff47fb361c88cf4b943fdbcaafe540",
"commander": "2.20.0",
"conf": "10.2.0",
"cpy": "7.3.0",
"cross-spawn": "6.0.5",
"fast-glob": "2.2.7",
"cross-spawn": "7.0.3",
"fast-glob": "3.3.1",
"got": "10.7.0",
"picocolors": "1.0.0",
"prettier-plugin-tailwindcss": "0.3.0",
Expand Down
18 changes: 7 additions & 11 deletions packages/create-next-app/templates/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { install } from '../helpers/install'
import { makeDir } from '../helpers/make-dir'
import { copy } from '../helpers/copy'

import cpy from 'cpy'
import { async as glob } from 'fast-glob'
import os from 'os'
import fs from 'fs'
Expand Down Expand Up @@ -50,14 +50,14 @@ export const installTemplate = async ({
if (!eslint) copySource.push('!eslintrc.json')
if (!tailwind) copySource.push('!tailwind.config.js', '!postcss.config.js')

await cpy(copySource, root, {
await copy(copySource, root, {
parents: true,
cwd: templatePath,
rename: (name) => {
rename(name) {
switch (name) {
case 'gitignore':
case 'eslintrc.json': {
return '.'.concat(name)
return `.${name}`
}
// README.md is ignored by webpack-asset-relocator-loader used by ncc:
// https://github.com/vercel/webpack-asset-relocator-loader/blob/e9308683d47ff507253e37c9bcbb99474603192b/src/asset-relocator.js#L227
Expand Down Expand Up @@ -87,7 +87,7 @@ export const installTemplate = async ({

// update import alias in any files if not using the default
if (importAlias !== '@/*') {
const files = await glob<string>('**/*', {
const files = await glob('**/*', {
cwd: root,
dot: true,
stats: false,
Expand Down Expand Up @@ -160,7 +160,7 @@ export const installTemplate = async ({
}

/**
* Create a package.json for the new project.
* Create a package.json for the new project and write it to disk.
*/
const packageJson = {
name: appName,
Expand All @@ -173,11 +173,7 @@ export const installTemplate = async ({
lint: 'next lint',
},
}

/**
* Write it to disk.
*/
fs.writeFileSync(
await fs.promises.writeFile(
path.join(root, 'package.json'),
JSON.stringify(packageJson, null, 2) + os.EOL
)
Expand Down

0 comments on commit 127e30e

Please sign in to comment.