+
+
Welcome!
+
+ About Page
+
+
+
+
+
diff --git a/packages/builder/src/builder.js b/packages/builder/src/builder.js
index 3964862df5..a25bb8c02f 100644
--- a/packages/builder/src/builder.js
+++ b/packages/builder/src/builder.js
@@ -238,6 +238,8 @@ export default class Builder {
this.resolveMiddleware(templateContext)
])
+ this.addOptionalTemplates(templateContext)
+
await this.resolveCustomTemplates(templateContext)
await this.resolveLoadingIndicator(templateContext)
@@ -303,6 +305,16 @@ export default class Builder {
)
}
+ addOptionalTemplates (templateContext) {
+ if (this.options.build.indicator) {
+ templateContext.templateFiles.push('components/nuxt-build-indicator.vue')
+ }
+
+ if (this.options.loading !== false) {
+ templateContext.templateFiles.push('components/nuxt-loading.vue')
+ }
+ }
+
async resolveFiles (dir, cwd = this.options.srcDir) {
return this.ignore.filter(await glob(this.globPathWithExtensions(dir), {
cwd,
@@ -316,6 +328,10 @@ export default class Builder {
}
async resolveLayouts ({ templateVars, templateFiles }) {
+ if (!this.options.features.layouts) {
+ return
+ }
+
if (await fsExtra.exists(path.resolve(this.options.srcDir, this.options.dir.layouts))) {
for (const file of await this.resolveFiles(this.options.dir.layouts)) {
const name = file
@@ -409,7 +425,7 @@ export default class Builder {
async resolveStore ({ templateVars, templateFiles }) {
// Add store if needed
- if (!this.options.store) {
+ if (!this.options.features.store || !this.options.store) {
return
}
@@ -428,17 +444,20 @@ export default class Builder {
templateFiles.push('store.js')
}
- async resolveMiddleware ({ templateVars }) {
- // -- Middleware --
+ async resolveMiddleware ({ templateVars, templateFiles }) {
+ if (!this.options.features.middleware) {
+ return
+ }
+
const middleware = await this.resolveRelative(this.options.dir.middleware)
-
const extRE = new RegExp(`\\.(${this.supportedExtensions.join('|')})$`)
-
templateVars.middleware = middleware.map(({ src }) => {
const name = src.replace(extRE, '')
const dst = this.relativeToBuild(this.options.srcDir, this.options.dir.middleware, src)
return { name, src, dst }
})
+
+ templateFiles.push('middleware.js')
}
async resolveCustomTemplates (templateContext) {
diff --git a/packages/builder/src/context/template.js b/packages/builder/src/context/template.js
index c51e356122..fe5f04e938 100644
--- a/packages/builder/src/context/template.js
+++ b/packages/builder/src/context/template.js
@@ -11,6 +11,7 @@ export default class TemplateContext {
this.templateFiles = Array.from(builder.template.files)
this.templateVars = {
nuxtOptions: options,
+ features: options.features,
extensions: options.extensions
.map(ext => ext.replace(/^\./, ''))
.join('|'),
@@ -27,7 +28,7 @@ export default class TemplateContext {
router: options.router,
env: options.env,
head: options.head,
- store: options.store,
+ store: options.features.store ? options.store : false,
globalName: options.globalName,
globals: builder.globals,
css: options.css,
diff --git a/packages/builder/test/builder.generate.test.js b/packages/builder/test/builder.generate.test.js
index 9bd3ab5ad2..2d7e7b7b56 100644
--- a/packages/builder/test/builder.generate.test.js
+++ b/packages/builder/test/builder.generate.test.js
@@ -48,12 +48,14 @@ describe('builder: builder generate', () => {
},
watch: []
}
+
const builder = new Builder(nuxt, BundleBuilder)
builder.normalizePlugins = jest.fn(() => [{ name: 'test_plugin', src: '/var/somesrc' }])
builder.resolveLayouts = jest.fn(() => 'resolveLayouts')
builder.resolveRoutes = jest.fn(() => 'resolveRoutes')
builder.resolveStore = jest.fn(() => 'resolveStore')
builder.resolveMiddleware = jest.fn(() => 'resolveMiddleware')
+ builder.addOptionalTemplates = jest.fn()
builder.resolveCustomTemplates = jest.fn()
builder.resolveLoadingIndicator = jest.fn()
builder.compileTemplates = jest.fn()
@@ -77,6 +79,7 @@ describe('builder: builder generate', () => {
'resolveStore',
'resolveMiddleware'
])
+ expect(builder.addOptionalTemplates).toBeCalledTimes(1)
expect(builder.resolveCustomTemplates).toBeCalledTimes(1)
expect(builder.resolveLoadingIndicator).toBeCalledTimes(1)
expect(builder.options.build.watch).toEqual(['/var/nuxt/src/template/**/*.{vue,js}'])
@@ -124,6 +127,7 @@ describe('builder: builder generate', () => {
test('should resolve store modules', async () => {
const nuxt = createNuxt()
+ nuxt.options.features = { store: true }
nuxt.options.store = true
nuxt.options.dir = {
store: '/var/nuxt/src/store'
@@ -153,8 +157,26 @@ describe('builder: builder generate', () => {
expect(templateFiles).toEqual(['store.js'])
})
- test('should disable store resolving', async () => {
+ test('should disable store resolving when not set', async () => {
const nuxt = createNuxt()
+ nuxt.options.features = { store: false }
+ nuxt.options.dir = {
+ store: '/var/nuxt/src/store'
+ }
+ const builder = new Builder(nuxt, BundleBuilder)
+
+ const templateVars = {}
+ const templateFiles = []
+ await builder.resolveStore({ templateVars, templateFiles })
+
+ expect(templateVars.storeModules).toBeUndefined()
+ expect(templateFiles).toEqual([])
+ })
+
+ test('should disable store resolving when feature disabled', async () => {
+ const nuxt = createNuxt()
+ nuxt.options.features = { store: false }
+ nuxt.options.store = true
nuxt.options.dir = {
store: '/var/nuxt/src/store'
}
@@ -170,6 +192,7 @@ describe('builder: builder generate', () => {
test('should resolve middleware', async () => {
const nuxt = createNuxt()
+ nuxt.options.features = { middleware: true }
nuxt.options.store = false
nuxt.options.srcDir = '/var/nuxt/src'
nuxt.options.dir = {
@@ -183,13 +206,31 @@ describe('builder: builder generate', () => {
builder.relativeToBuild = jest.fn().mockReturnValue(middlewarePath)
const templateVars = {}
- await builder.resolveMiddleware({ templateVars })
+ const templateFiles = []
+ await builder.resolveMiddleware({ templateVars, templateFiles })
- expect(templateVars.middleware).toEqual([{
- name: 'subfolder/midd',
- src: 'subfolder/midd.js',
- dst: 'subfolder/midd.js'
- }])
+ expect(templateVars.middleware).toEqual([
+ {
+ name: 'subfolder/midd',
+ src: 'subfolder/midd.js',
+ dst: 'subfolder/midd.js'
+ }
+ ])
+ expect(templateFiles).toEqual(['middleware.js'])
+ })
+
+ test('should disable middleware when feature disabled', async () => {
+ const nuxt = createNuxt()
+ nuxt.options.features = { middleware: false }
+ nuxt.options.store = false
+ nuxt.options.dir = {
+ middleware: '/var/nuxt/src/middleware'
+ }
+ const builder = new Builder(nuxt, BundleBuilder)
+ const templateVars = {}
+ const templateFiles = []
+ await builder.resolveMiddleware({ templateVars, templateFiles })
+ expect(templateFiles).toEqual([])
})
test('should custom templates', async () => {
@@ -414,6 +455,7 @@ describe('builder: builder generate', () => {
describe('builder: builder resolveLayouts', () => {
test('should resolve layouts', async () => {
const nuxt = createNuxt()
+ nuxt.options.features = { layouts: true }
nuxt.options.srcDir = '/var/nuxt/src'
nuxt.options.buildDir = '/var/nuxt/build'
nuxt.options.dir = {
@@ -466,6 +508,7 @@ describe('builder: builder generate', () => {
test('should resolve error layouts', async () => {
const nuxt = createNuxt()
+ nuxt.options.features = { layouts: true }
nuxt.options.srcDir = '/var/nuxt/src'
nuxt.options.dir = {
layouts: '/var/nuxt/src/layouts'
@@ -493,6 +536,7 @@ describe('builder: builder generate', () => {
test('should not resolve layouts if layouts dir does not exist', async () => {
const nuxt = createNuxt()
+ nuxt.options.features = { layouts: true }
nuxt.options.srcDir = '/var/nuxt/src'
nuxt.options.dir = {
layouts: '/var/nuxt/src/layouts'
diff --git a/packages/builder/test/context/__snapshots__/template.test.js.snap b/packages/builder/test/context/__snapshots__/template.test.js.snap
index b40a5fddbc..873cea0853 100644
--- a/packages/builder/test/context/__snapshots__/template.test.js.snap
+++ b/packages/builder/test/context/__snapshots__/template.test.js.snap
@@ -20,6 +20,9 @@ TemplateContext {
],
"env": "test_env",
"extensions": "test|ext",
+ "features": Object {
+ "store": true,
+ },
"fetch": undefined,
"globalName": "test_global",
"globals": Array [
@@ -59,6 +62,9 @@ TemplateContext {
"test",
"ext",
],
+ "features": Object {
+ "store": true,
+ },
"globalName": "test_global",
"head": "test_head",
"layoutTransition": Object {
diff --git a/packages/builder/test/context/template.test.js b/packages/builder/test/context/template.test.js
index aa099be03d..982344ea3c 100644
--- a/packages/builder/test/context/template.test.js
+++ b/packages/builder/test/context/template.test.js
@@ -16,6 +16,7 @@ describe('builder: buildContext', () => {
relativeToBuild: jest.fn((...args) => `relativeBuild(${args.join(', ')})`)
}
const options = {
+ features: { store: true },
extensions: [ 'test', 'ext' ],
messages: { test: 'test message' },
build: {
diff --git a/packages/config/src/config/_app.js b/packages/config/src/config/_app.js
index 12df0a4927..5d285c875d 100644
--- a/packages/config/src/config/_app.js
+++ b/packages/config/src/config/_app.js
@@ -56,5 +56,22 @@ export default () => ({
layoutTransition: {
name: 'layout',
mode: 'out-in'
+ },
+
+ features: {
+ store: true,
+ layouts: true,
+ meta: true,
+ middleware: true,
+ transitions: true,
+ deprecations: true,
+ validate: true,
+ asyncData: true,
+ fetch: true,
+ clientOnline: true,
+ clientPrefetch: true,
+ clientUseUrl: false,
+ componentAliases: true,
+ componentClientOnly: true
}
})
diff --git a/packages/config/test/__snapshots__/options.test.js.snap b/packages/config/test/__snapshots__/options.test.js.snap
index 9f9917d0cc..5fe1eb9c02 100644
--- a/packages/config/test/__snapshots__/options.test.js.snap
+++ b/packages/config/test/__snapshots__/options.test.js.snap
@@ -166,6 +166,22 @@ Object {
"js",
"mjs",
],
+ "features": Object {
+ "asyncData": true,
+ "clientOnline": true,
+ "clientPrefetch": true,
+ "clientUseUrl": false,
+ "componentAliases": true,
+ "componentClientOnly": true,
+ "deprecations": true,
+ "fetch": true,
+ "layouts": true,
+ "meta": true,
+ "middleware": true,
+ "store": true,
+ "transitions": true,
+ "validate": true,
+ },
"fetch": Object {
"client": true,
"server": true,
diff --git a/packages/config/test/config/__snapshots__/index.test.js.snap b/packages/config/test/config/__snapshots__/index.test.js.snap
index c56a3e057c..a0eacacdb0 100644
--- a/packages/config/test/config/__snapshots__/index.test.js.snap
+++ b/packages/config/test/config/__snapshots__/index.test.js.snap
@@ -143,6 +143,22 @@ Object {
"env": Object {},
"extendPlugins": null,
"extensions": Array [],
+ "features": Object {
+ "asyncData": true,
+ "clientOnline": true,
+ "clientPrefetch": true,
+ "clientUseUrl": false,
+ "componentAliases": true,
+ "componentClientOnly": true,
+ "deprecations": true,
+ "fetch": true,
+ "layouts": true,
+ "meta": true,
+ "middleware": true,
+ "store": true,
+ "transitions": true,
+ "validate": true,
+ },
"fetch": Object {
"client": true,
"server": true,
@@ -474,6 +490,22 @@ Object {
"env": Object {},
"extendPlugins": null,
"extensions": Array [],
+ "features": Object {
+ "asyncData": true,
+ "clientOnline": true,
+ "clientPrefetch": true,
+ "clientUseUrl": false,
+ "componentAliases": true,
+ "componentClientOnly": true,
+ "deprecations": true,
+ "fetch": true,
+ "layouts": true,
+ "meta": true,
+ "middleware": true,
+ "store": true,
+ "transitions": true,
+ "validate": true,
+ },
"fetch": Object {
"client": true,
"server": true,
diff --git a/packages/vue-app/src/index.js b/packages/vue-app/src/index.js
index 3b188dbdae..93700aee9a 100644
--- a/packages/vue-app/src/index.js
+++ b/packages/vue-app/src/index.js
@@ -8,15 +8,12 @@ export const template = {
'App.js',
'client.js',
'index.js',
- 'middleware.js',
'router.js',
'router.scrollBehavior.js',
'server.js',
'utils.js',
'empty.js',
- 'components/nuxt-build-indicator.vue',
'components/nuxt-error.vue',
- 'components/nuxt-loading.vue',
'components/nuxt-child.js',
'components/nuxt-link.server.js',
'components/nuxt-link.client.js',
diff --git a/packages/vue-app/template/App.js b/packages/vue-app/template/App.js
index e6544907c3..c910e44fa0 100644
--- a/packages/vue-app/template/App.js
+++ b/packages/vue-app/template/App.js
@@ -1,11 +1,18 @@
import Vue from 'vue'
-import { getMatchedComponentsInstances, promisify, globalHandleError } from './utils'
+<% if (features.asyncData || features.fetch) { %>
+import {
+ getMatchedComponentsInstances,
+ promisify,
+ globalHandleError
+} from './utils'
+<% } %>
<% if (loading) { %>import NuxtLoading from '<%= (typeof loading === "string" ? loading : "./components/nuxt-loading.vue") %>'<% } %>
-<%if (buildIndicator) { %>import NuxtBuildIndicator from './components/nuxt-build-indicator'<% } %>
+<% if (buildIndicator) { %>import NuxtBuildIndicator from './components/nuxt-build-indicator'<% } %>
<% css.forEach((c) => { %>
import '<%= relativeToBuild(resolvePath(c.src || c, { isStyle: true })) %>'
<% }) %>
+<% if (features.layouts) { %>
<%= Object.keys(layouts).map((key) => {
if (splitChunks.layouts) {
return `const _${hash(key)} = () => import('${layouts[key]}' /* webpackChunkName: "${wChunk('layouts/' + key)}" */).then(m => m.default || m)`
@@ -17,13 +24,17 @@ import '<%= relativeToBuild(resolvePath(c.src || c, { isStyle: true })) %>'
const layouts = { <%= Object.keys(layouts).map(key => `"_${key}": _${hash(key)}`).join(',') %> }<%= isTest ? '// eslint-disable-line' : '' %>
<% if (splitChunks.layouts) { %>let resolvedLayouts = {}<% } %>
+<% } %>
export default {
+ <% if (features.meta) { %>
<%= isTest ? '/* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %>
head: <%= serializeFunction(head) %>,
<%= isTest ? '/* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %>
+ <% } %>
render(h, props) {
<% if (loading) { %>const loadingEl = h('NuxtLoading', { ref: 'loading' })<% } %>
+ <% if (features.layouts) { %>
const layoutEl = h(this.layout || 'nuxt')
const templateEl = h('div', {
domProps: {
@@ -31,7 +42,11 @@ export default {
},
key: this.layoutName
}, [ layoutEl ])
+ <% } else { %>
+ const templateEl = h('nuxt')
+ <% } %>
+ <% if (features.transitions) { %>
const transitionEl = h('transition', {
props: {
name: '<%= layoutTransition.name %>',
@@ -46,18 +61,29 @@ export default {
}
}
}, [ templateEl ])
+ <% } %>
return h('div', {
domProps: {
id: '<%= globals.id %>'
}
- }, [<% if (loading) { %>loadingEl, <% } %><%if (buildIndicator) { %>h(NuxtBuildIndicator), <% } %>transitionEl])
+ }, [
+ <% if (loading) { %>loadingEl, <% } %>
+ <% if (buildIndicator) { %>h(NuxtBuildIndicator), <% } %>
+ <% if (features.transitions) { %>transitionEl<% } else { %>templateEl<% } %>
+ ])
},
+ <% if (features.clientOnline || features.layouts) { %>
data: () => ({
+ <% if (features.clientOnline) { %>
isOnline: true,
+ <% } %>
+ <% if (features.layouts) { %>
layout: null,
layoutName: ''
+ <% } %>
}),
+ <% } %>
beforeCreate() {
Vue.util.defineReactive(this, 'nuxt', this.$options.nuxt)
},
@@ -67,10 +93,12 @@ export default {
// add to window so we can listen when ready
if (process.client) {
window.<%= globals.nuxt %> = <%= (globals.nuxt !== '$nuxt' ? 'window.$nuxt = ' : '') %>this
+ <% if (features.clientOnline) { %>
this.refreshOnlineStatus()
// Setup the listeners
window.addEventListener('online', this.refreshOnlineStatus)
window.addEventListener('offline', this.refreshOnlineStatus)
+ <% } %>
}
// Add $nuxt.error()
this.error = this.nuxt.error
@@ -85,12 +113,15 @@ export default {
'nuxt.err': 'errorChanged'
},
<% } %>
+ <% if (features.clientOnline) { %>
computed: {
isOffline() {
return !this.isOnline
}
},
+ <% } %>
methods: {
+ <% if (features.clientOnline) { %>
refreshOnlineStatus() {
if (process.client) {
if (typeof window.navigator.onLine === 'undefined') {
@@ -103,19 +134,25 @@ export default {
}
}
},
+ <% } %>
async refresh() {
+ <% if (features.asyncData || features.fetch) { %>
const pages = getMatchedComponentsInstances(this.$route)
if (!pages.length) {
return
}
<% if (loading) { %>this.$loading.start()<% } %>
+
const promises = pages.map(async (page) => {
const p = []
+ <% if (features.fetch) { %>
if (page.$options.fetch) {
p.push(promisify(page.$options.fetch, this.context))
}
+ <% } %>
+ <% if (features.asyncData) { %>
if (page.$options.asyncData) {
p.push(
promisify(page.$options.asyncData, this.context)
@@ -126,6 +163,7 @@ export default {
})
)
}
+ <% } %>
return Promise.all(p)
})
try {
@@ -136,6 +174,7 @@ export default {
this.error(error)
}
<% if (loading) { %>this.$loading.finish()<% } %>
+ <% } %>
},
<% if (loading) { %>
errorChanged() {
@@ -145,6 +184,7 @@ export default {
}
},
<% } %>
+ <% if (features.layouts) { %>
<% if (splitChunks.layouts) { %>
setLayout(layout) {
<% if (debug) { %>
@@ -193,9 +233,12 @@ export default {
}
return Promise.resolve(layouts['_' + layout])
}
- <% } %>
+ <% } /* splitChunks.layouts */ %>
+ <% } /* features.layouts */ %>
},
+ <% if (loading) { %>
components: {
- <%= (loading ? 'NuxtLoading' : '') %>
+ NuxtLoading
}
+ <% } %>
}
diff --git a/packages/vue-app/template/client.js b/packages/vue-app/template/client.js
index 8989281d4a..7cdc6b11df 100644
--- a/packages/vue-app/template/client.js
+++ b/packages/vue-app/template/client.js
@@ -1,15 +1,15 @@
import Vue from 'vue'
<% if (fetch.client) { %>import fetch from 'unfetch'<% } %>
-import middleware from './middleware.js'
+<% if (features.middleware) { %>import middleware from './middleware.js'<% } %>
import {
- applyAsyncData,
+ <% if (features.asyncData) { %>applyAsyncData,<% } %>
+ <% if (features.middleware) { %>middlewareSeries,<% } %>
sanitizeComponent,
resolveRouteComponents,
getMatchedComponents,
getMatchedComponentsInstances,
flatMapComponents,
setContext,
- middlewareSeries,
promisify,
getLocation,
compile,
@@ -17,7 +17,7 @@ import {
globalHandleError
} from './utils.js'
import { createApp, NuxtError } from './index.js'
-import NuxtLink from './components/nuxt-link.<%= router.prefetchLinks ? "client" : "server" %>.js' // should be included after ./index.js
+import NuxtLink from './components/nuxt-link.<%= features.clientPrefetch && router.prefetchLinks ? "client" : "server" %>.js' // should be included after ./index.js
<% if (isDev) { %>import consola from 'consola'<% } %>
<% if (isDev) { %>consola.wrapConsole()
@@ -26,7 +26,7 @@ console.log = console.__log
// Component: