diff --git a/examples/custom-layouts/layouts/error.vue b/examples/custom-layouts/layouts/error.vue
index 3b4dc0ffc7..126edd0af2 100644
--- a/examples/custom-layouts/layouts/error.vue
+++ b/examples/custom-layouts/layouts/error.vue
@@ -1,7 +1,7 @@
Page not found
- An error occured
+ An error occurred
Home page
diff --git a/examples/dynamic-layouts/layouts/error.vue b/examples/dynamic-layouts/layouts/error.vue
index 61f4ddcebd..aa064f32ec 100644
--- a/examples/dynamic-layouts/layouts/error.vue
+++ b/examples/dynamic-layouts/layouts/error.vue
@@ -1,7 +1,7 @@
Page not found
- An error occured
+ An error occurred
Home page
diff --git a/examples/typescript/store/modules/people.ts b/examples/typescript/store/modules/people.ts
index e73da3a343..25f3fb6f4a 100644
--- a/examples/typescript/store/modules/people.ts
+++ b/examples/typescript/store/modules/people.ts
@@ -29,7 +29,7 @@ export interface Person {
gender: string
ip_address: string
avatar: string
- addres: PersonAddress
+ address: PersonAddress
}
export interface State {
diff --git a/examples/web-worker/pages/index.vue b/examples/web-worker/pages/index.vue
index ce7cc49ce3..eb307006c3 100644
--- a/examples/web-worker/pages/index.vue
+++ b/examples/web-worker/pages/index.vue
@@ -82,7 +82,7 @@ export default {
if (worker) worker.postMessage({ hello: 'world' })
else this.notification = 'No more test workers available'
},
- long (miliseconds) {
+ long (milliseconds) {
let worker = this.workers.shift()
if (worker) {
@@ -96,7 +96,7 @@ export default {
worker = this.longRunningWorkers[ this.longIndex++ % this.longRunningWorkers.length]
}
- worker.postMessage({ action: 'expensive', time: miliseconds })
+ worker.postMessage({ action: 'expensive', time: milliseconds })
},
freeWorker () {
// we can't really free a worker, we can only terminate it and create a new
diff --git a/examples/with-vuetify/nuxt.config.js b/examples/with-vuetify/nuxt.config.js
index 050a1d9e14..90677abf77 100644
--- a/examples/with-vuetify/nuxt.config.js
+++ b/examples/with-vuetify/nuxt.config.js
@@ -14,8 +14,7 @@ export default {
},
build: {
- extractCSS: true,
- transpile: [/^vuetify/]
+ extractCSS: true
},
/*
** Load Vuetify into the app
diff --git a/lib/app/client.js b/lib/app/client.js
index feff703a95..8a8b01be40 100644
--- a/lib/app/client.js
+++ b/lib/app/client.js
@@ -674,7 +674,7 @@ async function mountApp(__app) {
if (!path) {
normalizeComponents(router.currentRoute, router.currentRoute)
showNextPage.call(_app, router.currentRoute)
- // Dont call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render
+ // Don't call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render
mount()
return
}
diff --git a/lib/builder/builder.js b/lib/builder/builder.js
index b1190f638a..bafaccfa7d 100644
--- a/lib/builder/builder.js
+++ b/lib/builder/builder.js
@@ -59,6 +59,15 @@ export default class Builder {
this.mfs = new MFS()
}
+ if (this.options.build.analyze) {
+ this.nuxt.hook('build:done', () => {
+ consola.warn({
+ message: 'Notice: Please do not deploy bundles built with analyze mode, it\'s only for analyzing purpose.',
+ badge: true
+ })
+ })
+ }
+
// if(!this.options.dev) {
// TODO: enable again when unsafe concern resolved.(common/options.js:42)
// this.nuxt.hook('build:done', () => this.generateConfig())
diff --git a/lib/builder/generator.js b/lib/builder/generator.js
index c04ef183b5..407ca32794 100644
--- a/lib/builder/generator.js
+++ b/lib/builder/generator.js
@@ -4,7 +4,7 @@ import htmlMinifier from 'html-minifier'
import Chalk from 'chalk'
import fsExtra from 'fs-extra'
import consola from 'consola'
-import { isUrl, promisifyRoute, waitFor, flatRoutes } from '../common/utils'
+import { flatRoutes, isUrl, promisifyRoute, waitFor } from '../common/utils'
export default class Generator {
constructor(nuxt, builder) {
@@ -223,9 +223,19 @@ export default class Generator {
return false
}
- if (this.options.generate.minify) {
+ let minificationOptions = this.options.build.html.minify
+
+ // Legacy: Override minification options with generate.minify if present
+ // TODO: Remove in Nuxt version 3
+ if (typeof this.options.generate.minify !== 'undefined') {
+ minificationOptions = this.options.generate.minify
+ consola.warn('generate.minify has been deprecated and will be removed in the next major version.' +
+ ' Use build.html.minify instead!')
+ }
+
+ if (minificationOptions) {
try {
- html = htmlMinifier.minify(html, this.options.generate.minify)
+ html = htmlMinifier.minify(html, minificationOptions)
} catch (err) /* istanbul ignore next */ {
const minifyErr = new Error(
`HTML minification failed. Make sure the route generates valid HTML. Failed HTML:\n ${html}`
diff --git a/lib/builder/webpack/client.js b/lib/builder/webpack/client.js
index 4ed5549aaf..f337374bfa 100644
--- a/lib/builder/webpack/client.js
+++ b/lib/builder/webpack/client.js
@@ -15,6 +15,16 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
super(builder, { name: 'client', isServer: false })
}
+ getFileName(...args) {
+ if (this.options.build.analyze) {
+ const key = args[0]
+ if (['app', 'chunk'].includes(key)) {
+ return '[name].js'
+ }
+ }
+ return super.getFileName(...args)
+ }
+
env() {
return Object.assign(super.env(), {
'process.env.VUE_ENV': JSON.stringify('client'),
@@ -53,7 +63,7 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
new HTMLPlugin({
filename: '../server/index.ssr.html',
template: this.options.appTemplatePath,
- minify: true,
+ minify: this.options.build.html.minify,
inject: false // Resources will be injected using bundleRenderer
})
)
@@ -63,7 +73,7 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
new HTMLPlugin({
filename: '../server/index.spa.html',
template: this.options.appTemplatePath,
- minify: true,
+ minify: this.options.build.html.minify,
inject: true,
chunksSortMode: 'dependency'
}),
@@ -99,31 +109,36 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
extendConfig() {
const config = super.extendConfig(...arguments)
- if (!this.options.dev && !config.optimization.minimizer) {
+ // Add minimizer plugins
+ if (config.optimization.minimize && config.optimization.minimizer === undefined) {
config.optimization.minimizer = []
// https://github.com/webpack-contrib/terser-webpack-plugin
- const terserJsPlugin = new TerserWebpackPlugin({
- parallel: true,
- cache: this.options.build.cache,
- sourceMap: config.devtool && /source-?map/.test(config.devtool),
- extractComments: {
- filename: 'LICENSES'
- },
- terserOptions: {
- output: {
- comments: /^\**!|@preserve|@license|@cc_on/
- }
- }
- })
- config.optimization.minimizer.push(terserJsPlugin)
+ if (this.options.build.terser) {
+ config.optimization.minimizer.push(
+ new TerserWebpackPlugin(Object.assign({
+ parallel: true,
+ cache: this.options.build.cache,
+ sourceMap: config.devtool && /source-?map/.test(config.devtool),
+ extractComments: {
+ filename: 'LICENSES'
+ },
+ terserOptions: {
+ output: {
+ comments: /^\**!|@preserve|@license|@cc_on/
+ }
+ }
+ }, this.options.build.terser))
+ )
+ }
// https://github.com/NMFR/optimize-css-assets-webpack-plugin
// https://github.com/webpack-contrib/mini-css-extract-plugin#minimizing-for-production
// TODO: Remove OptimizeCSSAssetsPlugin when upgrading to webpack 5
- if (this.options.build.extractCSS) {
- const optimizeCSSPlugin = new OptimizeCSSAssetsPlugin({})
- config.optimization.minimizer.push(optimizeCSSPlugin)
+ if (this.options.build.optimizeCSS) {
+ config.optimization.minimizer.push(
+ new OptimizeCSSAssetsPlugin(Object.assign({}, this.options.build.optimizeCSS))
+ )
}
}
diff --git a/lib/common/nuxt.config.js b/lib/common/nuxt.config.js
index 97004e3ec4..8eafd7f9ff 100644
--- a/lib/common/nuxt.config.js
+++ b/lib/common/nuxt.config.js
@@ -55,7 +55,7 @@ export default {
// { isDev, isClient, isServer }
app: ({ isDev }) => isDev ? '[name].js' : '[chunkhash].js',
chunk: ({ isDev }) => isDev ? '[name].js' : '[chunkhash].js',
- css: ({ isDev }) => isDev ? '[name].js' : '[contenthash].css',
+ css: ({ isDev }) => isDev ? '[name].css' : '[contenthash].css',
img: ({ isDev }) => isDev ? '[path][name].[ext]' : 'img/[hash:7].[ext]',
font: ({ isDev }) => isDev ? '[path][name].[ext]' : 'fonts/[hash:7].[ext]',
video: ({ isDev }) => isDev ? '[path][name].[ext]' : 'videos/[hash:7].[ext]'
@@ -87,8 +87,12 @@ export default {
},
styleResources: {},
plugins: [],
+ terser: {},
+ optimizeCSS: undefined,
optimization: {
runtimeChunk: 'single',
+ minimize: undefined,
+ minimizer: undefined,
splitChunks: {
chunks: 'all',
automaticNameDelimiter: '.',
@@ -112,6 +116,20 @@ export default {
stage: 2
}
},
+ html: {
+ minify: {
+ collapseBooleanAttributes: true,
+ decodeEntities: true,
+ minifyCSS: true,
+ minifyJS: true,
+ processConditionalComments: true,
+ removeEmptyAttributes: true,
+ removeRedundantAttributes: true,
+ trimCustomFragments: true,
+ useShortDoctype: true
+ }
+ },
+
templates: [],
watch: [],
devMiddleware: {},
@@ -136,27 +154,7 @@ export default {
concurrency: 500,
interval: 0,
subFolders: true,
- fallback: '200.html',
- minify: {
- collapseBooleanAttributes: true,
- collapseWhitespace: false,
- decodeEntities: true,
- minifyCSS: true,
- minifyJS: true,
- processConditionalComments: true,
- removeAttributeQuotes: false,
- removeComments: false,
- removeEmptyAttributes: true,
- removeOptionalTags: false,
- removeRedundantAttributes: true,
- removeScriptTypeAttributes: false,
- removeStyleLinkTypeAttributes: false,
- removeTagWhitespace: false,
- sortAttributes: true,
- sortClassName: false,
- trimCustomFragments: true,
- useShortDoctype: true
- }
+ fallback: '200.html'
},
env: {},
head: {
diff --git a/lib/common/options.js b/lib/common/options.js
index 86749abad5..f2f5c56e6f 100644
--- a/lib/common/options.js
+++ b/lib/common/options.js
@@ -239,6 +239,16 @@ Options.from = function (_options) {
options.build.extractCSS = false
}
+ // 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
+ }
+
const loaders = options.build.loaders
const vueLoader = loaders.vue
if (vueLoader.productionMode === undefined) {
diff --git a/package.json b/package.json
index 91ff75121f..b331057e40 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "nuxt",
- "version": "2.0.0",
+ "version": "2.1.0",
"description": "A minimalistic framework for server-rendered Vue.js applications (inspired by Next.js)",
"contributors": [
{
@@ -69,19 +69,19 @@
"npm": ">=5.0.0"
},
"dependencies": {
- "@babel/core": "^7.1.0",
+ "@babel/core": "^7.1.2",
"@babel/polyfill": "^7.0.0",
"@nuxtjs/babel-preset-app": "^0.7.0",
"@nuxtjs/friendly-errors-webpack-plugin": "^2.0.2",
"@nuxtjs/opencollective": "^0.1.0",
"@nuxtjs/youch": "^4.2.3",
- "babel-loader": "^8.0.2",
+ "babel-loader": "^8.0.4",
"cache-loader": "^1.2.2",
- "caniuse-lite": "^1.0.30000887",
+ "caniuse-lite": "^1.0.30000888",
"chalk": "^2.4.1",
"chokidar": "^2.0.4",
"compression": "^1.7.3",
- "connect": "^3.6.5",
+ "connect": "^3.6.6",
"consola": "^1.4.3",
"css-loader": "^1.0.0",
"cssnano": "^4.1.4",
@@ -92,9 +92,9 @@
"file-loader": "^2.0.0",
"fresh": "^0.5.2",
"fs-extra": "^7.0.0",
- "glob": "^7.1.2",
+ "glob": "^7.1.3",
"hash-sum": "^1.0.2",
- "html-minifier": "^3.5.19",
+ "html-minifier": "^3.5.20",
"html-webpack-plugin": "^3.2.0",
"ip": "^1.1.5",
"launch-editor-middleware": "^2.2.1",
@@ -105,11 +105,11 @@
"minimist": "^1.2.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"pify": "^4.0.0",
- "postcss": "^7.0.2",
+ "postcss": "^7.0.4",
"postcss-import": "^12.0.0",
"postcss-import-resolver": "^1.1.0",
"postcss-loader": "^3.0.0",
- "postcss-preset-env": "^6.0.3",
+ "postcss-preset-env": "^6.0.7",
"postcss-url": "^8.0.0",
"semver": "^5.5.1",
"serialize-javascript": "^1.5.0",
@@ -124,7 +124,7 @@
"url-loader": "^1.1.1",
"vue": "^2.5.17",
"vue-loader": "^15.4.2",
- "vue-meta": "1.5.3",
+ "vue-meta": "^1.5.5",
"vue-no-ssr": "^1.0.0",
"vue-router": "^3.0.1",
"vue-server-renderer": "^2.5.17",
@@ -139,14 +139,14 @@
},
"devDependencies": {
"@babel/preset-env": "^7.1.0",
- "babel-core": "^7.0.0-0",
- "babel-eslint": "^10.0.0",
+ "babel-core": "^7.0.0-bridge",
+ "babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
"babel-plugin-dynamic-import-node": "^2.1.0",
"codecov": "^3.1.0",
"cross-env": "^5.2.0",
"cross-spawn": "^6.0.5",
- "eslint": "^5.6.0",
+ "eslint": "^5.6.1",
"eslint-config-standard": "^12.0.0",
"eslint-config-standard-jsx": "^6.0.2",
"eslint-plugin-import": "^2.14.0",
@@ -156,7 +156,7 @@
"eslint-plugin-react": "^7.11.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^5.0.0-beta.3",
- "express": "^4.16.2",
+ "express": "^4.16.3",
"finalhandler": "^1.1.1",
"get-port": "^4.0.0",
"jest": "^23.6.0",
diff --git a/packages/nuxt-legacy/package.json b/packages/nuxt-legacy/package.json
index 787134f337..916e026370 100644
--- a/packages/nuxt-legacy/package.json
+++ b/packages/nuxt-legacy/package.json
@@ -55,19 +55,19 @@
"npm": ">=5.0.0"
},
"dependencies": {
- "@babel/core": "^7.1.0",
+ "@babel/core": "^7.1.2",
"@babel/polyfill": "^7.0.0",
"@nuxtjs/babel-preset-app": "^0.7.0",
"@nuxtjs/friendly-errors-webpack-plugin": "^2.0.2",
"@nuxtjs/opencollective": "^0.1.0",
"@nuxtjs/youch": "^4.2.3",
- "babel-loader": "^8.0.2",
+ "babel-loader": "^8.0.4",
"cache-loader": "^1.2.2",
- "caniuse-lite": "^1.0.30000887",
+ "caniuse-lite": "^1.0.30000888",
"chalk": "^2.4.1",
"chokidar": "^2.0.4",
"compression": "^1.7.3",
- "connect": "^3.6.5",
+ "connect": "^3.6.6",
"consola": "^1.4.3",
"css-loader": "^1.0.0",
"cssnano": "^4.1.4",
@@ -78,9 +78,9 @@
"file-loader": "^2.0.0",
"fresh": "^0.5.2",
"fs-extra": "^7.0.0",
- "glob": "^7.1.2",
+ "glob": "^7.1.3",
"hash-sum": "^1.0.2",
- "html-minifier": "^3.5.19",
+ "html-minifier": "^3.5.20",
"html-webpack-plugin": "^3.2.0",
"ip": "^1.1.5",
"launch-editor-middleware": "^2.2.1",
@@ -91,11 +91,11 @@
"minimist": "^1.2.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"pify": "^4.0.0",
- "postcss": "^7.0.2",
+ "postcss": "^7.0.4",
"postcss-import": "^12.0.0",
"postcss-import-resolver": "^1.1.0",
"postcss-loader": "^3.0.0",
- "postcss-preset-env": "^6.0.3",
+ "postcss-preset-env": "^6.0.7",
"postcss-url": "^8.0.0",
"semver": "^5.5.1",
"serialize-javascript": "^1.5.0",
@@ -110,7 +110,7 @@
"url-loader": "^1.1.1",
"vue": "^2.5.17",
"vue-loader": "^15.4.2",
- "vue-meta": "^1.5.4",
+ "vue-meta": "^1.5.5",
"vue-no-ssr": "^1.0.0",
"vue-router": "^3.0.1",
"vue-server-renderer": "^2.5.17",
diff --git a/packages/nuxt-start/package.json b/packages/nuxt-start/package.json
index f932da17e3..0b7267de74 100644
--- a/packages/nuxt-start/package.json
+++ b/packages/nuxt-start/package.json
@@ -58,7 +58,7 @@
"@nuxtjs/youch": "^4.2.3",
"chalk": "^2.4.1",
"compression": "^1.7.3",
- "connect": "^3.6.5",
+ "connect": "^3.6.6",
"consola": "^1.4.3",
"devalue": "^1.0.4",
"esm": "^3.0.84",
@@ -75,7 +75,7 @@
"server-destroy": "^1.0.1",
"std-env": "^1.3.1",
"vue": "^2.5.17",
- "vue-meta": "^1.5.4",
+ "vue-meta": "^1.5.5",
"vue-no-ssr": "^1.0.0",
"vue-router": "^3.0.1",
"vue-server-renderer": "^2.5.17",
diff --git a/test/fixtures/with-config/with-config.test.js b/test/fixtures/with-config/with-config.test.js
index 3de1cbe586..d16e0f0a1e 100644
--- a/test/fixtures/with-config/with-config.test.js
+++ b/test/fixtures/with-config/with-config.test.js
@@ -14,13 +14,19 @@ const hooks = [
describe('with-config', () => {
buildFixture('with-config', () => {
- expect(consola.warn).toHaveBeenCalledTimes(1)
+ expect(consola.warn).toHaveBeenCalledTimes(2)
expect(consola.fatal).toHaveBeenCalledTimes(0)
- expect(consola.warn.mock.calls[0]).toMatchObject([{
- message: 'Found 2 plugins that match the configuration, suggest to specify extension:',
- additional: expect.stringContaining('plugins/test.json'),
- badge: true
- }])
+ expect(consola.warn.mock.calls).toMatchObject([
+ [{
+ message: 'Found 2 plugins that match the configuration, suggest to specify extension:',
+ additional: expect.stringContaining('plugins/test.json'),
+ badge: true
+ }],
+ [{
+ message: 'Notice: Please do not deploy bundles built with analyze mode, it\'s only for analyzing purpose.',
+ badge: true
+ }]
+ ])
expect(customCompressionMiddlewareFunctionName).toBe('damn')
}, hooks)
})
diff --git a/test/unit/extract-css.test.js b/test/unit/extract-css.test.js
index 51d3b6f4ff..74a5a30f16 100644
--- a/test/unit/extract-css.test.js
+++ b/test/unit/extract-css.test.js
@@ -9,7 +9,7 @@ describe('extract css', () => {
test('Verify global.css has been extracted and minified', async () => {
const pathToMinifiedGlobalCss = resolve(__dirname, '..', 'fixtures/extract-css/.nuxt/dist/client/7dc53e76acc7df734a24.css')
const content = await readFile(pathToMinifiedGlobalCss, 'utf-8')
- const expectedContent = 'h1[data-v-180e2718]{color:red}.container[data-v-180e2718]{-ms-grid-columns:60px 60px 60px 60px 60px;-ms-grid-rows:30px 30px;display:-ms-grid;display:grid;grid-auto-flow:row;grid-template-columns:60px 60px 60px 60px 60px;grid-template-rows:30px 30px}'
+ const expectedContent = 'h1[data-v-180e2718]{color:red}.container[data-v-180e2718]{display:-ms-grid;display:grid;-ms-grid-columns:60px 60px 60px 60px 60px;grid-template-columns:60px 60px 60px 60px 60px;-ms-grid-rows:30px 30px;grid-template-rows:30px 30px;grid-auto-flow:row}'
expect(content).toBe(expectedContent)
})
})
diff --git a/test/unit/with-config.test.js b/test/unit/with-config.test.js
index 76659d6372..2ad6726adf 100644
--- a/test/unit/with-config.test.js
+++ b/test/unit/with-config.test.js
@@ -19,6 +19,11 @@ describe('with-config', () => {
expect(html.includes('I have custom configurations
')).toBe(true)
})
+ test('/ (asset name for analyze mode)', async () => {
+ const { html } = await nuxt.renderRoute('/')
+ expect(html).toContain('