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

feat(create-next-app): add --ts, --typescript support #24655

Merged
merged 27 commits into from
May 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
30d849b
fix: do not compile template/ contents
ctjlewis Apr 30, 2021
9ce18d6
feat: add TypeScript create-next-app template
ctjlewis Apr 30, 2021
f0284fd
feat: add support for `-t, --typescript` option
ctjlewis Apr 30, 2021
55183d6
Merge remote-tracking branch 'upstream/canary' into create-next-app-t…
ctjlewis Apr 30, 2021
2402e48
Merge remote-tracking branch 'upstream/canary' into create-next-app-t…
ctjlewis May 1, 2021
b4a63ea
fix: do not transpile output in dist/
ctjlewis May 1, 2021
cb9fc80
chore: update `--typescript` option description
ctjlewis May 1, 2021
dafce6d
chore: document `--typescript` option in README
ctjlewis May 1, 2021
5614659
chore: better documentation, refactoring
ctjlewis May 1, 2021
df59c93
chore: add `next` as `devDependency`
ctjlewis May 1, 2021
2e535cd
chore: added comments, refactored code
ctjlewis May 1, 2021
9af3f44
chore: formatting
ctjlewis May 1, 2021
1103ab5
chore: comments, refactor
ctjlewis May 1, 2021
b3bc8fa
fix: add create-next-app templates to eslintignore
ctjlewis May 1, 2021
9c2970f
fix: use `yarn install --offline` when offline
ctjlewis May 1, 2021
5faf149
fix: ensure gitignore is included in template
ctjlewis May 1, 2021
dc352a1
fix: prefer `--ts` over `-t`
ctjlewis May 1, 2021
d950d42
fix: add `typescript` as devDependency when `--typescript` flag passed
ctjlewis May 2, 2021
5ee6c33
chore: use hyphen when logging deps
ctjlewis May 2, 2021
1554eff
Merge branch 'canary' into create-next-app-typescript
ctjlewis May 2, 2021
874783a
Merge branch 'canary' into create-next-app-typescript
ctjlewis May 4, 2021
8c0887a
Default to strict mode for new apps
timneutkens May 6, 2021
7fd159e
Add types (same as docs)
timneutkens May 6, 2021
5231ccb
Next has to be in dependencies
timneutkens May 6, 2021
dde8297
Add note to getting-started doc
timneutkens May 6, 2021
95dfde4
Add test for typescript flag
timneutkens May 6, 2021
1371c4d
Update order of arguments
timneutkens May 6, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ packages/next-codemod/transforms/__tests__/**/*
packages/next-codemod/**/*.js
packages/next-codemod/**/*.d.ts
packages/next-env/**/*.d.ts
packages/create-next-app/templates/**
test/integration/async-modules/**
test/integration/eslint/**
test-timings.json
8 changes: 8 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ npx create-next-app
yarn create next-app
```

If you want to start with a TypeScript project you can use the `--typescript` flag:

```bash
npx create-next-app --typescript
# or
yarn create next-app --typescript
```

After the installation is complete, follow the instructions to start the development server. Try editing `pages/index.js` and see the result on your browser.

For more information on how to use `create-next-app`, you can review the [`create-next-app` documentation](/docs/api-reference/create-next-app.md)
Expand Down
1 change: 1 addition & 0 deletions packages/create-next-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ npx create-next-app blog-app

`create-next-app` comes with the following options:

- **--ts, --typescript** - Initialize as a TypeScript project.
- **-e, --example [name]|[github-url]** - An example to bootstrap the app with. You can use an example name from the [Next.js repo](https://github.com/vercel/next.js/tree/master/examples) or a GitHub URL. The URL can use any branch and/or subdirectory.
- **--example-path <path-to-example>** - In a rare case, your GitHub URL might contain a branch name with a slash (e.g. bug/fix-1) and the path to the example (e.g. foo/bar). In this case, you must specify the path to the example separately: `--example-path foo/bar`
- **--use-npm** - Explicitly tell the CLI to bootstrap the app using npm. Yarn will be used by default if it's installed
Expand Down
81 changes: 70 additions & 11 deletions packages/create-next-app/create-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,16 @@ export async function createApp({
useNpm,
example,
examplePath,
typescript,
}: {
appPath: string
useNpm: boolean
example?: string
examplePath?: string
typescript?: boolean
}): Promise<void> {
let repoInfo: RepoInfo | undefined
const template = typescript ? 'typescript' : 'default'

if (example) {
let repoUrl: URL | undefined
Expand Down Expand Up @@ -124,6 +127,9 @@ export async function createApp({
process.chdir(root)

if (example) {
/**
* If an example repository is provided, clone it.
*/
try {
if (repoInfo) {
const repoInfo2 = repoInfo
Expand Down Expand Up @@ -154,7 +160,7 @@ export async function createApp({
const ignorePath = path.join(root, '.gitignore')
if (!fs.existsSync(ignorePath)) {
fs.copyFileSync(
path.join(__dirname, 'templates', 'default', 'gitignore'),
path.join(__dirname, 'templates', template, 'gitignore'),
ignorePath
)
}
Expand All @@ -165,30 +171,83 @@ export async function createApp({
await install(root, null, { useYarn, isOnline })
console.log()
} else {
/**
* Otherwise, if an example repository is not provided for cloning, proceed
* by installing from a template.
*/
console.log(chalk.bold(`Using ${displayedCommand}.`))
/**
* Create a package.json for the new project.
*/
const packageJson = {
name: appName,
version: '0.1.0',
private: true,
scripts: { dev: 'next dev', build: 'next build', start: 'next start' },
scripts: {
dev: 'next dev',
build: 'next build',
start: 'next start',
},
}
/**
* Write it to disk.
*/
fs.writeFileSync(
path.join(root, 'package.json'),
JSON.stringify(packageJson, null, 2) + os.EOL
)
/**
* These flags will be passed to `install()`.
*/
const installFlags = { useYarn, isOnline }
/**
* Default dependencies.
*/
const dependencies = ['react', 'react-dom', 'next']
/**
* Default devDependencies.
*/
const devDependencies = []
/**
* TypeScript projects will have type definitions and other devDependencies.
*/
if (typescript) {
devDependencies.push('typescript', '@types/react', '@types/next')
}
/**
* Install package.json dependencies if they exist.
*/
if (dependencies.length) {
console.log()
console.log('Installing dependencies:')
for (const dependency of dependencies) {
console.log(`- ${chalk.cyan(dependency)}`)
}
console.log()

console.log(
`Installing ${chalk.cyan('react')}, ${chalk.cyan(
'react-dom'
)}, and ${chalk.cyan('next')} using ${displayedCommand}...`
)
console.log()
await install(root, dependencies, installFlags)
}
/**
* Install package.json devDependencies if they exist.
*/
if (devDependencies.length) {
console.log()
console.log('Installing devDependencies:')
for (const devDependency of devDependencies) {
console.log(`- ${chalk.cyan(devDependency)}`)
}
console.log()

await install(root, ['react', 'react-dom', 'next'], { useYarn, isOnline })
const devInstallFlags = { devDependencies: true, ...installFlags }
await install(root, devDependencies, devInstallFlags)
}
console.log()

/**
* Copy the template files to the target directory.
*/
await cpy('**', root, {
parents: true,
cwd: path.join(__dirname, 'templates', 'default'),
cwd: path.join(__dirname, 'templates', template),
rename: (name) => {
switch (name) {
case 'gitignore': {
Expand Down
105 changes: 81 additions & 24 deletions packages/create-next-app/helpers/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,98 @@
import chalk from 'chalk'
import spawn from 'cross-spawn'

interface InstallArgs {
/**
* Indicate whether to install packages using Yarn.
*/
useYarn: boolean
/**
* Indicate whether there is an active Internet connection.
*/
isOnline: boolean
/**
* Indicate whether the given dependencies are devDependencies.
*/
devDependencies?: boolean
}

/**
* Spawn a package manager installation with either Yarn or NPM.
*
* @returns A Promise that resolves once the installation is finished.
*/
export function install(
root: string,
dependencies: string[] | null,
{ useYarn, isOnline }: { useYarn: boolean; isOnline: boolean }
{ useYarn, isOnline, devDependencies }: InstallArgs
): Promise<void> {
/**
* NPM-specific command-line flags.
*/
const npmFlags: string[] = ['--logLevel', 'error']
/**
* Yarn-specific command-line flags.
*/
const yarnFlags: string[] = []
/**
* Return a Promise that resolves once the installation is finished.
*/
return new Promise((resolve, reject) => {
let command: string
let args: string[]
if (useYarn) {
command = 'yarnpkg'
args = dependencies ? ['add', '--exact'] : ['install']
if (!isOnline) {
args.push('--offline')
}
if (dependencies) {
let command: string = useYarn ? 'yarnpkg' : 'npm'

if (dependencies && dependencies.length) {
/**
* If there are dependencies, run a variation of `{displayCommand} add`.
*/
if (useYarn) {
/**
* Call `yarn add --exact (--offline)? (-D)? ...`.
*/
args = ['add', '--exact']
if (!isOnline) args.push('--offline')
args.push('--cwd', root)
if (devDependencies) args.push('--dev')
args.push(...dependencies)
} else {
/**
* Call `npm install [--save|--save-dev] ...`.
*/
args = ['install', '--save-exact']
args.push(devDependencies ? '--save-dev' : '--save')
args.push(...dependencies)
}
args.push('--cwd', root)

if (!isOnline) {
console.log(chalk.yellow('You appear to be offline.'))
console.log(chalk.yellow('Falling back to the local Yarn cache.'))
console.log()
} else {
/**
* If there are no dependencies, run a variation of `{displayCommand}
* install`.
*/
args = ['install']
if (useYarn) {
if (!isOnline) {
console.log(chalk.yellow('You appear to be offline.'))
console.log(chalk.yellow('Falling back to the local Yarn cache.'))
console.log()
args.push('--offline')
}
} else {
if (!isOnline) {
console.log(chalk.yellow('You appear to be offline.'))
console.log()
}
}
}
/**
* Add any package manager-specific flags.
*/
if (useYarn) {
args.push(...yarnFlags)
} else {
command = 'npm'
args = ([
'install',
dependencies && '--save',
dependencies && '--save-exact',
'--loglevel',
'error',
].filter(Boolean) as string[]).concat(dependencies || [])
args.push(...npmFlags)
}

/**
* Spawn the installation process.
*/
const child = spawn(command, args, {
stdio: 'inherit',
env: { ...process.env, ADBLOCK: '1', DISABLE_OPENCOLLECTIVE: '1' },
Expand Down
22 changes: 20 additions & 2 deletions packages/create-next-app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,20 @@ const program = new Commander.Command(packageJson.name)
.action((name) => {
projectPath = name
})
.option('--use-npm', 'Explicitly tell the CLI to bootstrap the app using npm')
.option(
'--ts, --typescript',
`

Initialize as a TypeScript project.
`
)
.option(
'--use-npm',
`

Explicitly tell the CLI to bootstrap the app using npm
`
)
.option(
'-e, --example [name]|[github-url]',
`
Expand Down Expand Up @@ -113,6 +126,7 @@ async function run(): Promise<void> {
useNpm: !!program.useNpm,
example: example && example !== 'default' ? example : undefined,
examplePath: program.examplePath,
typescript: program.typescript,
})
} catch (reason) {
if (!(reason instanceof DownloadError)) {
Expand All @@ -131,7 +145,11 @@ async function run(): Promise<void> {
throw reason
}

await createApp({ appPath: resolvedProjectPath, useNpm: !!program.useNpm })
await createApp({
appPath: resolvedProjectPath,
useNpm: !!program.useNpm,
typescript: program.typescript,
})
}
}

Expand Down
34 changes: 34 additions & 0 deletions packages/create-next-app/templates/typescript/README-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
34 changes: 34 additions & 0 deletions packages/create-next-app/templates/typescript/gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel
2 changes: 2 additions & 0 deletions packages/create-next-app/templates/typescript/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
Loading