diff --git a/distributions/nuxt-legacy/package.json b/distributions/nuxt-legacy/package.json index 43c31dfde0..b0f5ad8555 100644 --- a/distributions/nuxt-legacy/package.json +++ b/distributions/nuxt-legacy/package.json @@ -54,6 +54,7 @@ "@nuxt/cli": "^2.2.0", "@nuxt/common": "^2.2.0", "@nuxt/core": "^2.2.0", + "@nuxt/generator": "^2.2.0", "consola": "^1.4.4" }, "engines": { diff --git a/distributions/nuxt/package.json b/distributions/nuxt/package.json index 7f65c434e1..11a3a06d31 100644 --- a/distributions/nuxt/package.json +++ b/distributions/nuxt/package.json @@ -50,6 +50,7 @@ "@nuxt/cli": "^2.2.0", "@nuxt/common": "^2.2.0", "@nuxt/core": "^2.2.0", + "@nuxt/generator": "^2.2.0", "consola": "^1.4.4" }, "engines": { diff --git a/distributions/nuxt/src/index.js b/distributions/nuxt/src/index.js index ba0a580bfa..3d17ff7a2d 100644 --- a/distributions/nuxt/src/index.js +++ b/distributions/nuxt/src/index.js @@ -1,2 +1,3 @@ export * from '@nuxt/core' export * from '@nuxt/builder' +export * from '@nuxt/generator' diff --git a/jest.config.js b/jest.config.js index dbb97bb3cb..fed3f02f49 100644 --- a/jest.config.js +++ b/jest.config.js @@ -21,7 +21,7 @@ module.exports = { coveragePathIgnorePatterns: [ 'node_modules', 'packages/app', - 'packages/builder/webpack/plugins/vue' + 'packages/webpack/plugins/vue' ], testPathIgnorePatterns: [ diff --git a/packages/builder/package.json b/packages/builder/package.json index 66b1f7eb93..6067cf8085 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -8,52 +8,19 @@ ], "main": "dist/builder.js", "dependencies": { - "@babel/core": "^7.1.2", - "@babel/polyfill": "^7.0.0", "@nuxt/app": "^2.2.0", "@nuxt/common": "^2.2.0", - "@nuxtjs/babel-preset-app": "^0.7.0", + "@nuxt/webpack": "^2.2.0", "@nuxtjs/devalue": "^1.0.1", - "@nuxtjs/friendly-errors-webpack-plugin": "^2.0.2", - "babel-loader": "^8.0.4", - "cache-loader": "^1.2.2", - "caniuse-lite": "^1.0.30000898", - "chalk": "^2.4.1", "chokidar": "^2.0.4", "consola": "^1.4.4", - "css-loader": "^1.0.0", - "cssnano": "^4.1.7", - "file-loader": "^2.0.0", "fs-extra": "^7.0.0", "glob": "^7.1.3", "hash-sum": "^1.0.2", - "html-minifier": "^3.5.20", - "html-webpack-plugin": "^3.2.0", "lodash": "^4.17.11", - "memory-fs": "^0.4.1", - "mini-css-extract-plugin": "^0.4.4", - "optimize-css-assets-webpack-plugin": "^5.0.1", "pify": "^4.0.1", - "postcss": "^7.0.5", - "postcss-import": "^12.0.1", - "postcss-import-resolver": "^1.1.0", - "postcss-loader": "^3.0.0", - "postcss-preset-env": "^6.2.0", - "postcss-url": "^8.0.0", "serialize-javascript": "^1.5.0", - "style-resources-loader": "^1.2.1", - "terser-webpack-plugin": "^1.1.0", - "thread-loader": "^1.2.0", - "time-fix-plugin": "^2.0.4", - "upath": "^1.1.0", - "url-loader": "^1.1.2", - "vue-loader": "^15.4.2", - "webpack": "^4.22.0", - "webpack-bundle-analyzer": "^3.0.3", - "webpack-dev-middleware": "^3.4.0", - "webpack-hot-middleware": "^2.24.3", - "webpack-node-externals": "^1.7.2", - "webpackbar": "^2.6.3" + "upath": "^1.1.0" }, "publishConfig": { "access": "public" diff --git a/packages/builder/src/builder.js b/packages/builder/src/builder.js index c46bde1f6d..31cc4cba09 100644 --- a/packages/builder/src/builder.js +++ b/packages/builder/src/builder.js @@ -1,66 +1,50 @@ import path from 'path' -import fs from 'fs' -import pify from 'pify' -import uniqBy from 'lodash/uniqBy' -import map from 'lodash/map' -import debounce from 'lodash/debounce' -import concat from 'lodash/concat' -import omit from 'lodash/omit' -import uniq from 'lodash/uniq' -import template from 'lodash/template' -import values from 'lodash/values' import chokidar from 'chokidar' -import fsExtra from 'fs-extra' -import hash from 'hash-sum' -import webpack from 'webpack' -import serialize from 'serialize-javascript' -import MFS from 'memory-fs' -import webpackDevMiddleware from 'webpack-dev-middleware' -import webpackHotMiddleware from 'webpack-hot-middleware' -import Glob from 'glob' -import upath from 'upath' import consola from 'consola' +import fsExtra from 'fs-extra' +import Glob from 'glob' +import hash from 'hash-sum' +import pify from 'pify' +import serialize from 'serialize-javascript' +import upath from 'upath' + +import concat from 'lodash/concat' +import debounce from 'lodash/debounce' +import map from 'lodash/map' +import omit from 'lodash/omit' +import template from 'lodash/template' +import uniq from 'lodash/uniq' +import uniqBy from 'lodash/uniqBy' +import values from 'lodash/values' import devalue from '@nuxtjs/devalue' import { Options, + BuildContext, r, wp, wChunk, createRoutes, - parallel, - sequence, relativeTo, waitFor, determineGlobals, stripWhitespace } from '@nuxt/common' -import PerfLoader from './webpack/utils/perf-loader' -import ClientWebpackConfig from './webpack/client' -import ServerWebpackConfig from './webpack/server' - const glob = pify(Glob) export default class Builder { - constructor(nuxt) { + constructor(nuxt, bundleBuilder) { this.nuxt = nuxt - this.isStatic = false // Flag to know if the build is for a generated app + this.plugins = [] this.options = nuxt.options this.globals = determineGlobals(nuxt.options.globalName, nuxt.options.globals) - - // Fields that set on build - this.compilers = [] - this.compilersWatching = [] - this.webpackDevMiddleware = null - this.webpackHotMiddleware = null this.watchers = { files: null, custom: null, restart: null } - this.perfLoader = null // Helper to resolve build paths this.relativeToBuild = (...args) => @@ -71,11 +55,7 @@ export default class Builder { // Stop watching on nuxt.close() if (this.options.dev) { this.nuxt.hook('close', () => this.unwatch()) - } - - // Initialize shared FS and Cache - if (this.options.dev) { - this.mfs = new MFS() + this.nuxt.hook('build:done', () => this.watchClient()) } if (this.options.build.analyze) { @@ -97,6 +77,18 @@ export default class Builder { // TODO: enable again when unsafe concern resolved.(common/options.js:42) // this.nuxt.hook('build:done', () => this.generateConfig()) // } + + this.bundleBuilder = this.getBundleBuilder(bundleBuilder) + } + + getBundleBuilder(bundleBuilder) { + if (typeof bundleBuilder === 'object') { + return bundleBuilder + } else { + const context = new BuildContext(this) + const BundleBuilder = typeof bundleBuilder === 'function' ? bundleBuilder : require('@nuxt/webpack') + return new BundleBuilder(context) + } } normalizePlugins() { @@ -117,8 +109,28 @@ export default class Builder { ) } + resolvePlugins() { + // Check plugins exist then set alias to their real path + return Promise.all(this.plugins.map(async (p) => { + const ext = path.extname(p.src) ? '' : '{.+([^.]),/index.+([^.])}' + const pluginFiles = await glob(`${p.src}${ext}`) + + if (!pluginFiles || pluginFiles.length === 0) { + throw new Error(`Plugin not found: ${p.src}`) + } else if (pluginFiles.length > 1) { + consola.warn({ + message: `Found ${pluginFiles.length} plugins that match the configuration, suggest to specify extension:`, + additional: ` ${pluginFiles.join('\n ')}`, + badge: true + }) + } + + p.src = this.relativeToBuild(p.src) + })) + } + forGenerate() { - this.isStatic = true + this.bundleBuilder.forGenerate() } async build() { @@ -186,8 +198,10 @@ export default class Builder { // Generate routes and interpret the template files await this.generateRoutesAndFiles() - // Start webpack build - await this.webpackBuild() + await this.resolvePlugins() + + // Start bundle build: webpack, rollup, parcel... + await this.bundleBuilder.build() // Flag to set that building is done this._buildStatus = STATUS.BUILD_DONE @@ -201,7 +215,7 @@ export default class Builder { async generateRoutesAndFiles() { consola.debug(`Generating nuxt files`) - this.plugins = this.normalizePlugins() + this.plugins.push.apply(this.plugins, this.normalizePlugins()) // -- Templates -- let templatesFiles = Array.from(this.template.templatesFiles) @@ -457,177 +471,15 @@ export default class Builder { consola.success('Nuxt files generated') } - async webpackBuild() { - this.perfLoader = new PerfLoader(this.options) - - const compilersOptions = [] - - // Client - const clientConfig = new ClientWebpackConfig(this).config() - compilersOptions.push(clientConfig) - - // Server - let serverConfig = null - if (this.options.build.ssr) { - serverConfig = new ServerWebpackConfig(this).config() - compilersOptions.push(serverConfig) - } - - // Check plugins exist then set alias to their real path - await Promise.all(this.plugins.map(async (p) => { - const ext = path.extname(p.src) ? '' : '{.+([^.]),/index.+([^.])}' - const pluginFiles = await glob(`${p.src}${ext}`) - - if (!pluginFiles || pluginFiles.length === 0) { - throw new Error(`Plugin not found: ${p.src}`) - } else if (pluginFiles.length > 1) { - consola.warn({ - message: `Found ${pluginFiles.length} plugins that match the configuration, suggest to specify extension:`, - additional: ` ${pluginFiles.join('\n ')}`, - badge: true - }) - } - - const src = this.relativeToBuild(p.src) - // Client config - if (!clientConfig.resolve.alias[p.name]) { - clientConfig.resolve.alias[p.name] = src - } - - // Server config - if (serverConfig && !serverConfig.resolve.alias[p.name]) { - // Alias to noop for ssr:false plugins - serverConfig.resolve.alias[p.name] = p.ssr ? src : './empty.js' - } - })) - - // Configure compilers - this.compilers = compilersOptions.map((compilersOption) => { - const compiler = webpack(compilersOption) - - // In dev, write files in memory FS - if (this.options.dev) { - compiler.outputFileSystem = this.mfs - } - - return compiler - }) - - // Warmup perfLoader before build - if (this.options.build.parallel) { - consola.info('Warming up worker pools') - this.perfLoader.warmupAll() - consola.success('Worker pools ready') - } - - // Start Builds - const runner = this.options.dev ? parallel : sequence - - await runner(this.compilers, (compiler) => { - return this.webpackCompile(compiler) - }) - } - - webpackCompile(compiler) { - return new Promise(async (resolve, reject) => { - const name = compiler.options.name - - await this.nuxt.callHook('build:compile', { name, compiler }) - - // Load renderer resources after build - compiler.hooks.done.tap('load-resources', async (stats) => { - await this.nuxt.callHook('build:compiled', { - name, - compiler, - stats - }) - - // Reload renderer if available - this.nuxt.renderer.loadResources(this.mfs || fs) - - // Resolve on next tick - process.nextTick(resolve) - }) - - if (this.options.dev) { - // --- Dev Build --- - // Client Build, watch is started by dev-middleware - if (compiler.options.name === 'client') { - return this.webpackDev(compiler) - } - // Server, build and watch for changes - this.compilersWatching.push( - compiler.watch(this.options.watchers.webpack, (err) => { - /* istanbul ignore if */ - if (err) return reject(err) - }) - ) - } else { - // --- Production Build --- - compiler.run((err, stats) => { - /* istanbul ignore next */ - if (err) { - return reject(err) - } else if (stats.hasErrors()) { - if (this.options.build.quiet === true) { - err = stats.toString(this.options.build.stats) - } - if (!err) { - // actual errors will be printed by webpack itself - err = 'Nuxt Build Error' - } - - return reject(err) - } - - resolve() - }) - } - }) - } - - webpackDev(compiler) { - consola.debug('Adding webpack middleware...') - - // Create webpack dev middleware - this.webpackDevMiddleware = pify( - webpackDevMiddleware( - compiler, - Object.assign( - { - publicPath: this.options.build.publicPath, - stats: false, - logLevel: 'silent', - watchOptions: this.options.watchers.webpack - }, - this.options.build.devMiddleware - ) - ) + // TODO: remove ignore when generateConfig enabled again + async generateConfig() /* istanbul ignore next */ { + const config = path.resolve(this.options.buildDir, 'build.config.js') + const options = omit(this.options, Options.unsafeKeys) + await fsExtra.writeFile( + config, + `export default ${JSON.stringify(options, null, ' ')}`, + 'utf8' ) - - this.webpackDevMiddleware.close = pify(this.webpackDevMiddleware.close) - - this.webpackHotMiddleware = pify( - webpackHotMiddleware( - compiler, - Object.assign( - { - log: false, - heartbeat: 10000 - }, - this.options.build.hotMiddleware - ) - ) - ) - - // Inject to renderer instance - if (this.nuxt.renderer) { - this.nuxt.renderer.webpackDevMiddleware = this.webpackDevMiddleware - this.nuxt.renderer.webpackHotMiddleware = this.webpackHotMiddleware - } - - // Start watching client files - this.watchClient() } watchClient() { @@ -694,24 +546,10 @@ export default class Builder { } } - this.compilersWatching.forEach(watching => watching.close()) - - // Stop webpack middleware - if (this.webpackDevMiddleware) { - await this.webpackDevMiddleware.close() + if (this.bundleBuilder.unwatch) { + await this.bundleBuilder.unwatch() } } - - // TODO: remove ignore when generateConfig enabled again - async generateConfig() /* istanbul ignore next */ { - const config = path.resolve(this.options.buildDir, 'build.config.js') - const options = omit(this.options, Options.unsafeKeys) - await fsExtra.writeFile( - config, - `export default ${JSON.stringify(options, null, ' ')}`, - 'utf8' - ) - } } const STATUS = { diff --git a/packages/builder/src/index.js b/packages/builder/src/index.js index cab57e9b4b..cc0865b7e1 100644 --- a/packages/builder/src/index.js +++ b/packages/builder/src/index.js @@ -1,2 +1 @@ export { default as Builder } from './builder' -export { default as Generator } from './generator' diff --git a/packages/cli/src/commands/build.js b/packages/cli/src/commands/build.js index a47d4a3518..955362fcc3 100644 --- a/packages/cli/src/commands/build.js +++ b/packages/cli/src/commands/build.js @@ -5,7 +5,8 @@ import { loadNuxtConfig } from '../common/utils' export default async function build() { const { Nuxt } = await import('@nuxt/core') - const { Builder, Generator } = await import('@nuxt/builder') + const { Builder } = await import('@nuxt/builder') + const { Generator } = await import('@nuxt/generator') const argv = parseArgs(process.argv.slice(2), { alias: { diff --git a/packages/cli/src/commands/generate.js b/packages/cli/src/commands/generate.js index d8ba97c54b..64ab9e934d 100644 --- a/packages/cli/src/commands/generate.js +++ b/packages/cli/src/commands/generate.js @@ -5,7 +5,8 @@ import { loadNuxtConfig } from '../common/utils' export default async function generate() { const { Nuxt } = await import('@nuxt/core') - const { Builder, Generator } = await import('@nuxt/builder') + const { Builder } = await import('@nuxt/builder') + const { Generator } = await import('@nuxt/generator') const argv = parseArgs(process.argv.slice(2), { alias: { diff --git a/packages/common/src/build/context.js b/packages/common/src/build/context.js new file mode 100644 index 0000000000..25178c150b --- /dev/null +++ b/packages/common/src/build/context.js @@ -0,0 +1,8 @@ +export default class BuildContext { + constructor(builder) { + this.nuxt = builder.nuxt + this.options = builder.nuxt.options + this.isStatic = false + this.plugins = builder.plugins + } +} diff --git a/packages/common/src/index.js b/packages/common/src/index.js index cb67f1ba56..80f0717de8 100644 --- a/packages/common/src/index.js +++ b/packages/common/src/index.js @@ -1,4 +1,5 @@ export { default as Modes } from './modes' export { default as NuxtConfig } from './nuxt.config' export { default as Options } from './options' +export { default as BuildContext } from './build/context' export * from './utils' diff --git a/packages/generator/package.js b/packages/generator/package.js new file mode 100644 index 0000000000..19d0ef6e2d --- /dev/null +++ b/packages/generator/package.js @@ -0,0 +1,3 @@ +export default { + build: true +} diff --git a/packages/generator/package.json b/packages/generator/package.json new file mode 100644 index 0000000000..461204da0b --- /dev/null +++ b/packages/generator/package.json @@ -0,0 +1,20 @@ +{ + "name": "@nuxt/generator", + "version": "2.2.0", + "repository": "nuxt/nuxt.js", + "license": "MIT", + "files": [ + "dist" + ], + "main": "dist/generator.js", + "dependencies": { + "@nuxt/common": "^2.2.0", + "chalk": "^2.4.1", + "consola": "^1.4.4", + "fs-extra": "^7.0.0", + "html-minifier": "^3.5.20" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/builder/src/generator.js b/packages/generator/src/generator.js similarity index 100% rename from packages/builder/src/generator.js rename to packages/generator/src/generator.js index 9d7df90926..2ca16d1c17 100644 --- a/packages/builder/src/generator.js +++ b/packages/generator/src/generator.js @@ -1,8 +1,8 @@ import path from 'path' -import htmlMinifier from 'html-minifier' import Chalk from 'chalk' -import fsExtra from 'fs-extra' import consola from 'consola' +import fsExtra from 'fs-extra' +import htmlMinifier from 'html-minifier' import { flatRoutes, isUrl, promisifyRoute, waitFor, isString } from '@nuxt/common' diff --git a/packages/generator/src/index.js b/packages/generator/src/index.js new file mode 100644 index 0000000000..a75639f90e --- /dev/null +++ b/packages/generator/src/index.js @@ -0,0 +1 @@ +export { default as Generator } from './generator' diff --git a/packages/webpack/package.js b/packages/webpack/package.js new file mode 100644 index 0000000000..19d0ef6e2d --- /dev/null +++ b/packages/webpack/package.js @@ -0,0 +1,3 @@ +export default { + build: true +} diff --git a/packages/webpack/package.json b/packages/webpack/package.json new file mode 100644 index 0000000000..e659acdaa0 --- /dev/null +++ b/packages/webpack/package.json @@ -0,0 +1,53 @@ +{ + "name": "@nuxt/webpack", + "version": "2.2.0", + "repository": "nuxt/nuxt.js", + "license": "MIT", + "files": [ + "dist" + ], + "main": "dist/webpack.js", + "dependencies": { + "@babel/core": "^7.1.2", + "@babel/polyfill": "^7.0.0", + "@nuxt/common": "^2.2.0", + "@nuxtjs/babel-preset-app": "^0.7.0", + "@nuxtjs/friendly-errors-webpack-plugin": "^2.0.2", + "babel-loader": "^8.0.4", + "cache-loader": "^1.2.2", + "caniuse-lite": "^1.0.30000898", + "chalk": "^2.4.1", + "consola": "^1.4.4", + "css-loader": "^1.0.0", + "cssnano": "^4.1.7", + "file-loader": "^2.0.0", + "fs-extra": "^7.0.0", + "hash-sum": "^1.0.2", + "html-webpack-plugin": "^3.2.0", + "lodash": "^4.17.11", + "memory-fs": "^0.4.1", + "mini-css-extract-plugin": "^0.4.4", + "optimize-css-assets-webpack-plugin": "^5.0.1", + "postcss": "^7.0.5", + "postcss-import": "^12.0.1", + "postcss-import-resolver": "^1.1.0", + "postcss-loader": "^3.0.0", + "postcss-preset-env": "^6.2.0", + "postcss-url": "^8.0.0", + "style-resources-loader": "^1.2.1", + "terser-webpack-plugin": "^1.1.0", + "thread-loader": "^1.2.0", + "time-fix-plugin": "^2.0.4", + "url-loader": "^1.1.2", + "vue-loader": "^15.4.2", + "webpack": "^4.22.0", + "webpack-bundle-analyzer": "^3.0.3", + "webpack-dev-middleware": "^3.4.0", + "webpack-hot-middleware": "^2.24.3", + "webpack-node-externals": "^1.7.2", + "webpackbar": "^2.6.3" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/webpack/src/builder.js b/packages/webpack/src/builder.js new file mode 100644 index 0000000000..cb526ab95f --- /dev/null +++ b/packages/webpack/src/builder.js @@ -0,0 +1,205 @@ +import fs from 'fs' +import pify from 'pify' +import webpack from 'webpack' +import MFS from 'memory-fs' +import webpackDevMiddleware from 'webpack-dev-middleware' +import webpackHotMiddleware from 'webpack-hot-middleware' +import consola from 'consola' + +import { + parallel, + sequence +} from '@nuxt/common' + +import { ClientConfig, ServerConfig, PerfLoader } from './config' + +export default class WebpackBuilder { + constructor(context) { + this.context = context + // Fields that set on build + this.compilers = [] + this.compilersWatching = [] + this.webpackDevMiddleware = null + this.webpackHotMiddleware = null + this.perfLoader = null + + // Initialize shared FS and Cache + if (this.context.options.dev) { + this.mfs = new MFS() + } + } + + async build() { + const options = this.context.options + + this.perfLoader = new PerfLoader(options) + + const compilersOptions = [] + + // Client + const clientConfig = new ClientConfig(this).config() + compilersOptions.push(clientConfig) + + // Server + let serverConfig = null + if (options.build.ssr) { + serverConfig = new ServerConfig(this).config() + compilersOptions.push(serverConfig) + } + + for (const p of this.context.plugins) { + // Client config + if (!clientConfig.resolve.alias[p.name]) { + clientConfig.resolve.alias[p.name] = p.src + } + + // Server config + if (serverConfig && !serverConfig.resolve.alias[p.name]) { + // Alias to noop for ssr:false plugins + serverConfig.resolve.alias[p.name] = p.ssr ? p.src : './empty.js' + } + } + + // Configure compilers + this.compilers = compilersOptions.map((compilersOption) => { + const compiler = webpack(compilersOption) + + // In dev, write files in memory FS + if (options.dev) { + compiler.outputFileSystem = this.mfs + } + + return compiler + }) + + // Warmup perfLoader before build + if (options.build.parallel) { + consola.info('Warming up worker pools') + this.perfLoader.warmupAll() + consola.success('Worker pools ready') + } + + // Start Builds + const runner = options.dev ? parallel : sequence + + await runner(this.compilers, (compiler) => { + return this.webpackCompile(compiler) + }) + } + + webpackCompile(compiler) { + return new Promise(async (resolve, reject) => { + const name = compiler.options.name + const { nuxt, options } = this.context + + await nuxt.callHook('build:compile', { name, compiler }) + + // Load renderer resources after build + compiler.hooks.done.tap('load-resources', async (stats) => { + await nuxt.callHook('build:compiled', { + name, + compiler, + stats + }) + + // Reload renderer if available + nuxt.renderer.loadResources(this.mfs || fs) + + // Resolve on next tick + process.nextTick(resolve) + }) + + if (options.dev) { + // --- Dev Build --- + // Client Build, watch is started by dev-middleware + if (compiler.options.name === 'client') { + return this.webpackDev(compiler) + } + // Server, build and watch for changes + this.compilersWatching.push( + compiler.watch(options.watchers.webpack, (err) => { + /* istanbul ignore if */ + if (err) return reject(err) + }) + ) + } else { + // --- Production Build --- + compiler.run((err, stats) => { + /* istanbul ignore next */ + if (err) { + return reject(err) + } else if (stats.hasErrors()) { + if (options.build.quiet === true) { + err = stats.toString(options.build.stats) + } + if (!err) { + // actual errors will be printed by webpack itself + err = 'Nuxt Build Error' + } + + return reject(err) + } + + resolve() + }) + } + }) + } + + webpackDev(compiler) { + consola.debug('Adding webpack middleware...') + + const { nuxt: { renderer }, options } = this.context + + // Create webpack dev middleware + this.webpackDevMiddleware = pify( + webpackDevMiddleware( + compiler, + Object.assign( + { + publicPath: options.build.publicPath, + stats: false, + logLevel: 'silent', + watchOptions: options.watchers.webpack + }, + options.build.devMiddleware + ) + ) + ) + + this.webpackDevMiddleware.close = pify(this.webpackDevMiddleware.close) + + this.webpackHotMiddleware = pify( + webpackHotMiddleware( + compiler, + Object.assign( + { + log: false, + heartbeat: 10000 + }, + options.build.hotMiddleware + ) + ) + ) + + // Inject to renderer instance + if (renderer) { + renderer.webpackDevMiddleware = this.webpackDevMiddleware + renderer.webpackHotMiddleware = this.webpackHotMiddleware + } + } + + async unwatch() { + for (const watching of this.compilersWatching) { + watching.close() + } + // Stop webpack middleware + if (this.webpackDevMiddleware) { + await this.webpackDevMiddleware.close() + } + } + + forGenerate() { + this.context.isStatic = true + } +} diff --git a/packages/builder/src/webpack/base.js b/packages/webpack/src/config/base.js similarity index 98% rename from packages/builder/src/webpack/base.js rename to packages/webpack/src/config/base.js index c7efcadb08..d98762fd8e 100644 --- a/packages/builder/src/webpack/base.js +++ b/packages/webpack/src/config/base.js @@ -18,9 +18,9 @@ export default class WebpackBaseConfig { this.name = options.name this.isServer = options.isServer this.builder = builder - this.nuxt = this.builder.nuxt - this.isStatic = builder.isStatic - this.options = builder.options + this.nuxt = builder.context.nuxt + this.isStatic = builder.context.isStatic + this.options = builder.context.options this.spinner = builder.spinner this.loaders = this.options.build.loaders } @@ -117,7 +117,7 @@ export default class WebpackBaseConfig { rules() { const styleLoader = new StyleLoader( this.options, - this.builder.nuxt, + this.nuxt, { isServer: this.isServer } ) diff --git a/packages/builder/src/webpack/client.js b/packages/webpack/src/config/client.js similarity index 100% rename from packages/builder/src/webpack/client.js rename to packages/webpack/src/config/client.js diff --git a/packages/webpack/src/config/index.js b/packages/webpack/src/config/index.js new file mode 100644 index 0000000000..bb996e1e71 --- /dev/null +++ b/packages/webpack/src/config/index.js @@ -0,0 +1,3 @@ +export { default as ClientConfig } from './client' +export { default as ServerConfig } from './server' +export { default as PerfLoader } from './utils/perf-loader' diff --git a/packages/builder/src/webpack/plugins/stats.js b/packages/webpack/src/config/plugins/stats.js similarity index 100% rename from packages/builder/src/webpack/plugins/stats.js rename to packages/webpack/src/config/plugins/stats.js diff --git a/packages/builder/src/webpack/plugins/vue/client.js b/packages/webpack/src/config/plugins/vue/client.js similarity index 100% rename from packages/builder/src/webpack/plugins/vue/client.js rename to packages/webpack/src/config/plugins/vue/client.js diff --git a/packages/builder/src/webpack/plugins/vue/server.js b/packages/webpack/src/config/plugins/vue/server.js similarity index 100% rename from packages/builder/src/webpack/plugins/vue/server.js rename to packages/webpack/src/config/plugins/vue/server.js diff --git a/packages/builder/src/webpack/plugins/vue/util.js b/packages/webpack/src/config/plugins/vue/util.js similarity index 100% rename from packages/builder/src/webpack/plugins/vue/util.js rename to packages/webpack/src/config/plugins/vue/util.js diff --git a/packages/builder/src/webpack/plugins/warnfix.js b/packages/webpack/src/config/plugins/warnfix.js similarity index 100% rename from packages/builder/src/webpack/plugins/warnfix.js rename to packages/webpack/src/config/plugins/warnfix.js diff --git a/packages/builder/src/webpack/server.js b/packages/webpack/src/config/server.js similarity index 94% rename from packages/builder/src/webpack/server.js rename to packages/webpack/src/config/server.js index beee5217f7..42db802d82 100644 --- a/packages/builder/src/webpack/server.js +++ b/packages/webpack/src/config/server.js @@ -3,10 +3,10 @@ import fs from 'fs' import webpack from 'webpack' import nodeExternals from 'webpack-node-externals' -import BaseConfig from './base' +import WebpackBaseConfig from './base' import VueSSRServerPlugin from './plugins/vue/server' -export default class WebpackServerConfig extends BaseConfig { +export default class WebpackServerConfig extends WebpackBaseConfig { constructor(builder) { super(builder, { name: 'server', isServer: true }) } diff --git a/packages/builder/src/webpack/utils/perf-loader.js b/packages/webpack/src/config/utils/perf-loader.js similarity index 100% rename from packages/builder/src/webpack/utils/perf-loader.js rename to packages/webpack/src/config/utils/perf-loader.js diff --git a/packages/builder/src/webpack/utils/postcss.js b/packages/webpack/src/config/utils/postcss.js similarity index 100% rename from packages/builder/src/webpack/utils/postcss.js rename to packages/webpack/src/config/utils/postcss.js diff --git a/packages/builder/src/webpack/utils/style-loader.js b/packages/webpack/src/config/utils/style-loader.js similarity index 100% rename from packages/builder/src/webpack/utils/style-loader.js rename to packages/webpack/src/config/utils/style-loader.js diff --git a/packages/webpack/src/index.js b/packages/webpack/src/index.js new file mode 100644 index 0000000000..ad27f6b008 --- /dev/null +++ b/packages/webpack/src/index.js @@ -0,0 +1 @@ +export { default } from './builder' diff --git a/test/unit/basic.dev.test.js b/test/unit/basic.dev.test.js index c756c03c60..6a42bf856b 100644 --- a/test/unit/basic.dev.test.js +++ b/test/unit/basic.dev.test.js @@ -1,5 +1,5 @@ import consola from 'consola' -import { Builder, getPort, loadFixture, Nuxt, rp } from '../utils' +import { Builder, WebpackBuilder, getPort, loadFixture, Nuxt, rp } from '../utils' let port const url = route => 'http://localhost:' + port + route @@ -45,7 +45,7 @@ describe('basic dev', () => { } }) nuxt = new Nuxt(config) - builder = new Builder(nuxt) + builder = new Builder(nuxt, WebpackBuilder) await builder.build() port = await getPort() await nuxt.listen(port, 'localhost') diff --git a/test/unit/basic.generate.test.js b/test/unit/basic.generate.test.js index 8d5c7ea273..5a274a7d8b 100644 --- a/test/unit/basic.generate.test.js +++ b/test/unit/basic.generate.test.js @@ -11,6 +11,7 @@ const url = route => 'http://localhost:' + port + route const rootDir = resolve(__dirname, '..', 'fixtures/basic') const distDir = resolve(rootDir, '.nuxt-generate') +let builder let server = null let generator = null let pathsBefore @@ -29,7 +30,7 @@ describe('basic generate', () => { writeFileSync(changedFileName, '') }) - const builder = new Builder(nuxt) + builder = new Builder(nuxt) builder.build = jest.fn() generator = new Generator(nuxt, builder) @@ -45,8 +46,8 @@ describe('basic generate', () => { }) test('Check builder', () => { - expect(generator.builder.isStatic).toBe(true) - expect(generator.builder.build).toHaveBeenCalledTimes(1) + expect(builder.bundleBuilder.context.isStatic).toBe(true) + expect(builder.build).toHaveBeenCalledTimes(1) }) test('Check ready hook called', () => { diff --git a/test/unit/wp.config.test.js b/test/unit/wp.config.test.js index b586ece91b..28302c13d1 100644 --- a/test/unit/wp.config.test.js +++ b/test/unit/wp.config.test.js @@ -1,6 +1,6 @@ import path from 'path' -import PerfLoader from '../../packages/builder/src/webpack/utils/perf-loader' +import PerfLoader from '../../packages/webpack/src/config/utils/perf-loader' describe('webpack configuration', () => { test('performance loader', () => { diff --git a/test/utils/index.js b/test/utils/index.js index 3eeb743807..5c6fd59496 100644 --- a/test/utils/index.js +++ b/test/utils/index.js @@ -1,4 +1,3 @@ - import klawSync from 'klaw-sync' import { waitFor } from '../../packages/common/src/utils' export { default as getPort } from 'get-port' diff --git a/test/utils/nuxt.js b/test/utils/nuxt.js index c96f5f55b7..80b4d4e1ef 100644 --- a/test/utils/nuxt.js +++ b/test/utils/nuxt.js @@ -5,7 +5,9 @@ import { defaultsDeep } from 'lodash' export { version } from '../../packages/core/package.json' export { Nuxt } from '../../packages/core/src/index' -export { Builder, Generator } from '../../packages/builder/src/index' +export { Builder } from '../../packages/builder/src/index' +export { Generator } from '../../packages/generator/src/index' +export { default as WebpackBuilder } from '../../packages/webpack/src/index' export * from '../../packages/common/src/index' export const loadFixture = async function (fixture, overrides) {