mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-27 08:02:01 +00:00
refactor(ts): better DX for typescript support (#5079)
Breaking change : `build.useForkTsChecker` renamed to `build.typescript.typeCheck`
This commit is contained in:
parent
821676511b
commit
920f444b6e
@ -9,6 +9,7 @@ coverage
|
|||||||
## cofeescript
|
## cofeescript
|
||||||
examples/coffeescript/pages/index.vue
|
examples/coffeescript/pages/index.vue
|
||||||
examples/pug-stylus-coffee/
|
examples/pug-stylus-coffee/
|
||||||
|
examples/typescript-eslint/
|
||||||
# Packages
|
# Packages
|
||||||
|
|
||||||
# vue-app
|
# vue-app
|
||||||
|
@ -1,21 +1,8 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
const { resolve } = require('path')
|
|
||||||
|
|
||||||
// Globally indicate we are running in ts mode
|
|
||||||
process.env.NUXT_TS = 'true'
|
|
||||||
|
|
||||||
const nuxtCommands = ['dev', 'build', 'generate', 'start']
|
|
||||||
const rootDir = (process.argv[2] && !nuxtCommands.includes(process.argv[2])) ? process.argv[2] : process.cwd()
|
|
||||||
const tsConfigPath = resolve(rootDir, 'tsconfig.json')
|
|
||||||
|
|
||||||
const suffix = require('../package.json').name.includes('-edge') ? '-edge' : ''
|
const suffix = require('../package.json').name.includes('-edge') ? '-edge' : ''
|
||||||
|
require('@nuxt/cli' + suffix).run()
|
||||||
const errorHandler = (error) => {
|
.catch((error) => {
|
||||||
require('consola').fatal(error)
|
require('consola').fatal(error)
|
||||||
process.exit(2)
|
process.exit(2)
|
||||||
}
|
})
|
||||||
|
|
||||||
require('@nuxt/typescript' + suffix).setup(tsConfigPath).then(() => {
|
|
||||||
require('@nuxt/cli' + suffix).run().catch(errorHandler)
|
|
||||||
}).catch(errorHandler)
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
apps: [
|
apps: [
|
||||||
{
|
{
|
||||||
name: 'pm2-nuxt-ts',
|
name: 'pm2-nuxt-typescript',
|
||||||
script: './node_modules/.bin/nuxt-ts',
|
script: './node_modules/.bin/nuxt',
|
||||||
args: 'start',
|
args: 'start',
|
||||||
instances: 2,
|
instances: 2,
|
||||||
exec_mode: 'cluster',
|
exec_mode: 'cluster',
|
||||||
|
@ -2,17 +2,16 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nuxt-ts": "latest",
|
"nuxt": "latest",
|
||||||
"vue-property-decorator": "^7.3.0"
|
"vue-property-decorator": "^7.3.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nuxt-ts",
|
"dev": "nuxt",
|
||||||
"build": "nuxt-ts build",
|
"build": "nuxt build",
|
||||||
"start": "nuxt-ts start",
|
"start": "nuxt start",
|
||||||
"generate": "nuxt-ts generate",
|
"generate": "nuxt generate"
|
||||||
"lint": "tslint --project ."
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tslint-config-standard": "^8.0.1"
|
"@nuxt/typescript": "latest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1 @@
|
|||||||
{
|
{}
|
||||||
"extends": "@nuxt/typescript",
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": ".",
|
|
||||||
"types": [
|
|
||||||
"@types/node",
|
|
||||||
"@nuxt/vue-app"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"defaultSeverity": "error",
|
|
||||||
"extends": [
|
|
||||||
"tslint-config-standard"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"prefer-const": true
|
|
||||||
}
|
|
||||||
}
|
|
9
examples/typescript-eslint/.eslintrc.js
Normal file
9
examples/typescript-eslint/.eslintrc.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: ['@typescript-eslint'],
|
||||||
|
parserOptions: {
|
||||||
|
parser: '@typescript-eslint/parser'
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'@nuxtjs'
|
||||||
|
]
|
||||||
|
}
|
15
examples/typescript-eslint/.gitignore
vendored
Normal file
15
examples/typescript-eslint/.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log*
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
# Nuxt build
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# Nuxt generate
|
||||||
|
dist
|
33
examples/typescript-eslint/README.md
Normal file
33
examples/typescript-eslint/README.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Nuxt with TypeScript & ESLint example
|
||||||
|
|
||||||
|
Use `yarn lint` or `npm run lint` to lint your TypeScript project !
|
||||||
|
|
||||||
|
## Why ESLint and not TSLint ?
|
||||||
|
|
||||||
|
See https://eslint.org/blog/2019/01/future-typescript-eslint
|
||||||
|
|
||||||
|
##
|
||||||
|
|
||||||
|
## VSCode settings
|
||||||
|
|
||||||
|
If you're using VSCode, we recommend using these settings :
|
||||||
|
|
||||||
|
```json
|
||||||
|
"eslint.autoFixOnSave": true,
|
||||||
|
"eslint.validate": [
|
||||||
|
{
|
||||||
|
"language": "javascript",
|
||||||
|
"autoFix": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "typescript",
|
||||||
|
"autoFix": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"language": "vue",
|
||||||
|
"autoFix": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
It will lint your `.js`, `.ts` & `.vue` files whenever you're saving them.
|
1
examples/typescript-eslint/nuxt.config.ts
Normal file
1
examples/typescript-eslint/nuxt.config.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default {}
|
30
examples/typescript-eslint/package.json
Normal file
30
examples/typescript-eslint/package.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"nuxt": "latest",
|
||||||
|
"vue-property-decorator": "^7.3.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nuxt",
|
||||||
|
"build": "nuxt build",
|
||||||
|
"start": "nuxt start",
|
||||||
|
"generate": "nuxt generate",
|
||||||
|
"lint": "eslint --ext .ts,.js,.vue --ignore-path .gitignore .",
|
||||||
|
"lint:fix": "yarn lint --fix",
|
||||||
|
"post-update": "yarn upgrade --latest"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nuxt/typescript": "latest",
|
||||||
|
"@nuxtjs/eslint-config": "latest",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^1.4.2",
|
||||||
|
"eslint": "^5.14.1",
|
||||||
|
"eslint-config-standard": "^12.0.0",
|
||||||
|
"eslint-plugin-import": "^2.16.0",
|
||||||
|
"eslint-plugin-jest": "^22.3.0",
|
||||||
|
"eslint-plugin-node": "^8.0.1",
|
||||||
|
"eslint-plugin-promise": "^4.0.1",
|
||||||
|
"eslint-plugin-standard": "^4.0.0",
|
||||||
|
"eslint-plugin-vue": "^5.2.2"
|
||||||
|
}
|
||||||
|
}
|
14
examples/typescript-eslint/pages/index.vue
Normal file
14
examples/typescript-eslint/pages/index.vue
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue } from 'vue-property-decorator'
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class Home extends Vue {
|
||||||
|
title = 'TypeScript + ESLint example'
|
||||||
|
}
|
||||||
|
</script>
|
1
examples/typescript-eslint/tsconfig.json
Normal file
1
examples/typescript-eslint/tsconfig.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
@ -3,20 +3,18 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nuxt-ts",
|
"dev": "nuxt",
|
||||||
"build": "nuxt-ts build",
|
"build": "nuxt build",
|
||||||
"start": "nuxt-ts start",
|
"start": "nuxt start",
|
||||||
"generate": "nuxt-ts generate",
|
"generate": "nuxt generate",
|
||||||
"lint": "tslint --project .",
|
|
||||||
"lint:fix": "tslint --project . --fix",
|
|
||||||
"post-update": "yarn upgrade --latest",
|
"post-update": "yarn upgrade --latest",
|
||||||
"watch:css": "tcm components -w"
|
"watch:css": "tcm components -w"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nuxt-ts": "latest"
|
"nuxt": "latest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tslint-config-standard": "^8.0.1",
|
"@nuxt/typescript": "latest",
|
||||||
"typed-css-modules": "^0.3.7"
|
"typed-css-modules": "^0.3.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "@nuxt/typescript",
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
"jsx": "preserve",
|
||||||
"noImplicitThis": true,
|
"noImplicitThis": true
|
||||||
"types": ["@types/node", "@nuxt/vue-app"]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"defaultSeverity": "error",
|
|
||||||
"extends": ["tslint-config-standard"],
|
|
||||||
"rules": {
|
|
||||||
"prefer-const": true
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,20 +3,19 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.18.0",
|
"axios": "^0.18.0",
|
||||||
"nuxt-ts": "latest",
|
"nuxt": "latest",
|
||||||
"tachyons": "^4.11.1",
|
"tachyons": "^4.11.1",
|
||||||
"vue-property-decorator": "^7.3.0",
|
"vue-property-decorator": "^7.3.0",
|
||||||
"vuex-class": "^0.3.1"
|
"vuex-class": "^0.3.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nuxt-ts",
|
"dev": "nuxt",
|
||||||
"build": "nuxt-ts build",
|
"build": "nuxt build",
|
||||||
"start": "nuxt-ts start",
|
"start": "nuxt start",
|
||||||
"generate": "nuxt-ts generate",
|
"generate": "nuxt generate",
|
||||||
"lint": "tslint --project .",
|
|
||||||
"post-update": "yarn upgrade --latest"
|
"post-update": "yarn upgrade --latest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tslint-config-standard": "^8.0.1"
|
"@nuxt/typescript": "latest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1 @@
|
|||||||
{
|
{}
|
||||||
"extends": "@nuxt/typescript",
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": ".",
|
|
||||||
"noImplicitAny": false,
|
|
||||||
"types": [
|
|
||||||
"@types/node",
|
|
||||||
"@nuxt/vue-app"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"defaultSeverity": "error",
|
|
||||||
"extends": [
|
|
||||||
"tslint-config-standard"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"prefer-const": true
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,18 +2,17 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nuxt-ts": "latest",
|
"nuxt": "latest",
|
||||||
"vue-property-decorator": "^7.3.0"
|
"vue-property-decorator": "^7.3.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nuxt-ts",
|
"dev": "nuxt",
|
||||||
"build": "nuxt-ts build",
|
"build": "nuxt build",
|
||||||
"start": "nuxt-ts start",
|
"start": "nuxt start",
|
||||||
"generate": "nuxt-ts generate",
|
"generate": "nuxt generate",
|
||||||
"lint": "tslint --project .",
|
|
||||||
"post-update": "yarn upgrade --latest"
|
"post-update": "yarn upgrade --latest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tslint-config-standard": "^8.0.1"
|
"@nuxt/typescript": "latest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1 @@
|
|||||||
{
|
{}
|
||||||
"extends": "@nuxt/typescript",
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": ".",
|
|
||||||
"types": [
|
|
||||||
"@types/node",
|
|
||||||
"@nuxt/vue-app"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"defaultSeverity": "error",
|
|
||||||
"extends": [
|
|
||||||
"tslint-config-standard"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"prefer-const": true
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +1,12 @@
|
|||||||
|
|
||||||
|
import path from 'path'
|
||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
import minimist from 'minimist'
|
import minimist from 'minimist'
|
||||||
import { name, version } from '../package.json'
|
import { name, version } from '../package.json'
|
||||||
import { loadNuxtConfig, forceExit } from './utils'
|
import { loadNuxtConfig, forceExit } from './utils'
|
||||||
import { indent, foldLines, colorize } from './utils/formatting'
|
import { indent, foldLines, colorize } from './utils/formatting'
|
||||||
import { startSpaces, optionSpaces, forceExitTimeout } from './utils/constants'
|
import { startSpaces, optionSpaces, forceExitTimeout } from './utils/constants'
|
||||||
|
import { detectAndSetupTypeScriptSupport } from './utils/typescript'
|
||||||
import * as imports from './imports'
|
import * as imports from './imports'
|
||||||
|
|
||||||
export default class NuxtCommand {
|
export default class NuxtCommand {
|
||||||
@ -73,7 +76,10 @@ export default class NuxtCommand {
|
|||||||
return this._parsedArgv
|
return this._parsedArgv
|
||||||
}
|
}
|
||||||
|
|
||||||
async getNuxtConfig(extraOptions) {
|
async getNuxtConfig(extraOptions = {}) {
|
||||||
|
const rootDir = path.resolve(this.argv._[0] || '.')
|
||||||
|
extraOptions._typescript = await detectAndSetupTypeScriptSupport(rootDir, { transpileOnly: this.cmd.name === 'start' })
|
||||||
|
|
||||||
const config = await loadNuxtConfig(this.argv)
|
const config = await loadNuxtConfig(this.argv)
|
||||||
const options = Object.assign(config, extraOptions)
|
const options = Object.assign(config, extraOptions)
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { existsSync } from 'fs'
|
|
||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
import esm from 'esm'
|
import esm from 'esm'
|
||||||
import exit from 'exit'
|
import exit from 'exit'
|
||||||
@ -11,14 +10,14 @@ import prettyBytes from 'pretty-bytes'
|
|||||||
import env from 'std-env'
|
import env from 'std-env'
|
||||||
import { successBox, warningBox } from './formatting'
|
import { successBox, warningBox } from './formatting'
|
||||||
|
|
||||||
export const requireModule = process.env.NUXT_TS ? require : esm(module, {
|
const esmOptions = {
|
||||||
cache: false,
|
cache: false,
|
||||||
cjs: {
|
cjs: {
|
||||||
cache: true,
|
cache: true,
|
||||||
vars: true,
|
vars: true,
|
||||||
namedExports: true
|
namedExports: true
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
export const eventsMapping = {
|
export const eventsMapping = {
|
||||||
add: { icon: '+', color: 'green', action: 'Created' },
|
add: { icon: '+', color: 'green', action: 'Created' },
|
||||||
@ -26,18 +25,23 @@ export const eventsMapping = {
|
|||||||
unlink: { icon: '-', color: 'red', action: 'Removed' }
|
unlink: { icon: '-', color: 'red', action: 'Removed' }
|
||||||
}
|
}
|
||||||
|
|
||||||
const getRootDir = argv => path.resolve(argv._[0] || '.')
|
|
||||||
const getNuxtConfigFile = argv => path.resolve(getRootDir(argv), argv['config-file'])
|
|
||||||
|
|
||||||
export async function loadNuxtConfig(argv) {
|
export async function loadNuxtConfig(argv) {
|
||||||
const rootDir = getRootDir(argv)
|
const rootDir = path.resolve(argv._[0] || '.')
|
||||||
const nuxtConfigFile = getNuxtConfigFile(argv)
|
let nuxtConfigFile
|
||||||
|
|
||||||
let options = {}
|
let options = {}
|
||||||
|
|
||||||
if (existsSync(nuxtConfigFile)) {
|
try {
|
||||||
delete require.cache[nuxtConfigFile]
|
nuxtConfigFile = require.resolve(path.resolve(rootDir, argv['config-file']))
|
||||||
options = requireModule(nuxtConfigFile) || {}
|
} catch (e) {
|
||||||
|
if (e.code !== 'MODULE_NOT_FOUND') {
|
||||||
|
throw (e)
|
||||||
|
} else if (argv['config-file'] !== defaultNuxtConfigFile) {
|
||||||
|
consola.fatal('Could not load config file: ' + argv['config-file'])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nuxtConfigFile) {
|
||||||
|
options = (nuxtConfigFile.endsWith('.ts') ? require(nuxtConfigFile) : esm(module, esmOptions)(nuxtConfigFile)) || {}
|
||||||
if (options.default) {
|
if (options.default) {
|
||||||
options = options.default
|
options = options.default
|
||||||
}
|
}
|
||||||
@ -56,9 +60,8 @@ export async function loadNuxtConfig(argv) {
|
|||||||
|
|
||||||
// Keep _nuxtConfigFile for watching
|
// Keep _nuxtConfigFile for watching
|
||||||
options._nuxtConfigFile = nuxtConfigFile
|
options._nuxtConfigFile = nuxtConfigFile
|
||||||
} else if (argv['config-file'] !== defaultNuxtConfigFile) {
|
|
||||||
consola.fatal('Could not load config file: ' + argv['config-file'])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof options.rootDir !== 'string') {
|
if (typeof options.rootDir !== 'string') {
|
||||||
options.rootDir = rootDir
|
options.rootDir = rootDir
|
||||||
}
|
}
|
||||||
|
38
packages/cli/src/utils/typescript.js
Normal file
38
packages/cli/src/utils/typescript.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import { existsSync } from 'fs'
|
||||||
|
import chalk from 'chalk'
|
||||||
|
import consola from 'consola'
|
||||||
|
import { warningBox } from './formatting'
|
||||||
|
|
||||||
|
const dependencyNotFoundMessage =
|
||||||
|
`Please install @nuxt/typescript and rerun the command
|
||||||
|
|
||||||
|
${chalk.bold('Using yarn')}
|
||||||
|
yarn add -D @nuxt/typescript
|
||||||
|
|
||||||
|
${chalk.bold('Using npm')}
|
||||||
|
npm install -D @nuxt/typescript`
|
||||||
|
|
||||||
|
export async function detectAndSetupTypeScriptSupport(rootDir, options = {}) {
|
||||||
|
const tsConfigPath = path.resolve(rootDir, 'tsconfig.json')
|
||||||
|
|
||||||
|
if (!existsSync(tsConfigPath)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
consola.info(`${chalk.bold.blue('tsconfig.json')} found, enabling TypeScript runtime support`)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { setup } = require('@nuxt/typescript')
|
||||||
|
await setup(tsConfigPath, options)
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code === 'MODULE_NOT_FOUND') {
|
||||||
|
process.stdout.write(warningBox(dependencyNotFoundMessage, chalk.yellow('An external official dependency is needed to enable TS support')))
|
||||||
|
process.exit(1)
|
||||||
|
} else {
|
||||||
|
throw (e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
@ -14,7 +14,7 @@ exports[`cli/command builds help text 1`] = `
|
|||||||
--universal, -u Launch in Universal
|
--universal, -u Launch in Universal
|
||||||
mode (default)
|
mode (default)
|
||||||
--config-file, -c Path to Nuxt.js
|
--config-file, -c Path to Nuxt.js
|
||||||
config file (default: nuxt.config.js)
|
config file (default: nuxt.config)
|
||||||
--modern, -m Build/Start app for
|
--modern, -m Build/Start app for
|
||||||
modern browsers, e.g. server, client and
|
modern browsers, e.g. server, client and
|
||||||
false
|
false
|
||||||
|
@ -54,7 +54,9 @@ export default () => ({
|
|||||||
},
|
},
|
||||||
vueStyle: {}
|
vueStyle: {}
|
||||||
},
|
},
|
||||||
useForkTsChecker: process.env.NUXT_TS === 'true',
|
typescript: {
|
||||||
|
typeCheck: true
|
||||||
|
},
|
||||||
styleResources: {},
|
styleResources: {},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
terser: {},
|
terser: {},
|
||||||
|
@ -10,7 +10,7 @@ import router from './router'
|
|||||||
import server from './server'
|
import server from './server'
|
||||||
import cli from './cli'
|
import cli from './cli'
|
||||||
|
|
||||||
export const defaultNuxtConfigFile = `nuxt.config${process.env.NUXT_TS === 'true' ? '.ts' : '.js'}`
|
export const defaultNuxtConfigFile = 'nuxt.config'
|
||||||
|
|
||||||
export function getDefaultNuxtConfig(options = {}) {
|
export function getDefaultNuxtConfig(options = {}) {
|
||||||
if (!options.env) {
|
if (!options.env) {
|
||||||
|
@ -84,7 +84,7 @@ export function getNuxtConfig(_options) {
|
|||||||
|
|
||||||
// Default value for _nuxtConfigFile
|
// Default value for _nuxtConfigFile
|
||||||
if (!options._nuxtConfigFile) {
|
if (!options._nuxtConfigFile) {
|
||||||
options._nuxtConfigFile = path.resolve(options.rootDir, defaultNuxtConfigFile)
|
options._nuxtConfigFile = path.resolve(options.rootDir, `${defaultNuxtConfigFile}.js`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watch for _nuxtConfigFile changes
|
// Watch for _nuxtConfigFile changes
|
||||||
|
@ -131,7 +131,9 @@ Object {
|
|||||||
"templates": Array [],
|
"templates": Array [],
|
||||||
"terser": Object {},
|
"terser": Object {},
|
||||||
"transpile": Array [],
|
"transpile": Array [],
|
||||||
"useForkTsChecker": false,
|
"typescript": Object {
|
||||||
|
"typeCheck": true,
|
||||||
|
},
|
||||||
"watch": Array [],
|
"watch": Array [],
|
||||||
},
|
},
|
||||||
"buildDir": "/var/nuxt/test/.nuxt",
|
"buildDir": "/var/nuxt/test/.nuxt",
|
||||||
|
@ -121,7 +121,9 @@ Object {
|
|||||||
"templates": Array [],
|
"templates": Array [],
|
||||||
"terser": Object {},
|
"terser": Object {},
|
||||||
"transpile": Array [],
|
"transpile": Array [],
|
||||||
"useForkTsChecker": false,
|
"typescript": Object {
|
||||||
|
"typeCheck": true,
|
||||||
|
},
|
||||||
"watch": Array [],
|
"watch": Array [],
|
||||||
},
|
},
|
||||||
"buildDir": ".nuxt",
|
"buildDir": ".nuxt",
|
||||||
@ -450,7 +452,9 @@ Object {
|
|||||||
"templates": Array [],
|
"templates": Array [],
|
||||||
"terser": Object {},
|
"terser": Object {},
|
||||||
"transpile": Array [],
|
"transpile": Array [],
|
||||||
"useForkTsChecker": false,
|
"typescript": Object {
|
||||||
|
"typeCheck": true,
|
||||||
|
},
|
||||||
"watch": Array [],
|
"watch": Array [],
|
||||||
},
|
},
|
||||||
"buildDir": ".nuxt",
|
"buildDir": ".nuxt",
|
||||||
|
@ -4,8 +4,7 @@
|
|||||||
"repository": "nuxt/nuxt.js",
|
"repository": "nuxt/nuxt.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist"
|
||||||
"tsconfig.json"
|
|
||||||
],
|
],
|
||||||
"main": "dist/typescript.js",
|
"main": "dist/typescript.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -22,15 +21,11 @@
|
|||||||
"@types/webpack-bundle-analyzer": "^2.13.1",
|
"@types/webpack-bundle-analyzer": "^2.13.1",
|
||||||
"@types/webpack-dev-middleware": "^2.0.2",
|
"@types/webpack-dev-middleware": "^2.0.2",
|
||||||
"@types/webpack-hot-middleware": "^2.16.5",
|
"@types/webpack-hot-middleware": "^2.16.5",
|
||||||
"chalk": "^2.4.2",
|
|
||||||
"consola": "^2.5.6",
|
|
||||||
"enquirer": "^2.3.0",
|
|
||||||
"fork-ts-checker-webpack-plugin": "^1.0.0",
|
"fork-ts-checker-webpack-plugin": "^1.0.0",
|
||||||
"fs-extra": "^7.0.1",
|
"fs-extra": "^7.0.1",
|
||||||
"std-env": "^2.2.1",
|
"lodash": "^4.17.11",
|
||||||
"ts-loader": "^5.3.3",
|
"ts-loader": "^5.3.3",
|
||||||
"ts-node": "^8.0.3",
|
"ts-node": "^8.0.3",
|
||||||
"tslint": "^5.14.0",
|
|
||||||
"typescript": "^3.3.3333"
|
"typescript": "^3.3.3333"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
@ -1,53 +1,57 @@
|
|||||||
import chalk from 'chalk'
|
import { readJSON, writeJSON } from 'fs-extra'
|
||||||
import consola from 'consola'
|
|
||||||
import env from 'std-env'
|
|
||||||
import { prompt } from 'enquirer'
|
|
||||||
import { existsSync, writeJSON } from 'fs-extra'
|
|
||||||
import { register } from 'ts-node'
|
import { register } from 'ts-node'
|
||||||
|
import defaultsDeep from 'lodash/defaultsDeep'
|
||||||
|
|
||||||
async function generateTsConfig(tsConfigPath) {
|
export const defaultTsJsonConfig = {
|
||||||
const configToExtend = '@nuxt/typescript'
|
compilerOptions: {
|
||||||
await writeJSON(tsConfigPath, {
|
target: 'esnext',
|
||||||
extends: configToExtend,
|
module: 'esnext',
|
||||||
compilerOptions: {
|
moduleResolution: 'node',
|
||||||
baseUrl: '.',
|
lib: [
|
||||||
types: [
|
'esnext',
|
||||||
'@types/node',
|
'esnext.asynciterable',
|
||||||
'@nuxt/vue-app'
|
'dom'
|
||||||
|
],
|
||||||
|
esModuleInterop: true,
|
||||||
|
experimentalDecorators: true,
|
||||||
|
allowJs: true,
|
||||||
|
sourceMap: true,
|
||||||
|
strict: true,
|
||||||
|
noImplicitAny: false,
|
||||||
|
noEmit: true,
|
||||||
|
baseUrl: '.',
|
||||||
|
paths: {
|
||||||
|
'~/*': [
|
||||||
|
'./*'
|
||||||
|
],
|
||||||
|
'@/*': [
|
||||||
|
'./*'
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
}, { spaces: 2 })
|
types: [
|
||||||
consola.info(`Extending ${chalk.bold.blue(`node_modules/${configToExtend}/tsconfig.json`)}`)
|
'@types/node',
|
||||||
consola.success(`Generated successfully at ${chalk.bold.green(tsConfigPath)}`)
|
'@nuxt/vue-app'
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _setup = false
|
let _setup = false
|
||||||
|
|
||||||
export async function setup(tsConfigPath) {
|
export async function setup(tsConfigPath, options = {}) {
|
||||||
if (_setup) {
|
if (_setup) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_setup = true
|
_setup = true
|
||||||
|
|
||||||
if (!existsSync(tsConfigPath)) {
|
const config = await readJSON(tsConfigPath)
|
||||||
const { confirmGeneration } = await prompt({
|
await writeJSON(tsConfigPath, defaultsDeep(config, defaultTsJsonConfig), { spaces: 2 })
|
||||||
type: 'confirm',
|
|
||||||
name: 'confirmGeneration',
|
|
||||||
message: `${chalk.bold.blue(tsConfigPath)} is missing, generate it ?`,
|
|
||||||
initial: true,
|
|
||||||
skip: env.minimal
|
|
||||||
})
|
|
||||||
|
|
||||||
if (confirmGeneration) {
|
|
||||||
await generateTsConfig(tsConfigPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// https://github.com/TypeStrong/ts-node
|
// https://github.com/TypeStrong/ts-node
|
||||||
register({
|
register({
|
||||||
project: tsConfigPath,
|
project: tsConfigPath,
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
module: 'commonjs'
|
module: 'commonjs'
|
||||||
},
|
},
|
||||||
transpileOnly: process.argv[2] === 'start'
|
...options
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import { resolve } from 'path'
|
import { resolve } from 'path'
|
||||||
import { exists, mkdirp, readJSON, remove } from 'fs-extra'
|
import { mkdirp, readJSON, remove, writeJSON } from 'fs-extra'
|
||||||
import { register } from 'ts-node'
|
import { register } from 'ts-node'
|
||||||
import { setup as setupTypeScript } from '@nuxt/typescript'
|
import { defaultTsJsonConfig, setup as setupTypeScript } from '@nuxt/typescript'
|
||||||
|
|
||||||
jest.mock('ts-node')
|
jest.mock('ts-node')
|
||||||
jest.mock('enquirer', () => ({
|
|
||||||
prompt: jest.fn(() => ({ confirmGeneration: true }))
|
|
||||||
}))
|
|
||||||
|
|
||||||
describe('typescript setup', () => {
|
describe('typescript setup', () => {
|
||||||
const rootDir = 'tmp'
|
const rootDir = 'tmp'
|
||||||
@ -15,21 +12,12 @@ describe('typescript setup', () => {
|
|||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
// We're assuming that rootDir provided to setupTypeScript is existing so we create the tested one
|
// We're assuming that rootDir provided to setupTypeScript is existing so we create the tested one
|
||||||
await mkdirp(rootDir)
|
await mkdirp(rootDir)
|
||||||
|
await writeJSON(tsConfigPath, {})
|
||||||
await setupTypeScript(tsConfigPath)
|
await setupTypeScript(tsConfigPath)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('tsconfig.json has been generated if missing', async () => {
|
test('tsconfig.json has been updated with defaults', async () => {
|
||||||
expect(await exists(tsConfigPath)).toBe(true)
|
expect(await readJSON(tsConfigPath)).toEqual(defaultTsJsonConfig)
|
||||||
expect(await readJSON(tsConfigPath)).toEqual({
|
|
||||||
extends: '@nuxt/typescript',
|
|
||||||
compilerOptions: {
|
|
||||||
baseUrl: '.',
|
|
||||||
types: [
|
|
||||||
'@types/node',
|
|
||||||
'@nuxt/vue-app'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('ts-node has been registered once', async () => {
|
test('ts-node has been registered once', async () => {
|
||||||
@ -41,13 +29,12 @@ describe('typescript setup', () => {
|
|||||||
project: tsConfigPath,
|
project: tsConfigPath,
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
module: 'commonjs'
|
module: 'commonjs'
|
||||||
},
|
}
|
||||||
transpileOnly: false
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
// Clean workspace by removing the temporary folder (and the generated tsconfig.json at the same time)
|
// Clean workspace by removing the temporary folder (and the generated tsconfig.json at the same time)
|
||||||
await remove(tsConfigPath)
|
await remove(rootDir)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "esnext",
|
|
||||||
"module": "esnext",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"lib": [
|
|
||||||
"esnext",
|
|
||||||
"esnext.asynciterable",
|
|
||||||
"dom"
|
|
||||||
],
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"sourceMap": true,
|
|
||||||
"strict": true,
|
|
||||||
"noImplicitAny": true,
|
|
||||||
"noEmit": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"~/*": [
|
|
||||||
"./*"
|
|
||||||
],
|
|
||||||
"@/*": [
|
|
||||||
"./*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import fs from 'fs'
|
|
||||||
import querystring from 'querystring'
|
import querystring from 'querystring'
|
||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
import webpack from 'webpack'
|
import webpack from 'webpack'
|
||||||
@ -77,7 +76,7 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
|
|
||||||
plugins() {
|
plugins() {
|
||||||
const plugins = super.plugins()
|
const plugins = super.plugins()
|
||||||
const { buildOptions, options: { appTemplatePath, buildDir, rootDir, modern } } = this.buildContext
|
const { buildOptions, options: { appTemplatePath, buildDir, modern, rootDir, _typescript } } = this.buildContext
|
||||||
|
|
||||||
// Generate output HTML for SSR
|
// Generate output HTML for SSR
|
||||||
if (buildOptions.ssr) {
|
if (buildOptions.ssr) {
|
||||||
@ -140,21 +139,16 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
|
|
||||||
// TypeScript type checker
|
// TypeScript type checker
|
||||||
// Only performs once per client compilation and only if `ts-loader` checker is not used (transpileOnly: true)
|
// Only performs once per client compilation and only if `ts-loader` checker is not used (transpileOnly: true)
|
||||||
if (!this.isModern && this.loaders.ts.transpileOnly && buildOptions.useForkTsChecker) {
|
if (_typescript && buildOptions.typescript && buildOptions.typescript.typeCheck && !this.isModern && this.loaders.ts.transpileOnly) {
|
||||||
const forkTsCheckerResolvedPath = this.buildContext.nuxt.resolver.resolveModule('fork-ts-checker-webpack-plugin')
|
// We assume that "_typescript" being truthy means @nuxt/typescript is installed <=> fork-ts-checker-webpack-plugin is installed
|
||||||
if (forkTsCheckerResolvedPath) {
|
const ForkTsCheckerWebpackPlugin = require(this.buildContext.nuxt.resolver.resolveModule('fork-ts-checker-webpack-plugin'))
|
||||||
const ForkTsCheckerWebpackPlugin = require(forkTsCheckerResolvedPath)
|
plugins.push(new ForkTsCheckerWebpackPlugin(Object.assign({
|
||||||
plugins.push(new ForkTsCheckerWebpackPlugin(Object.assign({
|
vue: true,
|
||||||
vue: true,
|
tsconfig: path.resolve(rootDir, 'tsconfig.json'),
|
||||||
tsconfig: path.resolve(rootDir, 'tsconfig.json'),
|
tslint: false, // We recommend using ESLint so we set this option to `false` by default
|
||||||
// https://github.com/Realytics/fork-ts-checker-webpack-plugin#options - tslint: boolean | string - So we set it false if file not found
|
formatter: 'codeframe',
|
||||||
tslint: (tslintPath => fs.existsSync(tslintPath) && tslintPath)(path.resolve(rootDir, 'tslint.json')),
|
logger: consola
|
||||||
formatter: 'codeframe',
|
}, buildOptions.typescript.typeCheck)))
|
||||||
logger: consola
|
|
||||||
}, buildOptions.useForkTsChecker)))
|
|
||||||
} else {
|
|
||||||
consola.warn('You need to install `fork-ts-checker-webpack-plugin` as devDependency to enable TypeScript type checking !')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return plugins
|
return plugins
|
||||||
|
26
test/fixtures/typescript/tsconfig.json
vendored
26
test/fixtures/typescript/tsconfig.json
vendored
@ -1,8 +1,30 @@
|
|||||||
{
|
{
|
||||||
"extends": "@nuxt/typescript",
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
"target": "esnext",
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"lib": [
|
||||||
|
"esnext",
|
||||||
|
"esnext.asynciterable",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
|
"noEmit": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"~/*": [
|
||||||
|
"./*"
|
||||||
|
],
|
||||||
|
"@/*": [
|
||||||
|
"./*"
|
||||||
|
]
|
||||||
|
},
|
||||||
"types": [
|
"types": [
|
||||||
"@types/node",
|
"@types/node",
|
||||||
"@nuxt/vue-app"
|
"@nuxt/vue-app"
|
||||||
|
@ -8,7 +8,7 @@ describe('typescript modern', () => {
|
|||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const options = await loadFixture('typescript')
|
const options = await loadFixture('typescript')
|
||||||
nuxt = new Nuxt(Object.assign(options, { modern: true, build: { useForkTsChecker: true } }))
|
nuxt = new Nuxt(Object.assign(options, { modern: true, _typescript: true }))
|
||||||
await new Builder(nuxt, BundleBuilder).build()
|
await new Builder(nuxt, BundleBuilder).build()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -2184,7 +2184,7 @@ ansi-align@^3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
string-width "^3.0.0"
|
string-width "^3.0.0"
|
||||||
|
|
||||||
ansi-colors@^3.0.0, ansi-colors@^3.2.1:
|
ansi-colors@^3.0.0:
|
||||||
version "3.2.4"
|
version "3.2.4"
|
||||||
resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
|
resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
|
||||||
integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
|
integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
|
||||||
@ -4284,13 +4284,6 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
|
|||||||
memory-fs "^0.4.0"
|
memory-fs "^0.4.0"
|
||||||
tapable "^1.0.0"
|
tapable "^1.0.0"
|
||||||
|
|
||||||
enquirer@^2.3.0:
|
|
||||||
version "2.3.0"
|
|
||||||
resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.0.tgz#c362c9d84984ebe854def63caaf12983a16af552"
|
|
||||||
integrity sha512-RNGUbRVlfnjmpxV+Ed+7CGu0rg3MK7MmlW+DW0v7V2zdAUBC1s4BxCRiIAozbYB2UJ+q4D+8tW9UFb11kF72/g==
|
|
||||||
dependencies:
|
|
||||||
ansi-colors "^3.2.1"
|
|
||||||
|
|
||||||
entities@^1.1.1, entities@~1.1.1:
|
entities@^1.1.1, entities@~1.1.1:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
|
resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
|
||||||
|
Loading…
Reference in New Issue
Block a user