2018-03-16 19:11:24 +00:00
|
|
|
import path from 'path'
|
|
|
|
import fs from 'fs'
|
2018-10-18 15:43:44 +00:00
|
|
|
import defaultsDeep from 'lodash/defaultsDeep'
|
|
|
|
import defaults from 'lodash/defaults'
|
|
|
|
import pick from 'lodash/pick'
|
|
|
|
import isObject from 'lodash/isObject'
|
2018-11-29 13:16:46 +00:00
|
|
|
import uniq from 'lodash/uniq'
|
2018-04-13 06:50:39 +00:00
|
|
|
import consola from 'consola'
|
2019-01-14 20:31:39 +00:00
|
|
|
import { guardDir, isNonEmptyString, isPureObject, isUrl, getMainModule } from '@nuxt/utils'
|
2019-01-22 19:52:43 +00:00
|
|
|
import { defaultNuxtConfigFile, getDefaultNuxtConfig } from './config'
|
2018-03-16 17:23:15 +00:00
|
|
|
|
2018-10-30 20:42:53 +00:00
|
|
|
export function getNuxtConfig(_options) {
|
2018-12-09 10:42:22 +00:00
|
|
|
// Prevent duplicate calls
|
|
|
|
if (_options.__normalized__) {
|
|
|
|
return _options
|
|
|
|
}
|
|
|
|
|
2017-06-14 16:13:43 +00:00
|
|
|
// Clone options to prevent unwanted side-effects
|
|
|
|
const options = Object.assign({}, _options)
|
2018-12-09 10:42:22 +00:00
|
|
|
options.__normalized__ = true
|
2017-06-14 16:13:43 +00:00
|
|
|
|
|
|
|
// Normalize options
|
|
|
|
if (options.loading === true) {
|
|
|
|
delete options.loading
|
|
|
|
}
|
2018-01-13 05:22:11 +00:00
|
|
|
if (
|
|
|
|
options.router &&
|
|
|
|
options.router.middleware &&
|
|
|
|
!Array.isArray(options.router.middleware)
|
|
|
|
) {
|
2017-06-14 16:13:43 +00:00
|
|
|
options.router.middleware = [options.router.middleware]
|
|
|
|
}
|
|
|
|
if (options.router && typeof options.router.base === 'string') {
|
|
|
|
options._routerBaseSpecified = true
|
|
|
|
}
|
|
|
|
if (typeof options.transition === 'string') {
|
|
|
|
options.transition = { name: options.transition }
|
|
|
|
}
|
2017-09-08 10:42:00 +00:00
|
|
|
if (typeof options.layoutTransition === 'string') {
|
|
|
|
options.layoutTransition = { name: options.layoutTransition }
|
|
|
|
}
|
2018-01-04 17:10:17 +00:00
|
|
|
if (typeof options.extensions === 'string') {
|
2018-01-13 05:22:11 +00:00
|
|
|
options.extensions = [options.extensions]
|
2018-01-04 17:10:17 +00:00
|
|
|
}
|
2017-06-14 16:13:43 +00:00
|
|
|
|
2018-10-30 20:42:53 +00:00
|
|
|
options.globalName = (isNonEmptyString(options.globalName) && /^[a-zA-Z]+$/.test(options.globalName))
|
2018-10-09 12:07:23 +00:00
|
|
|
? options.globalName.toLowerCase()
|
2018-10-17 22:35:43 +00:00
|
|
|
: `nuxt`
|
2018-10-09 12:07:23 +00:00
|
|
|
|
2018-09-14 07:06:44 +00:00
|
|
|
// Resolve rootDir
|
2018-10-30 20:42:53 +00:00
|
|
|
options.rootDir = isNonEmptyString(options.rootDir) ? path.resolve(options.rootDir) : process.cwd()
|
2017-12-04 19:52:50 +00:00
|
|
|
|
|
|
|
// Apply defaults by ${buildDir}/dist/build.config.js
|
2017-12-13 02:17:44 +00:00
|
|
|
// TODO: Unsafe operation.
|
2018-03-16 17:23:15 +00:00
|
|
|
// const buildDir = options.buildDir || defaults.buildDir
|
2017-12-13 02:17:44 +00:00
|
|
|
// const buildConfig = resolve(options.rootDir, buildDir, 'build.config.js')
|
|
|
|
// if (existsSync(buildConfig)) {
|
2018-10-18 15:43:44 +00:00
|
|
|
// defaultsDeep(options, require(buildConfig))
|
2017-12-13 02:17:44 +00:00
|
|
|
// }
|
|
|
|
|
2017-06-14 16:13:43 +00:00
|
|
|
// Apply defaults
|
2018-10-30 20:42:53 +00:00
|
|
|
const nuxtConfig = getDefaultNuxtConfig()
|
2018-11-20 17:12:05 +00:00
|
|
|
|
2018-10-30 20:42:53 +00:00
|
|
|
nuxtConfig.build._publicPath = nuxtConfig.build.publicPath
|
2018-11-20 17:12:05 +00:00
|
|
|
|
|
|
|
// Fall back to default if publicPath is falsy
|
|
|
|
if (options.build && !options.build.publicPath) {
|
|
|
|
options.build.publicPath = undefined
|
|
|
|
}
|
|
|
|
|
2018-10-30 20:42:53 +00:00
|
|
|
defaultsDeep(options, nuxtConfig)
|
2017-06-14 16:13:43 +00:00
|
|
|
|
2018-12-12 06:31:49 +00:00
|
|
|
// Check srcDir and generate.dir existence
|
2018-10-30 20:42:53 +00:00
|
|
|
const hasSrcDir = isNonEmptyString(options.srcDir)
|
|
|
|
const hasGenerateDir = isNonEmptyString(options.generate.dir)
|
2018-09-14 07:06:44 +00:00
|
|
|
|
|
|
|
// Resolve srcDir
|
|
|
|
options.srcDir = hasSrcDir
|
2018-03-16 19:11:24 +00:00
|
|
|
? path.resolve(options.rootDir, options.srcDir)
|
2018-01-13 05:22:11 +00:00
|
|
|
: options.rootDir
|
2018-09-14 07:06:44 +00:00
|
|
|
|
|
|
|
// Resolve buildDir
|
2018-03-16 19:11:24 +00:00
|
|
|
options.buildDir = path.resolve(options.rootDir, options.buildDir)
|
2017-06-14 16:13:43 +00:00
|
|
|
|
2018-12-09 10:42:22 +00:00
|
|
|
// Default value for _nuxtConfigFile
|
|
|
|
if (!options._nuxtConfigFile) {
|
2019-01-22 19:52:43 +00:00
|
|
|
options._nuxtConfigFile = path.resolve(options.rootDir, defaultNuxtConfigFile)
|
2018-12-09 10:42:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Watch for _nuxtConfigFile changes
|
|
|
|
options.watch.push(options._nuxtConfigFile)
|
|
|
|
|
2018-09-14 07:06:44 +00:00
|
|
|
// Protect rootDir against buildDir
|
|
|
|
guardDir(options, 'rootDir', 'buildDir')
|
|
|
|
|
|
|
|
if (hasGenerateDir) {
|
|
|
|
// Resolve generate.dir
|
|
|
|
options.generate.dir = path.resolve(options.rootDir, options.generate.dir)
|
|
|
|
|
|
|
|
// Protect rootDir against buildDir
|
|
|
|
guardDir(options, 'rootDir', 'generate.dir')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hasSrcDir) {
|
|
|
|
// Protect srcDir against buildDir
|
|
|
|
guardDir(options, 'srcDir', 'buildDir')
|
|
|
|
|
|
|
|
if (hasGenerateDir) {
|
|
|
|
// Protect srcDir against generate.dir
|
|
|
|
guardDir(options, 'srcDir', 'generate.dir')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-13 01:09:38 +00:00
|
|
|
// Populate modulesDir
|
2018-11-29 13:16:46 +00:00
|
|
|
options.modulesDir = uniq(
|
2019-01-14 20:31:39 +00:00
|
|
|
getMainModule().paths.concat(
|
2018-11-29 13:16:46 +00:00
|
|
|
[].concat(options.modulesDir).map(dir => path.resolve(options.rootDir, dir))
|
|
|
|
)
|
|
|
|
)
|
2017-12-12 12:57:01 +00:00
|
|
|
|
2018-12-17 15:21:53 +00:00
|
|
|
const mandatoryExtensions = ['js', 'mjs', 'ts']
|
2018-01-04 17:10:17 +00:00
|
|
|
|
2018-10-12 22:31:19 +00:00
|
|
|
options.extensions = mandatoryExtensions
|
|
|
|
.filter(ext => !options.extensions.includes(ext))
|
|
|
|
.concat(options.extensions)
|
2018-03-16 20:04:54 +00:00
|
|
|
|
2017-06-14 16:13:43 +00:00
|
|
|
// If app.html is defined, set the template path to the user template
|
2018-08-10 15:23:09 +00:00
|
|
|
if (options.appTemplatePath === undefined) {
|
|
|
|
options.appTemplatePath = path.resolve(options.buildDir, 'views/app.template.html')
|
|
|
|
if (fs.existsSync(path.join(options.srcDir, 'app.html'))) {
|
|
|
|
options.appTemplatePath = path.join(options.srcDir, 'app.html')
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
options.appTemplatePath = path.resolve(options.srcDir, options.appTemplatePath)
|
2017-06-14 16:13:43 +00:00
|
|
|
}
|
|
|
|
|
2018-11-20 17:12:05 +00:00
|
|
|
options.build.publicPath = options.build.publicPath.replace(/([^/])$/, '$1/')
|
|
|
|
options.build._publicPath = options.build._publicPath.replace(/([^/])$/, '$1/')
|
|
|
|
|
2017-06-14 17:32:25 +00:00
|
|
|
// Ignore publicPath on dev
|
|
|
|
if (options.dev && isUrl(options.build.publicPath)) {
|
2018-10-30 20:42:53 +00:00
|
|
|
options.build.publicPath = options.build._publicPath
|
2017-06-14 17:32:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If store defined, update store options to true unless explicitly disabled
|
2018-02-27 13:38:00 +00:00
|
|
|
if (
|
|
|
|
options.store !== false &&
|
2018-03-16 19:11:24 +00:00
|
|
|
fs.existsSync(path.join(options.srcDir, options.dir.store)) &&
|
|
|
|
fs.readdirSync(path.join(options.srcDir, options.dir.store))
|
2018-02-27 13:38:00 +00:00
|
|
|
.find(filename => filename !== 'README.md' && filename[0] !== '.')
|
|
|
|
) {
|
2017-06-14 17:38:07 +00:00
|
|
|
options.store = true
|
2017-06-14 17:32:25 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 09:13:36 +00:00
|
|
|
// SPA loadingIndicator
|
|
|
|
if (options.loadingIndicator) {
|
|
|
|
// Normalize loadingIndicator
|
|
|
|
if (!isPureObject(options.loadingIndicator)) {
|
|
|
|
options.loadingIndicator = { name: options.loadingIndicator }
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply defaults
|
|
|
|
options.loadingIndicator = Object.assign(
|
|
|
|
{
|
2018-03-25 18:35:13 +00:00
|
|
|
name: 'default',
|
2018-03-25 19:10:39 +00:00
|
|
|
color: (options.loading && options.loading.color) || '#D3D3D3',
|
2018-03-25 18:35:13 +00:00
|
|
|
color2: '#F5F5F5',
|
2018-03-25 19:10:39 +00:00
|
|
|
background: (options.manifest && options.manifest.theme_color) || 'white',
|
2018-03-25 18:35:13 +00:00
|
|
|
dev: options.dev,
|
|
|
|
loading: options.messages.loading
|
2018-03-20 09:13:36 +00:00
|
|
|
},
|
|
|
|
options.loadingIndicator
|
|
|
|
)
|
2017-08-18 10:26:19 +00:00
|
|
|
}
|
2018-01-10 16:36:32 +00:00
|
|
|
|
2018-03-21 06:20:14 +00:00
|
|
|
// Debug errors
|
|
|
|
if (options.debug === undefined) {
|
|
|
|
options.debug = options.dev
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:31:27 +00:00
|
|
|
// Apply default hash to CSP option
|
2019-01-17 21:18:29 +00:00
|
|
|
const { csp } = options.render
|
|
|
|
|
2018-07-01 12:39:30 +00:00
|
|
|
const cspDefaults = {
|
|
|
|
hashAlgorithm: 'sha256',
|
|
|
|
allowedSources: undefined,
|
2018-07-30 16:04:02 +00:00
|
|
|
policies: undefined,
|
|
|
|
reportOnly: options.debug
|
2018-07-01 12:39:30 +00:00
|
|
|
}
|
|
|
|
if (csp) {
|
2018-10-18 15:43:44 +00:00
|
|
|
options.render.csp = defaults(isObject(csp) ? csp : {}, cspDefaults)
|
2018-01-10 16:31:27 +00:00
|
|
|
}
|
2017-08-18 10:26:19 +00:00
|
|
|
|
2017-08-20 08:38:38 +00:00
|
|
|
// cssSourceMap
|
|
|
|
if (options.build.cssSourceMap === undefined) {
|
|
|
|
options.build.cssSourceMap = options.dev
|
|
|
|
}
|
|
|
|
|
2018-11-08 20:47:53 +00:00
|
|
|
const babelConfig = options.build.babel
|
2018-03-09 06:30:50 +00:00
|
|
|
// babel cacheDirectory
|
2018-11-08 20:47:53 +00:00
|
|
|
if (babelConfig.cacheDirectory === undefined) {
|
|
|
|
babelConfig.cacheDirectory = options.dev
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: remove this warn in Nuxt 3
|
|
|
|
if (Array.isArray(babelConfig.presets)) {
|
|
|
|
const warnPreset = (presetName) => {
|
|
|
|
const oldPreset = '@nuxtjs/babel-preset-app'
|
|
|
|
const newPreset = '@nuxt/babel-preset-app'
|
|
|
|
if (presetName.includes(oldPreset)) {
|
|
|
|
presetName = presetName.replace(oldPreset, newPreset)
|
|
|
|
consola.warn('@nuxtjs/babel-preset-app has been deprecated, please use @nuxt/babel-preset-app.')
|
|
|
|
}
|
|
|
|
return presetName
|
|
|
|
}
|
|
|
|
babelConfig.presets = babelConfig.presets.map((preset) => {
|
|
|
|
const hasOptions = Array.isArray(preset)
|
|
|
|
if (hasOptions) {
|
|
|
|
preset[0] = warnPreset(preset[0])
|
|
|
|
} else if (typeof preset === 'string') {
|
|
|
|
preset = warnPreset(preset)
|
|
|
|
}
|
|
|
|
return preset
|
|
|
|
})
|
2018-03-09 06:30:50 +00:00
|
|
|
}
|
|
|
|
|
2018-08-08 19:05:23 +00:00
|
|
|
// vue config
|
|
|
|
const vueConfig = options.vue.config
|
|
|
|
|
|
|
|
if (vueConfig.silent === undefined) {
|
|
|
|
vueConfig.silent = !options.dev
|
|
|
|
}
|
|
|
|
if (vueConfig.performance === undefined) {
|
|
|
|
vueConfig.performance = options.dev
|
|
|
|
}
|
|
|
|
|
2018-09-08 21:08:25 +00:00
|
|
|
// merge custom env with variables
|
2018-10-18 15:43:44 +00:00
|
|
|
const eligibleEnvVariables = pick(process.env, Object.keys(process.env).filter(k => k.startsWith('NUXT_ENV_')))
|
2018-09-08 21:08:25 +00:00
|
|
|
Object.assign(options.env, eligibleEnvVariables)
|
|
|
|
|
2018-01-15 09:44:44 +00:00
|
|
|
// Normalize ignore
|
|
|
|
options.ignore = options.ignore ? [].concat(options.ignore) : []
|
|
|
|
|
|
|
|
// Append ignorePrefix glob to ignore
|
|
|
|
if (typeof options.ignorePrefix === 'string') {
|
|
|
|
options.ignore.push(`**/${options.ignorePrefix}*.*`)
|
|
|
|
}
|
|
|
|
|
2018-09-08 20:18:14 +00:00
|
|
|
// Compression middleware legacy
|
|
|
|
if (options.render.gzip) {
|
2018-09-13 15:07:34 +00:00
|
|
|
consola.warn('render.gzip is deprecated and will be removed in a future version! Please switch to render.compressor')
|
2018-09-08 20:18:14 +00:00
|
|
|
options.render.compressor = options.render.gzip
|
|
|
|
delete options.render.gzip
|
|
|
|
}
|
|
|
|
|
2017-08-19 13:22:53 +00:00
|
|
|
// Apply mode preset
|
2018-10-30 20:42:53 +00:00
|
|
|
const modePreset = options.modes[options.mode || 'universal']
|
2018-11-11 11:21:53 +00:00
|
|
|
|
|
|
|
if (!modePreset) {
|
|
|
|
consola.warn(`Unknown mode: ${options.mode}. Falling back to universal`)
|
|
|
|
}
|
|
|
|
defaultsDeep(options, modePreset || options.modes.universal)
|
2017-07-11 00:24:39 +00:00
|
|
|
|
2017-08-18 13:44:34 +00:00
|
|
|
// If no server-side rendering, add appear true transition
|
2017-11-16 10:56:41 +00:00
|
|
|
if (options.render.ssr === false && options.transition) {
|
2017-08-18 13:44:34 +00:00
|
|
|
options.transition.appear = true
|
|
|
|
}
|
|
|
|
|
2018-01-27 00:20:03 +00:00
|
|
|
// We assume the SPA fallback path is 404.html (for GitHub Pages, Surge, etc.)
|
|
|
|
if (options.generate.fallback === true) {
|
|
|
|
options.generate.fallback = '404.html'
|
|
|
|
}
|
|
|
|
|
2018-08-12 12:39:43 +00:00
|
|
|
if (options.build.stats === 'none' || options.build.quiet === true) {
|
2018-03-29 07:11:34 +00:00
|
|
|
options.build.stats = false
|
|
|
|
}
|
|
|
|
|
2018-04-13 06:50:39 +00:00
|
|
|
// Vendor backward compatibility with nuxt 1.x
|
|
|
|
if (typeof options.build.vendor !== 'undefined') {
|
|
|
|
delete options.build.vendor
|
|
|
|
consola.warn('vendor has been deprecated due to webpack4 optimization')
|
2018-04-12 20:42:50 +00:00
|
|
|
}
|
|
|
|
|
2019-02-13 10:32:13 +00:00
|
|
|
// Disable CSS extraction due to incompatibility with thread-loader
|
|
|
|
if (options.build && options.build.extractCSS && options.build.parallel) {
|
|
|
|
options.build.parallel = false
|
|
|
|
consola.warn('extractCSS cannot work with parallel build due to limited work pool in thread-loader')
|
|
|
|
}
|
|
|
|
|
2018-10-16 21:57:25 +00:00
|
|
|
// build.extractCSS.allChunks has no effect
|
|
|
|
if (typeof options.build.extractCSS.allChunks !== 'undefined') {
|
|
|
|
consola.warn('build.extractCSS.allChunks has no effect from v2.0.0. Please use build.optimization.splitChunks settings instead.')
|
|
|
|
}
|
|
|
|
|
2018-09-30 16:09:06 +00:00
|
|
|
// Enable minimize for production builds
|
|
|
|
if (options.build.optimization.minimize === undefined) {
|
|
|
|
options.build.optimization.minimize = !options.dev
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enable optimizeCSS only when extractCSS is enabled
|
|
|
|
if (options.build.optimizeCSS === undefined) {
|
|
|
|
options.build.optimizeCSS = options.build.extractCSS ? {} : false
|
|
|
|
}
|
|
|
|
|
2019-01-17 21:18:29 +00:00
|
|
|
const { loaders } = options.build
|
2018-09-10 08:27:01 +00:00
|
|
|
const vueLoader = loaders.vue
|
|
|
|
if (vueLoader.productionMode === undefined) {
|
|
|
|
vueLoader.productionMode = !options.dev
|
|
|
|
}
|
|
|
|
const styleLoaders = [
|
|
|
|
'css', 'cssModules', 'less',
|
|
|
|
'sass', 'scss', 'stylus', 'vueStyle'
|
|
|
|
]
|
|
|
|
for (const name of styleLoaders) {
|
|
|
|
const loader = loaders[name]
|
|
|
|
if (loader && loader.sourceMap === undefined) {
|
|
|
|
loader.sourceMap = Boolean(options.build.cssSourceMap)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-31 13:10:24 +00:00
|
|
|
options.build.transpile = [].concat(options.build.transpile || [])
|
2018-05-06 19:48:19 +00:00
|
|
|
|
2018-08-13 16:16:25 +00:00
|
|
|
if (options.build.quiet === true) {
|
|
|
|
consola.level = 0
|
|
|
|
}
|
|
|
|
|
2018-12-09 21:37:36 +00:00
|
|
|
// Use runInNewContext for dev mode by default
|
|
|
|
const { bundleRenderer } = options.render
|
|
|
|
if (typeof bundleRenderer.runInNewContext === 'undefined') {
|
|
|
|
bundleRenderer.runInNewContext = options.dev
|
|
|
|
}
|
|
|
|
|
2017-06-14 16:13:43 +00:00
|
|
|
return options
|
|
|
|
}
|