From 2707bdb37e558672f0df60b2ab8bb553fe38824b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sun, 19 Jan 2020 09:36:06 +0100 Subject: [PATCH] feat: improve programatic usage (#6868) --- examples/programmatic/nuxt.config.js | 5 ++ examples/programmatic/package.json | 12 +++++ examples/programmatic/pages/index.vue | 5 ++ examples/programmatic/scripts/build.js | 8 +++ examples/programmatic/scripts/dev.js | 9 ++++ examples/programmatic/scripts/start.js | 8 +++ packages/builder/src/index.js | 9 ++++ packages/cli/src/utils/config.js | 67 ++++--------------------- packages/cli/test/unit/utils.test.js | 2 +- packages/config/src/index.js | 1 + packages/config/src/load.js | 68 ++++++++++++++++++++++++++ packages/core/src/index.js | 2 + packages/core/src/load.js | 40 +++++++++++++++ packages/generator/src/index.js | 5 ++ 14 files changed, 183 insertions(+), 58 deletions(-) create mode 100644 examples/programmatic/nuxt.config.js create mode 100644 examples/programmatic/package.json create mode 100644 examples/programmatic/pages/index.vue create mode 100644 examples/programmatic/scripts/build.js create mode 100644 examples/programmatic/scripts/dev.js create mode 100644 examples/programmatic/scripts/start.js create mode 100644 packages/config/src/load.js create mode 100644 packages/core/src/load.js diff --git a/examples/programmatic/nuxt.config.js b/examples/programmatic/nuxt.config.js new file mode 100644 index 0000000000..743331b422 --- /dev/null +++ b/examples/programmatic/nuxt.config.js @@ -0,0 +1,5 @@ +export default { + head: { + title: 'Programmatic Works' + } +} diff --git a/examples/programmatic/package.json b/examples/programmatic/package.json new file mode 100644 index 0000000000..bd2b095de9 --- /dev/null +++ b/examples/programmatic/package.json @@ -0,0 +1,12 @@ +{ + "name": "example-programmatic", + "dependencies": { + "nuxt": "latest" + }, + "scripts": { + "dev": "node scripts/dev", + "build": "node scripts/build", + "start": "node scripts/start", + "post-update": "yarn upgrade --latest" + } +} diff --git a/examples/programmatic/pages/index.vue b/examples/programmatic/pages/index.vue new file mode 100644 index 0000000000..e676eb3feb --- /dev/null +++ b/examples/programmatic/pages/index.vue @@ -0,0 +1,5 @@ + diff --git a/examples/programmatic/scripts/build.js b/examples/programmatic/scripts/build.js new file mode 100644 index 0000000000..2d30708bc2 --- /dev/null +++ b/examples/programmatic/scripts/build.js @@ -0,0 +1,8 @@ +const { loadNuxt, build } = require('nuxt') + +const main = async () => { + const nuxt = await loadNuxt({ for: 'build' }) + await build(nuxt) +} + +main() diff --git a/examples/programmatic/scripts/dev.js b/examples/programmatic/scripts/dev.js new file mode 100644 index 0000000000..2b6f1d5a29 --- /dev/null +++ b/examples/programmatic/scripts/dev.js @@ -0,0 +1,9 @@ +const { loadNuxt, build } = require('nuxt') + +const main = async () => { + const nuxt = await loadNuxt({ for: 'dev' }) + build(nuxt) + await nuxt.listen(3000) +} + +main() diff --git a/examples/programmatic/scripts/start.js b/examples/programmatic/scripts/start.js new file mode 100644 index 0000000000..8564596ffd --- /dev/null +++ b/examples/programmatic/scripts/start.js @@ -0,0 +1,8 @@ +const { loadNuxt } = require('nuxt-start') + +const main = async () => { + const nuxt = await loadNuxt({ for: 'start' }) + await nuxt.listen(3000) +} + +main() diff --git a/packages/builder/src/index.js b/packages/builder/src/index.js index cc0865b7e1..e00c399dec 100644 --- a/packages/builder/src/index.js +++ b/packages/builder/src/index.js @@ -1 +1,10 @@ +import Builder from './builder' export { default as Builder } from './builder' + +export function getBuilder (nuxt) { + return new Builder(nuxt) +} + +export function build (nuxt) { + return getBuilder(nuxt).build() +} diff --git a/packages/cli/src/utils/config.js b/packages/cli/src/utils/config.js index 227e366260..44ea8a5e7a 100644 --- a/packages/cli/src/utils/config.js +++ b/packages/cli/src/utils/config.js @@ -1,67 +1,20 @@ import path from 'path' -import consola from 'consola' import defaultsDeep from 'lodash/defaultsDeep' -import { defaultNuxtConfigFile, getDefaultNuxtConfig } from '@nuxt/config' -import { clearRequireCache, scanRequireTree } from '@nuxt/utils' -import esm from 'esm' +import { loadNuxtConfig as _loadNuxtConfig, getDefaultNuxtConfig } from '@nuxt/config' -export async function loadNuxtConfig (argv, context) { +export async function loadNuxtConfig (argv, configContext) { const rootDir = path.resolve(argv._[0] || '.') - let nuxtConfigFile - let options = {} + const configFile = argv['config-file'] - try { - nuxtConfigFile = require.resolve(path.resolve(rootDir, argv['config-file'])) - } 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) { - // Clear cache - clearRequireCache(nuxtConfigFile) - - options = esm(module)(nuxtConfigFile) || {} - - if (options.default) { - options = options.default - } - - if (typeof options === 'function') { - try { - options = await options(context) - if (options.default) { - options = options.default - } - } catch (error) { - consola.error(error) - consola.fatal('Error while fetching async configuration') - } - } - - // Don't mutate options export - options = Object.assign({}, options) - - // Keep _nuxtConfigFile for watching - options._nuxtConfigFile = nuxtConfigFile - - // Keep all related files for watching - options._nuxtConfigFiles = Array.from(scanRequireTree(nuxtConfigFile)) - if (!options._nuxtConfigFiles.includes(nuxtConfigFile)) { - options._nuxtConfigFiles.unshift(nuxtConfigFile) - } - } - - if (typeof options.rootDir !== 'string') { - options.rootDir = rootDir - } + // Load config + const options = await _loadNuxtConfig({ + rootDir, + configFile, + configContext + }) // Nuxt Mode - options.mode = - (argv.spa && 'spa') || (argv.universal && 'universal') || options.mode + options.mode = (argv.spa && 'spa') || (argv.universal && 'universal') || options.mode // Server options options.server = defaultsDeep({ diff --git a/packages/cli/test/unit/utils.test.js b/packages/cli/test/unit/utils.test.js index b30ce9ccbe..f40d85e9f7 100644 --- a/packages/cli/test/unit/utils.test.js +++ b/packages/cli/test/unit/utils.test.js @@ -56,7 +56,7 @@ describe('cli/utils', () => { expect(options.testOption).not.toBeDefined() expect(consola.fatal).toHaveBeenCalledTimes(1) - expect(consola.fatal).toHaveBeenCalledWith(expect.stringMatching(/Could not load config file/)) + expect(consola.fatal).toHaveBeenCalledWith(expect.stringMatching(/Config file not found/)) }) test('loadNuxtConfig: async config-file', async () => { diff --git a/packages/config/src/index.js b/packages/config/src/index.js index b0f66745b1..ecb6359c3e 100644 --- a/packages/config/src/index.js +++ b/packages/config/src/index.js @@ -1,2 +1,3 @@ export { defaultNuxtConfigFile, getDefaultNuxtConfig } from './config' export { getNuxtConfig } from './options' +export { loadNuxtConfig } from './load' diff --git a/packages/config/src/load.js b/packages/config/src/load.js new file mode 100644 index 0000000000..7c4a822c89 --- /dev/null +++ b/packages/config/src/load.js @@ -0,0 +1,68 @@ +import path from 'path' +import consola from 'consola' +import { clearRequireCache, scanRequireTree } from '@nuxt/utils' +import esm from 'esm' +import { defaultNuxtConfigFile } from './config' + +export async function loadNuxtConfig ({ + rootDir = '.', + configFile = defaultNuxtConfigFile, + configContext = {} +} = {}) { + rootDir = path.resolve(rootDir) + + let options = {} + + try { + configFile = require.resolve(path.resolve(rootDir, configFile)) + } catch (e) { + if (e.code !== 'MODULE_NOT_FOUND') { + throw (e) + } else if (configFile !== defaultNuxtConfigFile) { + consola.fatal('Config file not found: ' + configFile) + } + // Skip configFile if cannot resolve + configFile = undefined + } + + if (configFile) { + // Clear cache + clearRequireCache(configFile) + + options = esm(module)(configFile) || {} + + if (options.default) { + options = options.default + } + + if (typeof options === 'function') { + try { + options = await options(configContext) + if (options.default) { + options = options.default + } + } catch (error) { + consola.error(error) + consola.fatal('Error while fetching async configuration') + } + } + + // Don't mutate options export + options = Object.assign({}, options) + + // Keep _nuxtConfigFile for watching + options._nuxtConfigFile = configFile + + // Keep all related files for watching + options._nuxtConfigFiles = Array.from(scanRequireTree(configFile)) + if (!options._nuxtConfigFiles.includes(configFile)) { + options._nuxtConfigFiles.unshift(configFile) + } + } + + if (typeof options.rootDir !== 'string') { + options.rootDir = rootDir + } + + return options +} diff --git a/packages/core/src/index.js b/packages/core/src/index.js index 38ef78e5cd..f885225c90 100644 --- a/packages/core/src/index.js +++ b/packages/core/src/index.js @@ -1,3 +1,5 @@ export { default as Module } from './module' export { default as Nuxt } from './nuxt' export { default as Resolver } from './resolver' +export { loadNuxtConfig } from '@nuxt/config' +export { loadNuxt } from './load' diff --git a/packages/core/src/load.js b/packages/core/src/load.js new file mode 100644 index 0000000000..6ed0073c3e --- /dev/null +++ b/packages/core/src/load.js @@ -0,0 +1,40 @@ +import { loadNuxtConfig } from '@nuxt/config' +import Nuxt from './nuxt' + +const OVERRIDES = { + dry: { dev: false, server: false }, + dev: { dev: true, _build: true }, + build: { dev: false, server: false, _build: true }, + start: { dev: false, _start: true } +} + +export async function loadNuxt (loadOptions) { + // Normalize loadOptions + if (typeof loadOptions === 'string') { + loadOptions = { for: loadOptions } + } + const { ready = true } = loadOptions + const _for = loadOptions.for || 'dry' + + // Get overrides + const override = OVERRIDES[_for] + + // Unsupported purpose + if (!override) { + throw new Error('Unsupported for: ' + _for) + } + + // Load Config + const config = await loadNuxtConfig(loadOptions) + + // Apply config overrides + Object.assign(config, override) + + // Initiate Nuxt + const nuxt = new Nuxt(config) + if (ready) { + await nuxt.ready() + } + + return nuxt +} diff --git a/packages/generator/src/index.js b/packages/generator/src/index.js index a75639f90e..6e420c7e35 100644 --- a/packages/generator/src/index.js +++ b/packages/generator/src/index.js @@ -1 +1,6 @@ +import Generator from './generator' export { default as Generator } from './generator' + +export function getGenerator (nuxt) { + return new Generator(nuxt) +}