From fcb343012cec72c324e765749f401f4de17b4135 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 21 Dec 2017 08:30:06 +0100 Subject: [PATCH 001/132] Speed up next build --- package.json | 4 +-- server/build/plugins/combine-assets-plugin.js | 26 ++++++++++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 6f0e6cfffcf65..651a5e1d2586c 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,8 @@ "webpack-dev-middleware": "1.12.0", "webpack-hot-middleware": "2.19.1", "write-file-webpack-plugin": "4.2.0", - "xss-filters": "1.2.7" + "xss-filters": "1.2.7", + "uglifyjs-webpack-plugin": "^1.1.1" }, "devDependencies": { "@taskr/babel": "1.1.0", @@ -134,7 +135,6 @@ "react-dom": "16.0.0", "standard": "9.0.2", "taskr": "1.1.0", - "uglifyjs-webpack-plugin": "^1.1.1", "wd": "1.4.1" }, "peerDependencies": { diff --git a/server/build/plugins/combine-assets-plugin.js b/server/build/plugins/combine-assets-plugin.js index b7bae4a4b9dfc..1985ab56bfdd0 100644 --- a/server/build/plugins/combine-assets-plugin.js +++ b/server/build/plugins/combine-assets-plugin.js @@ -11,7 +11,7 @@ export default class CombineAssetsPlugin { apply (compiler) { compiler.plugin('compilation', (compilation) => { - compilation.plugin('additional-chunk-assets', (chunks) => { + compilation.plugin('after-optimize-chunk-assets', (chunks) => { const concat = new ConcatSource() this.input.forEach((name) => { @@ -19,7 +19,6 @@ export default class CombineAssetsPlugin { if (!asset) return concat.add(asset) - // We keep existing assets since that helps when analyzing the bundle }) @@ -27,10 +26,25 @@ export default class CombineAssetsPlugin { compilation.assets[this.output] = concat // Register the combined file as an output of the associated chunks - chunks.filter((chunk) => { - return chunk.files.reduce((prev, file) => prev || this.input.includes(file), false) - }) - .forEach((chunk) => chunk.files.push(this.output)) + // chunks.forEach((chunk) => { + + + // chunk.files.forEach((file) => { + // if(!this.input.includes(file)) { + // return + // } + + // const index = chunk.files.indexOf(file) + // chunk.files.splice(index, 1) + // }) + + // if(chunk.files.length === 0) { + // const index = compilation.chunks.indexOf(chunk) + // compilation.chunks.splice(index, 1) + // } + + // chunk.files.reduce((prev, file) => prev || this.input.includes(file), false) + // }) }) }) } From c1ebbf6ddb85454b56875fa65dd2e924723e3d65 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 21 Dec 2017 08:30:43 +0100 Subject: [PATCH 002/132] Document webpack config --- server/build/webpack.js | 100 ++++++++++++++++++++++++---------------- server/config.js | 3 +- 2 files changed, 62 insertions(+), 41 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 69a62cd03909e..98f160d14bfcf 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -29,55 +29,78 @@ const interpolateNames = new Map(defaultPages.map((p) => { const relativeResolve = rootModuleRelativePath(require) +async function getPages(dir, dev) { + let pages + + if(dev) { + pages = await glob('pages/+(_document|_error).+(js|jsx)', { cwd: dir }) + } else { + pages = await glob('pages/**/*.+(js|jsx)', { cwd: dir }) + } + + return pages +} + +function getPageEntries(pages) { + const entries = {} + for (const p of pages) { + entries[join('bundles', p.replace('.jsx', '.js'))] = [`./${p}?entry`] + } + + // The default pages (_document.js and _error.js) are only added when they're not provided by the user + for (const p of defaultPages) { + const entryName = join('bundles', 'pages', p) + if (!entries[entryName]) { + entries[entryName] = [join(nextPagesDir, p) + '?entry'] + } + } + + return entries +} + export default async function createCompiler (dir, { buildId, dev = false, quiet = false, buildDir, conf = null } = {}) { + // Resolve relative path to absolute path dir = realpathSync(resolve(dir)) + + // Used to track the amount of pages for webpack commons chunk plugin + let totalPages + + // Loads next.config.js and custom configuration provided in custom server initialization const config = getConfig(dir, conf) - const defaultEntries = dev ? [ + + // Middlewares to handle on-demand entries and hot updates in development + const devEntries = dev ? [ join(__dirname, '..', '..', 'client', 'webpack-hot-middleware-client'), join(__dirname, '..', '..', 'client', 'on-demand-entries-client') ] : [] - const mainJS = dev - ? require.resolve('../../client/next-dev') : require.resolve('../../client/next') - let totalPages + const mainJS = require.resolve(`../../client/next${dev ? '-dev' : ''}`) // Uses client/next-dev in development for code splitting dev dependencies const entry = async () => { - const entries = { - 'main.js': [ - ...defaultEntries, - ...config.clientBootstrap || [], - mainJS - ] - } + // Get entries for pages in production mode. In development only _document and _error are added. Because pages are added by on-demand-entry-handler. + const pages = await getPages(dir, dev) + const pageEntries = getPageEntries(pages) - const pages = await glob(config.pagesGlobPattern, { cwd: dir }) - const devPages = pages.filter((p) => p === 'pages/_document.js' || p === 'pages/_error.js') - - // In the dev environment, on-demand-entry-handler will take care of - // managing pages. - if (dev) { - for (const p of devPages) { - entries[join('bundles', p.replace('.jsx', '.js'))] = [`./${p}?entry`] - } - } else { - for (const p of pages) { - entries[join('bundles', p.replace('.jsx', '.js'))] = [`./${p}?entry`] - } + // Used for commons chunk calculations + totalPages = pages.length + if(pages.indexOf(documentPage) !== -1) { + totalPages = totalPages - 1 } - for (const p of defaultPages) { - const entryName = join('bundles', 'pages', p) - if (!entries[entryName]) { - entries[entryName] = [join(nextPagesDir, p) + '?entry'] - } + const entries = { + 'main.js': [ + ...devEntries, // Adds hot middleware and ondemand entries in development + ...config.clientBootstrap || [], // clientBootstrap can be used to load polyfills before code execution + mainJS // Main entrypoint in the client folder + ], + ...pageEntries } - totalPages = pages.filter((p) => p !== documentPage).length - return entries } const plugins = [ + new CaseSensitivePathPlugin(), new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), new webpack.LoaderOptionsPlugin({ options: { @@ -131,8 +154,7 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet 'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production') }), new PagesPlugin(), - new DynamicChunksPlugin(), - new CaseSensitivePathPlugin() + new DynamicChunksPlugin() ] if (dev) { @@ -147,19 +169,19 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet } else { plugins.push(new webpack.IgnorePlugin(/react-hot-loader/)) plugins.push( - new CombineAssetsPlugin({ - input: ['manifest.js', 'commons.js', 'main.js'], - output: 'app.js' - }), new UglifyJSPlugin({ - parallel: true, + parallel: false, sourceMap: false, uglifyOptions: { compress: { comparisons: false } } - }) + }), + new CombineAssetsPlugin({ + input: ['manifest.js', 'commons.js', 'main.js'], + output: 'app.js' + }), ) plugins.push(new webpack.optimize.ModuleConcatenationPlugin()) } diff --git a/server/config.js b/server/config.js index 395b92c526ab5..e53b7ecf7f5e8 100644 --- a/server/config.js +++ b/server/config.js @@ -9,8 +9,7 @@ const defaultConfig = { distDir: '.next', assetPrefix: '', configOrigin: 'default', - useFileSystemPublicRoutes: true, - pagesGlobPattern: 'pages/**/*.+(js|jsx)' + useFileSystemPublicRoutes: true } export default function getConfig (dir, customConfig) { From 83916b72bc5cbc33e01abbbee14714f875a8e6ab Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 21 Dec 2017 08:30:06 +0100 Subject: [PATCH 003/132] Speed up next build --- package.json | 4 +-- server/build/plugins/combine-assets-plugin.js | 26 ++++++++++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 6f0e6cfffcf65..651a5e1d2586c 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,8 @@ "webpack-dev-middleware": "1.12.0", "webpack-hot-middleware": "2.19.1", "write-file-webpack-plugin": "4.2.0", - "xss-filters": "1.2.7" + "xss-filters": "1.2.7", + "uglifyjs-webpack-plugin": "^1.1.1" }, "devDependencies": { "@taskr/babel": "1.1.0", @@ -134,7 +135,6 @@ "react-dom": "16.0.0", "standard": "9.0.2", "taskr": "1.1.0", - "uglifyjs-webpack-plugin": "^1.1.1", "wd": "1.4.1" }, "peerDependencies": { diff --git a/server/build/plugins/combine-assets-plugin.js b/server/build/plugins/combine-assets-plugin.js index b7bae4a4b9dfc..1985ab56bfdd0 100644 --- a/server/build/plugins/combine-assets-plugin.js +++ b/server/build/plugins/combine-assets-plugin.js @@ -11,7 +11,7 @@ export default class CombineAssetsPlugin { apply (compiler) { compiler.plugin('compilation', (compilation) => { - compilation.plugin('additional-chunk-assets', (chunks) => { + compilation.plugin('after-optimize-chunk-assets', (chunks) => { const concat = new ConcatSource() this.input.forEach((name) => { @@ -19,7 +19,6 @@ export default class CombineAssetsPlugin { if (!asset) return concat.add(asset) - // We keep existing assets since that helps when analyzing the bundle }) @@ -27,10 +26,25 @@ export default class CombineAssetsPlugin { compilation.assets[this.output] = concat // Register the combined file as an output of the associated chunks - chunks.filter((chunk) => { - return chunk.files.reduce((prev, file) => prev || this.input.includes(file), false) - }) - .forEach((chunk) => chunk.files.push(this.output)) + // chunks.forEach((chunk) => { + + + // chunk.files.forEach((file) => { + // if(!this.input.includes(file)) { + // return + // } + + // const index = chunk.files.indexOf(file) + // chunk.files.splice(index, 1) + // }) + + // if(chunk.files.length === 0) { + // const index = compilation.chunks.indexOf(chunk) + // compilation.chunks.splice(index, 1) + // } + + // chunk.files.reduce((prev, file) => prev || this.input.includes(file), false) + // }) }) }) } From 443ece9b47de59dd9e685951e86a26c32203d066 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 21 Dec 2017 08:34:46 +0100 Subject: [PATCH 004/132] Remove comment --- server/build/plugins/combine-assets-plugin.js | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/server/build/plugins/combine-assets-plugin.js b/server/build/plugins/combine-assets-plugin.js index 1985ab56bfdd0..901ed570e7260 100644 --- a/server/build/plugins/combine-assets-plugin.js +++ b/server/build/plugins/combine-assets-plugin.js @@ -24,27 +24,6 @@ export default class CombineAssetsPlugin { compilation.additionalChunkAssets.push(this.output) compilation.assets[this.output] = concat - - // Register the combined file as an output of the associated chunks - // chunks.forEach((chunk) => { - - - // chunk.files.forEach((file) => { - // if(!this.input.includes(file)) { - // return - // } - - // const index = chunk.files.indexOf(file) - // chunk.files.splice(index, 1) - // }) - - // if(chunk.files.length === 0) { - // const index = compilation.chunks.indexOf(chunk) - // compilation.chunks.splice(index, 1) - // } - - // chunk.files.reduce((prev, file) => prev || this.input.includes(file), false) - // }) }) }) } From 0aacb1768c7415abf162335097d0af200dccfbee Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 21 Dec 2017 08:45:31 +0100 Subject: [PATCH 005/132] Add comment --- server/build/plugins/combine-assets-plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/build/plugins/combine-assets-plugin.js b/server/build/plugins/combine-assets-plugin.js index 901ed570e7260..4d083c8129fbf 100644 --- a/server/build/plugins/combine-assets-plugin.js +++ b/server/build/plugins/combine-assets-plugin.js @@ -22,7 +22,7 @@ export default class CombineAssetsPlugin { // We keep existing assets since that helps when analyzing the bundle }) - compilation.additionalChunkAssets.push(this.output) + // Creates a new asset holding the concatted source compilation.assets[this.output] = concat }) }) From 6ce025e3ab806d4d50416a637d51d03c7d6362cc Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 21 Dec 2017 11:02:08 +0100 Subject: [PATCH 006/132] Clean up rules --- server/build/webpack.js | 252 ++++++++++++++++++++-------------------- 1 file changed, 127 insertions(+), 125 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 98f160d14bfcf..ab59137e88a50 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -29,20 +29,20 @@ const interpolateNames = new Map(defaultPages.map((p) => { const relativeResolve = rootModuleRelativePath(require) -async function getPages(dir, dev) { +async function getPages (dir, dev) { let pages - if(dev) { - pages = await glob('pages/+(_document|_error).+(js|jsx)', { cwd: dir }) + if (dev) { + pages = await glob('pages/+(_document|_error).+(js|jsx)', { cwd: dir }) } else { - pages = await glob('pages/**/*.+(js|jsx)', { cwd: dir }) + pages = await glob('pages/**/*.+(js|jsx)', { cwd: dir }) } return pages } -function getPageEntries(pages) { - const entries = {} +function getPageEntries (pages) { + const entries = {} for (const p of pages) { entries[join('bundles', p.replace('.jsx', '.js'))] = [`./${p}?entry`] } @@ -77,13 +77,13 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet const mainJS = require.resolve(`../../client/next${dev ? '-dev' : ''}`) // Uses client/next-dev in development for code splitting dev dependencies const entry = async () => { - // Get entries for pages in production mode. In development only _document and _error are added. Because pages are added by on-demand-entry-handler. + // Get entries for pages in production mode. In development only _document and _error are added. Because pages are added by on-demand-entry-handler. const pages = await getPages(dir, dev) const pageEntries = getPageEntries(pages) // Used for commons chunk calculations totalPages = pages.length - if(pages.indexOf(documentPage) !== -1) { + if (pages.indexOf(documentPage) !== -1) { totalPages = totalPages - 1 } @@ -213,7 +213,7 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet mainBabelOptions.presets.push(require.resolve('./babel/preset')) } - const rules = (dev ? [{ + const devLoaders = dev ? [{ test: /\.(js|jsx)(\?[^?]*)?$/, loader: 'hot-self-accept-loader', include: [ @@ -224,121 +224,7 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet test: /\.(js|jsx)(\?[^?]*)?$/, loader: 'react-hot-loader/webpack', exclude: /node_modules/ - }] : []) - .concat([{ - test: /\.json$/, - loader: 'json-loader' - }, { - test: /\.(js|jsx|json)(\?[^?]*)?$/, - loader: 'emit-file-loader', - include: [dir, nextPagesDir], - exclude (str) { - return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 - }, - options: { - name: 'dist/[path][name].[ext]', - // We need to strip off .jsx on the server. Otherwise require without .jsx doesn't work. - interpolateName: (name) => name.replace('.jsx', '.js'), - validateFileName (file) { - const cases = [{from: '.js', to: '.jsx'}, {from: '.jsx', to: '.js'}] - - for (const item of cases) { - const {from, to} = item - if (file.slice(-(from.length)) !== from) { - continue - } - - const filePath = file.slice(0, -(from.length)) + to - - if (existsSync(filePath)) { - throw new Error(`Both ${from} and ${to} file found. Please make sure you only have one of both.`) - } - } - }, - // By default, our babel config does not transpile ES2015 module syntax because - // webpack knows how to handle them. (That's how it can do tree-shaking) - // But Node.js doesn't know how to handle them. So, we have to transpile them here. - transform ({ content, sourceMap, interpolatedName }) { - // Only handle .js files - if (!(/\.(js|jsx)$/.test(interpolatedName))) { - return { content, sourceMap } - } - - const babelRuntimePath = require.resolve('babel-runtime/package').replace(/[\\/]package\.json$/, '') - const transpiled = babelCore.transform(content, { - babelrc: false, - sourceMaps: dev ? 'both' : false, - // Here we need to resolve all modules to the absolute paths. - // Earlier we did it with the babel-preset. - // But since we don't transpile ES2015 in the preset this is not resolving. - // That's why we need to do it here. - // See more: https://github.com/zeit/next.js/issues/951 - plugins: [ - require.resolve(join(__dirname, './babel/plugins/remove-dotjsx-from-import.js')), - [require.resolve('babel-plugin-transform-es2015-modules-commonjs')], - [ - require.resolve('babel-plugin-module-resolver'), - { - alias: { - 'babel-runtime': babelRuntimePath, - 'next/link': relativeResolve('../../lib/link'), - 'next/prefetch': relativeResolve('../../lib/prefetch'), - 'next/css': relativeResolve('../../lib/css'), - 'next/dynamic': relativeResolve('../../lib/dynamic'), - 'next/head': relativeResolve('../../lib/head'), - 'next/document': relativeResolve('../../server/document'), - 'next/router': relativeResolve('../../lib/router'), - 'next/error': relativeResolve('../../lib/error'), - 'styled-jsx/style': relativeResolve('styled-jsx/style') - } - } - ] - ], - inputSourceMap: sourceMap - }) - - // Strip ?entry to map back to filesystem and work with iTerm, etc. - let { map } = transpiled - let output = transpiled.code - - if (map) { - let nodeMap = Object.assign({}, map) - nodeMap.sources = nodeMap.sources.map((source) => source.replace(/\?entry/, '')) - delete nodeMap.sourcesContent - - // Output explicit inline source map that source-map-support can pickup via requireHook mode. - // Since these are not formal chunks, the devtool infrastructure in webpack does not output - // a source map for these files. - const sourceMapUrl = new Buffer(JSON.stringify(nodeMap), 'utf-8').toString('base64') - output = `${output}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${sourceMapUrl}` - } - - return { - content: output, - sourceMap: transpiled.map - } - } - } - }, { - loader: 'babel-loader', - include: nextPagesDir, - exclude (str) { - return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 - }, - options: { - babelrc: false, - cacheDirectory: true, - presets: [require.resolve('./babel/preset')] - } - }, { - test: /\.(js|jsx)(\?[^?]*)?$/, - loader: 'babel-loader', - include: [dir], - exclude (str) { - return /node_modules/.test(str) - }, - options: mainBabelOptions - }]) + }] : [] let webpackConfig = { context: dir, @@ -378,7 +264,123 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet }, plugins, module: { - rules + rules: [ + ...devLoaders, + { + test: /\.json$/, + loader: 'json-loader' + }, { + test: /\.(js|jsx|json)(\?[^?]*)?$/, + loader: 'emit-file-loader', + include: [dir, nextPagesDir], + exclude (str) { + return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 + }, + options: { + name: 'dist/[path][name].[ext]', + // We need to strip off .jsx on the server. Otherwise require without .jsx doesn't work. + interpolateName: (name) => name.replace('.jsx', '.js'), + validateFileName (file) { + const cases = [{from: '.js', to: '.jsx'}, {from: '.jsx', to: '.js'}] + + for (const item of cases) { + const {from, to} = item + if (file.slice(-(from.length)) !== from) { + continue + } + + const filePath = file.slice(0, -(from.length)) + to + + if (existsSync(filePath)) { + throw new Error(`Both ${from} and ${to} file found. Please make sure you only have one of both.`) + } + } + }, + // By default, our babel config does not transpile ES2015 module syntax because + // webpack knows how to handle them. (That's how it can do tree-shaking) + // But Node.js doesn't know how to handle them. So, we have to transpile them here. + transform ({ content, sourceMap, interpolatedName }) { + // Only handle .js files + if (!(/\.(js|jsx)$/.test(interpolatedName))) { + return { content, sourceMap } + } + + const babelRuntimePath = require.resolve('babel-runtime/package').replace(/[\\/]package\.json$/, '') + const transpiled = babelCore.transform(content, { + babelrc: false, + sourceMaps: dev ? 'both' : false, + // Here we need to resolve all modules to the absolute paths. + // Earlier we did it with the babel-preset. + // But since we don't transpile ES2015 in the preset this is not resolving. + // That's why we need to do it here. + // See more: https://github.com/zeit/next.js/issues/951 + plugins: [ + require.resolve(join(__dirname, './babel/plugins/remove-dotjsx-from-import.js')), + [require.resolve('babel-plugin-transform-es2015-modules-commonjs')], + [ + require.resolve('babel-plugin-module-resolver'), + { + alias: { + 'babel-runtime': babelRuntimePath, + 'next/link': relativeResolve('../../lib/link'), + 'next/prefetch': relativeResolve('../../lib/prefetch'), + 'next/css': relativeResolve('../../lib/css'), + 'next/dynamic': relativeResolve('../../lib/dynamic'), + 'next/head': relativeResolve('../../lib/head'), + 'next/document': relativeResolve('../../server/document'), + 'next/router': relativeResolve('../../lib/router'), + 'next/error': relativeResolve('../../lib/error'), + 'styled-jsx/style': relativeResolve('styled-jsx/style') + } + } + ] + ], + inputSourceMap: sourceMap + }) + + // Strip ?entry to map back to filesystem and work with iTerm, etc. + let { map } = transpiled + let output = transpiled.code + + if (map) { + let nodeMap = Object.assign({}, map) + nodeMap.sources = nodeMap.sources.map((source) => source.replace(/\?entry/, '')) + delete nodeMap.sourcesContent + + // Output explicit inline source map that source-map-support can pickup via requireHook mode. + // Since these are not formal chunks, the devtool infrastructure in webpack does not output + // a source map for these files. + const sourceMapUrl = new Buffer(JSON.stringify(nodeMap), 'utf-8').toString('base64') + output = `${output}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${sourceMapUrl}` + } + + return { + content: output, + sourceMap: transpiled.map + } + } + } + }, { + loader: 'babel-loader', + include: nextPagesDir, + exclude (str) { + return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 + }, + options: { + babelrc: false, + cacheDirectory: true, + presets: [require.resolve('./babel/preset')] + } + }, { + test: /\.(js|jsx)(\?[^?]*)?$/, + loader: 'babel-loader', + include: [dir], + exclude (str) { + return /node_modules/.test(str) + }, + options: mainBabelOptions + } + ] }, devtool: dev ? 'cheap-module-inline-source-map' : false, performance: { hints: false } From c3914ea77609d5b8c0af7d3a1aecabf46c6857dc Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 21 Dec 2017 11:18:13 +0100 Subject: [PATCH 007/132] Add comments --- server/build/webpack.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index ab59137e88a50..1f4e6a6f21d29 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -100,8 +100,13 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet } const plugins = [ - new CaseSensitivePathPlugin(), + // Defines NODE_ENV as development/production. This is used by some npm modules to determine if they should optimize. + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production') + }), + new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), + // Provide legacy options to webpack new webpack.LoaderOptionsPlugin({ options: { context: dir, @@ -110,12 +115,14 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet } } }), + // Writes all generated files to disk, even in development. For SSR. new WriteFilePlugin({ exitOnErrors: false, log: false, // required not to cache removed files useHashIndex: false }), + // Moves common modules into commons.js new webpack.optimize.CommonsChunkPlugin({ name: 'commons', filename: 'commons.js', @@ -150,10 +157,9 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet name: 'manifest', filename: 'manifest.js' }), - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production') - }), + // This adds Next.js route definitions to page bundles new PagesPlugin(), + // Implements support for dynamic imports new DynamicChunksPlugin() ] @@ -169,6 +175,7 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet } else { plugins.push(new webpack.IgnorePlugin(/react-hot-loader/)) plugins.push( + // Minifies javascript bundles new UglifyJSPlugin({ parallel: false, sourceMap: false, @@ -178,11 +185,13 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet } } }), + // Combines manifest.js commons.js and main.js into app.js in production new CombineAssetsPlugin({ input: ['manifest.js', 'commons.js', 'main.js'], output: 'app.js' }), ) + // Implements scope hoisting which speeds up browser execution of javascript plugins.push(new webpack.optimize.ModuleConcatenationPlugin()) } From b1aac7b5aef866ea6c9fabef2670ed09b0b2f55e Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 21 Dec 2017 11:40:20 +0100 Subject: [PATCH 008/132] Run in parallel --- server/build/webpack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 1f4e6a6f21d29..8b1a8a69d1cc0 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -177,7 +177,7 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet plugins.push( // Minifies javascript bundles new UglifyJSPlugin({ - parallel: false, + parallel: true, sourceMap: false, uglifyOptions: { compress: { From 7bee9a764a66798b9f7dca4e012f8858437e9837 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 21 Dec 2017 12:53:04 +0100 Subject: [PATCH 009/132] Push plugins seperately --- server/build/webpack.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 8b1a8a69d1cc0..0892b1fb46461 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -184,7 +184,9 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet comparisons: false } } - }), + }) + ) + plugins.push( // Combines manifest.js commons.js and main.js into app.js in production new CombineAssetsPlugin({ input: ['manifest.js', 'commons.js', 'main.js'], From 5373354f143c40f3bec8a8ac7a6a7fe1a805648d Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 21 Dec 2017 21:33:22 +0100 Subject: [PATCH 010/132] Create a new chunk for react --- server/build/webpack.js | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 0892b1fb46461..87890adec7b9a 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -153,10 +153,41 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet // This chunk contains all the webpack related code. So, all the changes // related to that happens to this chunk. // It won't touch commons.js and that gives us much better re-build perf. + new webpack.optimize.CommonsChunkPlugin({ + name: 'react', + filename: 'react.js', + minChunks (module, count) { + if (module.resource && module.resource.includes(`${sep}react-dom${sep}`) && count >= 0) { + return true + } + + if (module.resource && module.resource.includes(`${sep}react${sep}`) && count >= 0) { + return true + } + + return false + } + }), + new webpack.optimize.CommonsChunkPlugin({ + name: 'react', + filename: 'react.js', + minChunks (module, count) { + if (module.resource && module.resource.includes(`${sep}react-dom${sep}`) && count >= 0) { + return true + } + + if (module.resource && module.resource.includes(`${sep}react${sep}`) && count >= 0) { + return true + } + + return false + } + }), new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', filename: 'manifest.js' }), + // This adds Next.js route definitions to page bundles new PagesPlugin(), // Implements support for dynamic imports @@ -177,6 +208,7 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet plugins.push( // Minifies javascript bundles new UglifyJSPlugin({ + exclude: /react\.js/, parallel: true, sourceMap: false, uglifyOptions: { @@ -189,7 +221,7 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet plugins.push( // Combines manifest.js commons.js and main.js into app.js in production new CombineAssetsPlugin({ - input: ['manifest.js', 'commons.js', 'main.js'], + input: ['manifest.js', 'react.js', 'commons.js', 'main.js'], output: 'app.js' }), ) From dc3f242c1c626b4be3c6ed7872498ce0f3db3230 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 22 Dec 2017 08:57:30 +0100 Subject: [PATCH 011/132] =?UTF-8?q?Don=E2=80=99t=20uglify=20react=20since?= =?UTF-8?q?=20it=E2=80=99s=20already=20uglified.=20Move=20react=20to=20com?= =?UTF-8?q?mons=20in=20development?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/build/webpack.js | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 87890adec7b9a..c3653714d4c93 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -130,7 +130,11 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet // We need to move react-dom explicitly into common chunks. // Otherwise, if some other page or module uses it, it might // included in that bundle too. - if (module.context && module.context.indexOf(`${sep}react-dom${sep}`) >= 0) { + if (dev && module.context && module.context.indexOf(`${sep}react${sep}`) >= 0) { + return true + } + + if (dev && module.context && module.context.indexOf(`${sep}react-dom${sep}`) >= 0) { return true } @@ -150,28 +154,15 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet return count >= totalPages * 0.5 } }), - // This chunk contains all the webpack related code. So, all the changes - // related to that happens to this chunk. - // It won't touch commons.js and that gives us much better re-build perf. + // This chunk splits out react and react-dom in production to make sure it does not go through uglify new webpack.optimize.CommonsChunkPlugin({ name: 'react', filename: 'react.js', minChunks (module, count) { - if (module.resource && module.resource.includes(`${sep}react-dom${sep}`) && count >= 0) { - return true - } - - if (module.resource && module.resource.includes(`${sep}react${sep}`) && count >= 0) { - return true + if (dev) { + return false } - return false - } - }), - new webpack.optimize.CommonsChunkPlugin({ - name: 'react', - filename: 'react.js', - minChunks (module, count) { if (module.resource && module.resource.includes(`${sep}react-dom${sep}`) && count >= 0) { return true } @@ -183,6 +174,9 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet return false } }), + // This chunk contains all the webpack related code. So, all the changes + // related to that happens to this chunk. + // It won't touch commons.js and that gives us much better re-build perf. new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', filename: 'manifest.js' From 6fabf34bfe461cf02eefef8e5b5e8989e7586352 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 22 Dec 2017 10:22:55 +0100 Subject: [PATCH 012/132] Use the minified version directly --- server/build/webpack.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/build/webpack.js b/server/build/webpack.js index c3653714d4c93..ca8539f9d468a 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -284,6 +284,11 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet chunkFilename: '[name]' }, resolve: { + alias: { + // This bypasses React's check for production mode. Since we know it is in production this way. + // This allows us to exclude React from being uglified. Saving multiple seconds per build. + 'react-dom': dev ? 'react-dom/cjs/react-dom.development.js' : 'react-dom/cjs/react-dom.production.min.js' + }, extensions: ['.js', '.jsx', '.json'], modules: [ nextNodeModulesDir, From 654c48e863464677af5703aa9c445172d8d76318 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 22 Dec 2017 10:31:06 +0100 Subject: [PATCH 013/132] Re-add globpattern --- server/build/webpack.js | 6 +++--- server/config.js | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index ca8539f9d468a..82fe492f993dc 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -29,13 +29,13 @@ const interpolateNames = new Map(defaultPages.map((p) => { const relativeResolve = rootModuleRelativePath(require) -async function getPages (dir, dev) { +async function getPages ({dir, dev, pagesGlobPattern}) { let pages if (dev) { pages = await glob('pages/+(_document|_error).+(js|jsx)', { cwd: dir }) } else { - pages = await glob('pages/**/*.+(js|jsx)', { cwd: dir }) + pages = await glob(pagesGlobPattern, { cwd: dir }) } return pages @@ -78,7 +78,7 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet const entry = async () => { // Get entries for pages in production mode. In development only _document and _error are added. Because pages are added by on-demand-entry-handler. - const pages = await getPages(dir, dev) + const pages = await getPages({dir, dev, pagesGlobPattern: config.pagesGlobPattern}) const pageEntries = getPageEntries(pages) // Used for commons chunk calculations diff --git a/server/config.js b/server/config.js index e53b7ecf7f5e8..395b92c526ab5 100644 --- a/server/config.js +++ b/server/config.js @@ -9,7 +9,8 @@ const defaultConfig = { distDir: '.next', assetPrefix: '', configOrigin: 'default', - useFileSystemPublicRoutes: true + useFileSystemPublicRoutes: true, + pagesGlobPattern: 'pages/**/*.+(js|jsx)' } export default function getConfig (dir, customConfig) { From 25e8bcac7837e73656ad18cff02eec7df6d867f3 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 22 Dec 2017 10:35:13 +0100 Subject: [PATCH 014/132] Move loaders into a separate variable --- server/build/webpack.js | 230 ++++++++++++++++++++-------------------- 1 file changed, 116 insertions(+), 114 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 82fe492f993dc..986a0ee7bbf4e 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -263,6 +263,121 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet exclude: /node_modules/ }] : [] + const loaders = [{ + test: /\.json$/, + loader: 'json-loader' + }, { + test: /\.(js|jsx|json)(\?[^?]*)?$/, + loader: 'emit-file-loader', + include: [dir, nextPagesDir], + exclude (str) { + return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 + }, + options: { + name: 'dist/[path][name].[ext]', + // We need to strip off .jsx on the server. Otherwise require without .jsx doesn't work. + interpolateName: (name) => name.replace('.jsx', '.js'), + validateFileName (file) { + const cases = [{from: '.js', to: '.jsx'}, {from: '.jsx', to: '.js'}] + + for (const item of cases) { + const {from, to} = item + if (file.slice(-(from.length)) !== from) { + continue + } + + const filePath = file.slice(0, -(from.length)) + to + + if (existsSync(filePath)) { + throw new Error(`Both ${from} and ${to} file found. Please make sure you only have one of both.`) + } + } + }, + // By default, our babel config does not transpile ES2015 module syntax because + // webpack knows how to handle them. (That's how it can do tree-shaking) + // But Node.js doesn't know how to handle them. So, we have to transpile them here. + transform ({ content, sourceMap, interpolatedName }) { + // Only handle .js files + if (!(/\.(js|jsx)$/.test(interpolatedName))) { + return { content, sourceMap } + } + + const babelRuntimePath = require.resolve('babel-runtime/package').replace(/[\\/]package\.json$/, '') + const transpiled = babelCore.transform(content, { + babelrc: false, + sourceMaps: dev ? 'both' : false, + // Here we need to resolve all modules to the absolute paths. + // Earlier we did it with the babel-preset. + // But since we don't transpile ES2015 in the preset this is not resolving. + // That's why we need to do it here. + // See more: https://github.com/zeit/next.js/issues/951 + plugins: [ + require.resolve(join(__dirname, './babel/plugins/remove-dotjsx-from-import.js')), + [require.resolve('babel-plugin-transform-es2015-modules-commonjs')], + [ + require.resolve('babel-plugin-module-resolver'), + { + alias: { + 'babel-runtime': babelRuntimePath, + 'next/link': relativeResolve('../../lib/link'), + 'next/prefetch': relativeResolve('../../lib/prefetch'), + 'next/css': relativeResolve('../../lib/css'), + 'next/dynamic': relativeResolve('../../lib/dynamic'), + 'next/head': relativeResolve('../../lib/head'), + 'next/document': relativeResolve('../../server/document'), + 'next/router': relativeResolve('../../lib/router'), + 'next/error': relativeResolve('../../lib/error'), + 'styled-jsx/style': relativeResolve('styled-jsx/style') + } + } + ] + ], + inputSourceMap: sourceMap + }) + + // Strip ?entry to map back to filesystem and work with iTerm, etc. + let { map } = transpiled + let output = transpiled.code + + if (map) { + let nodeMap = Object.assign({}, map) + nodeMap.sources = nodeMap.sources.map((source) => source.replace(/\?entry/, '')) + delete nodeMap.sourcesContent + + // Output explicit inline source map that source-map-support can pickup via requireHook mode. + // Since these are not formal chunks, the devtool infrastructure in webpack does not output + // a source map for these files. + const sourceMapUrl = new Buffer(JSON.stringify(nodeMap), 'utf-8').toString('base64') + output = `${output}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${sourceMapUrl}` + } + + return { + content: output, + sourceMap: transpiled.map + } + } + } + }, { + loader: 'babel-loader', + include: nextPagesDir, + exclude (str) { + return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 + }, + options: { + babelrc: false, + cacheDirectory: true, + presets: [require.resolve('./babel/preset')] + } + }, { + test: /\.(js|jsx)(\?[^?]*)?$/, + loader: 'babel-loader', + include: [dir], + exclude (str) { + return /node_modules/.test(str) + }, + options: mainBabelOptions + }] + let webpackConfig = { context: dir, entry, @@ -308,120 +423,7 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet module: { rules: [ ...devLoaders, - { - test: /\.json$/, - loader: 'json-loader' - }, { - test: /\.(js|jsx|json)(\?[^?]*)?$/, - loader: 'emit-file-loader', - include: [dir, nextPagesDir], - exclude (str) { - return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 - }, - options: { - name: 'dist/[path][name].[ext]', - // We need to strip off .jsx on the server. Otherwise require without .jsx doesn't work. - interpolateName: (name) => name.replace('.jsx', '.js'), - validateFileName (file) { - const cases = [{from: '.js', to: '.jsx'}, {from: '.jsx', to: '.js'}] - - for (const item of cases) { - const {from, to} = item - if (file.slice(-(from.length)) !== from) { - continue - } - - const filePath = file.slice(0, -(from.length)) + to - - if (existsSync(filePath)) { - throw new Error(`Both ${from} and ${to} file found. Please make sure you only have one of both.`) - } - } - }, - // By default, our babel config does not transpile ES2015 module syntax because - // webpack knows how to handle them. (That's how it can do tree-shaking) - // But Node.js doesn't know how to handle them. So, we have to transpile them here. - transform ({ content, sourceMap, interpolatedName }) { - // Only handle .js files - if (!(/\.(js|jsx)$/.test(interpolatedName))) { - return { content, sourceMap } - } - - const babelRuntimePath = require.resolve('babel-runtime/package').replace(/[\\/]package\.json$/, '') - const transpiled = babelCore.transform(content, { - babelrc: false, - sourceMaps: dev ? 'both' : false, - // Here we need to resolve all modules to the absolute paths. - // Earlier we did it with the babel-preset. - // But since we don't transpile ES2015 in the preset this is not resolving. - // That's why we need to do it here. - // See more: https://github.com/zeit/next.js/issues/951 - plugins: [ - require.resolve(join(__dirname, './babel/plugins/remove-dotjsx-from-import.js')), - [require.resolve('babel-plugin-transform-es2015-modules-commonjs')], - [ - require.resolve('babel-plugin-module-resolver'), - { - alias: { - 'babel-runtime': babelRuntimePath, - 'next/link': relativeResolve('../../lib/link'), - 'next/prefetch': relativeResolve('../../lib/prefetch'), - 'next/css': relativeResolve('../../lib/css'), - 'next/dynamic': relativeResolve('../../lib/dynamic'), - 'next/head': relativeResolve('../../lib/head'), - 'next/document': relativeResolve('../../server/document'), - 'next/router': relativeResolve('../../lib/router'), - 'next/error': relativeResolve('../../lib/error'), - 'styled-jsx/style': relativeResolve('styled-jsx/style') - } - } - ] - ], - inputSourceMap: sourceMap - }) - - // Strip ?entry to map back to filesystem and work with iTerm, etc. - let { map } = transpiled - let output = transpiled.code - - if (map) { - let nodeMap = Object.assign({}, map) - nodeMap.sources = nodeMap.sources.map((source) => source.replace(/\?entry/, '')) - delete nodeMap.sourcesContent - - // Output explicit inline source map that source-map-support can pickup via requireHook mode. - // Since these are not formal chunks, the devtool infrastructure in webpack does not output - // a source map for these files. - const sourceMapUrl = new Buffer(JSON.stringify(nodeMap), 'utf-8').toString('base64') - output = `${output}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${sourceMapUrl}` - } - - return { - content: output, - sourceMap: transpiled.map - } - } - } - }, { - loader: 'babel-loader', - include: nextPagesDir, - exclude (str) { - return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 - }, - options: { - babelrc: false, - cacheDirectory: true, - presets: [require.resolve('./babel/preset')] - } - }, { - test: /\.(js|jsx)(\?[^?]*)?$/, - loader: 'babel-loader', - include: [dir], - exclude (str) { - return /node_modules/.test(str) - }, - options: mainBabelOptions - } + ...loaders ] }, devtool: dev ? 'cheap-module-inline-source-map' : false, From 82e5505ecd7ec88a8ac3f385557ead9131ea9dcc Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 22 Dec 2017 10:39:34 +0100 Subject: [PATCH 015/132] =?UTF-8?q?Add=20comment=20linking=20to=20Dan?= =?UTF-8?q?=E2=80=99s=20explanation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/build/webpack.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 986a0ee7bbf4e..53def747d356f 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -154,7 +154,8 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet return count >= totalPages * 0.5 } }), - // This chunk splits out react and react-dom in production to make sure it does not go through uglify + // This chunk splits out react and react-dom in production to make sure it does not go through uglify. This saved multiple seconds on production builds. + // See https://twitter.com/dan_abramov/status/944040306420408325. new webpack.optimize.CommonsChunkPlugin({ name: 'react', filename: 'react.js', From c8ff14bb1c1b41a9fe14b392b414c3a1c1eb731d Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 22 Dec 2017 10:41:07 +0100 Subject: [PATCH 016/132] Remove dot --- server/build/webpack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 53def747d356f..6889a70dafeed 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -155,7 +155,7 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet } }), // This chunk splits out react and react-dom in production to make sure it does not go through uglify. This saved multiple seconds on production builds. - // See https://twitter.com/dan_abramov/status/944040306420408325. + // See https://twitter.com/dan_abramov/status/944040306420408325 new webpack.optimize.CommonsChunkPlugin({ name: 'react', filename: 'react.js', From b4fbe50e122dcac8cb7709edab2d6d785723f58e Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 23 Dec 2017 12:39:54 +0100 Subject: [PATCH 017/132] Add universal webpack --- client/index.js | 3 + package.json | 10 +- server/build/index.js | 29 +- server/build/webpack.js | 2 +- server/build/webpack/base.config.js | 137 +++ server/build/webpack/utils.js | 44 + yarn.lock | 1424 +++++++++++++-------------- 7 files changed, 876 insertions(+), 773 deletions(-) create mode 100644 server/build/webpack/base.config.js create mode 100644 server/build/webpack/utils.js diff --git a/client/index.js b/client/index.js index 0283d98197fdd..2ccfeba0ddf00 100644 --- a/client/index.js +++ b/client/index.js @@ -59,10 +59,12 @@ let stripAnsi = (s) => s export const emitter = new EventEmitter() export default async ({ ErrorDebugComponent: passedDebugComponent, stripAnsi: passedStripAnsi } = {}) => { + console.log('TEST') // Wait for all the dynamic chunks to get loaded for (const chunkName of chunks) { await pageLoader.waitForChunk(chunkName) } + stripAnsi = passedStripAnsi || stripAnsi ErrorDebugComponent = passedDebugComponent @@ -87,6 +89,7 @@ export default async ({ ErrorDebugComponent: passedDebugComponent, stripAnsi: pa }) const hash = location.hash.substring(1) + console.log('TEST 1') render({ Component, props, hash, err, emitter }) return emitter diff --git a/package.json b/package.json index 651a5e1d2586c..adb77d6dbc750 100644 --- a/package.json +++ b/package.json @@ -68,8 +68,11 @@ "babel-template": "6.26.0", "case-sensitive-paths-webpack-plugin": "2.1.1", "cross-spawn": "5.1.0", + "css-hot-loader": "1.3.4", + "css-loader": "0.28.7", "del": "3.0.0", "etag": "1.8.1", + "extract-text-webpack-plugin": "3.0.2", "find-up": "2.1.0", "fresh": "0.5.2", "friendly-errors-webpack-plugin": "1.6.1", @@ -96,16 +99,17 @@ "strip-ansi": "3.0.1", "styled-jsx": "2.2.1", "touch": "3.1.0", + "uglifyjs-webpack-plugin": "^1.1.1", "unfetch": "3.0.0", "url": "0.11.0", "uuid": "3.1.0", "walk": "2.3.9", - "webpack": "3.6.0", + "webpack": "3.10.0", "webpack-dev-middleware": "1.12.0", "webpack-hot-middleware": "2.19.1", + "webpack-node-externals": "1.6.0", "write-file-webpack-plugin": "4.2.0", - "xss-filters": "1.2.7", - "uglifyjs-webpack-plugin": "^1.1.1" + "xss-filters": "1.2.7" }, "devDependencies": { "@taskr/babel": "1.1.0", diff --git a/server/build/index.js b/server/build/index.js index f1f3397d28c76..2258bf11410de 100644 --- a/server/build/index.js +++ b/server/build/index.js @@ -3,14 +3,16 @@ import { join } from 'path' import fs from 'mz/fs' import uuid from 'uuid' import del from 'del' -import webpack from './webpack' +import webpack from 'webpack' +import getConfig from '../config' +import baseConfig from './webpack/base.config.js' import replaceCurrentBuild from './replace' import md5File from 'md5-file/promise' export default async function build (dir, conf = null) { + const config = getConfig(dir, conf) const buildId = uuid.v4() const tempDir = tmpdir() - const buildDir = join(tempDir, uuid.v4()) try { await fs.access(tempDir, fs.constants.W_OK) @@ -19,26 +21,31 @@ export default async function build (dir, conf = null) { throw err } - const compiler = await webpack(dir, { buildId, buildDir, conf }) + const clientCompiler = baseConfig(dir, { buildId, isServer: false, config }) + const serverCompiler = baseConfig(dir, { buildId, isServer: true, config }) try { - const stats = await runCompiler(compiler) - await writeBuildStats(buildDir, stats) - await writeBuildId(buildDir, buildId) + const [stats] = await Promise.all([ + runCompiler(clientCompiler), + runCompiler(serverCompiler) + ]) + await writeBuildStats(dir, stats) + await writeBuildId(dir, buildId) } catch (err) { - console.error(`> Failed to build on ${buildDir}`) + console.error(`> Failed to build`) throw err } - await replaceCurrentBuild(dir, buildDir) + // await replaceCurrentBuild(dir, buildDir) // no need to wait - del(buildDir, { force: true }) + // del(buildDir, { force: true }) } function runCompiler (compiler) { - return new Promise((resolve, reject) => { - compiler.run((err, stats) => { + return new Promise(async (resolve, reject) => { + const webpackCompiler = await webpack(await compiler) + webpackCompiler.run((err, stats) => { if (err) return reject(err) const jsonStats = stats.toJson() diff --git a/server/build/webpack.js b/server/build/webpack.js index 6889a70dafeed..835b201c8460e 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -435,5 +435,5 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet console.log(`> Using "webpack" config function defined in ${config.configOrigin}.`) webpackConfig = await config.webpack(webpackConfig, { buildId, dev }) } - return webpack(webpackConfig) + return webpackConfig } diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js new file mode 100644 index 0000000000000..e05785b22946c --- /dev/null +++ b/server/build/webpack/base.config.js @@ -0,0 +1,137 @@ +import path, {sep} from 'path' +import webpack from 'webpack' +import nodeExternals from 'webpack-node-externals' +import ExtractTextPlugin from 'extract-text-webpack-plugin' +import {getPages} from './utils' +import CombineAssetsPlugin from '../plugins/combine-assets-plugin' +import PagesPlugin from '../plugins/pages-plugin' + +const nextDir = path.join(__dirname, '..', '..', '..', '..') +const nextNodeModulesDir = path.join(nextDir, 'node_modules') + +export default async function baseConfig(dir, {dev = false, isServer = false, buildId, config}) { + const extractCSS = new ExtractTextPlugin('stylesheets/style.css'); + + const cssLoader = { + loader: isServer ? 'css-loader/locals' : 'css-loader', + options: { + modules: true, + minimize: !dev, + sourceMap: dev + } + } + + const externals = isServer ? [nodeExternals(nextNodeModulesDir), nodeExternals(path.join(dir, 'node_modules'))] : [] + let webpackConfig = { + target: isServer ? 'node' : 'web', + externals, + context: dir, + entry: async () => { + const pages = await getPages(dir, {dev, isServer}) + const mainJS = require.resolve(`../../../client/next${dev ? '-dev' : ''}`) + return { + 'main.js': [ + mainJS + ], + ...pages + } + }, + output: { + path: path.join(dir, '.next'), + filename: '[name]', + libraryTarget: 'commonjs2', + publicPath: `/_next/${buildId}/webpack/` + }, + resolve: { + extensions: ['.js', '.jsx', '.json'], + modules: [ + nextNodeModulesDir, + 'node_modules' + ], + alias: { + 'next': nextDir, + 'react-dom': dev ? 'react-dom/cjs/react-dom.development.js' : 'react-dom/cjs/react-dom.production.min.js' + } + }, + resolveLoader: { + modules: [ + nextNodeModulesDir, + 'node_modules', + path.join(__dirname, '..', 'loaders') + ] + }, + module: { + rules: [ + { + test: /\.json$/, + loader: 'json-loader' + }, + { + test: /\.js$/, + include: [dir], + exclude: /node_modules/, + use: { + loader: 'babel-loader', + options: { + presets: [ + [require.resolve('babel-preset-env'), { + modules: false + }], + require.resolve('babel-preset-react') + ], + plugins: [ + require.resolve('babel-plugin-react-require'), + require.resolve('babel-plugin-transform-object-rest-spread'), + require.resolve('babel-plugin-transform-class-properties'), + ] + } + } + }, + { + test: /\.css$/, + use: [ + isServer && cssLoader, + ...(!isServer ? extractCSS.extract([cssLoader]) : []) + ].filter(Boolean) + } + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production') + }), + new CombineAssetsPlugin({ + input: ['manifest.js', 'react.js', 'commons.js', 'main.js'], + output: 'app.js' + }), + !dev && new webpack.optimize.ModuleConcatenationPlugin(), + !isServer && extractCSS, + !isServer && new PagesPlugin(), + !isServer && new webpack.optimize.CommonsChunkPlugin({ + name: 'react', + filename: 'react.js', + minChunks (module, count) { + if (dev) { + return false + } + + if (module.resource && module.resource.includes(`${sep}react-dom${sep}`) && count >= 0) { + return true + } + + if (module.resource && module.resource.includes(`${sep}react${sep}`) && count >= 0) { + return true + } + + return false + } + }), + ].filter(Boolean) + } + + if(isServer && typeof config.webpack === 'function') { + webpackConfig = config.webpack(webpackConfig, {dev, buildId}) + } + + return webpackConfig +} \ No newline at end of file diff --git a/server/build/webpack/utils.js b/server/build/webpack/utils.js new file mode 100644 index 0000000000000..13efa48baa361 --- /dev/null +++ b/server/build/webpack/utils.js @@ -0,0 +1,44 @@ +import path from 'path' +import glob from 'glob-promise' + +const nextPagesDir = path.join(__dirname, '..', '..', '..', 'pages') + +export async function getPages (dir, {dev, isServer}) { + const pageFiles = await getPageFiles(dir, {dev, isServer}) + + return getPageEntries(pageFiles, {isServer}) +} + +async function getPageFiles(dir, {dev, isServer}) { + let pages + + if (dev) { + pages = await glob(isServer ? 'pages/+(_document|_error).+(js|jsx)': 'pages/_error.+(js|jsx)', { cwd: dir }) + } else { + pages = await glob(isServer ? 'pages/**/*.+(js|jsx)' : 'pages/**/!(_document)*.+(js|jsx)', { cwd: dir }) + } + + return pages +} + +export function getPageEntries (pageFiles, {isServer}) { + const entries = {} + const bundleLocation = isServer ? 'dist' : 'bundles' + for (const p of pageFiles) { + entries[path.join(bundleLocation, p.replace('.jsx', '.js'))] = [`./${p}`] + } + + // The default pages (_document.js and _error.js) are only added when they're not provided by the user + const defaultPages = [ + '_error.js', + isServer && '_document.js' + ].filter(Boolean) + for (const p of defaultPages) { + const entryName = path.join(bundleLocation, 'pages', p) + if (!entries[entryName]) { + entries[entryName] = path.join(nextPagesDir, p) + } + } + + return entries +} diff --git a/yarn.lock b/yarn.lock index f418fed51d4ca..df901b6d333be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,51 +2,6 @@ # yarn lockfile v1 -"@semantic-release/commit-analyzer@^3.0.1": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@semantic-release/commit-analyzer/-/commit-analyzer-3.0.7.tgz#dc955444a6d3d2ae9b8e21f90c2c80c4e9142b2f" - dependencies: - "@semantic-release/error" "^2.0.0" - conventional-changelog-angular "^1.4.0" - conventional-commits-parser "^2.0.0" - import-from "^2.1.0" - lodash "^4.17.4" - pify "^3.0.0" - -"@semantic-release/condition-travis@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@semantic-release/condition-travis/-/condition-travis-6.1.0.tgz#7962c728f4c19389b57759c7ff9ee08df9b15795" - dependencies: - "@semantic-release/error" "^2.0.0" - github "^11.0.0" - parse-github-repo-url "^1.4.1" - semver "^5.0.3" - travis-deploy-once "^3.0.0" - -"@semantic-release/error@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@semantic-release/error/-/error-2.0.0.tgz#f156ecd509f5288c48bc7425a8abe22f975d1f8b" - -"@semantic-release/last-release-npm@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@semantic-release/last-release-npm/-/last-release-npm-2.0.2.tgz#c91b1ccb48b0d7095b107be6ebc2c0c08bd88c27" - dependencies: - "@semantic-release/error" "^2.0.0" - npm-registry-client "^8.4.0" - npmlog "^4.0.0" - -"@semantic-release/release-notes-generator@^4.0.0": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@semantic-release/release-notes-generator/-/release-notes-generator-4.0.5.tgz#46cc2f16bdb60fe9674bbcd616bfe0f8bb35347c" - dependencies: - "@semantic-release/error" "^2.0.0" - conventional-changelog-angular "^1.4.0" - conventional-changelog-core "^1.9.0" - get-stream "^3.0.0" - import-from "^2.1.0" - lodash "^4.17.4" - pify "^3.0.0" - "@taskr/babel@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@taskr/babel/-/babel-1.1.0.tgz#f5af6b236395cbd013d3f67328ca73651e0299a1" @@ -75,13 +30,6 @@ dependencies: chokidar "^1.7.0" -JSONStream@^1.0.4: - version "1.3.1" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.1.tgz#707f761e01dae9e16f1bcf93703b78c70966579a" - dependencies: - jsonparse "^1.2.0" - through ">=2.2.7 <3" - abab@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" @@ -127,13 +75,6 @@ acorn@^5.0.0, acorn@^5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7" -agent-base@2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.1.1.tgz#d6de10d5af6132d5bd692427d46fc538539094c7" - dependencies: - extend "~3.0.0" - semver "~5.0.1" - aggregate-error@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-1.0.0.tgz#888344dad0220a72e3af50906117f48771925fac" @@ -182,6 +123,10 @@ align-text@^0.1.1, align-text@^0.1.3: longest "^1.0.1" repeat-string "^1.5.2" +alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -301,18 +246,10 @@ array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" -array-ify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" - array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -382,20 +319,37 @@ async@2.0.1: dependencies: lodash "^4.8.0" -async@^1.4.0, async@^1.5.2, async@~1.5.2: +async@^1.4.0, async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.0.0, async@^2.0.1, async@^2.1.2, async@^2.1.4: +async@^2.0.0, async@^2.1.2, async@^2.1.4: version "2.5.0" resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d" dependencies: lodash "^4.14.0" +async@^2.4.1: + version "2.6.0" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" + dependencies: + lodash "^4.14.0" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" +autoprefixer@^6.3.1: + version "6.7.7" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" + dependencies: + browserslist "^1.7.6" + caniuse-db "^1.0.30000634" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^5.2.16" + postcss-value-parser "^3.2.3" + aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" @@ -416,7 +370,7 @@ babel-code-frame@7.0.0-beta.0: esutils "^2.0.2" js-tokens "^3.0.0" -babel-code-frame@^6.16.0, babel-code-frame@^6.26.0: +babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -1124,6 +1078,10 @@ babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" +balanced-match@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -1159,12 +1117,6 @@ bl@^1.0.0: dependencies: readable-stream "^2.0.5" -bl@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.1.2.tgz#fdca871a99713aa00d19e3bbba41c44787a65398" - dependencies: - readable-stream "~2.0.5" - block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" @@ -1278,6 +1230,13 @@ browserify-zlib@^0.1.4: dependencies: pako "~0.2.0" +browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: + version "1.7.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" + dependencies: + caniuse-db "^1.0.30000639" + electron-to-chromium "^1.2.7" + browserslist@^2.1.2: version "2.5.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.5.1.tgz#68e4bc536bbcc6086d62843a2ffccea8396821c6" @@ -1330,10 +1289,6 @@ builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" -builtins@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" - cacache@^10.0.0: version "10.0.1" resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.1.tgz#3e05f6e616117d9b54665b1b20c8aeb93ea5d36f" @@ -1374,21 +1329,10 @@ callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" @@ -1397,6 +1341,19 @@ camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" +caniuse-api@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" + dependencies: + browserslist "^1.3.6" + caniuse-db "^1.0.30000529" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: + version "1.0.30000784" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000784.tgz#1be95012d9489c7719074f81aee57dbdffe6361b" + caniuse-lite@^1.0.30000744: version "1.0.30000748" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000748.tgz#44c8d6da52ad65a5d7b9dca4efebd0bdd982ba09" @@ -1438,6 +1395,14 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" +chalk@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + cheerio@0.22.0: version "0.22.0" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" @@ -1503,6 +1468,12 @@ circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" +clap@^1.0.9: + version "1.2.3" + resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" + dependencies: + chalk "^1.1.3" + clean-stack@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31" @@ -1544,6 +1515,10 @@ cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" +clone@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" + clor@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/clor/-/clor-5.2.0.tgz#9ddc74e7e86728cfcd05a80546ba58d317b81035" @@ -1552,18 +1527,21 @@ co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" +coa@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" + dependencies: + q "^1.1.2" + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" -codeclimate-test-reporter@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/codeclimate-test-reporter/-/codeclimate-test-reporter-0.5.0.tgz#93fa06b1c18e4117349128dc4e38aad08043828e" +color-convert@^1.3.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" dependencies: - async "~1.5.2" - commander "2.9.0" - lcov-parse "0.0.10" - request "~2.79.0" + color-name "^1.1.1" color-convert@^1.9.0: version "1.9.0" @@ -1571,22 +1549,42 @@ color-convert@^1.9.0: dependencies: color-name "^1.1.1" -color-name@^1.1.1: +color-name@^1.0.0, color-name@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" +color-string@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" + dependencies: + color-name "^1.0.0" + +color@^0.11.0: + version "0.11.4" + resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" + dependencies: + clone "^1.0.2" + color-convert "^1.3.0" + color-string "^0.3.0" + +colormin@^1.0.5: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" + dependencies: + color "^0.11.0" + css-color-names "0.0.4" + has "^1.0.1" + +colors@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" dependencies: delayed-stream "~1.0.0" -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - dependencies: - graceful-readlink ">= 1.0.0" - commander@^2.9.0, commander@~2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" @@ -1595,13 +1593,6 @@ commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" -compare-func@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.2.tgz#99dd0ba457e1f9bc722b12c08ec33eeab31fa648" - dependencies: - array-ify "^1.0.0" - dot-prop "^3.0.0" - compress-commons@^1.2.0: version "1.2.2" resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.2.2.tgz#524a9f10903f3a813389b0225d27c48bb751890f" @@ -1623,13 +1614,6 @@ concat-stream@1.6.0, concat-stream@^1.5.0, concat-stream@^1.5.2: readable-stream "^2.2.2" typedarray "^0.0.6" -config-chain@~1.1.8: - version "1.1.11" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - console-browserify@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" @@ -1656,65 +1640,6 @@ content-type@~1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" -conventional-changelog-angular@^1.4.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-1.5.1.tgz#974e73aa1c39c392e4364f2952bd9a62904e9ea3" - dependencies: - compare-func "^1.3.1" - q "^1.4.1" - -conventional-changelog-core@^1.9.0: - version "1.9.2" - resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-1.9.2.tgz#a09b6b959161671ff45b93cc9efb0444e7c845c0" - dependencies: - conventional-changelog-writer "^2.0.1" - conventional-commits-parser "^2.0.0" - dateformat "^1.0.12" - get-pkg-repo "^1.0.0" - git-raw-commits "^1.2.0" - git-remote-origin-url "^2.0.0" - git-semver-tags "^1.2.2" - lodash "^4.0.0" - normalize-package-data "^2.3.5" - q "^1.4.1" - read-pkg "^1.1.0" - read-pkg-up "^1.0.1" - through2 "^2.0.0" - -conventional-changelog-writer@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-2.0.1.tgz#47c10d0faba526b78d194389d1e931d09ee62372" - dependencies: - compare-func "^1.3.1" - conventional-commits-filter "^1.0.0" - dateformat "^1.0.11" - handlebars "^4.0.2" - json-stringify-safe "^5.0.1" - lodash "^4.0.0" - meow "^3.3.0" - semver "^5.0.1" - split "^1.0.0" - through2 "^2.0.0" - -conventional-commits-filter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-1.0.0.tgz#6fc2a659372bc3f2339cf9ffff7e1b0344b93039" - dependencies: - is-subset "^0.1.1" - modify-values "^1.0.0" - -conventional-commits-parser@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-2.0.0.tgz#71d01910cb0a99aeb20c144e50f81f4df3178447" - dependencies: - JSONStream "^1.0.4" - is-text-path "^1.0.0" - lodash "^4.2.1" - meow "^3.3.0" - split2 "^2.0.0" - through2 "^2.0.0" - trim-off-newlines "^1.0.0" - convert-source-map@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" @@ -1750,7 +1675,7 @@ core-js@^2.4.0, core-js@^2.5.0: version "2.5.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b" -core-util-is@1.0.2, core-util-is@^1.0.1, core-util-is@~1.0.0: +core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -1871,6 +1796,36 @@ crypto-browserify@^3.11.0: public-encrypt "^4.0.0" randombytes "^2.0.0" +css-color-names@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + +css-hot-loader@1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/css-hot-loader/-/css-hot-loader-1.3.4.tgz#cd58b9419cd7ec82350b1d60713d86e480a8b286" + dependencies: + loader-utils "^1.1.0" + normalize-url "^1.9.1" + +css-loader@0.28.7: + version "0.28.7" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.7.tgz#5f2ee989dd32edd907717f953317656160999c1b" + dependencies: + babel-code-frame "^6.11.0" + css-selector-tokenizer "^0.7.0" + cssnano ">=2.6.1 <4" + icss-utils "^2.1.0" + loader-utils "^1.0.2" + lodash.camelcase "^4.3.0" + object-assign "^4.0.1" + postcss "^5.0.6" + postcss-modules-extract-imports "^1.0.0" + postcss-modules-local-by-default "^1.0.1" + postcss-modules-scope "^1.0.0" + postcss-modules-values "^1.1.0" + postcss-value-parser "^3.3.0" + source-list-map "^2.0.0" + css-select@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" @@ -1880,10 +1835,66 @@ css-select@~1.2.0: domutils "1.5.1" nth-check "~1.0.1" +css-selector-tokenizer@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86" + dependencies: + cssesc "^0.1.0" + fastparse "^1.1.1" + regexpu-core "^1.0.0" + css-what@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" +cssesc@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" + +"cssnano@>=2.6.1 <4": + version "3.10.0" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" + dependencies: + autoprefixer "^6.3.1" + decamelize "^1.1.2" + defined "^1.0.0" + has "^1.0.1" + object-assign "^4.0.1" + postcss "^5.0.14" + postcss-calc "^5.2.0" + postcss-colormin "^2.1.8" + postcss-convert-values "^2.3.4" + postcss-discard-comments "^2.0.4" + postcss-discard-duplicates "^2.0.1" + postcss-discard-empty "^2.0.1" + postcss-discard-overridden "^0.1.1" + postcss-discard-unused "^2.2.1" + postcss-filter-plugins "^2.0.0" + postcss-merge-idents "^2.1.5" + postcss-merge-longhand "^2.0.1" + postcss-merge-rules "^2.0.3" + postcss-minify-font-values "^1.0.2" + postcss-minify-gradients "^1.0.1" + postcss-minify-params "^1.0.4" + postcss-minify-selectors "^2.0.4" + postcss-normalize-charset "^1.1.0" + postcss-normalize-url "^3.0.7" + postcss-ordered-values "^2.1.0" + postcss-reduce-idents "^2.2.2" + postcss-reduce-initial "^1.0.0" + postcss-reduce-transforms "^1.0.3" + postcss-svgo "^2.1.1" + postcss-unique-selectors "^2.0.2" + postcss-value-parser "^3.2.3" + postcss-zindex "^2.0.1" + +csso@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" + dependencies: + clap "^1.0.9" + source-map "^0.5.3" + cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": version "0.3.2" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b" @@ -1894,12 +1905,6 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": dependencies: cssom "0.3.x" -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - dependencies: - array-find-index "^1.0.1" - cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" @@ -1910,12 +1915,6 @@ d@1: dependencies: es5-ext "^0.10.9" -dargs@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17" - dependencies: - number-is-nan "^1.0.0" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -1930,29 +1929,22 @@ date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" -dateformat@^1.0.11, dateformat@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" - dependencies: - get-stdin "^4.0.1" - meow "^3.3.0" - debug-log@^1.0.0, debug-log@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" -debug@2, debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.6.3, debug@^2.6.8: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - dependencies: - ms "2.0.0" - debug@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" dependencies: ms "0.7.1" +debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.6.3, debug@^2.6.8: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + debug@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -1984,6 +1976,10 @@ define-properties@^1.1.2: foreach "^2.0.5" object-keys "^1.0.8" +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + deglob@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/deglob/-/deglob-2.1.0.tgz#4d44abe16ef32c779b4972bd141a80325029a14a" @@ -2116,12 +2112,6 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" -dot-prop@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177" - dependencies: - is-obj "^1.0.0" - duplexify@^3.1.2, duplexify@^3.4.2: version "3.5.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd" @@ -2141,6 +2131,16 @@ ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" +electron-releases@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/electron-releases/-/electron-releases-2.1.0.tgz#c5614bf811f176ce3c836e368a0625782341fd4e" + +electron-to-chromium@^1.2.7: + version "1.3.30" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.30.tgz#9666f532a64586651fc56a72513692e820d06a80" + dependencies: + electron-releases "^2.1.0" + electron-to-chromium@^1.3.24: version "1.3.26" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.26.tgz#996427294861a74d9c7c82b9260ea301e8c02d66" @@ -2544,7 +2544,7 @@ express@4.15.5: utils-merge "1.0.0" vary "~1.1.1" -extend@3, extend@~3.0.0, extend@~3.0.1: +extend@~3.0.0, extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -2554,6 +2554,15 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" +extract-text-webpack-plugin@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz#5f043eaa02f9750a9258b78c0a6e0dc1408fb2f7" + dependencies: + async "^2.4.1" + loader-utils "^1.1.0" + schema-utils "^0.3.0" + webpack-sources "^1.0.1" + extract-zip@^1.6.5: version "1.6.5" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.5.tgz#99a06735b6ea20ea9b705d779acffcc87cff0440" @@ -2575,6 +2584,10 @@ fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" +fastparse@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" + fb-watchman@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" @@ -2677,6 +2690,12 @@ find-root@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" +find-up@2.1.0, find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -2684,12 +2703,6 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - dependencies: - locate-path "^2.0.0" - fkill@5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/fkill/-/fkill-5.1.0.tgz#d07c20a6bee698b02ae727fdcad61fbcdec198b8" @@ -2719,13 +2732,6 @@ flush-write-stream@^1.0.0: inherits "^2.0.1" readable-stream "^2.0.4" -follow-redirects@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-0.0.7.tgz#34b90bab2a911aa347571da90f22bd36ecd8a919" - dependencies: - debug "^2.2.0" - stream-consume "^0.1.0" - for-in@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2755,14 +2761,6 @@ forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" -form-data@~1.0.0-rc4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.1.tgz#ae315db9a4907fa065502304a66d7733475ee37c" - dependencies: - async "^2.0.1" - combined-stream "^1.0.5" - mime-types "^2.1.11" - form-data@~2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" @@ -2802,14 +2800,6 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" -fs-extra@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.2.tgz#f91704c53d1b461f893452b0c307d9997647ab6b" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" @@ -2882,20 +2872,6 @@ get-own-enumerable-property-symbols@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz#5c4ad87f2834c4b9b4e84549dc1e0650fb38c24b" -get-pkg-repo@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d" - dependencies: - hosted-git-info "^2.1.4" - meow "^3.3.0" - normalize-package-data "^2.3.0" - parse-github-repo-url "^1.3.0" - through2 "^2.0.0" - -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - get-stdin@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" @@ -2910,63 +2886,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -git-head@^1.2.1: - version "1.20.1" - resolved "https://registry.yarnpkg.com/git-head/-/git-head-1.20.1.tgz#036d16a4b374949e4e3daf15827903686d3ccd52" - dependencies: - git-refs "^1.1.3" - -git-raw-commits@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-1.2.0.tgz#0f3a8bfd99ae0f2d8b9224d58892975e9a52d03c" - dependencies: - dargs "^4.0.1" - lodash.template "^4.0.2" - meow "^3.3.0" - split2 "^2.0.0" - through2 "^2.0.0" - -git-refs@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/git-refs/-/git-refs-1.1.3.tgz#83097cb3a92585c4a4926ec54e2182df9e20e89d" - dependencies: - path-object "^2.3.0" - slash "^1.0.0" - walk "^2.3.9" - -git-remote-origin-url@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" - dependencies: - gitconfiglocal "^1.0.0" - pify "^2.3.0" - -git-semver-tags@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-1.2.2.tgz#a2139be1bf6e337e125f3eb8bb8fc6f5d4d6445f" - dependencies: - meow "^3.3.0" - semver "^5.0.1" - -gitconfiglocal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" - dependencies: - ini "^1.3.2" - -github@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/github/-/github-11.0.0.tgz#edb32df5efb33cad004ebf0bdd2a4b30bb63a854" - dependencies: - follow-redirects "0.0.7" - https-proxy-agent "^1.0.0" - mime "^1.2.11" - netrc "^0.1.4" - -github@~0.1.10: - version "0.1.16" - resolved "https://registry.yarnpkg.com/github/-/github-0.1.16.tgz#895d2a85b0feb7980d89ac0ce4f44dcaa03f17b5" - glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" @@ -2980,12 +2899,9 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob-promise@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/glob-promise/-/glob-promise-3.2.0.tgz#fa53179ef42b7c5a6450e77374ab54c9708b7fe9" - dependencies: - codeclimate-test-reporter "^0.5.0" - semantic-release "^8.0.3" +glob-promise@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/glob-promise/-/glob-promise-3.3.0.tgz#d1eb3625c4e6dcbb9b96eeae4425d5a3b135fed2" glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2: version "7.1.2" @@ -3044,19 +2960,15 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" -graceful-fs@^4.1.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6: +graceful-fs@^4.1.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" -handlebars@^4.0.2, handlebars@^4.0.3: +handlebars@^4.0.3: version "4.0.11" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" dependencies: @@ -3186,10 +3098,14 @@ home-or-tmp@^2.0.0: os-homedir "^1.0.0" os-tmpdir "^1.0.1" -hosted-git-info@^2.1.4, hosted-git-info@^2.4.2: +hosted-git-info@^2.1.4: version "2.5.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" +html-comment-regex@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e" + html-encoding-sniffer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz#79bf7a785ea495fe66165e734153f363ff5437da" @@ -3255,14 +3171,6 @@ https-browserify@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" -https-proxy-agent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz#35f7da6c48ce4ddbfa264891ac593ee5ff8671e6" - dependencies: - agent-base "2" - debug "2" - extend "3" - husky@0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/husky/-/husky-0.14.3.tgz#c69ed74e2d2779769a17ba8399b54ce0b63c12c3" @@ -3279,6 +3187,16 @@ iconv-lite@~0.4.13: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +icss-replace-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" + +icss-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962" + dependencies: + postcss "^6.0.1" + ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" @@ -3291,12 +3209,6 @@ ignore@^3.0.9, ignore@^3.2.0: version "3.3.5" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.5.tgz#c4e715455f6073a8d7e5dae72d2fc9d71663dba6" -import-from@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" - dependencies: - resolve-from "^3.0.0" - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -3311,6 +3223,10 @@ indent-string@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" @@ -3330,7 +3246,7 @@ inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" -ini@^1.2.0, ini@^1.3.2, ini@^1.3.4, ini@~1.3.0: +ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" @@ -3370,6 +3286,10 @@ ipaddr.js@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0" +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -3475,7 +3395,7 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-obj@^1.0.0, is-obj@^1.0.1: +is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -3495,6 +3415,10 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -3531,20 +3455,16 @@ is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" -is-subset@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" +is-svg@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" + dependencies: + html-comment-regex "^1.1.0" is-symbol@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" -is-text-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" - dependencies: - text-extensions "^1.0.0" - is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -3868,6 +3788,10 @@ jest-validate@^21.1.0, jest-validate@^21.2.1: leven "^2.1.0" pretty-format "^21.2.1" +js-base64@^2.1.9: + version "2.4.0" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.0.tgz#9e566fee624751a1d720c966cd6226d29d4025aa" + js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" @@ -3886,6 +3810,13 @@ js-yaml@^3.4.3, js-yaml@^3.5.1, js-yaml@^3.7.0: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@~3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" + dependencies: + argparse "^1.0.7" + esprima "^2.6.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -3940,7 +3871,7 @@ json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" -json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: +json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -3948,20 +3879,10 @@ json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - optionalDependencies: - graceful-fs "^4.1.6" - jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" -jsonparse@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - jsonpointer@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" @@ -4134,49 +4055,6 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - -lodash._bindcallback@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" - -lodash._createassigner@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11" - dependencies: - lodash._bindcallback "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash.restparam "^3.0.0" - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - -lodash._reinterpolate@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - -lodash.assign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa" - dependencies: - lodash._baseassign "^3.0.0" - lodash._createassigner "^3.0.0" - lodash.keys "^3.0.0" - lodash.assignin@^4.0.9: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" @@ -4185,6 +4063,10 @@ lodash.bind@^4.1.4: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + lodash.defaults@^4.0.1: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" @@ -4201,26 +4083,14 @@ lodash.foreach@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - lodash.map@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + lodash.merge@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5" @@ -4237,39 +4107,22 @@ lodash.reject@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - lodash.some@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" -lodash.template@^4.0.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" - dependencies: - lodash._reinterpolate "~3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316" - dependencies: - lodash._reinterpolate "~3.0.0" +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" lodash@4.16.2: version "4.16.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652" -lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1, lodash@^4.8.0: +lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1, lodash@^4.8.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -lodash@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.3.1.tgz#a4663b53686b895ff074e2ba504dfb76a8e2b770" - log-driver@1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" @@ -4303,13 +4156,6 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: dependencies: js-tokens "^3.0.0" -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - lru-cache@^4.0.0, lru-cache@^4.0.1, lru-cache@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" @@ -4317,6 +4163,10 @@ lru-cache@^4.0.0, lru-cache@^4.0.1, lru-cache@^4.1.1: pseudomap "^1.0.2" yallist "^2.1.2" +macaddress@^0.2.8: + version "0.2.8" + resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12" + make-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" @@ -4329,9 +4179,9 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" +math-expression-evaluator@^1.2.14: + version "1.2.17" + resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" maximatch@^0.1.0: version "0.1.0" @@ -4382,21 +4232,6 @@ memory-fs@^0.4.0, memory-fs@~0.4.1: errno "^0.1.3" readable-stream "^2.0.1" -meow@^3.3.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" - merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -4444,7 +4279,7 @@ mime-db@~1.30.0: version "1.30.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" -mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.7: +mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.7: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" dependencies: @@ -4454,7 +4289,7 @@ mime@1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" -mime@1.4.1, mime@^1.2.11, mime@^1.3.4: +mime@1.4.1, mime@^1.3.4: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" @@ -4486,7 +4321,7 @@ minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: +minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -4532,10 +4367,6 @@ mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkd dependencies: minimist "0.0.8" -modify-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.0.tgz#e2b6cdeb9ce19f99317a53722f3dbf5df5eaaab2" - moment@^2.11.2: version "2.19.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.1.tgz#56da1a2d1cbf01d38b7e1afc31c10bcfa1929167" @@ -4599,14 +4430,6 @@ negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" -nerf-dart@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/nerf-dart/-/nerf-dart-1.0.0.tgz#e6dab7febf5ad816ea81cf5c629c5a0ebde72c1a" - -netrc@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/netrc/-/netrc-0.1.4.tgz#6be94fcaca8d77ade0a9670dc460914c94472444" - node-fetch@1.7.3, node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -4670,11 +4493,7 @@ node-pre-gyp@^0.6.36: tar "^2.2.1" tar-pack "^3.4.0" -node-uuid@~1.4.7: - version "1.4.8" - resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" - -nopt@^4.0.0, nopt@^4.0.1: +nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" dependencies: @@ -4687,13 +4506,7 @@ nopt@~1.0.10: dependencies: abbrev "1" -nopt@~3.0.1: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - dependencies: - abbrev "1" - -normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, "normalize-package-data@~1.0.1 || ^2.0.0": +normalize-package-data@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" dependencies: @@ -4712,14 +4525,18 @@ normalize-path@^2.0.0, normalize-path@^2.0.1: dependencies: remove-trailing-separator "^1.0.1" -"npm-package-arg@^3.0.0 || ^4.0.0 || ^5.0.0": - version "5.1.2" - resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-5.1.2.tgz#fb18d17bb61e60900d6312619919bd753755ab37" +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + +normalize-url@^1.4.0, normalize-url@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" dependencies: - hosted-git-info "^2.4.2" - osenv "^0.1.4" - semver "^5.1.0" - validate-npm-package-name "^3.0.0" + object-assign "^4.0.1" + prepend-http "^1.0.0" + query-string "^4.1.0" + sort-keys "^1.0.0" npm-path@^2.0.2: version "2.0.3" @@ -4727,23 +4544,6 @@ npm-path@^2.0.2: dependencies: which "^1.2.10" -npm-registry-client@^8.4.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/npm-registry-client/-/npm-registry-client-8.5.0.tgz#4878fb6fa1f18a5dc08ae83acf94d0d0112d7ed0" - dependencies: - concat-stream "^1.5.2" - graceful-fs "^4.1.6" - normalize-package-data "~1.0.1 || ^2.0.0" - npm-package-arg "^3.0.0 || ^4.0.0 || ^5.0.0" - once "^1.3.3" - request "^2.74.0" - retry "^0.10.0" - semver "2 >=2.2.1 || 3.x || 4 || 5" - slide "^1.1.3" - ssri "^4.1.2" - optionalDependencies: - npmlog "2 || ^3.1.0 || ^4.0.0" - npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -4758,21 +4558,7 @@ npm-which@^3.0.1: npm-path "^2.0.2" which "^1.2.10" -npmconf@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/npmconf/-/npmconf-2.1.2.tgz#66606a4a736f1e77a059aa071a79c94ab781853a" - dependencies: - config-chain "~1.1.8" - inherits "~2.0.0" - ini "^1.2.0" - mkdirp "^0.5.0" - nopt "~3.0.1" - once "~1.3.0" - osenv "^0.1.0" - semver "2 || 3 || 4" - uid-number "0.0.5" - -"npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@^4.0.0, npmlog@^4.0.2: +npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" dependencies: @@ -4787,6 +4573,10 @@ nth-check@~1.0.1: dependencies: boolbase "~1.0.0" +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -4866,12 +4656,6 @@ once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0: dependencies: wrappy "1" -once@~1.3.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" - dependencies: - wrappy "1" - onetime@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" @@ -4923,7 +4707,7 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" -osenv@^0.1.0, osenv@^0.1.4: +osenv@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" dependencies: @@ -4952,22 +4736,6 @@ p-map@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" -p-reduce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" - -p-retry@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-1.0.0.tgz#3927332a4b7d70269b535515117fc547da1a6968" - dependencies: - retry "^0.10.0" - -p-series@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-series/-/p-series-1.0.0.tgz#7ec9e7b4406cc32066298a6f9860e55e91b36e07" - dependencies: - p-reduce "^1.0.0" - pako@~0.2.0: version "0.2.9" resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" @@ -4990,10 +4758,6 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" -parse-github-repo-url@^1.3.0, parse-github-repo-url@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50" - parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -5050,13 +4814,6 @@ path-match@1.2.4: http-errors "~1.4.0" path-to-regexp "^1.0.0" -path-object@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/path-object/-/path-object-2.3.0.tgz#03e46653e5c375c60af1cabdd94bc6448a5d9110" - dependencies: - core-util-is "^1.0.1" - lodash.assign "^3.0.0" - path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" @@ -5174,10 +4931,260 @@ portfinder@1.0.13: debug "^2.2.0" mkdirp "0.5.x" +postcss-calc@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" + dependencies: + postcss "^5.0.2" + postcss-message-helpers "^2.0.0" + reduce-css-calc "^1.2.6" + +postcss-colormin@^2.1.8: + version "2.2.2" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" + dependencies: + colormin "^1.0.5" + postcss "^5.0.13" + postcss-value-parser "^3.2.3" + +postcss-convert-values@^2.3.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" + dependencies: + postcss "^5.0.11" + postcss-value-parser "^3.1.2" + +postcss-discard-comments@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" + dependencies: + postcss "^5.0.14" + +postcss-discard-duplicates@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" + dependencies: + postcss "^5.0.4" + +postcss-discard-empty@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" + dependencies: + postcss "^5.0.14" + +postcss-discard-overridden@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" + dependencies: + postcss "^5.0.16" + +postcss-discard-unused@^2.2.1: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" + dependencies: + postcss "^5.0.14" + uniqs "^2.0.0" + +postcss-filter-plugins@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz#6d85862534d735ac420e4a85806e1f5d4286d84c" + dependencies: + postcss "^5.0.4" + uniqid "^4.0.0" + +postcss-merge-idents@^2.1.5: + version "2.1.7" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" + dependencies: + has "^1.0.1" + postcss "^5.0.10" + postcss-value-parser "^3.1.1" + +postcss-merge-longhand@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" + dependencies: + postcss "^5.0.4" + +postcss-merge-rules@^2.0.3: + version "2.1.2" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" + dependencies: + browserslist "^1.5.2" + caniuse-api "^1.5.2" + postcss "^5.0.4" + postcss-selector-parser "^2.2.2" + vendors "^1.0.0" + +postcss-message-helpers@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" + +postcss-minify-font-values@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" + dependencies: + object-assign "^4.0.1" + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + +postcss-minify-gradients@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" + dependencies: + postcss "^5.0.12" + postcss-value-parser "^3.3.0" + +postcss-minify-params@^1.0.4: + version "1.2.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.2" + postcss-value-parser "^3.0.2" + uniqs "^2.0.0" + +postcss-minify-selectors@^2.0.4: + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" + dependencies: + alphanum-sort "^1.0.2" + has "^1.0.1" + postcss "^5.0.14" + postcss-selector-parser "^2.0.0" + +postcss-modules-extract-imports@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb" + dependencies: + postcss "^6.0.1" + +postcss-modules-local-by-default@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" + +postcss-modules-scope@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" + +postcss-modules-values@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" + dependencies: + icss-replace-symbols "^1.1.0" + postcss "^6.0.1" + +postcss-normalize-charset@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" + dependencies: + postcss "^5.0.5" + +postcss-normalize-url@^3.0.7: + version "3.0.8" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^1.4.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + +postcss-ordered-values@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.1" + +postcss-reduce-idents@^2.2.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + +postcss-reduce-initial@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" + dependencies: + postcss "^5.0.4" + +postcss-reduce-transforms@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" + dependencies: + has "^1.0.1" + postcss "^5.0.8" + postcss-value-parser "^3.0.1" + +postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" + dependencies: + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-svgo@^2.1.1: + version "2.1.6" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" + dependencies: + is-svg "^2.0.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + svgo "^0.7.0" + +postcss-unique-selectors@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" + +postcss-zindex@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" + dependencies: + has "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + +postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16: + version "5.2.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" + dependencies: + chalk "^1.1.3" + js-base64 "^2.1.9" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^6.0.1: + version "6.0.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885" + dependencies: + chalk "^2.3.0" + source-map "^0.6.1" + supports-color "^4.4.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" +prepend-http@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" @@ -5234,10 +5241,6 @@ prop-types@15.6.0, prop-types@^15.5.4, prop-types@^15.6.0: loose-envify "^1.3.1" object-assign "^4.1.1" -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - proxy-addr@~1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918" @@ -5290,7 +5293,7 @@ q@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" -q@^1.4.1: +q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -5298,10 +5301,6 @@ qs@6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49" -qs@~6.2.0: - version "6.2.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" - qs@~6.3.0: version "6.3.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" @@ -5314,6 +5313,13 @@ qs@~6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" +query-string@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" + dependencies: + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -5400,7 +5406,7 @@ read-pkg-up@^2.0.0: find-up "^2.0.0" read-pkg "^2.0.0" -read-pkg@^1.0.0, read-pkg@^1.1.0: +read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" dependencies: @@ -5428,17 +5434,6 @@ read-pkg@^2.0.0: string_decoder "~1.0.3" util-deprecate "~1.0.1" -readable-stream@~2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - string_decoder "~0.10.x" - util-deprecate "~1.0.1" - readdirp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" @@ -5486,12 +5481,19 @@ redbox-react@^1.3.6: prop-types "^15.5.4" sourcemapped-stacktrace "^1.1.6" -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" +reduce-css-calc@^1.2.6: + version "1.3.0" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" + balanced-match "^0.4.2" + math-expression-evaluator "^1.2.14" + reduce-function-call "^1.0.1" + +reduce-function-call@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99" + dependencies: + balanced-match "^0.4.2" regenerate@^1.2.1: version "1.3.3" @@ -5515,6 +5517,14 @@ regex-cache@^0.4.2: dependencies: is-equal-shallow "^0.1.3" +regexpu-core@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" @@ -5551,7 +5561,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@2.79.0, request@~2.79.0: +request@2.79.0: version "2.79.0" resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" dependencies: @@ -5603,7 +5613,7 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" -request@^2.74.0, request@^2.79.0, request@^2.81.0: +request@^2.79.0, request@^2.81.0: version "2.83.0" resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" dependencies: @@ -5630,32 +5640,6 @@ request@^2.74.0, request@^2.79.0, request@^2.81.0: tunnel-agent "^0.6.0" uuid "^3.1.0" -request@~2.74.0: - version "2.74.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.74.0.tgz#7693ca768bbb0ea5c8ce08c084a45efa05b892ab" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - bl "~1.1.2" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~1.0.0-rc4" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - node-uuid "~1.4.7" - oauth-sign "~0.8.1" - qs "~6.2.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -5672,10 +5656,6 @@ require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" -require-relative@^0.8.7: - version "0.8.7" - resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" - require-uncached@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" @@ -5691,10 +5671,6 @@ resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" @@ -5712,10 +5688,6 @@ restore-cursor@^1.0.1: exit-hook "^1.0.0" onetime "^1.0.0" -retry@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" - rewrite-imports@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/rewrite-imports/-/rewrite-imports-1.0.0.tgz#a4705c3829006e4f7541bf29d534d8d3b1717c83" @@ -5789,7 +5761,7 @@ sane@^2.0.0: optionalDependencies: fsevents "^1.1.1" -sax@^1.2.1: +sax@^1.2.1, sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -5799,42 +5771,10 @@ schema-utils@^0.3.0: dependencies: ajv "^5.0.0" -semantic-release@^8.0.3: - version "8.2.1" - resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-8.2.1.tgz#0bd4c2d372b328b2617fb34688937e58387f1bc1" - dependencies: - "@semantic-release/commit-analyzer" "^3.0.1" - "@semantic-release/condition-travis" "^6.0.0" - "@semantic-release/error" "^2.0.0" - "@semantic-release/last-release-npm" "^2.0.0" - "@semantic-release/release-notes-generator" "^4.0.0" - execa "^0.8.0" - fs-extra "^4.0.2" - git-head "^1.2.1" - github "^11.0.0" - lodash "^4.0.0" - nerf-dart "^1.0.0" - nopt "^4.0.0" - normalize-package-data "^2.3.4" - npmconf "^2.1.2" - npmlog "^4.0.0" - p-series "^1.0.0" - parse-github-repo-url "^1.3.0" - require-relative "^0.8.7" - semver "^5.4.1" - -"semver@2 >=2.2.1 || 3.x || 4 || 5", "semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1: +"semver@2 || 3 || 4 || 5", semver@^5.3.0: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" -"semver@2 || 3 || 4": - version "4.3.6" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" - -semver@~5.0.1: - version "5.0.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" - send@0.15.6: version "0.15.6" resolved "https://registry.yarnpkg.com/send/-/send-0.15.6.tgz#20f23a9c925b762ab82705fe2f9db252ace47e34" @@ -5937,7 +5877,7 @@ slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" -slide@^1.1.3, slide@^1.1.5: +slide@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -5953,6 +5893,12 @@ sntp@2.x.x: dependencies: hoek "4.x.x" +sort-keys@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + dependencies: + is-plain-obj "^1.0.0" + source-list-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" @@ -6012,18 +5958,6 @@ spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" -split2@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" - dependencies: - through2 "^2.0.2" - -split@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - dependencies: - through "2" - sprintf-js@^1.0.3: version "1.1.1" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" @@ -6046,12 +5980,6 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" -ssri@^4.1.2: - version "4.1.6" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-4.1.6.tgz#0cb49b6ac84457e7bdd466cb730c3cb623e9a25b" - dependencies: - safe-buffer "^5.1.0" - ssri@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.0.0.tgz#13c19390b606c821f2a10d02b351c1729b94d8cf" @@ -6103,10 +6031,6 @@ stream-browserify@^2.0.1: inherits "~2.0.1" readable-stream "^2.0.2" -stream-consume@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.0.tgz#a41ead1a6d6081ceb79f65b061901b6d8f3d1d0f" - stream-each@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd" @@ -6132,6 +6056,10 @@ stream-to-observable@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + string-hash@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" @@ -6164,7 +6092,7 @@ string-width@^2.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string_decoder@^0.10.25, string_decoder@~0.10.x: +string_decoder@^0.10.25: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" @@ -6186,18 +6114,18 @@ stringstream@~0.0.4, stringstream@~0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" -strip-ansi@4.0.0, strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: +strip-ansi@3.0.1, strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" dependencies: ansi-regex "^2.0.0" +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + strip-bom@3.0.0, strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -6212,12 +6140,6 @@ strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - dependencies: - get-stdin "^4.0.1" - strip-indent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" @@ -6250,18 +6172,30 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^3.1.2: +supports-color@^3.1.2, supports-color@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" dependencies: has-flag "^1.0.0" -supports-color@^4.0.0, supports-color@^4.2.1: +supports-color@^4.0.0, supports-color@^4.2.1, supports-color@^4.4.0: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" dependencies: has-flag "^2.0.0" +svgo@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" + dependencies: + coa "~1.0.1" + colors "~1.1.2" + csso "~2.3.1" + js-yaml "~3.7.0" + mkdirp "~0.5.1" + sax "~1.2.1" + whet.extend "~0.9.9" + symbol-observable@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" @@ -6343,10 +6277,6 @@ test-exclude@^4.1.1: read-pkg-up "^1.0.1" require-main-filename "^1.0.1" -text-extensions@^1.0.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.7.0.tgz#faaaba2625ed746d568a23e4d0aacd9bf08a8b39" - text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -6367,14 +6297,14 @@ throat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" -through2@^2.0.0, through2@^2.0.2: +through2@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" dependencies: readable-stream "^2.1.5" xtend "~4.0.1" -through@2, "through@>=2.2.7 <3", through@^2.3.6: +through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -6424,32 +6354,6 @@ tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" -travis-ci@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/travis-ci/-/travis-ci-2.1.1.tgz#98696265af827ae3576f31aa06d876e74b4b082e" - dependencies: - github "~0.1.10" - lodash "~1.3.1" - request "~2.74.0" - underscore.string "~2.2.0rc" - -travis-deploy-once@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/travis-deploy-once/-/travis-deploy-once-3.0.0.tgz#079f7c2d56472ef8e87d540c9b108bed9d9e1fdd" - dependencies: - chalk "^2.1.0" - p-retry "^1.0.0" - semver "^5.4.1" - travis-ci "^2.1.1" - -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - -trim-off-newlines@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" - trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" @@ -6537,10 +6441,6 @@ uglifyjs-webpack-plugin@^1.1.1: webpack-sources "^1.0.1" worker-farm "^1.4.1" -uid-number@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.5.tgz#5a3db23ef5dbd55b81fce0ec9a2ac6fccdebb81e" - uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" @@ -6552,10 +6452,6 @@ underscore.string@3.3.4: sprintf-js "^1.0.3" util-deprecate "^1.0.2" -underscore.string@~2.2.0rc: - version "2.2.1" - resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.2.1.tgz#d7c0fa2af5d5a1a67f4253daee98132e733f0f19" - unfetch@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-3.0.0.tgz#8d1e0513a4ecd0e5ff2d41a6ba77771aae8b6482" @@ -6564,6 +6460,16 @@ uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" +uniqid@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/uniqid/-/uniqid-4.1.1.tgz#89220ddf6b751ae52b5f72484863528596bb84c1" + dependencies: + macaddress "^0.2.8" + +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + unique-filename@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3" @@ -6576,10 +6482,6 @@ unique-slug@^2.0.0: dependencies: imurmurhash "^0.1.4" -universalify@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" - unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -6622,12 +6524,6 @@ validate-npm-package-license@^3.0.1: spdx-correct "~1.0.0" spdx-expression-parse "~1.0.0" -validate-npm-package-name@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" - dependencies: - builtins "^1.0.3" - vargs@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/vargs/-/vargs-0.1.0.tgz#6b6184da6520cc3204ce1b407cac26d92609ebff" @@ -6636,6 +6532,10 @@ vary@~1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" +vendors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22" + verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -6650,7 +6550,7 @@ vm-browserify@0.0.4: dependencies: indexof "0.0.1" -walk@2.3.9, walk@^2.3.9: +walk@2.3.9: version "2.3.9" resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.9.tgz#31b4db6678f2ae01c39ea9fb8725a9031e558a7b" dependencies: @@ -6721,6 +6621,10 @@ webpack-hot-middleware@2.19.1: querystring "^0.2.0" strip-ansi "^3.0.0" +webpack-node-externals@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.6.0.tgz#232c62ec6092b100635a3d29d83c1747128df9bd" + webpack-sources@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf" @@ -6728,9 +6632,9 @@ webpack-sources@^1.0.1: source-list-map "^2.0.0" source-map "~0.5.3" -webpack@3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.6.0.tgz#a89a929fbee205d35a4fa2cc487be9cbec8898bc" +webpack@3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.10.0.tgz#5291b875078cf2abf42bdd23afe3f8f96c17d725" dependencies: acorn "^5.0.0" acorn-dynamic-import "^2.0.0" @@ -6772,6 +6676,10 @@ whatwg-url@^4.3.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +whet.extend@~0.9.9: + version "0.9.9" + resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" From a05741549aae9c29830ba3168fe02665dc9c3127 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 27 Dec 2017 17:37:48 +0100 Subject: [PATCH 018/132] Initial dev support --- package.json | 1 + server/build/babel/preset.js | 32 +++++------ server/build/index.js | 16 ++++-- server/build/webpack/base.config.js | 89 +++++++++++++++++++++-------- server/build/webpack/utils.js | 2 +- server/hot-reloader.js | 27 ++++++--- server/on-demand-entry-handler.js | 3 +- 7 files changed, 114 insertions(+), 56 deletions(-) diff --git a/package.json b/package.json index adb77d6dbc750..4066f4238358b 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "recursive-copy": "2.0.6", "send": "0.16.1", "source-map-support": "0.4.18", + "stats-webpack-plugin": "0.6.1", "strip-ansi": "3.0.1", "styled-jsx": "2.2.1", "touch": "3.1.0", diff --git a/server/build/babel/preset.js b/server/build/babel/preset.js index 6ccebdc941dc1..f7a01020eb216 100644 --- a/server/build/babel/preset.js +++ b/server/build/babel/preset.js @@ -54,21 +54,21 @@ module.exports = (context, opts = {}) => ({ [require.resolve('babel-plugin-transform-runtime'), opts['transform-runtime'] || {}], [require.resolve('styled-jsx/babel'), styledJsxOptions(opts['styled-jsx'])], ...plugins, - [ - require.resolve('babel-plugin-module-resolver'), - { - alias: { - 'babel-runtime': babelRuntimePath, - 'next/link': relativeResolve('../../../lib/link'), - 'next/prefetch': relativeResolve('../../../lib/prefetch'), - 'next/css': relativeResolve('../../../lib/css'), - 'next/dynamic': relativeResolve('../../../lib/dynamic'), - 'next/head': relativeResolve('../../../lib/head'), - 'next/document': relativeResolve('../../../server/document'), - 'next/router': relativeResolve('../../../lib/router'), - 'next/error': relativeResolve('../../../lib/error') - } - } - ] + // [ + // require.resolve('babel-plugin-module-resolver'), + // { + // alias: { + // 'babel-runtime': babelRuntimePath, + // 'next/link': relativeResolve('../../../lib/link'), + // 'next/prefetch': relativeResolve('../../../lib/prefetch'), + // 'next/css': relativeResolve('../../../lib/css'), + // 'next/dynamic': relativeResolve('../../../lib/dynamic'), + // 'next/head': relativeResolve('../../../lib/head'), + // 'next/document': relativeResolve('../../../server/document'), + // 'next/router': relativeResolve('../../../lib/router'), + // 'next/error': relativeResolve('../../../lib/error') + // } + // } + // ] ] }) diff --git a/server/build/index.js b/server/build/index.js index 2258bf11410de..5f0a31c53b1e1 100644 --- a/server/build/index.js +++ b/server/build/index.js @@ -25,11 +25,17 @@ export default async function build (dir, conf = null) { const serverCompiler = baseConfig(dir, { buildId, isServer: true, config }) try { - const [stats] = await Promise.all([ - runCompiler(clientCompiler), - runCompiler(serverCompiler) + const configs = await Promise.all([ + baseConfig(dir, { buildId, isServer: false, config }), + baseConfig(dir, { buildId, isServer: true, config }) ]) - await writeBuildStats(dir, stats) + + await runCompiler(configs) + + // await fs.writeFile(join(dir, '.next', 'server-stats.json'), JSON.stringify(serverStats), 'utf8') + // await fs.writeFile(join(dir, '.next', 'client-stats.json'), JSON.stringify(stats), 'utf8') + + await writeBuildStats(dir) await writeBuildId(dir, buildId) } catch (err) { console.error(`> Failed to build`) @@ -62,7 +68,7 @@ function runCompiler (compiler) { }) } -async function writeBuildStats (dir, stats) { +async function writeBuildStats (dir) { // Here we can't use hashes in webpack chunks. // That's because the "app.js" is not tied to a chunk. // It's created by merging a few assets. (commons.js and main.js) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index e05785b22946c..46141b8404f64 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -1,10 +1,16 @@ import path, {sep} from 'path' import webpack from 'webpack' import nodeExternals from 'webpack-node-externals' +import UglifyJSPlugin from 'uglifyjs-webpack-plugin' +import CaseSensitivePathPlugin from 'case-sensitive-paths-webpack-plugin' +import WriteFilePlugin from 'write-file-webpack-plugin' +import FriendlyErrorsWebpackPlugin from 'friendly-errors-webpack-plugin' import ExtractTextPlugin from 'extract-text-webpack-plugin' import {getPages} from './utils' import CombineAssetsPlugin from '../plugins/combine-assets-plugin' import PagesPlugin from '../plugins/pages-plugin' +import DynamicChunksPlugin from '../plugins/dynamic-chunks-plugin' +import StatsPlugin from 'stats-webpack-plugin' const nextDir = path.join(__dirname, '..', '..', '..', '..') const nextNodeModulesDir = path.join(nextDir, 'node_modules') @@ -23,21 +29,28 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu const externals = isServer ? [nodeExternals(nextNodeModulesDir), nodeExternals(path.join(dir, 'node_modules'))] : [] let webpackConfig = { + name: isServer ? 'server' : 'client', + cache: true, + profile: true, target: isServer ? 'node' : 'web', externals, context: dir, entry: async () => { - const pages = await getPages(dir, {dev, isServer}) + // We use on-demand-entries in development + const pages = dev ? {} : await getPages(dir, {dev, isServer}) const mainJS = require.resolve(`../../../client/next${dev ? '-dev' : ''}`) - return { + const clientConfig = !isServer ? { 'main.js': [ mainJS ], + } : {} + return { + ...clientConfig, ...pages } }, output: { - path: path.join(dir, '.next'), + path: path.join(dir, '.next', isServer ? 'dist' : ''), filename: '[name]', libraryTarget: 'commonjs2', publicPath: `/_next/${buildId}/webpack/` @@ -62,10 +75,6 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu }, module: { rules: [ - { - test: /\.json$/, - loader: 'json-loader' - }, { test: /\.js$/, include: [dir], @@ -73,17 +82,8 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu use: { loader: 'babel-loader', options: { - presets: [ - [require.resolve('babel-preset-env'), { - modules: false - }], - require.resolve('babel-preset-react') - ], - plugins: [ - require.resolve('babel-plugin-react-require'), - require.resolve('babel-plugin-transform-object-rest-spread'), - require.resolve('babel-plugin-transform-class-properties'), - ] + cacheDirectory: true, + presets: [require.resolve('../babel/preset')], } } }, @@ -94,19 +94,57 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu ...(!isServer ? extractCSS.extract([cssLoader]) : []) ].filter(Boolean) } - ] + ].filter(Boolean) }, plugins: [ + // Useful when profiling + // new webpack.ProgressPlugin({ + // profile: true + // }), + // new StatsPlugin(`stats-${isServer ? 'server':'client'}.json`), + new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), + dev && new FriendlyErrorsWebpackPlugin(), + dev && new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive + dev && new webpack.LoaderOptionsPlugin({ + options: { + context: dir, + customInterpolateName (url, name, opts) { + return interpolateNames.get(this.resourcePath) || url + } + } + }), + dev && new WriteFilePlugin({ + exitOnErrors: false, + log: false, + // required not to cache removed files + useHashIndex: false + }), + !isServer && new UglifyJSPlugin({ + exclude: /react\.js/, + parallel: true, + sourceMap: false, + uglifyOptions: { + compress: { + comparisons: false + } + } + }), new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production') }), - new CombineAssetsPlugin({ + !isServer && new CombineAssetsPlugin({ input: ['manifest.js', 'react.js', 'commons.js', 'main.js'], output: 'app.js' }), !dev && new webpack.optimize.ModuleConcatenationPlugin(), !isServer && extractCSS, - !isServer && new PagesPlugin(), + !isServer && new PagesPlugin(), + !isServer && new DynamicChunksPlugin(), + !isServer && new webpack.optimize.CommonsChunkPlugin({ + name: `commons`, + filename: `commons.js`, + minChunks: 2, + }), !isServer && new webpack.optimize.CommonsChunkPlugin({ name: 'react', filename: 'react.js', @@ -125,13 +163,14 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu return false } - }), + }) + ].filter(Boolean) } - if(isServer && typeof config.webpack === 'function') { - webpackConfig = config.webpack(webpackConfig, {dev, buildId}) - } + // if(isServer && typeof config.webpack === 'function') { + // webpackConfig = config.webpack(webpackConfig, {dev, buildId}) + // } return webpackConfig } \ No newline at end of file diff --git a/server/build/webpack/utils.js b/server/build/webpack/utils.js index 13efa48baa361..dd99be8eab516 100644 --- a/server/build/webpack/utils.js +++ b/server/build/webpack/utils.js @@ -23,7 +23,7 @@ async function getPageFiles(dir, {dev, isServer}) { export function getPageEntries (pageFiles, {isServer}) { const entries = {} - const bundleLocation = isServer ? 'dist' : 'bundles' + const bundleLocation = isServer ? '' : 'bundles' for (const p of pageFiles) { entries[path.join(bundleLocation, p.replace('.jsx', '.js'))] = [`./${p}`] } diff --git a/server/hot-reloader.js b/server/hot-reloader.js index 3cebfb2823efd..9542bf20eab92 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -2,7 +2,8 @@ import { join, relative, sep } from 'path' import WebpackDevMiddleware from 'webpack-dev-middleware' import WebpackHotMiddleware from 'webpack-hot-middleware' import onDemandEntryHandler from './on-demand-entry-handler' -import webpack from './build/webpack' +import webpack from 'webpack' +import baseConfig from './build/webpack/base.config' import clean from './build/clean' import getConfig from './config' import UUID from 'uuid' @@ -45,11 +46,15 @@ export default class HotReloader { } async start () { - const [compiler] = await Promise.all([ - webpack(this.dir, { buildId: this.buildId, dev: true, quiet: this.quiet }), - clean(this.dir) + await clean(this.dir) + + const configs = await Promise.all([ + baseConfig(this.dir, { dev: true, isServer: false, config: this.conf }), + baseConfig(this.dir, { dev: true,isServer: true, config: this.conf }) ]) + const compiler = webpack(configs) + const buildTools = await this.prepareBuildTools(compiler) this.assignBuildTools(buildTools) @@ -71,11 +76,15 @@ export default class HotReloader { async reload () { this.stats = null - const [compiler] = await Promise.all([ - webpack(this.dir, { buildId: this.buildId, dev: true, quiet: this.quiet }), - clean(this.dir) + await clean(this.dir) + + const configs = await Promise.all([ + baseConfig(this.dir, { dev: true, isServer: false, config: this.conf }), + baseConfig(this.dir, { dev: true,isServer: true, config: this.conf }) ]) + const compiler = webpack(configs) + const buildTools = await this.prepareBuildTools(compiler) this.stats = await this.waitUntilValid(buildTools.webpackDevMiddleware) @@ -116,7 +125,9 @@ export default class HotReloader { }) compiler.plugin('done', (stats) => { - const { compilation } = stats + const clientStats = stats.stats.find((stats) => stats.compilation.compiler.name === 'client') + + const { compilation } = clientStats const chunkNames = new Set( compilation.chunks .map((c) => c.name) diff --git a/server/on-demand-entry-handler.js b/server/on-demand-entry-handler.js index fdd55328dfc4b..b4b196b166029 100644 --- a/server/on-demand-entry-handler.js +++ b/server/on-demand-entry-handler.js @@ -41,7 +41,8 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { }) compiler.plugin('done', function (stats) { - const { compilation } = stats + const clientStats = stats.stats.find((stats) => stats.compilation.compiler.name === 'client') + const { compilation } = clientStats const hardFailedPages = compilation.errors .filter(e => { // Make sure to only pick errors which marked with missing modules From 8226bd9c7273317e7b20b13aa584ad227e5198ba Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 27 Dec 2017 17:38:25 +0100 Subject: [PATCH 019/132] Fix linting --- client/index.js | 1 - server/build/babel/preset.js | 2 +- server/build/index.js | 6 +++--- server/build/webpack/base.config.js | 28 ++++++++++++++-------------- server/build/webpack/utils.js | 4 ++-- server/hot-reloader.js | 4 ++-- 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/client/index.js b/client/index.js index 2ccfeba0ddf00..39475087bdb41 100644 --- a/client/index.js +++ b/client/index.js @@ -64,7 +64,6 @@ export default async ({ ErrorDebugComponent: passedDebugComponent, stripAnsi: pa for (const chunkName of chunks) { await pageLoader.waitForChunk(chunkName) } - stripAnsi = passedStripAnsi || stripAnsi ErrorDebugComponent = passedDebugComponent diff --git a/server/build/babel/preset.js b/server/build/babel/preset.js index f7a01020eb216..f792c207d9613 100644 --- a/server/build/babel/preset.js +++ b/server/build/babel/preset.js @@ -53,7 +53,7 @@ module.exports = (context, opts = {}) => ({ require.resolve('babel-plugin-transform-class-properties'), [require.resolve('babel-plugin-transform-runtime'), opts['transform-runtime'] || {}], [require.resolve('styled-jsx/babel'), styledJsxOptions(opts['styled-jsx'])], - ...plugins, + ...plugins // [ // require.resolve('babel-plugin-module-resolver'), // { diff --git a/server/build/index.js b/server/build/index.js index 5f0a31c53b1e1..6548f26e9216e 100644 --- a/server/build/index.js +++ b/server/build/index.js @@ -32,9 +32,9 @@ export default async function build (dir, conf = null) { await runCompiler(configs) - // await fs.writeFile(join(dir, '.next', 'server-stats.json'), JSON.stringify(serverStats), 'utf8') - // await fs.writeFile(join(dir, '.next', 'client-stats.json'), JSON.stringify(stats), 'utf8') - + // await fs.writeFile(join(dir, '.next', 'server-stats.json'), JSON.stringify(serverStats), 'utf8') + // await fs.writeFile(join(dir, '.next', 'client-stats.json'), JSON.stringify(stats), 'utf8') + await writeBuildStats(dir) await writeBuildId(dir, buildId) } catch (err) { diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 46141b8404f64..616ad9d8dcffd 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -15,8 +15,8 @@ import StatsPlugin from 'stats-webpack-plugin' const nextDir = path.join(__dirname, '..', '..', '..', '..') const nextNodeModulesDir = path.join(nextDir, 'node_modules') -export default async function baseConfig(dir, {dev = false, isServer = false, buildId, config}) { - const extractCSS = new ExtractTextPlugin('stylesheets/style.css'); +export default async function baseConfig (dir, {dev = false, isServer = false, buildId, config}) { + const extractCSS = new ExtractTextPlugin('stylesheets/style.css') const cssLoader = { loader: isServer ? 'css-loader/locals' : 'css-loader', @@ -42,7 +42,7 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu const clientConfig = !isServer ? { 'main.js': [ mainJS - ], + ] } : {} return { ...clientConfig, @@ -60,7 +60,7 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu modules: [ nextNodeModulesDir, 'node_modules' - ], + ], alias: { 'next': nextDir, 'react-dom': dev ? 'react-dom/cjs/react-dom.development.js' : 'react-dom/cjs/react-dom.production.min.js' @@ -83,7 +83,7 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu loader: 'babel-loader', options: { cacheDirectory: true, - presets: [require.resolve('../babel/preset')], + presets: [require.resolve('../babel/preset')] } } }, @@ -104,7 +104,7 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu // new StatsPlugin(`stats-${isServer ? 'server':'client'}.json`), new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), dev && new FriendlyErrorsWebpackPlugin(), - dev && new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive + dev && new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive dev && new webpack.LoaderOptionsPlugin({ options: { context: dir, @@ -139,12 +139,12 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu !dev && new webpack.optimize.ModuleConcatenationPlugin(), !isServer && extractCSS, !isServer && new PagesPlugin(), - !isServer && new DynamicChunksPlugin(), + !isServer && new DynamicChunksPlugin(), !isServer && new webpack.optimize.CommonsChunkPlugin({ name: `commons`, filename: `commons.js`, - minChunks: 2, - }), + minChunks: 2 + }), !isServer && new webpack.optimize.CommonsChunkPlugin({ name: 'react', filename: 'react.js', @@ -152,19 +152,19 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu if (dev) { return false } - + if (module.resource && module.resource.includes(`${sep}react-dom${sep}`) && count >= 0) { return true } - + if (module.resource && module.resource.includes(`${sep}react${sep}`) && count >= 0) { return true } - + return false } }) - + ].filter(Boolean) } @@ -173,4 +173,4 @@ export default async function baseConfig(dir, {dev = false, isServer = false, bu // } return webpackConfig -} \ No newline at end of file +} diff --git a/server/build/webpack/utils.js b/server/build/webpack/utils.js index dd99be8eab516..a1c1417817865 100644 --- a/server/build/webpack/utils.js +++ b/server/build/webpack/utils.js @@ -9,11 +9,11 @@ export async function getPages (dir, {dev, isServer}) { return getPageEntries(pageFiles, {isServer}) } -async function getPageFiles(dir, {dev, isServer}) { +async function getPageFiles (dir, {dev, isServer}) { let pages if (dev) { - pages = await glob(isServer ? 'pages/+(_document|_error).+(js|jsx)': 'pages/_error.+(js|jsx)', { cwd: dir }) + pages = await glob(isServer ? 'pages/+(_document|_error).+(js|jsx)' : 'pages/_error.+(js|jsx)', { cwd: dir }) } else { pages = await glob(isServer ? 'pages/**/*.+(js|jsx)' : 'pages/**/!(_document)*.+(js|jsx)', { cwd: dir }) } diff --git a/server/hot-reloader.js b/server/hot-reloader.js index 9542bf20eab92..655f218fde548 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -50,7 +50,7 @@ export default class HotReloader { const configs = await Promise.all([ baseConfig(this.dir, { dev: true, isServer: false, config: this.conf }), - baseConfig(this.dir, { dev: true,isServer: true, config: this.conf }) + baseConfig(this.dir, { dev: true, isServer: true, config: this.conf }) ]) const compiler = webpack(configs) @@ -80,7 +80,7 @@ export default class HotReloader { const configs = await Promise.all([ baseConfig(this.dir, { dev: true, isServer: false, config: this.conf }), - baseConfig(this.dir, { dev: true,isServer: true, config: this.conf }) + baseConfig(this.dir, { dev: true, isServer: true, config: this.conf }) ]) const compiler = webpack(configs) From e5d2078ee15ab8a33794608842e24ab62b0092a4 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 27 Dec 2017 20:02:46 +0100 Subject: [PATCH 020/132] Add changes from Arunoda's work --- server/build/webpack/base.config.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 616ad9d8dcffd..fbc1ebae0d199 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -53,7 +53,9 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b path: path.join(dir, '.next', isServer ? 'dist' : ''), filename: '[name]', libraryTarget: 'commonjs2', - publicPath: `/_next/${buildId}/webpack/` + publicPath: `/_next/webpack/`, + // This saves chunks with the name given via require.ensure() + chunkFilename: '[name]-[chunkhash].js' }, resolve: { extensions: ['.js', '.jsx', '.json'], From b843e6e793e90b26cd7765eb4a50301adfd135a3 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Thu, 4 Jan 2018 15:55:13 +0530 Subject: [PATCH 021/132] Made next dev works. But super slow and no HMR support. --- server/build/webpack.js | 13 +++------ server/build/webpack/base.config.js | 16 ++++++++--- server/build/webpack/utils.js | 2 +- server/hot-reloader.js | 41 ++++++++++++++++++----------- server/index.js | 8 +++++- server/on-demand-entry-handler.js | 5 ++-- server/render.js | 6 +++-- yarn.lock | 6 +++++ 8 files changed, 62 insertions(+), 35 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index afe367ae4da05..f5796c17efe11 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -24,7 +24,7 @@ const defaultPages = [ const nextPagesDir = join(__dirname, '..', '..', 'pages') const nextNodeModulesDir = join(__dirname, '..', '..', '..', 'node_modules') const interpolateNames = new Map(defaultPages.map((p) => { - return [join(nextPagesDir, p), `dist/pages/${p}`] + return [join(nextPagesDir, p), `dist/bundles/pages/${p}`] })) const relativeResolve = rootModuleRelativePath(require) @@ -59,6 +59,7 @@ function getPageEntries (pages) { } export default async function createCompiler (dir, { buildId, dev = false, quiet = false, buildDir, conf = null } = {}) { + console.log('XXXXXXX CREATE') // Resolve relative path to absolute path dir = realpathSync(resolve(dir)) @@ -175,14 +176,6 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet return false } }), - // This chunk contains all the webpack related code. So, all the changes - // related to that happens to this chunk. - // It won't touch commons.js and that gives us much better re-build perf. - new webpack.optimize.CommonsChunkPlugin({ - name: 'manifest', - filename: 'manifest.js' - }), - // This adds Next.js route definitions to page bundles new PagesPlugin(), // Implements support for dynamic imports @@ -275,7 +268,7 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 }, options: { - name: 'dist/[path][name].[ext]', + name: 'dist/bundles/[path][name].[ext]', // We need to strip off .jsx on the server. Otherwise require without .jsx doesn't work. interpolateName: (name) => name.replace('.jsx', '.js'), validateFileName (file) { diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index fbc1ebae0d199..5548e4c0de6a4 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -10,10 +10,17 @@ import {getPages} from './utils' import CombineAssetsPlugin from '../plugins/combine-assets-plugin' import PagesPlugin from '../plugins/pages-plugin' import DynamicChunksPlugin from '../plugins/dynamic-chunks-plugin' -import StatsPlugin from 'stats-webpack-plugin' const nextDir = path.join(__dirname, '..', '..', '..', '..') const nextNodeModulesDir = path.join(nextDir, 'node_modules') +const nextPagesDir = path.join(nextDir, 'pages') +const defaultPages = [ + '_error.js', + '_document.js' +] +const interpolateNames = new Map(defaultPages.map((p) => { + return [path.join(nextPagesDir, p), `dist/bundles/pages/${p}`] +})) export default async function baseConfig (dir, {dev = false, isServer = false, buildId, config}) { const extractCSS = new ExtractTextPlugin('stylesheets/style.css') @@ -36,8 +43,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b externals, context: dir, entry: async () => { - // We use on-demand-entries in development - const pages = dev ? {} : await getPages(dir, {dev, isServer}) + const pages = await getPages(dir, {dev, isServer}) const mainJS = require.resolve(`../../../client/next${dev ? '-dev' : ''}`) const clientConfig = !isServer ? { 'main.js': [ @@ -165,6 +171,10 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b return false } + }), + !isServer && new webpack.optimize.CommonsChunkPlugin({ + name: 'manifest', + filename: 'manifest.js' }) ].filter(Boolean) diff --git a/server/build/webpack/utils.js b/server/build/webpack/utils.js index a1c1417817865..f0086c827c4e3 100644 --- a/server/build/webpack/utils.js +++ b/server/build/webpack/utils.js @@ -23,7 +23,7 @@ async function getPageFiles (dir, {dev, isServer}) { export function getPageEntries (pageFiles, {isServer}) { const entries = {} - const bundleLocation = isServer ? '' : 'bundles' + const bundleLocation = 'bundles' for (const p of pageFiles) { entries[path.join(bundleLocation, p.replace('.jsx', '.js'))] = [`./${p}`] } diff --git a/server/hot-reloader.js b/server/hot-reloader.js index 5ec207818922a..157786eb323c4 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -58,7 +58,8 @@ export default class HotReloader { const buildTools = await this.prepareBuildTools(compiler) this.assignBuildTools(buildTools) - this.stats = await this.waitUntilValid() + this.stats = (await this.waitUntilValid()).stats[0] + console.log('XXXX', Object.keys(this.stats)) } async stop (webpackDevMiddleware) { @@ -94,19 +95,21 @@ export default class HotReloader { await this.stop(oldWebpackDevMiddleware) } - assignBuildTools ({ webpackDevMiddleware, webpackHotMiddleware, onDemandEntries }) { + assignBuildTools ({ webpackDevMiddleware, webpackHotMiddleware, onDemandEntriesClient, onDemandEntriesServer }) { this.webpackDevMiddleware = webpackDevMiddleware this.webpackHotMiddleware = webpackHotMiddleware - this.onDemandEntries = onDemandEntries + this.onDemandEntriesClient = onDemandEntriesClient + this.onDemandEntriesServer = onDemandEntriesServer this.middlewares = [ webpackDevMiddleware, webpackHotMiddleware, - onDemandEntries.middleware() + onDemandEntriesClient.middleware(), + onDemandEntriesServer.middleware() ] } async prepareBuildTools (compiler) { - compiler.plugin('after-emit', (compilation, callback) => { + compiler.compilers[0].plugin('after-emit', (compilation, callback) => { const { assets } = compilation if (this.prevAssets) { @@ -124,10 +127,8 @@ export default class HotReloader { callback() }) - compiler.plugin('done', (stats) => { - const clientStats = stats.stats.find((stats) => stats.compilation.compiler.name === 'client') - - const { compilation } = clientStats + compiler.compilers[0].plugin('done', (stats) => { + const { compilation } = stats const chunkNames = new Set( compilation.chunks .map((c) => c.name) @@ -204,12 +205,19 @@ export default class HotReloader { const webpackDevMiddleware = WebpackDevMiddleware(compiler, webpackDevMiddlewareConfig) - const webpackHotMiddleware = WebpackHotMiddleware(compiler, { + const webpackHotMiddleware = WebpackHotMiddleware(compiler.compilers[0], { path: '/_next/webpack-hmr', log: false, heartbeat: 2500 }) - const onDemandEntries = onDemandEntryHandler(webpackDevMiddleware, compiler, { + const onDemandEntriesClient = onDemandEntryHandler(webpackDevMiddleware, compiler.compilers[0], { + dir: this.dir, + dev: true, + reload: this.reload.bind(this), + ...this.config.onDemandEntries + }) + + const onDemandEntriesServer = onDemandEntryHandler(webpackDevMiddleware, compiler.compilers[1], { dir: this.dir, dev: true, reload: this.reload.bind(this), @@ -219,7 +227,8 @@ export default class HotReloader { return { webpackDevMiddleware, webpackHotMiddleware, - onDemandEntries + onDemandEntriesClient, + onDemandEntriesServer } } @@ -232,7 +241,8 @@ export default class HotReloader { async getCompilationErrors () { // When we are reloading, we need to wait until it's reloaded properly. - await this.onDemandEntries.waitUntilReloaded() + await this.onDemandEntriesClient.waitUntilReloaded() + await this.onDemandEntriesServer.waitUntilReloaded() if (!this.compilationErrors) { this.compilationErrors = new Map() @@ -260,8 +270,9 @@ export default class HotReloader { this.webpackHotMiddleware.publish({ action, data: args }) } - ensurePage (page) { - return this.onDemandEntries.ensurePage(page) + async ensurePage (page) { + await this.onDemandEntriesClient.ensurePage(page) + await this.onDemandEntriesServer.ensurePage(page) } } diff --git a/server/index.js b/server/index.js index a88b313aaaccc..a2aeb8cf930f1 100644 --- a/server/index.js +++ b/server/index.js @@ -248,6 +248,7 @@ export default class Server { if (this.config.useFileSystemPublicRoutes) { routes['/:path*'] = async (req, res, params, parsedUrl) => { const { pathname, query } = parsedUrl + console.log('XXXX - render', pathname, typeof (res)) await this.render(req, res, pathname, query) } } @@ -307,7 +308,9 @@ export default class Server { async renderToHTML (req, res, pathname, query) { if (this.dev) { + console.log('XXX - Taking Error', typeof (res)) const compilationErr = await this.getCompilationError() + console.log('XXX - ERROR Found', compilationErr, typeof (res)) if (compilationErr) { res.statusCode = 500 return this.renderErrorToHTML(compilationErr, req, res, pathname, query) @@ -315,7 +318,10 @@ export default class Server { } try { - return await renderToHTML(req, res, pathname, query, this.renderOpts) + console.log('XXX - Rendering HTML', typeof (res)) + const out = await renderToHTML(req, res, pathname, query, this.renderOpts) + console.log('XXX - HTML Rendered', typeof (res)) + return out } catch (err) { if (err.code === 'ENOENT') { res.statusCode = 404 diff --git a/server/on-demand-entry-handler.js b/server/on-demand-entry-handler.js index b4b196b166029..0c94e16601b98 100644 --- a/server/on-demand-entry-handler.js +++ b/server/on-demand-entry-handler.js @@ -14,7 +14,7 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { dir, dev, reload, - maxInactiveAge = 1000 * 25, + maxInactiveAge = 1000 * 60, pagesBufferLength = 2 }) { let entries = {} @@ -41,8 +41,7 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { }) compiler.plugin('done', function (stats) { - const clientStats = stats.stats.find((stats) => stats.compilation.compiler.name === 'client') - const { compilation } = clientStats + const { compilation } = stats const hardFailedPages = compilation.errors .filter(e => { // Make sure to only pick errors which marked with missing modules diff --git a/server/render.js b/server/render.js index d3ab29ce052dc..a29ab27fa3b15 100644 --- a/server/render.js +++ b/server/render.js @@ -49,13 +49,15 @@ async function doRender (req, res, pathname, query, { } = {}) { page = page || pathname + console.log('XXX - Ensure page', page) await ensurePage(page, { dir, hotReloader }) + console.log('XXX - Page available', page) const dist = getConfig(dir).distDir let [Component, Document] = await Promise.all([ - requireModule(join(dir, dist, 'dist', 'pages', page)), - requireModule(join(dir, dist, 'dist', 'pages', '_document')) + requireModule(join(dir, dist, 'dist', 'bundles', 'pages', page)), + requireModule(join(dir, dist, 'dist', 'bundles', 'pages', '_document')) ]) Component = Component.default || Component Document = Document.default || Document diff --git a/yarn.lock b/yarn.lock index df901b6d333be..b55da53295cd3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6020,6 +6020,12 @@ standard@9.0.2: eslint-plugin-standard "~2.0.1" standard-engine "~5.4.0" +stats-webpack-plugin@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/stats-webpack-plugin/-/stats-webpack-plugin-0.6.1.tgz#5db260514387bc3d4ba6fb85fc4990bd4a71c415" + dependencies: + lodash "^4.17.4" + "statuses@>= 1.2.1 < 2", "statuses@>= 1.3.1 < 2", statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" From 9da64045a2f4ce73ee856b7e9b5a453ab4a78fcd Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 4 Jan 2018 20:48:43 +0100 Subject: [PATCH 022/132] Fix client side hot reload --- .../build/loaders/hot-self-accept-loader.js | 9 +++++---- server/build/webpack/base.config.js | 19 +++++++++++++++++-- server/on-demand-entry-handler.js | 2 +- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/server/build/loaders/hot-self-accept-loader.js b/server/build/loaders/hot-self-accept-loader.js index 1c6968d215621..18a7b910d92c2 100644 --- a/server/build/loaders/hot-self-accept-loader.js +++ b/server/build/loaders/hot-self-accept-loader.js @@ -8,12 +8,13 @@ module.exports = function (content, sourceMap) { this.callback(null, `${content} (function (Component, route) { if (!module.hot) return - if (!__resourceQuery) return + // if (!__resourceQuery) return - var qs = require('querystring') - var params = qs.parse(__resourceQuery.slice(1)) - if (params.entry == null) return + // var qs = require('querystring') + // var params = qs.parse(__resourceQuery.slice(1)) + // if (params.entry == null) return + console.log('ACCEPTING') module.hot.accept() Component.__route = route diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 5548e4c0de6a4..49ad06ab5d374 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -36,6 +36,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b const externals = isServer ? [nodeExternals(nextNodeModulesDir), nodeExternals(path.join(dir, 'node_modules'))] : [] let webpackConfig = { + devtool: dev ? 'inline-source-map' : 'source-map', name: isServer ? 'server' : 'client', cache: true, profile: true, @@ -83,6 +84,19 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b }, module: { rules: [ + dev && { + test: /\.(js|jsx)(\?[^?]*)?$/, + loader: 'hot-self-accept-loader', + include: [ + path.join(dir, 'pages'), + nextPagesDir + ] + }, + dev && { + test: /\.(js|jsx)(\?[^?]*)?$/, + loader: 'react-hot-loader/webpack', + exclude: /node_modules/ + }, { test: /\.js$/, include: [dir], @@ -111,7 +125,8 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b // }), // new StatsPlugin(`stats-${isServer ? 'server':'client'}.json`), new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), - dev && new FriendlyErrorsWebpackPlugin(), + // dev && new FriendlyErrorsWebpackPlugin(), + dev && new webpack.HotModuleReplacementPlugin(), // Hot module replacement dev && new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive dev && new webpack.LoaderOptionsPlugin({ options: { @@ -127,7 +142,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b // required not to cache removed files useHashIndex: false }), - !isServer && new UglifyJSPlugin({ + !isServer && !dev && new UglifyJSPlugin({ exclude: /react\.js/, parallel: true, sourceMap: false, diff --git a/server/on-demand-entry-handler.js b/server/on-demand-entry-handler.js index 0c94e16601b98..8c06579405508 100644 --- a/server/on-demand-entry-handler.js +++ b/server/on-demand-entry-handler.js @@ -132,7 +132,7 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { const pathname = await resolvePath(pagePath) const name = join('bundles', pathname.substring(dir.length)) - const entry = [`${pathname}?entry`] + const entry = [`${pathname}`] await new Promise((resolve, reject) => { const entryInfo = entries[page] From 5cb819a6dbfefa5f34aa6080bd09e90bd2d53033 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 4 Jan 2018 21:41:44 +0100 Subject: [PATCH 023/132] Server side hmr --- server/build/webpack/base.config.js | 4 ++-- server/render.js | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 49ad06ab5d374..f42d4f6fff63b 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -84,7 +84,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b }, module: { rules: [ - dev && { + dev && !isServer && { test: /\.(js|jsx)(\?[^?]*)?$/, loader: 'hot-self-accept-loader', include: [ @@ -92,7 +92,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b nextPagesDir ] }, - dev && { + dev && !isServer && { test: /\.(js|jsx)(\?[^?]*)?$/, loader: 'react-hot-loader/webpack', exclude: /node_modules/ diff --git a/server/render.js b/server/render.js index a29ab27fa3b15..55d42966a6ebf 100644 --- a/server/render.js +++ b/server/render.js @@ -55,9 +55,17 @@ async function doRender (req, res, pathname, query, { const dist = getConfig(dir).distDir + const pagePath = join(dir, dist, 'dist', 'bundles', 'pages', page) + const documentPath = join(dir, dist, 'dist', 'bundles', 'pages', '_document') + + if(page === '/') { + delete require.cache[pagePath + 'index.js'] + } else { + delete require.cache[pagePath + '.js'] + } let [Component, Document] = await Promise.all([ - requireModule(join(dir, dist, 'dist', 'bundles', 'pages', page)), - requireModule(join(dir, dist, 'dist', 'bundles', 'pages', '_document')) + requireModule(pagePath), + requireModule(documentPath) ]) Component = Component.default || Component Document = Document.default || Document From b97bc2f45d53380e06cacdd1a8ff2a882ed34631 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 4 Jan 2018 21:43:55 +0100 Subject: [PATCH 024/132] Only in dev --- server/render.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/server/render.js b/server/render.js index 55d42966a6ebf..9efdd189ec712 100644 --- a/server/render.js +++ b/server/render.js @@ -58,10 +58,13 @@ async function doRender (req, res, pathname, query, { const pagePath = join(dir, dist, 'dist', 'bundles', 'pages', page) const documentPath = join(dir, dist, 'dist', 'bundles', 'pages', '_document') - if(page === '/') { - delete require.cache[pagePath + 'index.js'] - } else { - delete require.cache[pagePath + '.js'] + // Delete the require cache to facilitate hot reloading on the server side. + if(hotReloader) { + if(page === '/') { + delete require.cache[pagePath + 'index.js'] + } else { + delete require.cache[pagePath + '.js'] + } } let [Component, Document] = await Promise.all([ requireModule(pagePath), From 89f97934b9066b2da807b0b533cd2c3f9d224d71 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 5 Jan 2018 09:49:40 +0100 Subject: [PATCH 025/132] Add on-demand-entries client + hot-middleware --- package.json | 2 +- server/build/webpack/base.config.js | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 4066f4238358b..7010a90da3664 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "react-hot-loader": "3.1.1", "recursive-copy": "2.0.6", "send": "0.16.1", - "source-map-support": "0.4.18", + "source-map-support": "0.5.0", "stats-webpack-plugin": "0.6.1", "strip-ansi": "3.0.1", "styled-jsx": "2.2.1", diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index f42d4f6fff63b..115af5f74e617 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -36,7 +36,8 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b const externals = isServer ? [nodeExternals(nextNodeModulesDir), nodeExternals(path.join(dir, 'node_modules'))] : [] let webpackConfig = { - devtool: dev ? 'inline-source-map' : 'source-map', + devtool: dev ? 'cheap-module-source-map' : 'source-map', + // devtool: 'source-map', name: isServer ? 'server' : 'client', cache: true, profile: true, @@ -48,8 +49,10 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b const mainJS = require.resolve(`../../../client/next${dev ? '-dev' : ''}`) const clientConfig = !isServer ? { 'main.js': [ + dev && !isServer && path.join(__dirname, '..', '..', '..', 'client', 'webpack-hot-middleware-client'), + dev && !isServer && path.join(__dirname, '..', '..', '..', 'client', 'on-demand-entries-client'), mainJS - ] + ].filter(Boolean) } : {} return { ...clientConfig, @@ -62,7 +65,8 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b libraryTarget: 'commonjs2', publicPath: `/_next/webpack/`, // This saves chunks with the name given via require.ensure() - chunkFilename: '[name]-[chunkhash].js' + chunkFilename: '[name]-[chunkhash].js', + sourceMapFilename: '[file].map?[contenthash]' }, resolve: { extensions: ['.js', '.jsx', '.json'], From aec6aa1a1044dae4d8cff819a7ab0db324d58411 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 5 Jan 2018 09:55:51 +0100 Subject: [PATCH 026/132] Add .babelrc support --- server/build/webpack/base.config.js | 33 +++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 115af5f74e617..b3b375bd499dc 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -10,6 +10,7 @@ import {getPages} from './utils' import CombineAssetsPlugin from '../plugins/combine-assets-plugin' import PagesPlugin from '../plugins/pages-plugin' import DynamicChunksPlugin from '../plugins/dynamic-chunks-plugin' +import findBabelConfig from '../babel/find-config' const nextDir = path.join(__dirname, '..', '..', '..', '..') const nextNodeModulesDir = path.join(nextDir, 'node_modules') @@ -22,6 +23,33 @@ const interpolateNames = new Map(defaultPages.map((p) => { return [path.join(nextPagesDir, p), `dist/bundles/pages/${p}`] })) +function babelConfig(dir) { + const mainBabelOptions = { + cacheDirectory: true, + presets: [] + } + + const externalBabelConfig = findBabelConfig(dir) + if (externalBabelConfig) { + console.log(`> Using external babel configuration`) + console.log(`> Location: "${externalBabelConfig.loc}"`) + // It's possible to turn off babelrc support via babelrc itself. + // In that case, we should add our default preset. + // That's why we need to do this. + const { options } = externalBabelConfig + mainBabelOptions.babelrc = options.babelrc !== false + } else { + mainBabelOptions.babelrc = false + } + + // Add our default preset if the no "babelrc" found. + if (!mainBabelOptions.babelrc) { + mainBabelOptions.presets.push(require.resolve('../babel/preset')) + } + + return mainBabelOptions +} + export default async function baseConfig (dir, {dev = false, isServer = false, buildId, config}) { const extractCSS = new ExtractTextPlugin('stylesheets/style.css') @@ -107,10 +135,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b exclude: /node_modules/, use: { loader: 'babel-loader', - options: { - cacheDirectory: true, - presets: [require.resolve('../babel/preset')] - } + options: babelConfig(dir) } }, { From 888bc3582250024c0846973051a068c022164495 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 5 Jan 2018 11:48:54 +0100 Subject: [PATCH 027/132] Speed up on demand entries by running in parallel --- server/hot-reloader.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/hot-reloader.js b/server/hot-reloader.js index 157786eb323c4..b3a51267e64ef 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -271,8 +271,11 @@ export default class HotReloader { } async ensurePage (page) { - await this.onDemandEntriesClient.ensurePage(page) - await this.onDemandEntriesServer.ensurePage(page) + await Promise.all([ + this.onDemandEntriesClient.ensurePage(page), + this.onDemandEntriesServer.ensurePage(page) + ]) + } } From ab263692203b361d68e2aea086cb6f917466c250 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 5 Jan 2018 11:49:30 +0100 Subject: [PATCH 028/132] Serve static generated files --- server/build/webpack/base.config.js | 2 +- server/index.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index b3b375bd499dc..a76cab7e6096e 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -51,7 +51,7 @@ function babelConfig(dir) { } export default async function baseConfig (dir, {dev = false, isServer = false, buildId, config}) { - const extractCSS = new ExtractTextPlugin('stylesheets/style.css') + const extractCSS = new ExtractTextPlugin('static/style.css') const cssLoader = { loader: isServer ? 'css-loader/locals' : 'css-loader', diff --git a/server/index.js b/server/index.js index a2aeb8cf930f1..7a0b71d1ea3ac 100644 --- a/server/index.js +++ b/server/index.js @@ -226,6 +226,11 @@ export default class Server { await renderScript(req, res, page, this.renderOpts) }, + '/_next/static/:path*': async (req, res, params) => { + const p = join(this.dist, 'static', ...(params.path || [])) + await this.serveStatic(req, res, p) + }, + // It's very important keep this route's param optional. // (but it should support as many as params, seperated by '/') // Othewise this will lead to a pretty simple DOS attack. From 8859c5f0a6e6981de29a1f83c04b5db1963b2c81 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 5 Jan 2018 15:03:39 +0100 Subject: [PATCH 029/132] Add missing config in dev --- server/hot-reloader.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/hot-reloader.js b/server/hot-reloader.js index b3a51267e64ef..576d8a56db4b2 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -49,8 +49,8 @@ export default class HotReloader { await clean(this.dir) const configs = await Promise.all([ - baseConfig(this.dir, { dev: true, isServer: false, config: this.conf }), - baseConfig(this.dir, { dev: true, isServer: true, config: this.conf }) + baseConfig(this.dir, { dev: true, isServer: false, config: this.config }), + baseConfig(this.dir, { dev: true, isServer: true, config: this.config }) ]) const compiler = webpack(configs) From 84d785a6bf70dd7d2044e5428e6f035f2c4e2b81 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 5 Jan 2018 15:04:20 +0100 Subject: [PATCH 030/132] Add sass support --- package.json | 4 ++ server/build/webpack/base.config.js | 57 +++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 7010a90da3664..e028836ede9c5 100644 --- a/package.json +++ b/package.json @@ -88,16 +88,20 @@ "mkdirp-then": "1.2.0", "mv": "2.1.1", "mz": "2.7.0", + "node-sass": "4.7.2", "path-match": "1.2.4", "pkg-up": "2.0.0", + "postcss-loader": "2.0.10", "prop-types": "15.6.0", "prop-types-exact": "1.1.1", "react-hot-loader": "3.1.1", "recursive-copy": "2.0.6", + "sass-loader": "6.0.6", "send": "0.16.1", "source-map-support": "0.5.0", "stats-webpack-plugin": "0.6.1", "strip-ansi": "3.0.1", + "style-loader": "0.19.1", "styled-jsx": "2.2.1", "touch": "3.1.0", "uglifyjs-webpack-plugin": "^1.1.1", diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index a76cab7e6096e..4913f05f1bfe3 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -51,17 +51,30 @@ function babelConfig(dir) { } export default async function baseConfig (dir, {dev = false, isServer = false, buildId, config}) { - const extractCSS = new ExtractTextPlugin('static/style.css') + const extractCSS = new ExtractTextPlugin({ + filename: 'static/style.css', + disable: dev + }) const cssLoader = { loader: isServer ? 'css-loader/locals' : 'css-loader', options: { modules: true, minimize: !dev, - sourceMap: dev + sourceMap: dev, + importLoaders: 1 } } + const postcssLoader = { + loader: 'postcss-loader', + options: { + plugins: () => {} + } + } + + const babelLoaderOptions = babelConfig(dir) + const externals = isServer ? [nodeExternals(nextNodeModulesDir), nodeExternals(path.join(dir, 'node_modules'))] : [] let webpackConfig = { devtool: dev ? 'cheap-module-source-map' : 'source-map', @@ -135,14 +148,44 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b exclude: /node_modules/, use: { loader: 'babel-loader', - options: babelConfig(dir) + options: babelLoaderOptions } }, { test: /\.css$/, use: [ isServer && cssLoader, - ...(!isServer ? extractCSS.extract([cssLoader]) : []) + isServer && postcssLoader, + ...(!isServer ? extractCSS.extract({ + use: [cssLoader, postcssLoader], + // Use style-loader in development + fallback: { + loader: 'style-loader', + options: { + sourceMap: true, + importLoaders: 1 + } + } + }) : []) + ].filter(Boolean) + }, + { + test: /\.scss$/, + use: [ + isServer && cssLoader, + isServer && postcssLoader, + isServer && 'sass-loader', + ...(!isServer ? extractCSS.extract({ + use: [cssLoader, postcssLoader, 'sass-loader'], + // Use style-loader in development + fallback: { + loader: 'style-loader', + options: { + sourceMap: true, + importLoaders: 1 + } + } + }) : []) ].filter(Boolean) } ].filter(Boolean) @@ -224,9 +267,9 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b ].filter(Boolean) } - // if(isServer && typeof config.webpack === 'function') { - // webpackConfig = config.webpack(webpackConfig, {dev, buildId}) - // } + if(typeof config.webpack === 'function') { + webpackConfig = config.webpack(webpackConfig, {dev, isServer, buildId, babelLoaderOptions}) + } return webpackConfig } From c5ccf23b2d1bec5d8faaa3b7b38de09e70b0374d Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 5 Jan 2018 17:32:14 +0100 Subject: [PATCH 031/132] Add support for .map --- server/index.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/server/index.js b/server/index.js index 7a0b71d1ea3ac..88849494a8b5b 100644 --- a/server/index.js +++ b/server/index.js @@ -17,6 +17,7 @@ import getConfig from './config' // We need to go up one more level since we are in the `dist` directory import pkg from '../../package' import reactPkg from 'react/package' +import resolvePath from './resolve' // TODO: Remove this in Next.js 5 if (!(/^16\./.test(reactPkg.version))) { @@ -183,6 +184,28 @@ export default class Server { await this.serveStatic(req, res, p) }, + '/_next/:buildId/page/:path*.js.map': async (req, res, params) => { + const paths = params.path || [''] + const page = `/${paths.join('/')}` + + if (this.dev) { + try { + await this.hotReloader.ensurePage(page) + } catch (error) {} + + const compilationErr = await this.getCompilationError() + if (compilationErr) { + const customFields = { statusCode: 500 } + return await renderScriptError(req, res, page, compilationErr, customFields, this.renderOpts) + } + } + + const dist = getConfig(this.dir).distDir + + const path = join(this.dir, dist, 'bundles', 'pages', `${page}.js.map`) + await serveStatic(req, res, path) + }, + '/_next/:buildId/page/_error*': async (req, res, params) => { if (!this.handleBuildId(params.buildId, res)) { const error = new Error('INVALID_BUILD_ID') From bb5cf9a9b09fb35f6cbe078fdb83bb667240f38e Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 6 Jan 2018 00:16:09 +0100 Subject: [PATCH 032/132] Add cssloader config and fix .jsx support --- server/build/webpack/base.config.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 4913f05f1bfe3..7bd4123c9551e 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -62,7 +62,8 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b modules: true, minimize: !dev, sourceMap: dev, - importLoaders: 1 + importLoaders: 1, + ...(config.cssLoaderConfig || {}) } } @@ -143,7 +144,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b exclude: /node_modules/ }, { - test: /\.js$/, + test: /\.+(js|jsx)$/, include: [dir], exclude: /node_modules/, use: { From 565bf5482b7211ec17cbcf8b448b87c9017d53f6 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 6 Jan 2018 00:23:27 +0100 Subject: [PATCH 033/132] Rename --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e028836ede9c5..2c377128f5784 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "4.3.0-canary.1", + "version": "4.3.0-universal-alpha.1", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 122fc928e688bc415018ec0f57552e8026f0e4f4 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 9 Jan 2018 16:51:43 +0100 Subject: [PATCH 034/132] use same defaults as css-loader. Fix linting --- bin/next-dev | 1 - package.json | 3 + server/build/babel/preset.js | 19 -- server/build/index.js | 7 +- server/build/webpack/base.config.js | 80 +++-- server/hot-reloader.js | 1 - server/index.js | 11 +- server/render.js | 6 +- yarn.lock | 506 +++++++++++++++++++++++++--- 9 files changed, 513 insertions(+), 121 deletions(-) diff --git a/bin/next-dev b/bin/next-dev index bfdfc29c27809..45d695ab34f6e 100755 --- a/bin/next-dev +++ b/bin/next-dev @@ -1,5 +1,4 @@ #!/usr/bin/env node -import 'source-map-support/register' import { resolve, join } from 'path' import parseArgs from 'minimist' import { existsSync, readFileSync } from 'fs' diff --git a/package.json b/package.json index 2c377128f5784..f0c21cb9bec38 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,10 @@ "hoist-non-react-statics": "2.3.1", "htmlescape": "1.1.1", "http-status": "1.0.1", + "ignore-loader": "0.1.2", "json-loader": "0.5.7", + "less": "2.7.3", + "less-loader": "4.0.5", "loader-utils": "1.1.0", "md5-file": "3.2.3", "minimist": "1.2.0", diff --git a/server/build/babel/preset.js b/server/build/babel/preset.js index f792c207d9613..2a402b6f26684 100644 --- a/server/build/babel/preset.js +++ b/server/build/babel/preset.js @@ -1,6 +1,3 @@ -const babelRuntimePath = require.resolve('babel-runtime/package').replace(/[\\/]package\.json$/, '') -const relativeResolve = require('../root-module-relative-path').default(require) - // Resolve styled-jsx plugins function styledJsxOptions (opts) { if (!opts) { @@ -54,21 +51,5 @@ module.exports = (context, opts = {}) => ({ [require.resolve('babel-plugin-transform-runtime'), opts['transform-runtime'] || {}], [require.resolve('styled-jsx/babel'), styledJsxOptions(opts['styled-jsx'])], ...plugins - // [ - // require.resolve('babel-plugin-module-resolver'), - // { - // alias: { - // 'babel-runtime': babelRuntimePath, - // 'next/link': relativeResolve('../../../lib/link'), - // 'next/prefetch': relativeResolve('../../../lib/prefetch'), - // 'next/css': relativeResolve('../../../lib/css'), - // 'next/dynamic': relativeResolve('../../../lib/dynamic'), - // 'next/head': relativeResolve('../../../lib/head'), - // 'next/document': relativeResolve('../../../server/document'), - // 'next/router': relativeResolve('../../../lib/router'), - // 'next/error': relativeResolve('../../../lib/error') - // } - // } - // ] ] }) diff --git a/server/build/index.js b/server/build/index.js index 6548f26e9216e..ea72a168a801c 100644 --- a/server/build/index.js +++ b/server/build/index.js @@ -2,11 +2,11 @@ import { tmpdir } from 'os' import { join } from 'path' import fs from 'mz/fs' import uuid from 'uuid' -import del from 'del' +// import del from 'del' import webpack from 'webpack' import getConfig from '../config' import baseConfig from './webpack/base.config.js' -import replaceCurrentBuild from './replace' +// import replaceCurrentBuild from './replace' import md5File from 'md5-file/promise' export default async function build (dir, conf = null) { @@ -21,9 +21,6 @@ export default async function build (dir, conf = null) { throw err } - const clientCompiler = baseConfig(dir, { buildId, isServer: false, config }) - const serverCompiler = baseConfig(dir, { buildId, isServer: true, config }) - try { const configs = await Promise.all([ baseConfig(dir, { buildId, isServer: false, config }), diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 7bd4123c9551e..5dedff8a00af8 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -23,7 +23,7 @@ const interpolateNames = new Map(defaultPages.map((p) => { return [path.join(nextPagesDir, p), `dist/bundles/pages/${p}`] })) -function babelConfig(dir) { +function babelConfig (dir) { const mainBabelOptions = { cacheDirectory: true, presets: [] @@ -59,7 +59,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b const cssLoader = { loader: isServer ? 'css-loader/locals' : 'css-loader', options: { - modules: true, + modules: false, minimize: !dev, sourceMap: dev, importLoaders: 1, @@ -74,9 +74,40 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b } } + function cssLoaderConfig (loader = false) { + return [ + isServer && !cssLoader.options.modules && 'ignore-loader', + isServer && cssLoader.options.modules && cssLoader, + isServer && cssLoader.options.modules && postcssLoader, + isServer && cssLoader.options.modules && loader, + ...(!isServer ? extractCSS.extract({ + use: [cssLoader, postcssLoader, loader].filter(Boolean), + // Use style-loader in development + fallback: { + loader: 'style-loader', + options: { + sourceMap: true, + importLoaders: 1 + } + } + }) : []) + ].filter(Boolean) + } + const babelLoaderOptions = babelConfig(dir) - const externals = isServer ? [nodeExternals(nextNodeModulesDir), nodeExternals(path.join(dir, 'node_modules'))] : [] + const externals = isServer ? [ + nodeExternals({ + modulesDir: nextNodeModulesDir, + includeAbsolutePaths: true, + whitelist: [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i] + }), + nodeExternals({ + modulesDir: path.join(dir, 'node_modules'), + includeAbsolutePaths: true, + whitelist: [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i] + }) + ] : [] let webpackConfig = { devtool: dev ? 'cheap-module-source-map' : 'source-map', // devtool: 'source-map', @@ -154,40 +185,15 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b }, { test: /\.css$/, - use: [ - isServer && cssLoader, - isServer && postcssLoader, - ...(!isServer ? extractCSS.extract({ - use: [cssLoader, postcssLoader], - // Use style-loader in development - fallback: { - loader: 'style-loader', - options: { - sourceMap: true, - importLoaders: 1 - } - } - }) : []) - ].filter(Boolean) + use: cssLoaderConfig() }, { test: /\.scss$/, - use: [ - isServer && cssLoader, - isServer && postcssLoader, - isServer && 'sass-loader', - ...(!isServer ? extractCSS.extract({ - use: [cssLoader, postcssLoader, 'sass-loader'], - // Use style-loader in development - fallback: { - loader: 'style-loader', - options: { - sourceMap: true, - importLoaders: 1 - } - } - }) : []) - ].filter(Boolean) + use: cssLoaderConfig('sass-loader') + }, + { + test: /\.less$/, + use: cssLoaderConfig('less-loader') } ].filter(Boolean) }, @@ -198,8 +204,8 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b // }), // new StatsPlugin(`stats-${isServer ? 'server':'client'}.json`), new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), - // dev && new FriendlyErrorsWebpackPlugin(), - dev && new webpack.HotModuleReplacementPlugin(), // Hot module replacement + dev && !isServer && new FriendlyErrorsWebpackPlugin(), + dev && new webpack.HotModuleReplacementPlugin(), // Hot module replacement dev && new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive dev && new webpack.LoaderOptionsPlugin({ options: { @@ -268,7 +274,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b ].filter(Boolean) } - if(typeof config.webpack === 'function') { + if (typeof config.webpack === 'function') { webpackConfig = config.webpack(webpackConfig, {dev, isServer, buildId, babelLoaderOptions}) } diff --git a/server/hot-reloader.js b/server/hot-reloader.js index 576d8a56db4b2..ec7e6735948fe 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -275,7 +275,6 @@ export default class HotReloader { this.onDemandEntriesClient.ensurePage(page), this.onDemandEntriesServer.ensurePage(page) ]) - } } diff --git a/server/index.js b/server/index.js index 88849494a8b5b..8a40f57aaf396 100644 --- a/server/index.js +++ b/server/index.js @@ -17,7 +17,6 @@ import getConfig from './config' // We need to go up one more level since we are in the `dist` directory import pkg from '../../package' import reactPkg from 'react/package' -import resolvePath from './resolve' // TODO: Remove this in Next.js 5 if (!(/^16\./.test(reactPkg.version))) { @@ -43,14 +42,6 @@ const blockedPages = { export default class Server { constructor ({ dir = '.', dev = false, staticMarkup = false, quiet = false, conf = null } = {}) { - // When in dev mode, remap the inline source maps that we generate within the webpack portion - // of the build. - if (dev) { - require('source-map-support').install({ - hookRequire: true - }) - } - this.dir = resolve(dir) this.dev = dev this.quiet = quiet @@ -199,7 +190,7 @@ export default class Server { return await renderScriptError(req, res, page, compilationErr, customFields, this.renderOpts) } } - + const dist = getConfig(this.dir).distDir const path = join(this.dir, dist, 'bundles', 'pages', `${page}.js.map`) diff --git a/server/render.js b/server/render.js index 9efdd189ec712..3d29e683c3108 100644 --- a/server/render.js +++ b/server/render.js @@ -57,10 +57,10 @@ async function doRender (req, res, pathname, query, { const pagePath = join(dir, dist, 'dist', 'bundles', 'pages', page) const documentPath = join(dir, dist, 'dist', 'bundles', 'pages', '_document') - + // Delete the require cache to facilitate hot reloading on the server side. - if(hotReloader) { - if(page === '/') { + if (hotReloader) { + if (page === '/') { delete require.cache[pagePath + 'index.js'] } else { delete require.cache[pagePath + '.js'] diff --git a/yarn.lock b/yarn.lock index b55da53295cd3..d1c2a98715525 100644 --- a/yarn.lock +++ b/yarn.lock @@ -246,6 +246,10 @@ array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -313,6 +317,10 @@ async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" +async-foreach@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" + async@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/async/-/async-2.0.1.tgz#b709cc0280a9c36f09f4536be823c838a9049e25" @@ -329,7 +337,7 @@ async@^2.0.0, async@^2.1.2, async@^2.1.4: dependencies: lodash "^4.14.0" -async@^2.4.1: +async@^2.1.5, async@^2.4.1: version "2.6.0" resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" dependencies: @@ -1329,10 +1337,21 @@ callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" @@ -1515,10 +1534,23 @@ cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" +clone-deep@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.3.0.tgz#348c61ae9cdbe0edfe053d91ff4cc521d790ede8" + dependencies: + for-own "^1.0.0" + is-plain-object "^2.0.1" + kind-of "^3.2.2" + shallow-clone "^0.1.2" + clone@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" +clone@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" + clor@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/clor/-/clor-5.2.0.tgz#9ddc74e7e86728cfcd05a80546ba58d317b81035" @@ -1692,6 +1724,18 @@ cosmiconfig@^1.1.0: pinkie-promise "^2.0.0" require-from-string "^1.1.0" +cosmiconfig@^2.1.0, cosmiconfig@^2.1.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.2.2.tgz#6173cebd56fac042c1f4390edf7af6c07c7cb892" + dependencies: + is-directory "^0.3.1" + js-yaml "^3.4.3" + minimist "^1.2.0" + object-assign "^4.1.0" + os-homedir "^1.0.1" + parse-json "^2.2.0" + require-from-string "^1.1.0" + coveralls@2.13.1: version "2.13.1" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.13.1.tgz#d70bb9acc1835ec4f063ff9dac5423c17b11f178" @@ -1762,6 +1806,13 @@ cross-spawn@5.1.0, cross-spawn@^5.0.1, cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + cross-spawn@^4: version "4.0.2" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" @@ -1905,6 +1956,12 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": dependencies: cssom "0.3.x" +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + dependencies: + array-find-index "^1.0.1" + cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" @@ -2198,6 +2255,12 @@ entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" +errno@^0.1.1: + version "0.1.6" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.6.tgz#c386ce8a6283f14fc09563b71560908c9bf53026" + dependencies: + prr "~1.0.1" + errno@^0.1.2, errno@^0.1.3, errno@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" @@ -2732,6 +2795,10 @@ flush-write-stream@^1.0.0: inherits "^2.0.1" readable-stream "^2.0.4" +for-in@^0.1.3: + version "0.1.8" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1" + for-in@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2742,6 +2809,12 @@ for-own@^0.1.4: dependencies: for-in "^1.0.1" +for-own@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" + dependencies: + for-in "^1.0.1" + foreach@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" @@ -2854,6 +2927,12 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +gaze@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.2.tgz#847224677adb8870d679257ed3388fdb61e40105" + dependencies: + globule "^1.0.0" + generate-function@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" @@ -2872,6 +2951,10 @@ get-own-enumerable-property-symbols@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz#5c4ad87f2834c4b9b4e84549dc1e0650fb38c24b" +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + get-stdin@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" @@ -2903,7 +2986,7 @@ glob-promise@3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/glob-promise/-/glob-promise-3.3.0.tgz#d1eb3625c4e6dcbb9b96eeae4425d5a3b135fed2" -glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2: +glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -2914,7 +2997,7 @@ glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glo once "^1.3.0" path-is-absolute "^1.0.0" -glob@^6.0.1: +glob@^6.0.1, glob@^6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" dependencies: @@ -2960,6 +3043,14 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" +globule@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.0.tgz#1dc49c6822dd9e8a2fa00ba2a295006e8664bd09" + dependencies: + glob "~7.1.1" + lodash "~4.17.4" + minimatch "~3.0.2" + graceful-fs@^4.1.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -3205,14 +3296,26 @@ iferr@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" +ignore-loader@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463" + ignore@^3.0.9, ignore@^3.2.0: version "3.3.5" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.5.tgz#c4e715455f6073a8d7e5dae72d2fc9d71663dba6" +image-size@~0.5.0: + version "0.5.5" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" +in-publish@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" + indent-string@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" @@ -3300,6 +3403,10 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" +is-buffer@^1.0.2: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + is-buffer@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" @@ -3324,6 +3431,10 @@ is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -3419,6 +3530,12 @@ is-plain-obj@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" +is-plain-object@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -3495,6 +3612,10 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + isomorphic-fetch@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" @@ -3788,7 +3909,7 @@ jest-validate@^21.1.0, jest-validate@^21.2.1: leven "^2.1.0" pretty-format "^21.2.1" -js-base64@^2.1.9: +js-base64@^2.1.8, js-base64@^2.1.9: version "2.4.0" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.0.tgz#9e566fee624751a1d720c966cd6226d29d4025aa" @@ -3908,7 +4029,13 @@ kew@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b" -kind-of@^3.0.2: +kind-of@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-2.0.1.tgz#018ec7a4ce7e3a86cb9141be519d24c8faa981b5" + dependencies: + is-buffer "^1.0.2" + +kind-of@^3.0.2, kind-of@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: @@ -3920,6 +4047,10 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" +lazy-cache@^0.2.3: + version "0.2.7" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-0.2.7.tgz#7feddf2dcb6edb77d11ef1d117ab5ffdf0ab1b65" + lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" @@ -3940,6 +4071,27 @@ lcov-parse@0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" +less-loader@4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-4.0.5.tgz#ae155a7406cac6acd293d785587fcff0f478c4dd" + dependencies: + clone "^2.1.1" + loader-utils "^1.1.0" + pify "^2.3.0" + +less@2.7.3: + version "2.7.3" + resolved "https://registry.yarnpkg.com/less/-/less-2.7.3.tgz#cc1260f51c900a9ec0d91fb6998139e02507b63b" + optionalDependencies: + errno "^0.1.1" + graceful-fs "^4.1.2" + image-size "~0.5.0" + mime "^1.2.11" + mkdirp "^0.5.0" + promise "^7.1.1" + request "2.81.0" + source-map "^0.5.3" + leven@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" @@ -4040,7 +4192,7 @@ loader-runner@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" -loader-utils@1.1.0, loader-utils@^1.0.2, loader-utils@^1.1.0: +loader-utils@1.1.0, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" dependencies: @@ -4055,6 +4207,10 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" +lodash.assign@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + lodash.assignin@^4.0.9: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" @@ -4067,6 +4223,10 @@ lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" +lodash.clonedeep@^4.3.2: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + lodash.defaults@^4.0.1: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" @@ -4095,6 +4255,10 @@ lodash.merge@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5" +lodash.mergewith@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" + lodash.pick@^4.2.1: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" @@ -4111,6 +4275,10 @@ lodash.some@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" +lodash.tail@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" + lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" @@ -4119,7 +4287,7 @@ lodash@4.16.2: version "4.16.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652" -lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1, lodash@^4.8.0: +lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1, lodash@^4.8.0, lodash@~4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -4156,6 +4324,13 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: dependencies: js-tokens "^3.0.0" +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + lru-cache@^4.0.0, lru-cache@^4.0.1, lru-cache@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" @@ -4179,6 +4354,10 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + math-expression-evaluator@^1.2.14: version "1.2.17" resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" @@ -4232,6 +4411,21 @@ memory-fs@^0.4.0, memory-fs@~0.4.1: errno "^0.1.3" readable-stream "^2.0.1" +meow@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -4293,6 +4487,10 @@ mime@1.4.1, mime@^1.3.4: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" +mime@^1.2.11: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" @@ -4311,7 +4509,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -4321,7 +4519,7 @@ minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0: +minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -4344,6 +4542,13 @@ mississippi@^1.3.0: stream-each "^1.1.0" through2 "^2.0.0" +mixin-object@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e" + dependencies: + for-in "^0.1.3" + is-extendable "^0.1.1" + mk-dirs@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/mk-dirs/-/mk-dirs-1.0.0.tgz#44ee67f82341c6762718e88e85e577882e1f67fd" @@ -4418,6 +4623,10 @@ nan@^2.3.0: version "2.7.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46" +nan@^2.3.2: + version "2.8.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -4437,6 +4646,24 @@ node-fetch@1.7.3, node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" +node-gyp@^3.3.1: + version "3.6.2" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60" + dependencies: + fstream "^1.0.0" + glob "^7.0.3" + graceful-fs "^4.1.2" + minimatch "^3.0.2" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2 || 3 || 4" + osenv "0" + request "2" + rimraf "2" + semver "~5.3.0" + tar "^2.0.0" + which "1" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -4493,6 +4720,36 @@ node-pre-gyp@^0.6.36: tar "^2.2.1" tar-pack "^3.4.0" +node-sass@4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.2.tgz#9366778ba1469eb01438a9e8592f4262bcb6794e" + dependencies: + async-foreach "^0.1.3" + chalk "^1.1.1" + cross-spawn "^3.0.0" + gaze "^1.0.0" + get-stdin "^4.0.1" + glob "^7.0.3" + in-publish "^2.0.0" + lodash.assign "^4.2.0" + lodash.clonedeep "^4.3.2" + lodash.mergewith "^4.6.0" + meow "^3.7.0" + mkdirp "^0.5.1" + nan "^2.3.2" + node-gyp "^3.3.1" + npmlog "^4.0.0" + request "~2.79.0" + sass-graph "^2.2.4" + stdout-stream "^1.4.0" + "true-case-path" "^1.0.2" + +"nopt@2 || 3": + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -4506,7 +4763,7 @@ nopt@~1.0.10: dependencies: abbrev "1" -normalize-package-data@^2.3.2: +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" dependencies: @@ -4558,7 +4815,7 @@ npm-which@^3.0.1: npm-path "^2.0.2" which "^1.2.10" -npmlog@^4.0.2: +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" dependencies: @@ -4695,6 +4952,12 @@ os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + dependencies: + lcid "^1.0.0" + os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" @@ -4707,7 +4970,7 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" -osenv@^0.1.4: +osenv@0, osenv@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" dependencies: @@ -4992,6 +5255,38 @@ postcss-filter-plugins@^2.0.0: postcss "^5.0.4" uniqid "^4.0.0" +postcss-load-config@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-1.2.0.tgz#539e9afc9ddc8620121ebf9d8c3673e0ce50d28a" + dependencies: + cosmiconfig "^2.1.0" + object-assign "^4.1.0" + postcss-load-options "^1.2.0" + postcss-load-plugins "^2.3.0" + +postcss-load-options@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-load-options/-/postcss-load-options-1.2.0.tgz#b098b1559ddac2df04bc0bb375f99a5cfe2b6d8c" + dependencies: + cosmiconfig "^2.1.0" + object-assign "^4.1.0" + +postcss-load-plugins@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz#745768116599aca2f009fad426b00175049d8d92" + dependencies: + cosmiconfig "^2.1.1" + object-assign "^4.1.0" + +postcss-loader@2.0.10: + version "2.0.10" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.0.10.tgz#090db0540140bd56a7a7f717c41bc29aeef4c674" + dependencies: + loader-utils "^1.1.0" + postcss "^6.0.0" + postcss-load-config "^1.2.0" + schema-utils "^0.3.0" + postcss-merge-idents@^2.1.5: version "2.1.7" resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" @@ -5169,6 +5464,14 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0 source-map "^0.5.6" supports-color "^3.2.3" +postcss@^6.0.0: + version "6.0.15" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.15.tgz#f460cd6269fede0d1bf6defff0b934a9845d974d" + dependencies: + chalk "^2.3.0" + source-map "^0.6.1" + supports-color "^5.1.0" + postcss@^6.0.1: version "6.0.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885" @@ -5252,6 +5555,10 @@ prr@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -5481,6 +5788,13 @@ redbox-react@^1.3.6: prop-types "^15.5.4" sourcemapped-stacktrace "^1.1.6" +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + reduce-css-calc@^1.2.6: version "1.3.0" resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" @@ -5561,7 +5875,34 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@2.79.0: +request@2, request@^2.79.0, request@^2.81.0: + version "2.83.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +request@2.79.0, request@~2.79.0: version "2.79.0" resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" dependencies: @@ -5613,33 +5954,6 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" -request@^2.79.0, request@^2.81.0: - version "2.83.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -5761,6 +6075,25 @@ sane@^2.0.0: optionalDependencies: fsevents "^1.1.1" +sass-graph@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" + dependencies: + glob "^7.0.0" + lodash "^4.0.0" + scss-tokenizer "^0.2.3" + yargs "^7.0.0" + +sass-loader@6.0.6: + version "6.0.6" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-6.0.6.tgz#e9d5e6c1f155faa32a4b26d7a9b7107c225e40f9" + dependencies: + async "^2.1.5" + clone-deep "^0.3.0" + loader-utils "^1.0.1" + lodash.tail "^4.1.1" + pify "^3.0.0" + sax@^1.2.1, sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -5771,10 +6104,21 @@ schema-utils@^0.3.0: dependencies: ajv "^5.0.0" +scss-tokenizer@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" + dependencies: + js-base64 "^2.1.8" + source-map "^0.4.2" + "semver@2 || 3 || 4 || 5", semver@^5.3.0: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" +semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + send@0.15.6: version "0.15.6" resolved "https://registry.yarnpkg.com/send/-/send-0.15.6.tgz#20f23a9c925b762ab82705fe2f9db252ace47e34" @@ -5843,6 +6187,15 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +shallow-clone@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-0.1.2.tgz#5909e874ba77106d73ac414cfec1ffca87d97060" + dependencies: + is-extendable "^0.1.1" + kind-of "^2.0.1" + lazy-cache "^0.2.3" + mixin-object "^2.0.1" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -5903,7 +6256,13 @@ source-list-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" -source-map-support@0.4.18, source-map-support@^0.4.15: +source-map-support@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.0.tgz#2018a7ad2bdf8faf2691e5fddab26bed5a2bacab" + dependencies: + source-map "^0.6.0" + +source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" dependencies: @@ -5913,11 +6272,11 @@ source-map@0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" -source-map@0.6.1, source-map@^0.6.1, source-map@~0.6.1: +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" -source-map@^0.4.4: +source-map@^0.4.2, source-map@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" dependencies: @@ -6030,6 +6389,12 @@ stats-webpack-plugin@0.6.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" +stdout-stream@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" + dependencies: + readable-stream "^2.0.1" + stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" @@ -6146,6 +6511,12 @@ strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + dependencies: + get-stdin "^4.0.1" + strip-indent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" @@ -6154,6 +6525,13 @@ strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" +style-loader@0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.19.1.tgz#591ffc80bcefe268b77c5d9ebc0505d772619f85" + dependencies: + loader-utils "^1.0.2" + schema-utils "^0.3.0" + styled-jsx@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-2.2.1.tgz#8b38b9e53e5d9767e392595ab1afdc8426b3ba5d" @@ -6190,6 +6568,12 @@ supports-color@^4.0.0, supports-color@^4.2.1, supports-color@^4.4.0: dependencies: has-flag "^2.0.0" +supports-color@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5" + dependencies: + has-flag "^2.0.0" + svgo@^0.7.0: version "0.7.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" @@ -6247,7 +6631,7 @@ tar-stream@^1.5.0: readable-stream "^2.0.0" xtend "^4.0.0" -tar@^2.2.1: +tar@^2.0.0, tar@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" dependencies: @@ -6360,10 +6744,20 @@ tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" +"true-case-path@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.2.tgz#7ec91130924766c7f573be3020c34f8fdfd00d62" + dependencies: + glob "^6.0.4" + tryit@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" @@ -6686,11 +7080,15 @@ whet.extend@~0.9.9: version "0.9.9" resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" -which@^1.2.10, which@^1.2.12, which@^1.2.4, which@^1.2.8, which@^1.2.9: +which@1, which@^1.2.10, which@^1.2.12, which@^1.2.4, which@^1.2.8, which@^1.2.9: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" dependencies: @@ -6801,6 +7199,24 @@ yargs-parser@^7.0.0: dependencies: camelcase "^4.1.0" +yargs@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^5.0.0" + yargs@^8.0.1, yargs@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" From c487416b68bf7ae7e1f17f313cd3d60781f3c917 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 9 Jan 2018 19:45:42 +0100 Subject: [PATCH 035/132] Add NoEmitErrorsPlugin --- server/build/webpack/base.config.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 5dedff8a00af8..d0366525540c1 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -1,5 +1,6 @@ import path, {sep} from 'path' import webpack from 'webpack' + import nodeExternals from 'webpack-node-externals' import UglifyJSPlugin from 'uglifyjs-webpack-plugin' import CaseSensitivePathPlugin from 'case-sensitive-paths-webpack-plugin' @@ -141,6 +142,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b chunkFilename: '[name]-[chunkhash].js', sourceMapFilename: '[file].map?[contenthash]' }, + performance: { hints: false }, resolve: { extensions: ['.js', '.jsx', '.json'], modules: [ @@ -204,6 +206,8 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b // }), // new StatsPlugin(`stats-${isServer ? 'server':'client'}.json`), new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), + dev && new webpack.NoEmitOnErrorsPlugin(), + // dev && new UnlinkFilePlugin(), dev && !isServer && new FriendlyErrorsWebpackPlugin(), dev && new webpack.HotModuleReplacementPlugin(), // Hot module replacement dev && new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive @@ -221,6 +225,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b // required not to cache removed files useHashIndex: false }), + !dev && new webpack.IgnorePlugin(/react-hot-loader/), !isServer && !dev && new UglifyJSPlugin({ exclude: /react\.js/, parallel: true, From c6c7e15bc91e10d573ac0b6680e36d12a4010829 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 9 Jan 2018 19:51:30 +0100 Subject: [PATCH 036/132] Add clientBootstrap --- server/build/webpack/base.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index d0366525540c1..4195c7dcbb956 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -123,6 +123,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b const mainJS = require.resolve(`../../../client/next${dev ? '-dev' : ''}`) const clientConfig = !isServer ? { 'main.js': [ + ...config.clientBootstrap || [], dev && !isServer && path.join(__dirname, '..', '..', '..', 'client', 'webpack-hot-middleware-client'), dev && !isServer && path.join(__dirname, '..', '..', '..', 'client', 'on-demand-entries-client'), mainJS From 008e65958ccbaa0a772ef54fab6cbc2bd0271df1 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 9 Jan 2018 20:36:12 +0100 Subject: [PATCH 037/132] Use webpackhotmiddleware on the multi compiler --- package.json | 2 +- server/hot-reloader.js | 5 +++-- server/index.js | 10 +++++----- server/render.js | 4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index f0c21cb9bec38..a39d219afa515 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "4.3.0-universal-alpha.1", + "version": "4.3.0-universal-alpha.2", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", diff --git a/server/hot-reloader.js b/server/hot-reloader.js index ec7e6735948fe..6ba675c2d2e1d 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -59,7 +59,7 @@ export default class HotReloader { this.assignBuildTools(buildTools) this.stats = (await this.waitUntilValid()).stats[0] - console.log('XXXX', Object.keys(this.stats)) + // console.log('XXXX', Object.keys(this.stats)) } async stop (webpackDevMiddleware) { @@ -205,11 +205,12 @@ export default class HotReloader { const webpackDevMiddleware = WebpackDevMiddleware(compiler, webpackDevMiddlewareConfig) - const webpackHotMiddleware = WebpackHotMiddleware(compiler.compilers[0], { + const webpackHotMiddleware = WebpackHotMiddleware(compiler, { path: '/_next/webpack-hmr', log: false, heartbeat: 2500 }) + const onDemandEntriesClient = onDemandEntryHandler(webpackDevMiddleware, compiler.compilers[0], { dir: this.dir, dev: true, diff --git a/server/index.js b/server/index.js index 8a40f57aaf396..b85e74584f46d 100644 --- a/server/index.js +++ b/server/index.js @@ -267,7 +267,7 @@ export default class Server { if (this.config.useFileSystemPublicRoutes) { routes['/:path*'] = async (req, res, params, parsedUrl) => { const { pathname, query } = parsedUrl - console.log('XXXX - render', pathname, typeof (res)) + // console.log('XXXX - render', pathname, typeof (res)) await this.render(req, res, pathname, query) } } @@ -327,9 +327,9 @@ export default class Server { async renderToHTML (req, res, pathname, query) { if (this.dev) { - console.log('XXX - Taking Error', typeof (res)) + // console.log('XXX - Taking Error', typeof (res)) const compilationErr = await this.getCompilationError() - console.log('XXX - ERROR Found', compilationErr, typeof (res)) + // console.log('XXX - ERROR Found', compilationErr, typeof (res)) if (compilationErr) { res.statusCode = 500 return this.renderErrorToHTML(compilationErr, req, res, pathname, query) @@ -337,9 +337,9 @@ export default class Server { } try { - console.log('XXX - Rendering HTML', typeof (res)) + // console.log('XXX - Rendering HTML', typeof (res)) const out = await renderToHTML(req, res, pathname, query, this.renderOpts) - console.log('XXX - HTML Rendered', typeof (res)) + // console.log('XXX - HTML Rendered', typeof (res)) return out } catch (err) { if (err.code === 'ENOENT') { diff --git a/server/render.js b/server/render.js index 3d29e683c3108..0913939df776f 100644 --- a/server/render.js +++ b/server/render.js @@ -49,9 +49,9 @@ async function doRender (req, res, pathname, query, { } = {}) { page = page || pathname - console.log('XXX - Ensure page', page) + // console.log('XXX - Ensure page', page) await ensurePage(page, { dir, hotReloader }) - console.log('XXX - Page available', page) + // console.log('XXX - Page available', page) const dist = getConfig(dir).distDir From fa4b18f3b5bd205a84b4d263721de7c543a180bc Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 9 Jan 2018 20:36:39 +0100 Subject: [PATCH 038/132] alpha.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a39d219afa515..9fa7ae80099fa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "4.3.0-universal-alpha.2", + "version": "4.3.0-universal-alpha.3", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 2057482557a4cfaabcea4461ecd1a26c66f486e6 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 11 Jan 2018 10:26:21 +0100 Subject: [PATCH 039/132] Use babel 16.2.x --- package.json | 4 ++-- yarn.lock | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 9fa7ae80099fa..78c5564b89928 100644 --- a/package.json +++ b/package.json @@ -143,8 +143,8 @@ "node-notifier": "5.1.2", "nyc": "11.2.1", "portfinder": "1.0.13", - "react": "16.0.0", - "react-dom": "16.0.0", + "react": "16.2.0", + "react-dom": "16.2.0", "standard": "9.0.2", "taskr": "1.1.0", "wd": "1.4.1" diff --git a/yarn.lock b/yarn.lock index d1c2a98715525..4817a8f95df6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5665,9 +5665,9 @@ react-deep-force-update@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-2.1.1.tgz#8ea4263cd6455a050b37445b3f08fd839d86e909" -react-dom@16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.0.0.tgz#9cc3079c3dcd70d4c6e01b84aab2a7e34c303f58" +react-dom@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" dependencies: fbjs "^0.8.16" loose-envify "^1.1.0" @@ -5690,9 +5690,9 @@ react-proxy@^3.0.0-alpha.0: dependencies: lodash "^4.6.1" -react@16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.0.0.tgz#ce7df8f1941b036f02b2cca9dbd0cb1f0e855e2d" +react@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba" dependencies: fbjs "^0.8.16" loose-envify "^1.1.0" From 7bd31782d5f02b311ec59f044a5e49c0a3aed08b Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 11 Jan 2018 16:05:18 +0100 Subject: [PATCH 040/132] Fix reloading after error --- client/index.js | 2 -- lib/app.js | 5 ----- package.json | 4 ++-- server/build/webpack/base.config.js | 1 + server/hot-reloader.js | 8 +++++--- yarn.lock | 12 ++++++------ 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/client/index.js b/client/index.js index 39475087bdb41..0283d98197fdd 100644 --- a/client/index.js +++ b/client/index.js @@ -59,7 +59,6 @@ let stripAnsi = (s) => s export const emitter = new EventEmitter() export default async ({ ErrorDebugComponent: passedDebugComponent, stripAnsi: passedStripAnsi } = {}) => { - console.log('TEST') // Wait for all the dynamic chunks to get loaded for (const chunkName of chunks) { await pageLoader.waitForChunk(chunkName) @@ -88,7 +87,6 @@ export default async ({ ErrorDebugComponent: passedDebugComponent, stripAnsi: pa }) const hash = location.hash.substring(1) - console.log('TEST 1') render({ Component, props, hash, err, emitter }) return emitter diff --git a/lib/app.js b/lib/app.js index bae48f0b97679..c29e82ddef090 100644 --- a/lib/app.js +++ b/lib/app.js @@ -22,11 +22,6 @@ export default class App extends Component { } } - componentDidCatch (error, info) { - error.stack = `${error.stack}\n\n${info.componentStack}` - window.next.renderError(error) - this.setState({ hasError: true }) - } render () { if (this.state.hasError) return null diff --git a/package.json b/package.json index 78c5564b89928..8cff676b3d8fb 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "postcss-loader": "2.0.10", "prop-types": "15.6.0", "prop-types-exact": "1.1.1", - "react-hot-loader": "3.1.1", + "react-hot-loader": "3.1.3", "recursive-copy": "2.0.6", "sass-loader": "6.0.6", "send": "0.16.1", @@ -114,7 +114,7 @@ "walk": "2.3.9", "webpack": "3.10.0", "webpack-dev-middleware": "1.12.0", - "webpack-hot-middleware": "2.19.1", + "webpack-hot-middleware": "2.21.0", "webpack-node-externals": "1.6.0", "write-file-webpack-plugin": "4.2.0", "xss-filters": "1.2.7" diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 4195c7dcbb956..7a01a311f979a 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -210,6 +210,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b dev && new webpack.NoEmitOnErrorsPlugin(), // dev && new UnlinkFilePlugin(), dev && !isServer && new FriendlyErrorsWebpackPlugin(), + dev && new webpack.NamedModulesPlugin(), dev && new webpack.HotModuleReplacementPlugin(), // Hot module replacement dev && new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive dev && new webpack.LoaderOptionsPlugin({ diff --git a/server/hot-reloader.js b/server/hot-reloader.js index 6ba675c2d2e1d..c3ccb37d3f0dc 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -205,7 +205,7 @@ export default class HotReloader { const webpackDevMiddleware = WebpackDevMiddleware(compiler, webpackDevMiddlewareConfig) - const webpackHotMiddleware = WebpackHotMiddleware(compiler, { + const webpackHotMiddleware = WebpackHotMiddleware(compiler.compilers[0], { path: '/_next/webpack-hmr', log: false, heartbeat: 2500 @@ -242,8 +242,10 @@ export default class HotReloader { async getCompilationErrors () { // When we are reloading, we need to wait until it's reloaded properly. - await this.onDemandEntriesClient.waitUntilReloaded() - await this.onDemandEntriesServer.waitUntilReloaded() + await Promise.all([ + this.onDemandEntriesClient.waitUntilReloaded(), + this.onDemandEntriesServer.waitUntilReloaded() + ]) if (!this.compilationErrors) { this.compilationErrors = new Map() diff --git a/yarn.lock b/yarn.lock index 4817a8f95df6e..1a6b7339100f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5674,9 +5674,9 @@ react-dom@16.2.0: object-assign "^4.1.1" prop-types "^15.6.0" -react-hot-loader@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-3.1.1.tgz#e06db8cd0841c41e3ab0b395b2b774126fc8914e" +react-hot-loader@3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-3.1.3.tgz#6f92877326958c7cb0134b512474517869126082" dependencies: global "^4.3.0" react-deep-force-update "^2.1.1" @@ -7012,9 +7012,9 @@ webpack-dev-middleware@1.12.0: range-parser "^1.0.3" time-stamp "^2.0.0" -webpack-hot-middleware@2.19.1: - version "2.19.1" - resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.19.1.tgz#5db32c31c955c1ead114d37c7519ea554da0d405" +webpack-hot-middleware@2.21.0: + version "2.21.0" + resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.21.0.tgz#7b3c113a7a4b301c91e0749573c7aab28b414b52" dependencies: ansi-html "0.0.7" html-entities "^1.2.0" From c136af8c8cd0415f3871b8238c10431c80d6c4ff Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 11 Jan 2018 16:07:47 +0100 Subject: [PATCH 041/132] Remove comment --- server/build/webpack/base.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 7a01a311f979a..d77c8fb897fb9 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -208,7 +208,6 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b // new StatsPlugin(`stats-${isServer ? 'server':'client'}.json`), new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), dev && new webpack.NoEmitOnErrorsPlugin(), - // dev && new UnlinkFilePlugin(), dev && !isServer && new FriendlyErrorsWebpackPlugin(), dev && new webpack.NamedModulesPlugin(), dev && new webpack.HotModuleReplacementPlugin(), // Hot module replacement From bf7829260b4d8932f672b04e57e9162bd5073eb1 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 11 Jan 2018 16:12:15 +0100 Subject: [PATCH 042/132] Release 5.0.0-univeral-alpha.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8cff676b3d8fb..79eeeeabe0ca3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "4.3.0-universal-alpha.3", + "version": "5.0.0-universal-alpha.1", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 5e5b9e886ee469a44a582f3300176dde4a98de62 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 11 Jan 2018 16:36:59 +0100 Subject: [PATCH 043/132] Remove check for React 16 --- server/index.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/server/index.js b/server/index.js index b85e74584f46d..003a8cf2aabbf 100644 --- a/server/index.js +++ b/server/index.js @@ -16,19 +16,6 @@ import { getAvailableChunks } from './utils' import getConfig from './config' // We need to go up one more level since we are in the `dist` directory import pkg from '../../package' -import reactPkg from 'react/package' - -// TODO: Remove this in Next.js 5 -if (!(/^16\./.test(reactPkg.version))) { - const message = ` -Error: Next.js 4 requires React 16. -Install React 16 with: - npm remove react react-dom - npm install --save react@16 react-dom@16 -` - console.error(message) - process.exit(1) -} const internalPrefixes = [ /^\/_next\//, From 7b339a447b53afe00c378ea3da676201b08207e5 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 11 Jan 2018 16:38:05 +0100 Subject: [PATCH 044/132] Release 5.0.0-universal-alpha.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 79eeeeabe0ca3..3cc99ecfa608d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.1", + "version": "5.0.0-universal-alpha.2", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 64943598cd47da9fbf08fcf19bdf956e68e39785 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 13 Jan 2018 06:45:59 +0100 Subject: [PATCH 045/132] React hot loader v4 --- client/index.js | 2 +- client/next-dev.js | 1 - lib/app.js | 15 +++--- package.json | 4 +- server/build/babel/preset.js | 1 + server/build/webpack/base.config.js | 5 -- yarn.lock | 73 ++++++++++++++++++++++------- 7 files changed, 70 insertions(+), 31 deletions(-) diff --git a/client/index.js b/client/index.js index 0283d98197fdd..b85b222c2169b 100644 --- a/client/index.js +++ b/client/index.js @@ -159,7 +159,7 @@ async function doRender ({ Component, props, hash, err, emitter: emitterProp = e let isInitialRender = true function renderReactElement (reactEl, domEl) { - if (isInitialRender) { + if (isInitialRender && typeof ReactDOM.hydrate === 'function') { ReactDOM.hydrate(reactEl, domEl) isInitialRender = false } else { diff --git a/client/next-dev.js b/client/next-dev.js index ef771c32c6156..f7c2386406354 100644 --- a/client/next-dev.js +++ b/client/next-dev.js @@ -1,4 +1,3 @@ -import 'react-hot-loader/patch' import stripAnsi from 'strip-ansi' import initNext, * as next from './' import ErrorDebugComponent from '../lib/error-debug' diff --git a/lib/app.js b/lib/app.js index c29e82ddef090..314e2ca30cab7 100644 --- a/lib/app.js +++ b/lib/app.js @@ -72,15 +72,18 @@ class Container extends Component { return () } else { const ErrorDebug = require('./error-debug').default - const { AppContainer } = require('react-hot-loader') + // const { hot, setConfig } = require('react-hot-loader').default + // setConfig({ logLevel: 'debug' }) // includes AppContainer which bypasses shouldComponentUpdate method // https://github.com/gaearon/react-hot-loader/issues/442 - return ( - - - - ) + // return ( + // + // + // + // ) + return + // return hot(module)(Component) } } } diff --git a/package.json b/package.json index 3cc99ecfa608d..91930120ad8d0 100644 --- a/package.json +++ b/package.json @@ -95,9 +95,11 @@ "path-match": "1.2.4", "pkg-up": "2.0.0", "postcss-loader": "2.0.10", + "preact": "8.2.7", + "preact-compat": "3.17.0", "prop-types": "15.6.0", "prop-types-exact": "1.1.1", - "react-hot-loader": "3.1.3", + "react-hot-loader": "4.0.0-beta.13", "recursive-copy": "2.0.6", "sass-loader": "6.0.6", "send": "0.16.1", diff --git a/server/build/babel/preset.js b/server/build/babel/preset.js index 2a402b6f26684..21b10d4aa2d41 100644 --- a/server/build/babel/preset.js +++ b/server/build/babel/preset.js @@ -43,6 +43,7 @@ module.exports = (context, opts = {}) => ({ require.resolve('babel-preset-react') ], plugins: [ + require.resolve('react-hot-loader/babel'), require.resolve('./plugins/remove-dotjsx-from-import'), require.resolve('babel-plugin-react-require'), require.resolve('./plugins/handle-import'), diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index d77c8fb897fb9..5bdd75e7bbbab 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -172,11 +172,6 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b nextPagesDir ] }, - dev && !isServer && { - test: /\.(js|jsx)(\?[^?]*)?$/, - loader: 'react-hot-loader/webpack', - exclude: /node_modules/ - }, { test: /\.+(js|jsx)$/, include: [dir], diff --git a/yarn.lock b/yarn.lock index 1a6b7339100f9..45a976688f69a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2643,7 +2643,7 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" -fast-levenshtein@~2.0.4: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -3178,7 +3178,7 @@ hoek@4.x.x: version "4.2.0" resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" -hoist-non-react-statics@2.3.1: +hoist-non-react-statics@2.3.1, hoist-non-react-statics@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0" @@ -3308,6 +3308,12 @@ image-size@~0.5.0: version "0.5.5" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" +immutability-helper@^2.1.2: + version "2.6.4" + resolved "https://registry.yarnpkg.com/immutability-helper/-/immutability-helper-2.6.4.tgz#a931aef97257fcb6d2b5456de652ab6e3bba8408" + dependencies: + invariant "^2.2.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -4287,7 +4293,7 @@ lodash@4.16.2: version "4.16.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652" -lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1, lodash@^4.8.0, lodash@~4.17.4: +lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.8.0, lodash@~4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -5480,6 +5486,30 @@ postcss@^6.0.1: source-map "^0.6.1" supports-color "^4.4.0" +preact-compat@3.17.0: + version "3.17.0" + resolved "https://registry.yarnpkg.com/preact-compat/-/preact-compat-3.17.0.tgz#528cfdfc301190c1a0f47567336be1f4be0266b3" + dependencies: + immutability-helper "^2.1.2" + preact-render-to-string "^3.6.0" + preact-transition-group "^1.1.0" + prop-types "^15.5.8" + standalone-react-addons-pure-render-mixin "^0.1.1" + +preact-render-to-string@^3.6.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-3.7.0.tgz#7db4177454bc01395e0d01d6ac07bc5e838e31ee" + dependencies: + pretty-format "^3.5.1" + +preact-transition-group@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/preact-transition-group/-/preact-transition-group-1.1.1.tgz#f0a49327ea515ece34ea2be864c4a7d29e5d6e10" + +preact@8.2.7: + version "8.2.7" + resolved "https://registry.yarnpkg.com/preact/-/preact-8.2.7.tgz#316249fb678cd5e93e7cee63cea7bfb62dbd6814" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -5499,6 +5529,10 @@ pretty-format@^21.2.1: ansi-regex "^3.0.0" ansi-styles "^3.2.0" +pretty-format@^3.5.1: + version "3.8.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385" + private@^0.1.6, private@^0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -5536,7 +5570,7 @@ prop-types-exact@1.1.1: has "^1.0.1" object.assign "^4.0.4" -prop-types@15.6.0, prop-types@^15.5.4, prop-types@^15.6.0: +prop-types@15.6.0, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.0: version "15.6.0" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" dependencies: @@ -5661,10 +5695,6 @@ rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-deep-force-update@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-2.1.1.tgz#8ea4263cd6455a050b37445b3f08fd839d86e909" - react-dom@16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" @@ -5674,21 +5704,22 @@ react-dom@16.2.0: object-assign "^4.1.1" prop-types "^15.6.0" -react-hot-loader@3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-3.1.3.tgz#6f92877326958c7cb0134b512474517869126082" +react-hot-loader@4.0.0-beta.13: + version "4.0.0-beta.13" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.0.0-beta.13.tgz#0d145579124e44bd0c9d517f86462a1231a9c9d9" dependencies: + fast-levenshtein "^2.0.6" global "^4.3.0" - react-deep-force-update "^2.1.1" - react-proxy "^3.0.0-alpha.0" + hoist-non-react-statics "^2.3.1" + react-stand-in "^4.0.0-beta.13" redbox-react "^1.3.6" source-map "^0.6.1" -react-proxy@^3.0.0-alpha.0: - version "3.0.0-alpha.1" - resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-3.0.0-alpha.1.tgz#4400426bcfa80caa6724c7755695315209fa4b07" +react-stand-in@^4.0.0-beta.13: + version "4.0.0-beta.13" + resolved "https://registry.yarnpkg.com/react-stand-in/-/react-stand-in-4.0.0-beta.13.tgz#70b9dfe15b573a664bd1927a45bb67fb04de0ad7" dependencies: - lodash "^4.6.1" + shallowequal "^1.0.2" react@16.2.0: version "16.2.0" @@ -6196,6 +6227,10 @@ shallow-clone@^0.1.2: lazy-cache "^0.2.3" mixin-object "^2.0.1" +shallowequal@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.0.2.tgz#1561dbdefb8c01408100319085764da3fcf83f8f" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -6357,6 +6392,10 @@ staged-git-files@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-0.0.4.tgz#d797e1b551ca7a639dec0237dc6eb4bb9be17d35" +standalone-react-addons-pure-render-mixin@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/standalone-react-addons-pure-render-mixin/-/standalone-react-addons-pure-render-mixin-0.1.1.tgz#3c7409f4c79c40de9ac72c616cf679a994f37551" + standard-engine@~5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/standard-engine/-/standard-engine-5.4.0.tgz#e0e86959ea0786425d3383e40c1bf70d2f985579" From f8f1fbaf81d13b8fa0daa9b4f262f1f921c0be0f Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Sat, 13 Jan 2018 10:36:50 +0530 Subject: [PATCH 046/132] Use our static file rendering machanism to serve pages. This should work well since the file path for a page is predictable. --- server/index.js | 10 +++++----- test/integration/ondemand/test/index.test.js | 6 +++--- test/integration/production/info.json | 3 +++ test/integration/production/test/index.test.js | 16 ++++++++++++++++ 4 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 test/integration/production/info.json diff --git a/server/index.js b/server/index.js index 003a8cf2aabbf..ba8a7ca0fc7a2 100644 --- a/server/index.js +++ b/server/index.js @@ -8,7 +8,6 @@ import { renderErrorToHTML, sendHTML, serveStatic, - renderScript, renderScriptError } from './render' import Router from './router' @@ -198,9 +197,9 @@ export default class Server { '/_next/:buildId/page/:path*': async (req, res, params) => { const paths = params.path || [''] - // We need to remove `.js` from the page otherwise it won't work with - // page rewrites - // eg:- we re-write page/index.js into page.js + // URL is asks for ${page}.js (to support loading assets from static dirs) + // But there's no .js in the actual page. + // So, we need to remove .js to get the page name. const page = `/${paths.join('/')}`.replace('.js', '') if (!this.handleBuildId(params.buildId, res)) { @@ -224,7 +223,8 @@ export default class Server { } } - await renderScript(req, res, page, this.renderOpts) + const p = join(this.dir, this.dist, 'bundles', 'pages', paths.join('/')) + await this.serveStatic(req, res, p) }, '/_next/static/:path*': async (req, res, params) => { diff --git a/test/integration/ondemand/test/index.test.js b/test/integration/ondemand/test/index.test.js index 2ccf419fe0d5b..976d01736a208 100644 --- a/test/integration/ondemand/test/index.test.js +++ b/test/integration/ondemand/test/index.test.js @@ -30,7 +30,7 @@ describe('On Demand Entries', () => { }) it('should compile pages for JSON page requests', async () => { - const pageContent = await renderViaHTTP(context.appPort, '/_next/-/page/about') + const pageContent = await renderViaHTTP(context.appPort, '/_next/-/page/about.js') expect(pageContent.includes('About Page')).toBeTruthy() }) @@ -39,11 +39,11 @@ describe('On Demand Entries', () => { expect(existsSync(indexPagePath)).toBeTruthy() // Render two pages after the index, since the server keeps at least two pages - await renderViaHTTP(context.appPort, '/_next/-/page/about') + await renderViaHTTP(context.appPort, '/about') await renderViaHTTP(context.appPort, '/_next/on-demand-entries-ping', {page: '/about'}) const aboutPagePath = resolve(__dirname, '../.next/bundles/pages/about.js') - await renderViaHTTP(context.appPort, '/_next/-/page/third') + await renderViaHTTP(context.appPort, '/third') await renderViaHTTP(context.appPort, '/_next/on-demand-entries-ping', {page: '/third'}) const thirdPagePath = resolve(__dirname, '../.next/bundles/pages/third.js') diff --git a/test/integration/production/info.json b/test/integration/production/info.json new file mode 100644 index 0000000000000..dbfa930f6f379 --- /dev/null +++ b/test/integration/production/info.json @@ -0,0 +1,3 @@ +{ + "version": "cool-version" +} diff --git a/test/integration/production/test/index.test.js b/test/integration/production/test/index.test.js index 5450e23b06739..217818f9d9a96 100644 --- a/test/integration/production/test/index.test.js +++ b/test/integration/production/test/index.test.js @@ -13,6 +13,7 @@ import { import webdriver from 'next-webdriver' import fetch from 'node-fetch' import dynamicImportTests from '../../basic/test/dynamic' +import { readFileSync } from 'fs' const appDir = join(__dirname, '../') let appPort @@ -110,6 +111,21 @@ describe('Production Usage', () => { const data = await renderViaHTTP(appPort, '/static/data/item.txt') expect(data).toBe('item') }) + + it('should only access files inside .next directory', async () => { + const buildId = readFileSync(join(__dirname, '../.next/BUILD_ID'), 'utf8') + + const pathsToCheck = [ + `/_next/${buildId}/page/../../../info`, + `/_next/${buildId}/page/../../../info.js`, + `/_next/${buildId}/page/../../../info.json` + ] + + for (const path of pathsToCheck) { + const data = await renderViaHTTP(appPort, path) + expect(data.includes('cool-version')).toBeFalsy() + } + }) }) describe('X-Powered-By header', () => { From 820d3c3e9db52daad0dba72a5e1bf21459395956 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 13 Jan 2018 06:49:31 +0100 Subject: [PATCH 047/132] Release 5.0.0-universal-alpha.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 91930120ad8d0..0f2acc5dad1fe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.2", + "version": "5.0.0-universal-alpha.3", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 48e4d63a90b8acbd924f9a177f158a1ab03cb7a0 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 13 Jan 2018 06:53:11 +0100 Subject: [PATCH 048/132] Remove optional loaders --- package.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/package.json b/package.json index 0f2acc5dad1fe..c06b9dc9c1155 100644 --- a/package.json +++ b/package.json @@ -83,25 +83,18 @@ "http-status": "1.0.1", "ignore-loader": "0.1.2", "json-loader": "0.5.7", - "less": "2.7.3", - "less-loader": "4.0.5", "loader-utils": "1.1.0", "md5-file": "3.2.3", "minimist": "1.2.0", "mkdirp-then": "1.2.0", "mv": "2.1.1", "mz": "2.7.0", - "node-sass": "4.7.2", "path-match": "1.2.4", "pkg-up": "2.0.0", - "postcss-loader": "2.0.10", - "preact": "8.2.7", - "preact-compat": "3.17.0", "prop-types": "15.6.0", "prop-types-exact": "1.1.1", "react-hot-loader": "4.0.0-beta.13", "recursive-copy": "2.0.6", - "sass-loader": "6.0.6", "send": "0.16.1", "source-map-support": "0.5.0", "stats-webpack-plugin": "0.6.1", From 190b930d73e7bd96c198de6cf52f15a34b437c3b Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 13 Jan 2018 06:54:36 +0100 Subject: [PATCH 049/132] Release 5.0.0-universal-alpha.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c06b9dc9c1155..22fc9c4d4a62f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.3", + "version": "5.0.0-universal-alpha.4", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 573d4a6627cf6860d0d306584fbeb9afdf9edd05 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sun, 14 Jan 2018 13:37:31 +0100 Subject: [PATCH 050/132] Remove clientBootstrap --- server/build/webpack/base.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 5bdd75e7bbbab..19eaaf4c67a66 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -123,7 +123,6 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b const mainJS = require.resolve(`../../../client/next${dev ? '-dev' : ''}`) const clientConfig = !isServer ? { 'main.js': [ - ...config.clientBootstrap || [], dev && !isServer && path.join(__dirname, '..', '..', '..', 'client', 'webpack-hot-middleware-client'), dev && !isServer && path.join(__dirname, '..', '..', '..', 'client', 'on-demand-entries-client'), mainJS From e0d2a41c535a2ba6db43564bc889a30384bf08ab Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 15 Jan 2018 15:18:42 +0100 Subject: [PATCH 051/132] Remove renderScript --- server/render.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/server/render.js b/server/render.js index 0913939df776f..ecd24770b1e48 100644 --- a/server/render.js +++ b/server/render.js @@ -133,22 +133,6 @@ async function doRender (req, res, pathname, query, { return '' + renderToStaticMarkup(doc) } -export async function renderScript (req, res, page, opts) { - try { - const dist = getConfig(opts.dir).distDir - const path = join(opts.dir, dist, 'bundles', 'pages', page) - const realPath = await resolvePath(path) - await serveStatic(req, res, realPath) - } catch (err) { - if (err.code === 'ENOENT') { - renderScriptError(req, res, page, err, {}, opts) - return - } - - throw err - } -} - export async function renderScriptError (req, res, page, error, customFields, { dev }) { // Asks CDNs and others to not to cache the errored page res.setHeader('Cache-Control', 'no-store, must-revalidate') From 7d83ae41e395e34aa63dba690961ff5fab894235 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 13 Jan 2018 08:34:48 +0100 Subject: [PATCH 052/132] Make sure pages bundles are served correctly --- lib/page-loader.js | 8 ++------ server/index.js | 11 +++++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/page-loader.js b/lib/page-loader.js index 9c7c1dc2e860c..99bb47a494532 100644 --- a/lib/page-loader.js +++ b/lib/page-loader.js @@ -1,4 +1,4 @@ -/* global window, document, __NEXT_DATA__ */ +/* global window, document */ import EventEmitter from './EventEmitter' const webpackModule = module @@ -69,11 +69,7 @@ export default class PageLoader { loadScript (route) { route = this.normalizeRoute(route) - let scriptRoute = route - - if (__NEXT_DATA__.nextExport) { - scriptRoute = route === '/' ? '/index.js' : `${route}.js` - } + const scriptRoute = route === '/' ? '/index.js' : `${route}.js` const script = document.createElement('script') const url = `${this.assetPrefix}/_next/${encodeURIComponent(this.buildId)}/page${scriptRoute}` diff --git a/server/index.js b/server/index.js index ba8a7ca0fc7a2..d6ae7989b9cbf 100644 --- a/server/index.js +++ b/server/index.js @@ -195,12 +195,12 @@ export default class Server { await this.serveStatic(req, res, p) }, - '/_next/:buildId/page/:path*': async (req, res, params) => { + '/_next/:buildId/page/:path*.js': async (req, res, params) => { const paths = params.path || [''] // URL is asks for ${page}.js (to support loading assets from static dirs) // But there's no .js in the actual page. // So, we need to remove .js to get the page name. - const page = `/${paths.join('/')}`.replace('.js', '') + const page = `/${paths.join('/')}` if (!this.handleBuildId(params.buildId, res)) { const error = new Error('INVALID_BUILD_ID') @@ -223,8 +223,11 @@ export default class Server { } } - const p = join(this.dir, this.dist, 'bundles', 'pages', paths.join('/')) - await this.serveStatic(req, res, p) + let p = join(this.dir, this.dist, 'bundles', 'pages', paths.join('/')) + if (!fs.existsSync(`${p}.js`)) { + p = join(p, 'index') // It's possible to have index.js in a subfolder + } + await this.serveStatic(req, res, `${p}.js`) }, '/_next/static/:path*': async (req, res, params) => { From 9eac841345978533910189e4e0aa4c97ad246a6b Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 15 Jan 2018 15:19:18 +0100 Subject: [PATCH 053/132] Remove unused import --- server/render.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server/render.js b/server/render.js index ecd24770b1e48..ca64e6c1b9628 100644 --- a/server/render.js +++ b/server/render.js @@ -6,7 +6,6 @@ import generateETag from 'etag' import fresh from 'fresh' import requireModule from './require' import getConfig from './config' -import resolvePath from './resolve' import { Router } from '../lib/router' import { loadGetInitialProps } from '../lib/utils' import { getAvailableChunks } from './utils' From ea674546bfe2f892f6315245c6a31cb357acfa88 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 15 Jan 2018 16:53:21 +0100 Subject: [PATCH 054/132] Revert to using the same code as canary --- client/next-dev.js | 1 + lib/app.js | 16 +- package.json | 2 +- server/build/babel/preset.js | 1 - server/build/webpack/base.config.js | 5 + yarn.lock | 556 +++------------------------- 6 files changed, 72 insertions(+), 509 deletions(-) diff --git a/client/next-dev.js b/client/next-dev.js index f7c2386406354..ef771c32c6156 100644 --- a/client/next-dev.js +++ b/client/next-dev.js @@ -1,3 +1,4 @@ +import 'react-hot-loader/patch' import stripAnsi from 'strip-ansi' import initNext, * as next from './' import ErrorDebugComponent from '../lib/error-debug' diff --git a/lib/app.js b/lib/app.js index 314e2ca30cab7..63e46b22c80b5 100644 --- a/lib/app.js +++ b/lib/app.js @@ -22,7 +22,6 @@ export default class App extends Component { } } - render () { if (this.state.hasError) return null @@ -72,18 +71,15 @@ class Container extends Component { return () } else { const ErrorDebug = require('./error-debug').default - // const { hot, setConfig } = require('react-hot-loader').default - // setConfig({ logLevel: 'debug' }) + const { AppContainer } = require('react-hot-loader') // includes AppContainer which bypasses shouldComponentUpdate method // https://github.com/gaearon/react-hot-loader/issues/442 - // return ( - // - // - // - // ) - return - // return hot(module)(Component) + return ( + + + + ) } } } diff --git a/package.json b/package.json index 22fc9c4d4a62f..cc19564e7bea9 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "pkg-up": "2.0.0", "prop-types": "15.6.0", "prop-types-exact": "1.1.1", - "react-hot-loader": "4.0.0-beta.13", + "react-hot-loader": "3.1.1", "recursive-copy": "2.0.6", "send": "0.16.1", "source-map-support": "0.5.0", diff --git a/server/build/babel/preset.js b/server/build/babel/preset.js index 21b10d4aa2d41..2a402b6f26684 100644 --- a/server/build/babel/preset.js +++ b/server/build/babel/preset.js @@ -43,7 +43,6 @@ module.exports = (context, opts = {}) => ({ require.resolve('babel-preset-react') ], plugins: [ - require.resolve('react-hot-loader/babel'), require.resolve('./plugins/remove-dotjsx-from-import'), require.resolve('babel-plugin-react-require'), require.resolve('./plugins/handle-import'), diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 19eaaf4c67a66..ad22647aba09e 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -163,6 +163,11 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b }, module: { rules: [ + dev && !isServer && { + test: /\.(js|jsx)(\?[^?]*)?$/, + loader: 'react-hot-loader/webpack', + exclude: /node_modules/ + }, dev && !isServer && { test: /\.(js|jsx)(\?[^?]*)?$/, loader: 'hot-self-accept-loader', diff --git a/yarn.lock b/yarn.lock index 45a976688f69a..09e1e6b3f1778 100644 --- a/yarn.lock +++ b/yarn.lock @@ -246,10 +246,6 @@ array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -317,10 +313,6 @@ async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" -async-foreach@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" - async@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/async/-/async-2.0.1.tgz#b709cc0280a9c36f09f4536be823c838a9049e25" @@ -337,7 +329,7 @@ async@^2.0.0, async@^2.1.2, async@^2.1.4: dependencies: lodash "^4.14.0" -async@^2.1.5, async@^2.4.1: +async@^2.4.1: version "2.6.0" resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" dependencies: @@ -1337,21 +1329,10 @@ callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" @@ -1534,23 +1515,10 @@ cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" -clone-deep@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.3.0.tgz#348c61ae9cdbe0edfe053d91ff4cc521d790ede8" - dependencies: - for-own "^1.0.0" - is-plain-object "^2.0.1" - kind-of "^3.2.2" - shallow-clone "^0.1.2" - clone@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" -clone@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" - clor@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/clor/-/clor-5.2.0.tgz#9ddc74e7e86728cfcd05a80546ba58d317b81035" @@ -1724,18 +1692,6 @@ cosmiconfig@^1.1.0: pinkie-promise "^2.0.0" require-from-string "^1.1.0" -cosmiconfig@^2.1.0, cosmiconfig@^2.1.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.2.2.tgz#6173cebd56fac042c1f4390edf7af6c07c7cb892" - dependencies: - is-directory "^0.3.1" - js-yaml "^3.4.3" - minimist "^1.2.0" - object-assign "^4.1.0" - os-homedir "^1.0.1" - parse-json "^2.2.0" - require-from-string "^1.1.0" - coveralls@2.13.1: version "2.13.1" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.13.1.tgz#d70bb9acc1835ec4f063ff9dac5423c17b11f178" @@ -1806,13 +1762,6 @@ cross-spawn@5.1.0, cross-spawn@^5.0.1, cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - cross-spawn@^4: version "4.0.2" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" @@ -1956,12 +1905,6 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": dependencies: cssom "0.3.x" -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - dependencies: - array-find-index "^1.0.1" - cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" @@ -2255,12 +2198,6 @@ entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" -errno@^0.1.1: - version "0.1.6" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.6.tgz#c386ce8a6283f14fc09563b71560908c9bf53026" - dependencies: - prr "~1.0.1" - errno@^0.1.2, errno@^0.1.3, errno@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" @@ -2643,7 +2580,7 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.4: +fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -2795,10 +2732,6 @@ flush-write-stream@^1.0.0: inherits "^2.0.1" readable-stream "^2.0.4" -for-in@^0.1.3: - version "0.1.8" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1" - for-in@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2809,12 +2742,6 @@ for-own@^0.1.4: dependencies: for-in "^1.0.1" -for-own@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" - dependencies: - for-in "^1.0.1" - foreach@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" @@ -2927,12 +2854,6 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -gaze@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.2.tgz#847224677adb8870d679257ed3388fdb61e40105" - dependencies: - globule "^1.0.0" - generate-function@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" @@ -2951,10 +2872,6 @@ get-own-enumerable-property-symbols@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz#5c4ad87f2834c4b9b4e84549dc1e0650fb38c24b" -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - get-stdin@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" @@ -2986,7 +2903,7 @@ glob-promise@3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/glob-promise/-/glob-promise-3.3.0.tgz#d1eb3625c4e6dcbb9b96eeae4425d5a3b135fed2" -glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: +glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -2997,7 +2914,7 @@ glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glo once "^1.3.0" path-is-absolute "^1.0.0" -glob@^6.0.1, glob@^6.0.4: +glob@^6.0.1: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" dependencies: @@ -3043,14 +2960,6 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" -globule@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.0.tgz#1dc49c6822dd9e8a2fa00ba2a295006e8664bd09" - dependencies: - glob "~7.1.1" - lodash "~4.17.4" - minimatch "~3.0.2" - graceful-fs@^4.1.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -3178,7 +3087,7 @@ hoek@4.x.x: version "4.2.0" resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" -hoist-non-react-statics@2.3.1, hoist-non-react-statics@^2.3.1: +hoist-non-react-statics@2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0" @@ -3304,24 +3213,10 @@ ignore@^3.0.9, ignore@^3.2.0: version "3.3.5" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.5.tgz#c4e715455f6073a8d7e5dae72d2fc9d71663dba6" -image-size@~0.5.0: - version "0.5.5" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" - -immutability-helper@^2.1.2: - version "2.6.4" - resolved "https://registry.yarnpkg.com/immutability-helper/-/immutability-helper-2.6.4.tgz#a931aef97257fcb6d2b5456de652ab6e3bba8408" - dependencies: - invariant "^2.2.0" - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" -in-publish@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" - indent-string@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" @@ -3409,10 +3304,6 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" -is-buffer@^1.0.2: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - is-buffer@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" @@ -3437,10 +3328,6 @@ is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -3536,12 +3423,6 @@ is-plain-obj@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" -is-plain-object@^2.0.1: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - dependencies: - isobject "^3.0.1" - is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -3618,10 +3499,6 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - isomorphic-fetch@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" @@ -3915,7 +3792,7 @@ jest-validate@^21.1.0, jest-validate@^21.2.1: leven "^2.1.0" pretty-format "^21.2.1" -js-base64@^2.1.8, js-base64@^2.1.9: +js-base64@^2.1.9: version "2.4.0" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.0.tgz#9e566fee624751a1d720c966cd6226d29d4025aa" @@ -4035,13 +3912,7 @@ kew@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b" -kind-of@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-2.0.1.tgz#018ec7a4ce7e3a86cb9141be519d24c8faa981b5" - dependencies: - is-buffer "^1.0.2" - -kind-of@^3.0.2, kind-of@^3.2.2: +kind-of@^3.0.2: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: @@ -4053,10 +3924,6 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" -lazy-cache@^0.2.3: - version "0.2.7" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-0.2.7.tgz#7feddf2dcb6edb77d11ef1d117ab5ffdf0ab1b65" - lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" @@ -4077,27 +3944,6 @@ lcov-parse@0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" -less-loader@4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-4.0.5.tgz#ae155a7406cac6acd293d785587fcff0f478c4dd" - dependencies: - clone "^2.1.1" - loader-utils "^1.1.0" - pify "^2.3.0" - -less@2.7.3: - version "2.7.3" - resolved "https://registry.yarnpkg.com/less/-/less-2.7.3.tgz#cc1260f51c900a9ec0d91fb6998139e02507b63b" - optionalDependencies: - errno "^0.1.1" - graceful-fs "^4.1.2" - image-size "~0.5.0" - mime "^1.2.11" - mkdirp "^0.5.0" - promise "^7.1.1" - request "2.81.0" - source-map "^0.5.3" - leven@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" @@ -4198,7 +4044,7 @@ loader-runner@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" -loader-utils@1.1.0, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0: +loader-utils@1.1.0, loader-utils@^1.0.2, loader-utils@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" dependencies: @@ -4213,10 +4059,6 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -lodash.assign@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - lodash.assignin@^4.0.9: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" @@ -4229,10 +4071,6 @@ lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" -lodash.clonedeep@^4.3.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - lodash.defaults@^4.0.1: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" @@ -4261,10 +4099,6 @@ lodash.merge@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5" -lodash.mergewith@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" - lodash.pick@^4.2.1: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" @@ -4281,10 +4115,6 @@ lodash.some@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" -lodash.tail@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" - lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" @@ -4293,7 +4123,7 @@ lodash@4.16.2: version "4.16.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652" -lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.8.0, lodash@~4.17.4: +lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1, lodash@^4.8.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -4330,13 +4160,6 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: dependencies: js-tokens "^3.0.0" -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - lru-cache@^4.0.0, lru-cache@^4.0.1, lru-cache@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" @@ -4360,10 +4183,6 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - math-expression-evaluator@^1.2.14: version "1.2.17" resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" @@ -4417,21 +4236,6 @@ memory-fs@^0.4.0, memory-fs@~0.4.1: errno "^0.1.3" readable-stream "^2.0.1" -meow@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" - merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -4493,10 +4297,6 @@ mime@1.4.1, mime@^1.3.4: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" -mime@^1.2.11: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" @@ -4515,7 +4315,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -4525,7 +4325,7 @@ minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: +minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -4548,13 +4348,6 @@ mississippi@^1.3.0: stream-each "^1.1.0" through2 "^2.0.0" -mixin-object@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e" - dependencies: - for-in "^0.1.3" - is-extendable "^0.1.1" - mk-dirs@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/mk-dirs/-/mk-dirs-1.0.0.tgz#44ee67f82341c6762718e88e85e577882e1f67fd" @@ -4629,10 +4422,6 @@ nan@^2.3.0: version "2.7.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46" -nan@^2.3.2: - version "2.8.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -4652,24 +4441,6 @@ node-fetch@1.7.3, node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" -node-gyp@^3.3.1: - version "3.6.2" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60" - dependencies: - fstream "^1.0.0" - glob "^7.0.3" - graceful-fs "^4.1.2" - minimatch "^3.0.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - osenv "0" - request "2" - rimraf "2" - semver "~5.3.0" - tar "^2.0.0" - which "1" - node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -4726,36 +4497,6 @@ node-pre-gyp@^0.6.36: tar "^2.2.1" tar-pack "^3.4.0" -node-sass@4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.2.tgz#9366778ba1469eb01438a9e8592f4262bcb6794e" - dependencies: - async-foreach "^0.1.3" - chalk "^1.1.1" - cross-spawn "^3.0.0" - gaze "^1.0.0" - get-stdin "^4.0.1" - glob "^7.0.3" - in-publish "^2.0.0" - lodash.assign "^4.2.0" - lodash.clonedeep "^4.3.2" - lodash.mergewith "^4.6.0" - meow "^3.7.0" - mkdirp "^0.5.1" - nan "^2.3.2" - node-gyp "^3.3.1" - npmlog "^4.0.0" - request "~2.79.0" - sass-graph "^2.2.4" - stdout-stream "^1.4.0" - "true-case-path" "^1.0.2" - -"nopt@2 || 3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - dependencies: - abbrev "1" - nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -4769,7 +4510,7 @@ nopt@~1.0.10: dependencies: abbrev "1" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: +normalize-package-data@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" dependencies: @@ -4821,7 +4562,7 @@ npm-which@^3.0.1: npm-path "^2.0.2" which "^1.2.10" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: +npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" dependencies: @@ -4958,12 +4699,6 @@ os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - dependencies: - lcid "^1.0.0" - os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" @@ -4976,7 +4711,7 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" -osenv@0, osenv@^0.1.4: +osenv@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" dependencies: @@ -5261,38 +4996,6 @@ postcss-filter-plugins@^2.0.0: postcss "^5.0.4" uniqid "^4.0.0" -postcss-load-config@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-1.2.0.tgz#539e9afc9ddc8620121ebf9d8c3673e0ce50d28a" - dependencies: - cosmiconfig "^2.1.0" - object-assign "^4.1.0" - postcss-load-options "^1.2.0" - postcss-load-plugins "^2.3.0" - -postcss-load-options@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-load-options/-/postcss-load-options-1.2.0.tgz#b098b1559ddac2df04bc0bb375f99a5cfe2b6d8c" - dependencies: - cosmiconfig "^2.1.0" - object-assign "^4.1.0" - -postcss-load-plugins@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz#745768116599aca2f009fad426b00175049d8d92" - dependencies: - cosmiconfig "^2.1.1" - object-assign "^4.1.0" - -postcss-loader@2.0.10: - version "2.0.10" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.0.10.tgz#090db0540140bd56a7a7f717c41bc29aeef4c674" - dependencies: - loader-utils "^1.1.0" - postcss "^6.0.0" - postcss-load-config "^1.2.0" - schema-utils "^0.3.0" - postcss-merge-idents@^2.1.5: version "2.1.7" resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" @@ -5470,14 +5173,6 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0 source-map "^0.5.6" supports-color "^3.2.3" -postcss@^6.0.0: - version "6.0.15" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.15.tgz#f460cd6269fede0d1bf6defff0b934a9845d974d" - dependencies: - chalk "^2.3.0" - source-map "^0.6.1" - supports-color "^5.1.0" - postcss@^6.0.1: version "6.0.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885" @@ -5486,30 +5181,6 @@ postcss@^6.0.1: source-map "^0.6.1" supports-color "^4.4.0" -preact-compat@3.17.0: - version "3.17.0" - resolved "https://registry.yarnpkg.com/preact-compat/-/preact-compat-3.17.0.tgz#528cfdfc301190c1a0f47567336be1f4be0266b3" - dependencies: - immutability-helper "^2.1.2" - preact-render-to-string "^3.6.0" - preact-transition-group "^1.1.0" - prop-types "^15.5.8" - standalone-react-addons-pure-render-mixin "^0.1.1" - -preact-render-to-string@^3.6.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-3.7.0.tgz#7db4177454bc01395e0d01d6ac07bc5e838e31ee" - dependencies: - pretty-format "^3.5.1" - -preact-transition-group@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/preact-transition-group/-/preact-transition-group-1.1.1.tgz#f0a49327ea515ece34ea2be864c4a7d29e5d6e10" - -preact@8.2.7: - version "8.2.7" - resolved "https://registry.yarnpkg.com/preact/-/preact-8.2.7.tgz#316249fb678cd5e93e7cee63cea7bfb62dbd6814" - prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -5529,10 +5200,6 @@ pretty-format@^21.2.1: ansi-regex "^3.0.0" ansi-styles "^3.2.0" -pretty-format@^3.5.1: - version "3.8.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385" - private@^0.1.6, private@^0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -5570,7 +5237,7 @@ prop-types-exact@1.1.1: has "^1.0.1" object.assign "^4.0.4" -prop-types@15.6.0, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.0: +prop-types@15.6.0, prop-types@^15.5.4, prop-types@^15.6.0: version "15.6.0" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" dependencies: @@ -5589,10 +5256,6 @@ prr@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -5695,6 +5358,10 @@ rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-deep-force-update@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-2.1.1.tgz#8ea4263cd6455a050b37445b3f08fd839d86e909" + react-dom@16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" @@ -5704,22 +5371,21 @@ react-dom@16.2.0: object-assign "^4.1.1" prop-types "^15.6.0" -react-hot-loader@4.0.0-beta.13: - version "4.0.0-beta.13" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.0.0-beta.13.tgz#0d145579124e44bd0c9d517f86462a1231a9c9d9" +react-hot-loader@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-3.1.1.tgz#e06db8cd0841c41e3ab0b395b2b774126fc8914e" dependencies: - fast-levenshtein "^2.0.6" global "^4.3.0" - hoist-non-react-statics "^2.3.1" - react-stand-in "^4.0.0-beta.13" + react-deep-force-update "^2.1.1" + react-proxy "^3.0.0-alpha.0" redbox-react "^1.3.6" source-map "^0.6.1" -react-stand-in@^4.0.0-beta.13: - version "4.0.0-beta.13" - resolved "https://registry.yarnpkg.com/react-stand-in/-/react-stand-in-4.0.0-beta.13.tgz#70b9dfe15b573a664bd1927a45bb67fb04de0ad7" +react-proxy@^3.0.0-alpha.0: + version "3.0.0-alpha.1" + resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-3.0.0-alpha.1.tgz#4400426bcfa80caa6724c7755695315209fa4b07" dependencies: - shallowequal "^1.0.2" + lodash "^4.6.1" react@16.2.0: version "16.2.0" @@ -5819,13 +5485,6 @@ redbox-react@^1.3.6: prop-types "^15.5.4" sourcemapped-stacktrace "^1.1.6" -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - reduce-css-calc@^1.2.6: version "1.3.0" resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" @@ -5906,34 +5565,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@2, request@^2.79.0, request@^2.81.0: - version "2.83.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@2.79.0, request@~2.79.0: +request@2.79.0: version "2.79.0" resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" dependencies: @@ -5985,6 +5617,33 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" +request@^2.79.0, request@^2.81.0: + version "2.83.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -6106,25 +5765,6 @@ sane@^2.0.0: optionalDependencies: fsevents "^1.1.1" -sass-graph@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" - dependencies: - glob "^7.0.0" - lodash "^4.0.0" - scss-tokenizer "^0.2.3" - yargs "^7.0.0" - -sass-loader@6.0.6: - version "6.0.6" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-6.0.6.tgz#e9d5e6c1f155faa32a4b26d7a9b7107c225e40f9" - dependencies: - async "^2.1.5" - clone-deep "^0.3.0" - loader-utils "^1.0.1" - lodash.tail "^4.1.1" - pify "^3.0.0" - sax@^1.2.1, sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -6135,21 +5775,10 @@ schema-utils@^0.3.0: dependencies: ajv "^5.0.0" -scss-tokenizer@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" - dependencies: - js-base64 "^2.1.8" - source-map "^0.4.2" - "semver@2 || 3 || 4 || 5", semver@^5.3.0: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - send@0.15.6: version "0.15.6" resolved "https://registry.yarnpkg.com/send/-/send-0.15.6.tgz#20f23a9c925b762ab82705fe2f9db252ace47e34" @@ -6218,19 +5847,6 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -shallow-clone@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-0.1.2.tgz#5909e874ba77106d73ac414cfec1ffca87d97060" - dependencies: - is-extendable "^0.1.1" - kind-of "^2.0.1" - lazy-cache "^0.2.3" - mixin-object "^2.0.1" - -shallowequal@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.0.2.tgz#1561dbdefb8c01408100319085764da3fcf83f8f" - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -6311,7 +5927,7 @@ source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" -source-map@^0.4.2, source-map@^0.4.4: +source-map@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" dependencies: @@ -6392,10 +6008,6 @@ staged-git-files@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-0.0.4.tgz#d797e1b551ca7a639dec0237dc6eb4bb9be17d35" -standalone-react-addons-pure-render-mixin@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/standalone-react-addons-pure-render-mixin/-/standalone-react-addons-pure-render-mixin-0.1.1.tgz#3c7409f4c79c40de9ac72c616cf679a994f37551" - standard-engine@~5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/standard-engine/-/standard-engine-5.4.0.tgz#e0e86959ea0786425d3383e40c1bf70d2f985579" @@ -6428,12 +6040,6 @@ stats-webpack-plugin@0.6.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" -stdout-stream@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" - dependencies: - readable-stream "^2.0.1" - stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" @@ -6550,12 +6156,6 @@ strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - dependencies: - get-stdin "^4.0.1" - strip-indent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" @@ -6607,12 +6207,6 @@ supports-color@^4.0.0, supports-color@^4.2.1, supports-color@^4.4.0: dependencies: has-flag "^2.0.0" -supports-color@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5" - dependencies: - has-flag "^2.0.0" - svgo@^0.7.0: version "0.7.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" @@ -6670,7 +6264,7 @@ tar-stream@^1.5.0: readable-stream "^2.0.0" xtend "^4.0.0" -tar@^2.0.0, tar@^2.2.1: +tar@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" dependencies: @@ -6783,20 +6377,10 @@ tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" -"true-case-path@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.2.tgz#7ec91130924766c7f573be3020c34f8fdfd00d62" - dependencies: - glob "^6.0.4" - tryit@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" @@ -7119,15 +6703,11 @@ whet.extend@~0.9.9: version "0.9.9" resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" -which@1, which@^1.2.10, which@^1.2.12, which@^1.2.4, which@^1.2.8, which@^1.2.9: +which@^1.2.10, which@^1.2.12, which@^1.2.4, which@^1.2.8, which@^1.2.9: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" dependencies: @@ -7238,24 +6818,6 @@ yargs-parser@^7.0.0: dependencies: camelcase "^4.1.0" -yargs@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^5.0.0" - yargs@^8.0.1, yargs@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" From 340b93d7e8003cf035f130606ed8c578c33c34b0 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 15 Jan 2018 17:33:01 +0100 Subject: [PATCH 055/132] Fix hot loader --- client/next-dev.js | 1 - package.json | 2 +- server/build/webpack/base.config.js | 14 ++++++------ yarn.lock | 33 +++++++++++++++-------------- 4 files changed, 24 insertions(+), 26 deletions(-) diff --git a/client/next-dev.js b/client/next-dev.js index ef771c32c6156..f7c2386406354 100644 --- a/client/next-dev.js +++ b/client/next-dev.js @@ -1,4 +1,3 @@ -import 'react-hot-loader/patch' import stripAnsi from 'strip-ansi' import initNext, * as next from './' import ErrorDebugComponent from '../lib/error-debug' diff --git a/package.json b/package.json index cc19564e7bea9..9ad4d943268a7 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "pkg-up": "2.0.0", "prop-types": "15.6.0", "prop-types-exact": "1.1.1", - "react-hot-loader": "3.1.1", + "react-hot-loader": "4.0.0-beta.14", "recursive-copy": "2.0.6", "send": "0.16.1", "source-map-support": "0.5.0", diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index ad22647aba09e..0f67e2e505d21 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -24,10 +24,13 @@ const interpolateNames = new Map(defaultPages.map((p) => { return [path.join(nextPagesDir, p), `dist/bundles/pages/${p}`] })) -function babelConfig (dir) { +function babelConfig (dir, isServer) { const mainBabelOptions = { cacheDirectory: true, - presets: [] + presets: [], + plugins: [ + !isServer && require.resolve('react-hot-loader/babel') + ].filter(Boolean) } const externalBabelConfig = findBabelConfig(dir) @@ -95,7 +98,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b ].filter(Boolean) } - const babelLoaderOptions = babelConfig(dir) + const babelLoaderOptions = babelConfig(dir, isServer) const externals = isServer ? [ nodeExternals({ @@ -163,11 +166,6 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b }, module: { rules: [ - dev && !isServer && { - test: /\.(js|jsx)(\?[^?]*)?$/, - loader: 'react-hot-loader/webpack', - exclude: /node_modules/ - }, dev && !isServer && { test: /\.(js|jsx)(\?[^?]*)?$/, loader: 'hot-self-accept-loader', diff --git a/yarn.lock b/yarn.lock index 09e1e6b3f1778..a072958b124f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2580,7 +2580,7 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" -fast-levenshtein@~2.0.4: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -3087,7 +3087,7 @@ hoek@4.x.x: version "4.2.0" resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" -hoist-non-react-statics@2.3.1: +hoist-non-react-statics@2.3.1, hoist-non-react-statics@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0" @@ -4123,7 +4123,7 @@ lodash@4.16.2: version "4.16.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652" -lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1, lodash@^4.8.0: +lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.8.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -5358,10 +5358,6 @@ rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-deep-force-update@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-2.1.1.tgz#8ea4263cd6455a050b37445b3f08fd839d86e909" - react-dom@16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" @@ -5371,21 +5367,22 @@ react-dom@16.2.0: object-assign "^4.1.1" prop-types "^15.6.0" -react-hot-loader@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-3.1.1.tgz#e06db8cd0841c41e3ab0b395b2b774126fc8914e" +react-hot-loader@4.0.0-beta.14: + version "4.0.0-beta.14" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.0.0-beta.14.tgz#9575065aadda9c53ef455e757b8b36c1fd14e5d6" dependencies: + fast-levenshtein "^2.0.6" global "^4.3.0" - react-deep-force-update "^2.1.1" - react-proxy "^3.0.0-alpha.0" + hoist-non-react-statics "^2.3.1" + react-stand-in "^4.0.0-beta.14" redbox-react "^1.3.6" source-map "^0.6.1" -react-proxy@^3.0.0-alpha.0: - version "3.0.0-alpha.1" - resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-3.0.0-alpha.1.tgz#4400426bcfa80caa6724c7755695315209fa4b07" +react-stand-in@^4.0.0-beta.14: + version "4.0.0-beta.14" + resolved "https://registry.yarnpkg.com/react-stand-in/-/react-stand-in-4.0.0-beta.14.tgz#0a06a94b44bc4ca1d06575414acf400585d84e35" dependencies: - lodash "^4.6.1" + shallowequal "^1.0.2" react@16.2.0: version "16.2.0" @@ -5847,6 +5844,10 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +shallowequal@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.0.2.tgz#1561dbdefb8c01408100319085764da3fcf83f8f" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" From 52605da0b17a8b616ea16e20699c9b5d9c277cb6 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 15 Jan 2018 17:37:44 +0100 Subject: [PATCH 056/132] Release 5.0.0-universal-alpha.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9ad4d943268a7..81eed0586b66a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.4", + "version": "5.0.0-universal-alpha.5", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 3347940ad066874c0adb2c18697153109a542ba1 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 15 Jan 2018 20:38:36 +0100 Subject: [PATCH 057/132] Check if externals dir exist before applying config --- server/build/webpack/base.config.js | 42 ++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 0f67e2e505d21..bad3b07e34b4d 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -1,4 +1,5 @@ import path, {sep} from 'path' +import fs from 'fs' import webpack from 'webpack' import nodeExternals from 'webpack-node-externals' @@ -54,6 +55,33 @@ function babelConfig (dir, isServer) { return mainBabelOptions } +function externalsConfig (dir, isServer) { + const externals = [] + + if (!isServer) { + return externals + } + + if (fs.existsSync(nextNodeModulesDir)) { + externals.push(nodeExternals({ + modulesDir: nextNodeModulesDir, + includeAbsolutePaths: true, + whitelist: [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i] + })) + } + + const dirNodeModules = path.join(dir, 'node_modules') + if (fs.existsSync(dirNodeModules)) { + nodeExternals({ + modulesDir: dirNodeModules, + includeAbsolutePaths: true, + whitelist: [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i] + }) + } + + return externals +} + export default async function baseConfig (dir, {dev = false, isServer = false, buildId, config}) { const extractCSS = new ExtractTextPlugin({ filename: 'static/style.css', @@ -100,18 +128,6 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b const babelLoaderOptions = babelConfig(dir, isServer) - const externals = isServer ? [ - nodeExternals({ - modulesDir: nextNodeModulesDir, - includeAbsolutePaths: true, - whitelist: [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i] - }), - nodeExternals({ - modulesDir: path.join(dir, 'node_modules'), - includeAbsolutePaths: true, - whitelist: [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i] - }) - ] : [] let webpackConfig = { devtool: dev ? 'cheap-module-source-map' : 'source-map', // devtool: 'source-map', @@ -119,7 +135,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b cache: true, profile: true, target: isServer ? 'node' : 'web', - externals, + externals: externalsConfig(dir, isServer), context: dir, entry: async () => { const pages = await getPages(dir, {dev, isServer}) From 5434104a3ce801996031286c77a6916d8163f8cb Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 16 Jan 2018 10:28:07 +0100 Subject: [PATCH 058/132] Add typescript support --- server/build/webpack/base.config.js | 19 ++++++++++++++++++- server/build/webpack/utils.js | 6 +++--- server/on-demand-entry-handler.js | 5 ++--- server/resolve.js | 8 ++++++++ server/utils.js | 4 ++-- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index bad3b07e34b4d..c57556dba5108 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -163,7 +163,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b }, performance: { hints: false }, resolve: { - extensions: ['.js', '.jsx', '.json'], + extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'], modules: [ nextNodeModulesDir, 'node_modules' @@ -199,6 +199,23 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b options: babelLoaderOptions } }, + { + test: /\.+(ts|tsx)$/, + include: [dir], + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: babelLoaderOptions + }, + { + loader: 'ts-loader', + options: { + transpileOnly: true + } + } + ] + }, { test: /\.css$/, use: cssLoaderConfig() diff --git a/server/build/webpack/utils.js b/server/build/webpack/utils.js index f0086c827c4e3..ca02abb725c18 100644 --- a/server/build/webpack/utils.js +++ b/server/build/webpack/utils.js @@ -13,9 +13,9 @@ async function getPageFiles (dir, {dev, isServer}) { let pages if (dev) { - pages = await glob(isServer ? 'pages/+(_document|_error).+(js|jsx)' : 'pages/_error.+(js|jsx)', { cwd: dir }) + pages = await glob(isServer ? 'pages/+(_document|_error).+(js|jsx|ts|tsx)' : 'pages/_error.+(js|jsx|ts|tsx)', { cwd: dir }) } else { - pages = await glob(isServer ? 'pages/**/*.+(js|jsx)' : 'pages/**/!(_document)*.+(js|jsx)', { cwd: dir }) + pages = await glob(isServer ? 'pages/**/*.+(js|jsx|ts|tsx)' : 'pages/**/!(_document)*.+(js|jsx|ts|tsx)', { cwd: dir }) } return pages @@ -25,7 +25,7 @@ export function getPageEntries (pageFiles, {isServer}) { const entries = {} const bundleLocation = 'bundles' for (const p of pageFiles) { - entries[path.join(bundleLocation, p.replace('.jsx', '.js'))] = [`./${p}`] + entries[path.join(bundleLocation, p.replace(/\.+(jsx|tsx|ts)/, '.js'))] = [`./${p}`] } // The default pages (_document.js and _error.js) are only added when they're not provided by the user diff --git a/server/on-demand-entry-handler.js b/server/on-demand-entry-handler.js index 8c06579405508..f3c7bf6de7625 100644 --- a/server/on-demand-entry-handler.js +++ b/server/on-demand-entry-handler.js @@ -1,6 +1,6 @@ import DynamicEntryPlugin from 'webpack/lib/DynamicEntryPlugin' import { EventEmitter } from 'events' -import { join } from 'path' +import { join, relative } from 'path' import { parse } from 'url' import resolvePath from './resolve' import touch from 'touch' @@ -130,8 +130,7 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { const pagePath = join(dir, 'pages', page) const pathname = await resolvePath(pagePath) - const name = join('bundles', pathname.substring(dir.length)) - + const name = join('bundles', relative(dir, pathname.replace(/\.+(jsx|tsx|ts)/, '.js'))) const entry = [`${pathname}`] await new Promise((resolve, reject) => { diff --git a/server/resolve.js b/server/resolve.js index 543dded791122..d33fee65184aa 100644 --- a/server/resolve.js +++ b/server/resolve.js @@ -28,12 +28,16 @@ function getPaths (id) { if (i.slice(-3) === '.js') return [i] if (i.slice(-4) === '.jsx') return [i] + if (i.slice(-4) === '.tsx') return [i] + if (i.slice(-3) === '.ts') return [i] if (i.slice(-5) === '.json') return [i] if (i[i.length - 1] === sep) { return [ i + 'index.js', i + 'index.jsx', + i + 'index.ts', + i + 'index.tsx', i + 'index.json' ] } @@ -43,6 +47,10 @@ function getPaths (id) { join(i, 'index.js'), i + '.jsx', join(i, 'index.jsx'), + i + '.tsx', + join(i, 'index.tsx'), + i + '.ts', + join(i, 'index.ts'), i + '.json', join(i, 'index.json') ] diff --git a/server/utils.js b/server/utils.js index 5821a8617495e..66b87c0975453 100644 --- a/server/utils.js +++ b/server/utils.js @@ -1,8 +1,8 @@ import { join } from 'path' import { readdirSync, existsSync } from 'fs' -export const IS_BUNDLED_PAGE = /^bundles[/\\]pages.*\.(js|jsx)$/ -export const MATCH_ROUTE_NAME = /^bundles[/\\]pages[/\\](.*)\.(js|jsx)$/ +export const IS_BUNDLED_PAGE = /^bundles[/\\]pages.*\.js$/ +export const MATCH_ROUTE_NAME = /^bundles[/\\]pages[/\\](.*)\.js$/ export function getAvailableChunks (dir, dist) { const chunksDir = join(dir, dist, 'chunks') From d4b1d9babfb4b9ed4f4b12d56d52dee233e862da Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 16 Jan 2018 11:29:57 +0100 Subject: [PATCH 059/132] Add support for transpiling certain packages in node_modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to @giuseppeg’s work in https://github.com/zeit/next.js/pull/3319 --- server/build/webpack/base.config.js | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index c57556dba5108..8bfaa96fa80b1 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -25,6 +25,28 @@ const interpolateNames = new Map(defaultPages.map((p) => { return [path.join(nextPagesDir, p), `dist/bundles/pages/${p}`] })) +function shouldTranspileModule (transpileModules, path) { + return (transpileModules || []).some(pattern => { + if (!(pattern instanceof RegExp)) { + const message = `Incorrect pattern in config.transpileModules: "${pattern}".` + + 'It accepts an array of regular expression' + throw new Error(message) + } + + return pattern.test(path) + }) +} + +function excludeModules (config) { + return (str) => { + if (shouldTranspileModule(config.transpileModules, str)) { + return false + } + + return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 + } +} + function babelConfig (dir, isServer) { const mainBabelOptions = { cacheDirectory: true, @@ -193,7 +215,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b { test: /\.+(js|jsx)$/, include: [dir], - exclude: /node_modules/, + exclude: excludeModules(config), use: { loader: 'babel-loader', options: babelLoaderOptions @@ -202,7 +224,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b { test: /\.+(ts|tsx)$/, include: [dir], - exclude: /node_modules/, + exclude: excludeModules(config), use: [ { loader: 'babel-loader', From 4ca1a44bc24fe29d69237bdc5730934b3ea06a57 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 16 Jan 2018 15:28:58 +0100 Subject: [PATCH 060/132] Add BABEL_DISABLE_CACHE support --- server/build/webpack/base.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 8bfaa96fa80b1..5fe53b8a59133 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -49,7 +49,7 @@ function excludeModules (config) { function babelConfig (dir, isServer) { const mainBabelOptions = { - cacheDirectory: true, + cacheDirectory: Boolean(process.env.BABEL_DISABLE_CACHE), presets: [], plugins: [ !isServer && require.resolve('react-hot-loader/babel') From 5821d491fb9c09b01fda4840ccaa8ed32c111832 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 16 Jan 2018 15:38:25 +0100 Subject: [PATCH 061/132] Make sourcemaps in production opt-in --- server/build/webpack/base.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 5fe53b8a59133..e554432fed05b 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -151,7 +151,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b const babelLoaderOptions = babelConfig(dir, isServer) let webpackConfig = { - devtool: dev ? 'cheap-module-source-map' : 'source-map', + devtool: dev ? 'cheap-module-source-map' : false, // devtool: 'source-map', name: isServer ? 'server' : 'client', cache: true, From 91ad1933dc46247565e058d87f836bb6b1889373 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 16 Jan 2018 15:45:43 +0100 Subject: [PATCH 062/132] Revert "Add support for transpiling certain packages in node_modules" This reverts commit d4b1d9babfb4b9ed4f4b12d56d52dee233e862da. In favor of a better api around this. --- server/build/webpack/base.config.js | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index e554432fed05b..2295724f9d292 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -25,28 +25,6 @@ const interpolateNames = new Map(defaultPages.map((p) => { return [path.join(nextPagesDir, p), `dist/bundles/pages/${p}`] })) -function shouldTranspileModule (transpileModules, path) { - return (transpileModules || []).some(pattern => { - if (!(pattern instanceof RegExp)) { - const message = `Incorrect pattern in config.transpileModules: "${pattern}".` + - 'It accepts an array of regular expression' - throw new Error(message) - } - - return pattern.test(path) - }) -} - -function excludeModules (config) { - return (str) => { - if (shouldTranspileModule(config.transpileModules, str)) { - return false - } - - return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 - } -} - function babelConfig (dir, isServer) { const mainBabelOptions = { cacheDirectory: Boolean(process.env.BABEL_DISABLE_CACHE), @@ -215,7 +193,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b { test: /\.+(js|jsx)$/, include: [dir], - exclude: excludeModules(config), + exclude: /node_modules/, use: { loader: 'babel-loader', options: babelLoaderOptions @@ -224,7 +202,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b { test: /\.+(ts|tsx)$/, include: [dir], - exclude: excludeModules(config), + exclude: /node_modules/, use: [ { loader: 'babel-loader', From dbbdec421abb30e1c39d312e704a03bb7daf929b Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 17 Jan 2018 10:39:20 +0100 Subject: [PATCH 063/132] Support typescript through next.config.js --- server/build/webpack/base.config.js | 46 +++++++++++------------------ 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 2295724f9d292..576617dc3cda9 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -95,7 +95,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b minimize: !dev, sourceMap: dev, importLoaders: 1, - ...(config.cssLoaderConfig || {}) + ...(config.cssLoader || {}) } } @@ -128,6 +128,16 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b const babelLoaderOptions = babelConfig(dir, isServer) + const defaultLoaders = { + babel: { + loader: 'babel-loader', + options: babelLoaderOptions + }, + css: cssLoaderConfig(), + scss: cssLoaderConfig('sass-loader'), + less: cssLoaderConfig('less-loader') + } + let webpackConfig = { devtool: dev ? 'cheap-module-source-map' : false, // devtool: 'source-map', @@ -153,7 +163,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b } }, output: { - path: path.join(dir, '.next', isServer ? 'dist' : ''), + path: path.join(dir, '.next', isServer ? 'dist' : ''), // server compilation goes to `.next/dist` filename: '[name]', libraryTarget: 'commonjs2', publicPath: `/_next/webpack/`, @@ -163,7 +173,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b }, performance: { hints: false }, resolve: { - extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'], + extensions: ['.js', '.jsx', '.json'], modules: [ nextNodeModulesDir, 'node_modules' @@ -194,39 +204,19 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b test: /\.+(js|jsx)$/, include: [dir], exclude: /node_modules/, - use: { - loader: 'babel-loader', - options: babelLoaderOptions - } - }, - { - test: /\.+(ts|tsx)$/, - include: [dir], - exclude: /node_modules/, - use: [ - { - loader: 'babel-loader', - options: babelLoaderOptions - }, - { - loader: 'ts-loader', - options: { - transpileOnly: true - } - } - ] + use: defaultLoaders.babel }, { test: /\.css$/, - use: cssLoaderConfig() + use: defaultLoaders.css }, { test: /\.scss$/, - use: cssLoaderConfig('sass-loader') + use: defaultLoaders.scss }, { test: /\.less$/, - use: cssLoaderConfig('less-loader') + use: defaultLoaders.less } ].filter(Boolean) }, @@ -311,7 +301,7 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b } if (typeof config.webpack === 'function') { - webpackConfig = config.webpack(webpackConfig, {dev, isServer, buildId, babelLoaderOptions}) + webpackConfig = config.webpack(webpackConfig, {dir, dev, isServer, buildId, config, defaultLoaders}) } return webpackConfig From 5fd08f1d2ce7253afdb4733f7b74954abd81dbab Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 17 Jan 2018 11:09:11 +0100 Subject: [PATCH 064/132] Remove comments --- server/build/loaders/hot-self-accept-loader.js | 7 ------- server/build/webpack.js | 1 - server/hot-reloader.js | 1 - server/index.js | 8 -------- server/render.js | 2 -- 5 files changed, 19 deletions(-) diff --git a/server/build/loaders/hot-self-accept-loader.js b/server/build/loaders/hot-self-accept-loader.js index 18a7b910d92c2..3f0aa8cc5ce85 100644 --- a/server/build/loaders/hot-self-accept-loader.js +++ b/server/build/loaders/hot-self-accept-loader.js @@ -8,13 +8,6 @@ module.exports = function (content, sourceMap) { this.callback(null, `${content} (function (Component, route) { if (!module.hot) return - // if (!__resourceQuery) return - - // var qs = require('querystring') - // var params = qs.parse(__resourceQuery.slice(1)) - // if (params.entry == null) return - - console.log('ACCEPTING') module.hot.accept() Component.__route = route diff --git a/server/build/webpack.js b/server/build/webpack.js index f5796c17efe11..39965b16d1b36 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -59,7 +59,6 @@ function getPageEntries (pages) { } export default async function createCompiler (dir, { buildId, dev = false, quiet = false, buildDir, conf = null } = {}) { - console.log('XXXXXXX CREATE') // Resolve relative path to absolute path dir = realpathSync(resolve(dir)) diff --git a/server/hot-reloader.js b/server/hot-reloader.js index c3ccb37d3f0dc..7aa55d4c2820a 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -59,7 +59,6 @@ export default class HotReloader { this.assignBuildTools(buildTools) this.stats = (await this.waitUntilValid()).stats[0] - // console.log('XXXX', Object.keys(this.stats)) } async stop (webpackDevMiddleware) { diff --git a/server/index.js b/server/index.js index d6ae7989b9cbf..804d034043319 100644 --- a/server/index.js +++ b/server/index.js @@ -197,9 +197,6 @@ export default class Server { '/_next/:buildId/page/:path*.js': async (req, res, params) => { const paths = params.path || [''] - // URL is asks for ${page}.js (to support loading assets from static dirs) - // But there's no .js in the actual page. - // So, we need to remove .js to get the page name. const page = `/${paths.join('/')}` if (!this.handleBuildId(params.buildId, res)) { @@ -257,7 +254,6 @@ export default class Server { if (this.config.useFileSystemPublicRoutes) { routes['/:path*'] = async (req, res, params, parsedUrl) => { const { pathname, query } = parsedUrl - // console.log('XXXX - render', pathname, typeof (res)) await this.render(req, res, pathname, query) } } @@ -317,9 +313,7 @@ export default class Server { async renderToHTML (req, res, pathname, query) { if (this.dev) { - // console.log('XXX - Taking Error', typeof (res)) const compilationErr = await this.getCompilationError() - // console.log('XXX - ERROR Found', compilationErr, typeof (res)) if (compilationErr) { res.statusCode = 500 return this.renderErrorToHTML(compilationErr, req, res, pathname, query) @@ -327,9 +321,7 @@ export default class Server { } try { - // console.log('XXX - Rendering HTML', typeof (res)) const out = await renderToHTML(req, res, pathname, query, this.renderOpts) - // console.log('XXX - HTML Rendered', typeof (res)) return out } catch (err) { if (err.code === 'ENOENT') { diff --git a/server/render.js b/server/render.js index ca64e6c1b9628..f6b4a9f5b924c 100644 --- a/server/render.js +++ b/server/render.js @@ -48,9 +48,7 @@ async function doRender (req, res, pathname, query, { } = {}) { page = page || pathname - // console.log('XXX - Ensure page', page) await ensurePage(page, { dir, hotReloader }) - // console.log('XXX - Page available', page) const dist = getConfig(dir).distDir From fcea07cf9b4ce83cd910dc52f2c76da8ad2eb241 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 17 Jan 2018 11:12:57 +0100 Subject: [PATCH 065/132] Bring back commons.js calculation --- server/build/webpack/base.config.js | 42 ++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js index 576617dc3cda9..1764153fef11b 100644 --- a/server/build/webpack/base.config.js +++ b/server/build/webpack/base.config.js @@ -66,7 +66,7 @@ function externalsConfig (dir, isServer) { externals.push(nodeExternals({ modulesDir: nextNodeModulesDir, includeAbsolutePaths: true, - whitelist: [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i] + whitelist: [/\.(?!(?:js|json)$).{1,5}$/i] })) } @@ -75,7 +75,7 @@ function externalsConfig (dir, isServer) { nodeExternals({ modulesDir: dirNodeModules, includeAbsolutePaths: true, - whitelist: [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i] + whitelist: [/\.(?!(?:js|json)$).{1,5}$/i] }) } @@ -138,17 +138,18 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b less: cssLoaderConfig('less-loader') } + let totalPages + let webpackConfig = { devtool: dev ? 'cheap-module-source-map' : false, - // devtool: 'source-map', name: isServer ? 'server' : 'client', cache: true, - profile: true, target: isServer ? 'node' : 'web', externals: externalsConfig(dir, isServer), context: dir, entry: async () => { const pages = await getPages(dir, {dev, isServer}) + totalPages = Object.keys(pages).length const mainJS = require.resolve(`../../../client/next${dev ? '-dev' : ''}`) const clientConfig = !isServer ? { 'main.js': [ @@ -221,11 +222,6 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b ].filter(Boolean) }, plugins: [ - // Useful when profiling - // new webpack.ProgressPlugin({ - // profile: true - // }), - // new StatsPlugin(`stats-${isServer ? 'server':'client'}.json`), new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), dev && new webpack.NoEmitOnErrorsPlugin(), dev && !isServer && new FriendlyErrorsWebpackPlugin(), @@ -271,7 +267,33 @@ export default async function baseConfig (dir, {dev = false, isServer = false, b !isServer && new webpack.optimize.CommonsChunkPlugin({ name: `commons`, filename: `commons.js`, - minChunks: 2 + minChunks (module, count) { + // We need to move react-dom explicitly into common chunks. + // Otherwise, if some other page or module uses it, it might + // included in that bundle too. + if (dev && module.context && module.context.indexOf(`${sep}react${sep}`) >= 0) { + return true + } + + if (dev && module.context && module.context.indexOf(`${sep}react-dom${sep}`) >= 0) { + return true + } + + // In the dev we use on-demand-entries. + // So, it makes no sense to use commonChunks based on the minChunks count. + // Instead, we move all the code in node_modules into each of the pages. + if (dev) { + return false + } + + // If there are one or two pages, only move modules to common if they are + // used in all of the pages. Otherwise, move modules used in at-least + // 1/2 of the total pages into commons. + if (totalPages <= 2) { + return count >= totalPages + } + return count >= totalPages * 0.5 + } }), !isServer && new webpack.optimize.CommonsChunkPlugin({ name: 'react', From 04651beb897a59f314e86c408f68bcbf08ed2301 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 17 Jan 2018 11:31:25 +0100 Subject: [PATCH 066/132] Remove unused dependencies --- package.json | 4 - yarn.lock | 627 +-------------------------------------------------- 2 files changed, 6 insertions(+), 625 deletions(-) diff --git a/package.json b/package.json index 81eed0586b66a..94c97c1a95c9c 100644 --- a/package.json +++ b/package.json @@ -68,8 +68,6 @@ "babel-template": "6.26.0", "case-sensitive-paths-webpack-plugin": "2.1.1", "cross-spawn": "5.1.0", - "css-hot-loader": "1.3.4", - "css-loader": "0.28.7", "del": "3.0.0", "etag": "1.8.1", "extract-text-webpack-plugin": "3.0.2", @@ -97,9 +95,7 @@ "recursive-copy": "2.0.6", "send": "0.16.1", "source-map-support": "0.5.0", - "stats-webpack-plugin": "0.6.1", "strip-ansi": "3.0.1", - "style-loader": "0.19.1", "styled-jsx": "2.2.1", "touch": "3.1.0", "uglifyjs-webpack-plugin": "^1.1.1", diff --git a/yarn.lock b/yarn.lock index a072958b124f1..ee407ca104056 100644 --- a/yarn.lock +++ b/yarn.lock @@ -123,10 +123,6 @@ align-text@^0.1.1, align-text@^0.1.3: longest "^1.0.1" repeat-string "^1.5.2" -alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -339,17 +335,6 @@ asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" -autoprefixer@^6.3.1: - version "6.7.7" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" - dependencies: - browserslist "^1.7.6" - caniuse-db "^1.0.30000634" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^5.2.16" - postcss-value-parser "^3.2.3" - aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" @@ -370,7 +355,7 @@ babel-code-frame@7.0.0-beta.0: esutils "^2.0.2" js-tokens "^3.0.0" -babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.26.0: +babel-code-frame@^6.16.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -1078,10 +1063,6 @@ babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" -balanced-match@^0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" - balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -1230,13 +1211,6 @@ browserify-zlib@^0.1.4: dependencies: pako "~0.2.0" -browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: - version "1.7.7" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" - dependencies: - caniuse-db "^1.0.30000639" - electron-to-chromium "^1.2.7" - browserslist@^2.1.2: version "2.5.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.5.1.tgz#68e4bc536bbcc6086d62843a2ffccea8396821c6" @@ -1341,19 +1315,6 @@ camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" -caniuse-api@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" - dependencies: - browserslist "^1.3.6" - caniuse-db "^1.0.30000529" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000784" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000784.tgz#1be95012d9489c7719074f81aee57dbdffe6361b" - caniuse-lite@^1.0.30000744: version "1.0.30000748" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000748.tgz#44c8d6da52ad65a5d7b9dca4efebd0bdd982ba09" @@ -1395,14 +1356,6 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" -chalk@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" - cheerio@0.22.0: version "0.22.0" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" @@ -1468,12 +1421,6 @@ circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" -clap@^1.0.9: - version "1.2.3" - resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" - dependencies: - chalk "^1.1.3" - clean-stack@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31" @@ -1515,10 +1462,6 @@ cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" -clone@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" - clor@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/clor/-/clor-5.2.0.tgz#9ddc74e7e86728cfcd05a80546ba58d317b81035" @@ -1527,58 +1470,20 @@ co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" -coa@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" - dependencies: - q "^1.1.2" - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" -color-convert@^1.3.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" - dependencies: - color-name "^1.1.1" - color-convert@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" dependencies: color-name "^1.1.1" -color-name@^1.0.0, color-name@^1.1.1: +color-name@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" -color-string@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" - dependencies: - color-name "^1.0.0" - -color@^0.11.0: - version "0.11.4" - resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" - dependencies: - clone "^1.0.2" - color-convert "^1.3.0" - color-string "^0.3.0" - -colormin@^1.0.5: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" - dependencies: - color "^0.11.0" - css-color-names "0.0.4" - has "^1.0.1" - -colors@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" - combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" @@ -1796,36 +1701,6 @@ crypto-browserify@^3.11.0: public-encrypt "^4.0.0" randombytes "^2.0.0" -css-color-names@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - -css-hot-loader@1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/css-hot-loader/-/css-hot-loader-1.3.4.tgz#cd58b9419cd7ec82350b1d60713d86e480a8b286" - dependencies: - loader-utils "^1.1.0" - normalize-url "^1.9.1" - -css-loader@0.28.7: - version "0.28.7" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.7.tgz#5f2ee989dd32edd907717f953317656160999c1b" - dependencies: - babel-code-frame "^6.11.0" - css-selector-tokenizer "^0.7.0" - cssnano ">=2.6.1 <4" - icss-utils "^2.1.0" - loader-utils "^1.0.2" - lodash.camelcase "^4.3.0" - object-assign "^4.0.1" - postcss "^5.0.6" - postcss-modules-extract-imports "^1.0.0" - postcss-modules-local-by-default "^1.0.1" - postcss-modules-scope "^1.0.0" - postcss-modules-values "^1.1.0" - postcss-value-parser "^3.3.0" - source-list-map "^2.0.0" - css-select@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" @@ -1835,66 +1710,10 @@ css-select@~1.2.0: domutils "1.5.1" nth-check "~1.0.1" -css-selector-tokenizer@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86" - dependencies: - cssesc "^0.1.0" - fastparse "^1.1.1" - regexpu-core "^1.0.0" - css-what@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" -cssesc@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" - -"cssnano@>=2.6.1 <4": - version "3.10.0" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" - dependencies: - autoprefixer "^6.3.1" - decamelize "^1.1.2" - defined "^1.0.0" - has "^1.0.1" - object-assign "^4.0.1" - postcss "^5.0.14" - postcss-calc "^5.2.0" - postcss-colormin "^2.1.8" - postcss-convert-values "^2.3.4" - postcss-discard-comments "^2.0.4" - postcss-discard-duplicates "^2.0.1" - postcss-discard-empty "^2.0.1" - postcss-discard-overridden "^0.1.1" - postcss-discard-unused "^2.2.1" - postcss-filter-plugins "^2.0.0" - postcss-merge-idents "^2.1.5" - postcss-merge-longhand "^2.0.1" - postcss-merge-rules "^2.0.3" - postcss-minify-font-values "^1.0.2" - postcss-minify-gradients "^1.0.1" - postcss-minify-params "^1.0.4" - postcss-minify-selectors "^2.0.4" - postcss-normalize-charset "^1.1.0" - postcss-normalize-url "^3.0.7" - postcss-ordered-values "^2.1.0" - postcss-reduce-idents "^2.2.2" - postcss-reduce-initial "^1.0.0" - postcss-reduce-transforms "^1.0.3" - postcss-svgo "^2.1.1" - postcss-unique-selectors "^2.0.2" - postcss-value-parser "^3.2.3" - postcss-zindex "^2.0.1" - -csso@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" - dependencies: - clap "^1.0.9" - source-map "^0.5.3" - cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": version "0.3.2" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b" @@ -1951,7 +1770,7 @@ debug@^3.0.1: dependencies: ms "2.0.0" -decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: +decamelize@^1.0.0, decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1976,10 +1795,6 @@ define-properties@^1.1.2: foreach "^2.0.5" object-keys "^1.0.8" -defined@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - deglob@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/deglob/-/deglob-2.1.0.tgz#4d44abe16ef32c779b4972bd141a80325029a14a" @@ -2131,16 +1946,6 @@ ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" -electron-releases@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/electron-releases/-/electron-releases-2.1.0.tgz#c5614bf811f176ce3c836e368a0625782341fd4e" - -electron-to-chromium@^1.2.7: - version "1.3.30" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.30.tgz#9666f532a64586651fc56a72513692e820d06a80" - dependencies: - electron-releases "^2.1.0" - electron-to-chromium@^1.3.24: version "1.3.26" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.26.tgz#996427294861a74d9c7c82b9260ea301e8c02d66" @@ -2584,10 +2389,6 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" -fastparse@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" - fb-watchman@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" @@ -3102,10 +2903,6 @@ hosted-git-info@^2.1.4: version "2.5.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" -html-comment-regex@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e" - html-encoding-sniffer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz#79bf7a785ea495fe66165e734153f363ff5437da" @@ -3187,16 +2984,6 @@ iconv-lite@~0.4.13: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" -icss-replace-symbols@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" - -icss-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962" - dependencies: - postcss "^6.0.1" - ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" @@ -3227,10 +3014,6 @@ indent-string@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" @@ -3290,10 +3073,6 @@ ipaddr.js@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0" -is-absolute-url@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -3419,10 +3198,6 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-plain-obj@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -3459,12 +3234,6 @@ is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" -is-svg@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" - dependencies: - html-comment-regex "^1.1.0" - is-symbol@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" @@ -3792,10 +3561,6 @@ jest-validate@^21.1.0, jest-validate@^21.2.1: leven "^2.1.0" pretty-format "^21.2.1" -js-base64@^2.1.9: - version "2.4.0" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.0.tgz#9e566fee624751a1d720c966cd6226d29d4025aa" - js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" @@ -3814,13 +3579,6 @@ js-yaml@^3.4.3, js-yaml@^3.5.1, js-yaml@^3.7.0: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@~3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" - dependencies: - argparse "^1.0.7" - esprima "^2.6.0" - jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -4067,10 +3825,6 @@ lodash.bind@^4.1.4: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - lodash.defaults@^4.0.1: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" @@ -4091,10 +3845,6 @@ lodash.map@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - lodash.merge@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5" @@ -4115,10 +3865,6 @@ lodash.some@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - lodash@4.16.2: version "4.16.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652" @@ -4167,10 +3913,6 @@ lru-cache@^4.0.0, lru-cache@^4.0.1, lru-cache@^4.1.1: pseudomap "^1.0.2" yallist "^2.1.2" -macaddress@^0.2.8: - version "0.2.8" - resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12" - make-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" @@ -4183,10 +3925,6 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" -math-expression-evaluator@^1.2.14: - version "1.2.17" - resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" - maximatch@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/maximatch/-/maximatch-0.1.0.tgz#86cd8d6b04c9f307c05a6b9419906d0360fb13a2" @@ -4529,19 +4267,6 @@ normalize-path@^2.0.0, normalize-path@^2.0.1: dependencies: remove-trailing-separator "^1.0.1" -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - -normalize-url@^1.4.0, normalize-url@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" - dependencies: - object-assign "^4.0.1" - prepend-http "^1.0.0" - query-string "^4.1.0" - sort-keys "^1.0.0" - npm-path@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.3.tgz#15cff4e1c89a38da77f56f6055b24f975dfb2bbe" @@ -4577,10 +4302,6 @@ nth-check@~1.0.1: dependencies: boolbase "~1.0.0" -num2fraction@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -4935,260 +4656,10 @@ portfinder@1.0.13: debug "^2.2.0" mkdirp "0.5.x" -postcss-calc@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" - dependencies: - postcss "^5.0.2" - postcss-message-helpers "^2.0.0" - reduce-css-calc "^1.2.6" - -postcss-colormin@^2.1.8: - version "2.2.2" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" - dependencies: - colormin "^1.0.5" - postcss "^5.0.13" - postcss-value-parser "^3.2.3" - -postcss-convert-values@^2.3.4: - version "2.6.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" - dependencies: - postcss "^5.0.11" - postcss-value-parser "^3.1.2" - -postcss-discard-comments@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" - dependencies: - postcss "^5.0.14" - -postcss-discard-duplicates@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" - dependencies: - postcss "^5.0.4" - -postcss-discard-empty@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" - dependencies: - postcss "^5.0.14" - -postcss-discard-overridden@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" - dependencies: - postcss "^5.0.16" - -postcss-discard-unused@^2.2.1: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" - dependencies: - postcss "^5.0.14" - uniqs "^2.0.0" - -postcss-filter-plugins@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz#6d85862534d735ac420e4a85806e1f5d4286d84c" - dependencies: - postcss "^5.0.4" - uniqid "^4.0.0" - -postcss-merge-idents@^2.1.5: - version "2.1.7" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" - dependencies: - has "^1.0.1" - postcss "^5.0.10" - postcss-value-parser "^3.1.1" - -postcss-merge-longhand@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" - dependencies: - postcss "^5.0.4" - -postcss-merge-rules@^2.0.3: - version "2.1.2" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" - dependencies: - browserslist "^1.5.2" - caniuse-api "^1.5.2" - postcss "^5.0.4" - postcss-selector-parser "^2.2.2" - vendors "^1.0.0" - -postcss-message-helpers@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" - -postcss-minify-font-values@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" - dependencies: - object-assign "^4.0.1" - postcss "^5.0.4" - postcss-value-parser "^3.0.2" - -postcss-minify-gradients@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" - dependencies: - postcss "^5.0.12" - postcss-value-parser "^3.3.0" - -postcss-minify-params@^1.0.4: - version "1.2.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" - dependencies: - alphanum-sort "^1.0.1" - postcss "^5.0.2" - postcss-value-parser "^3.0.2" - uniqs "^2.0.0" - -postcss-minify-selectors@^2.0.4: - version "2.1.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" - dependencies: - alphanum-sort "^1.0.2" - has "^1.0.1" - postcss "^5.0.14" - postcss-selector-parser "^2.0.0" - -postcss-modules-extract-imports@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb" - dependencies: - postcss "^6.0.1" - -postcss-modules-local-by-default@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" - dependencies: - css-selector-tokenizer "^0.7.0" - postcss "^6.0.1" - -postcss-modules-scope@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" - dependencies: - css-selector-tokenizer "^0.7.0" - postcss "^6.0.1" - -postcss-modules-values@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" - dependencies: - icss-replace-symbols "^1.1.0" - postcss "^6.0.1" - -postcss-normalize-charset@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" - dependencies: - postcss "^5.0.5" - -postcss-normalize-url@^3.0.7: - version "3.0.8" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" - dependencies: - is-absolute-url "^2.0.0" - normalize-url "^1.4.0" - postcss "^5.0.14" - postcss-value-parser "^3.2.3" - -postcss-ordered-values@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" - dependencies: - postcss "^5.0.4" - postcss-value-parser "^3.0.1" - -postcss-reduce-idents@^2.2.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" - dependencies: - postcss "^5.0.4" - postcss-value-parser "^3.0.2" - -postcss-reduce-initial@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" - dependencies: - postcss "^5.0.4" - -postcss-reduce-transforms@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" - dependencies: - has "^1.0.1" - postcss "^5.0.8" - postcss-value-parser "^3.0.1" - -postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" - dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-svgo@^2.1.1: - version "2.1.6" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" - dependencies: - is-svg "^2.0.0" - postcss "^5.0.14" - postcss-value-parser "^3.2.3" - svgo "^0.7.0" - -postcss-unique-selectors@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" - dependencies: - alphanum-sort "^1.0.1" - postcss "^5.0.4" - uniqs "^2.0.0" - -postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" - -postcss-zindex@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" - dependencies: - has "^1.0.1" - postcss "^5.0.4" - uniqs "^2.0.0" - -postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16: - version "5.2.18" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" - dependencies: - chalk "^1.1.3" - js-base64 "^2.1.9" - source-map "^0.5.6" - supports-color "^3.2.3" - -postcss@^6.0.1: - version "6.0.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885" - dependencies: - chalk "^2.3.0" - source-map "^0.6.1" - supports-color "^4.4.0" - prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" -prepend-http@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" @@ -5297,10 +4768,6 @@ q@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" -q@^1.1.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - qs@6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49" @@ -5317,13 +4784,6 @@ qs@~6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" -query-string@^4.1.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" - dependencies: - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -5482,20 +4942,6 @@ redbox-react@^1.3.6: prop-types "^15.5.4" sourcemapped-stacktrace "^1.1.6" -reduce-css-calc@^1.2.6: - version "1.3.0" - resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" - dependencies: - balanced-match "^0.4.2" - math-expression-evaluator "^1.2.14" - reduce-function-call "^1.0.1" - -reduce-function-call@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99" - dependencies: - balanced-match "^0.4.2" - regenerate@^1.2.1: version "1.3.3" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" @@ -5518,14 +4964,6 @@ regex-cache@^0.4.2: dependencies: is-equal-shallow "^0.1.3" -regexpu-core@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" @@ -5762,7 +5200,7 @@ sane@^2.0.0: optionalDependencies: fsevents "^1.1.1" -sax@^1.2.1, sax@~1.2.1: +sax@^1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -5898,12 +5336,6 @@ sntp@2.x.x: dependencies: hoek "4.x.x" -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - dependencies: - is-plain-obj "^1.0.0" - source-list-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" @@ -6031,12 +5463,6 @@ standard@9.0.2: eslint-plugin-standard "~2.0.1" standard-engine "~5.4.0" -stats-webpack-plugin@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/stats-webpack-plugin/-/stats-webpack-plugin-0.6.1.tgz#5db260514387bc3d4ba6fb85fc4990bd4a71c415" - dependencies: - lodash "^4.17.4" - "statuses@>= 1.2.1 < 2", "statuses@>= 1.3.1 < 2", statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" @@ -6073,10 +5499,6 @@ stream-to-observable@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - string-hash@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" @@ -6165,13 +5587,6 @@ strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -style-loader@0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.19.1.tgz#591ffc80bcefe268b77c5d9ebc0505d772619f85" - dependencies: - loader-utils "^1.0.2" - schema-utils "^0.3.0" - styled-jsx@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-2.2.1.tgz#8b38b9e53e5d9767e392595ab1afdc8426b3ba5d" @@ -6196,30 +5611,18 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^3.1.2, supports-color@^3.2.3: +supports-color@^3.1.2: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" dependencies: has-flag "^1.0.0" -supports-color@^4.0.0, supports-color@^4.2.1, supports-color@^4.4.0: +supports-color@^4.0.0, supports-color@^4.2.1: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" dependencies: has-flag "^2.0.0" -svgo@^0.7.0: - version "0.7.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" - dependencies: - coa "~1.0.1" - colors "~1.1.2" - csso "~2.3.1" - js-yaml "~3.7.0" - mkdirp "~0.5.1" - sax "~1.2.1" - whet.extend "~0.9.9" - symbol-observable@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" @@ -6484,16 +5887,6 @@ uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" -uniqid@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/uniqid/-/uniqid-4.1.1.tgz#89220ddf6b751ae52b5f72484863528596bb84c1" - dependencies: - macaddress "^0.2.8" - -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - unique-filename@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3" @@ -6556,10 +5949,6 @@ vary@~1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" -vendors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22" - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -6700,10 +6089,6 @@ whatwg-url@^4.3.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -whet.extend@~0.9.9: - version "0.9.9" - resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" - which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" From 1f023a87e0ecdb72a1a773d71a07ffb3f964427f Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 17 Jan 2018 11:53:41 +0100 Subject: [PATCH 067/132] Move base.config.js to webpack.js --- server/build/index.js | 6 +- server/build/webpack.js | 613 ++++++++++++---------------- server/build/webpack/base.config.js | 330 --------------- server/hot-reloader.js | 10 +- 4 files changed, 264 insertions(+), 695 deletions(-) delete mode 100644 server/build/webpack/base.config.js diff --git a/server/build/index.js b/server/build/index.js index ea72a168a801c..0254008db3987 100644 --- a/server/build/index.js +++ b/server/build/index.js @@ -5,7 +5,7 @@ import uuid from 'uuid' // import del from 'del' import webpack from 'webpack' import getConfig from '../config' -import baseConfig from './webpack/base.config.js' +import getBaseWebpackConfig from './webpack' // import replaceCurrentBuild from './replace' import md5File from 'md5-file/promise' @@ -23,8 +23,8 @@ export default async function build (dir, conf = null) { try { const configs = await Promise.all([ - baseConfig(dir, { buildId, isServer: false, config }), - baseConfig(dir, { buildId, isServer: true, config }) + getBaseWebpackConfig(dir, { buildId, isServer: false, config }), + getBaseWebpackConfig(dir, { buildId, isServer: true, config }) ]) await runCompiler(configs) diff --git a/server/build/webpack.js b/server/build/webpack.js index 39965b16d1b36..d2287b1c94d25 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -1,228 +1,37 @@ -import { resolve, join, sep } from 'path' -import { createHash } from 'crypto' -import { realpathSync, existsSync } from 'fs' +import path, {sep} from 'path' +import fs from 'fs' import webpack from 'webpack' -import glob from 'glob-promise' + +import nodeExternals from 'webpack-node-externals' +import UglifyJSPlugin from 'uglifyjs-webpack-plugin' +import CaseSensitivePathPlugin from 'case-sensitive-paths-webpack-plugin' import WriteFilePlugin from 'write-file-webpack-plugin' import FriendlyErrorsWebpackPlugin from 'friendly-errors-webpack-plugin' -import CaseSensitivePathPlugin from 'case-sensitive-paths-webpack-plugin' -import UglifyJSPlugin from 'uglifyjs-webpack-plugin' -import UnlinkFilePlugin from './plugins/unlink-file-plugin' +import ExtractTextPlugin from 'extract-text-webpack-plugin' +import {getPages} from './webpack/utils' +import CombineAssetsPlugin from './plugins/combine-assets-plugin' import PagesPlugin from './plugins/pages-plugin' import DynamicChunksPlugin from './plugins/dynamic-chunks-plugin' -import CombineAssetsPlugin from './plugins/combine-assets-plugin' -import getConfig from '../config' -import * as babelCore from 'babel-core' import findBabelConfig from './babel/find-config' -import rootModuleRelativePath from './root-module-relative-path' -const documentPage = join('pages', '_document.js') +const nextDir = path.join(__dirname, '..', '..', '..') +const nextNodeModulesDir = path.join(nextDir, 'node_modules') +const nextPagesDir = path.join(nextDir, 'pages') const defaultPages = [ '_error.js', '_document.js' ] -const nextPagesDir = join(__dirname, '..', '..', 'pages') -const nextNodeModulesDir = join(__dirname, '..', '..', '..', 'node_modules') const interpolateNames = new Map(defaultPages.map((p) => { - return [join(nextPagesDir, p), `dist/bundles/pages/${p}`] + return [path.join(nextPagesDir, p), `dist/bundles/pages/${p}`] })) -const relativeResolve = rootModuleRelativePath(require) - -async function getPages ({dir, dev, pagesGlobPattern}) { - let pages - - if (dev) { - pages = await glob('pages/+(_document|_error).+(js|jsx)', { cwd: dir }) - } else { - pages = await glob(pagesGlobPattern, { cwd: dir }) - } - - return pages -} - -function getPageEntries (pages) { - const entries = {} - for (const p of pages) { - entries[join('bundles', p.replace('.jsx', '.js'))] = [`./${p}?entry`] - } - - // The default pages (_document.js and _error.js) are only added when they're not provided by the user - for (const p of defaultPages) { - const entryName = join('bundles', 'pages', p) - if (!entries[entryName]) { - entries[entryName] = [join(nextPagesDir, p) + '?entry'] - } - } - - return entries -} - -export default async function createCompiler (dir, { buildId, dev = false, quiet = false, buildDir, conf = null } = {}) { - // Resolve relative path to absolute path - dir = realpathSync(resolve(dir)) - - // Used to track the amount of pages for webpack commons chunk plugin - let totalPages - - // Loads next.config.js and custom configuration provided in custom server initialization - const config = getConfig(dir, conf) - - // Middlewares to handle on-demand entries and hot updates in development - const devEntries = dev ? [ - join(__dirname, '..', '..', 'client', 'webpack-hot-middleware-client'), - join(__dirname, '..', '..', 'client', 'on-demand-entries-client') - ] : [] - - const mainJS = require.resolve(`../../client/next${dev ? '-dev' : ''}`) // Uses client/next-dev in development for code splitting dev dependencies - - const entry = async () => { - // Get entries for pages in production mode. In development only _document and _error are added. Because pages are added by on-demand-entry-handler. - const pages = await getPages({dir, dev, pagesGlobPattern: config.pagesGlobPattern}) - const pageEntries = getPageEntries(pages) - - // Used for commons chunk calculations - totalPages = pages.length - if (pages.indexOf(documentPage) !== -1) { - totalPages = totalPages - 1 - } - - const entries = { - 'main.js': [ - ...devEntries, // Adds hot middleware and ondemand entries in development - ...config.clientBootstrap || [], // clientBootstrap can be used to load polyfills before code execution - mainJS // Main entrypoint in the client folder - ], - ...pageEntries - } - - return entries - } - - const plugins = [ - // Defines NODE_ENV as development/production. This is used by some npm modules to determine if they should optimize. - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production') - }), - new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive - new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), - // Provide legacy options to webpack - new webpack.LoaderOptionsPlugin({ - options: { - context: dir, - customInterpolateName (url, name, opts) { - return interpolateNames.get(this.resourcePath) || url - } - } - }), - // Writes all generated files to disk, even in development. For SSR. - new WriteFilePlugin({ - exitOnErrors: false, - log: false, - // required not to cache removed files - useHashIndex: false - }), - // Moves common modules into commons.js - new webpack.optimize.CommonsChunkPlugin({ - name: 'commons', - filename: 'commons.js', - minChunks (module, count) { - // We need to move react-dom explicitly into common chunks. - // Otherwise, if some other page or module uses it, it might - // included in that bundle too. - if (dev && module.context && module.context.indexOf(`${sep}react${sep}`) >= 0) { - return true - } - - if (dev && module.context && module.context.indexOf(`${sep}react-dom${sep}`) >= 0) { - return true - } - - // In the dev we use on-demand-entries. - // So, it makes no sense to use commonChunks based on the minChunks count. - // Instead, we move all the code in node_modules into each of the pages. - if (dev) { - return false - } - - // If there are one or two pages, only move modules to common if they are - // used in all of the pages. Otherwise, move modules used in at-least - // 1/2 of the total pages into commons. - if (totalPages <= 2) { - return count >= totalPages - } - return count >= totalPages * 0.5 - } - }), - // This chunk splits out react and react-dom in production to make sure it does not go through uglify. This saved multiple seconds on production builds. - // See https://twitter.com/dan_abramov/status/944040306420408325 - new webpack.optimize.CommonsChunkPlugin({ - name: 'react', - filename: 'react.js', - minChunks (module, count) { - if (dev) { - return false - } - - if (module.resource && module.resource.includes(`${sep}react-dom${sep}`) && count >= 0) { - return true - } - - if (module.resource && module.resource.includes(`${sep}react${sep}`) && count >= 0) { - return true - } - - return false - } - }), - // This adds Next.js route definitions to page bundles - new PagesPlugin(), - // Implements support for dynamic imports - new DynamicChunksPlugin() - ] - - if (dev) { - plugins.push( - new webpack.HotModuleReplacementPlugin(), - new webpack.NoEmitOnErrorsPlugin(), - new UnlinkFilePlugin() - ) - if (!quiet) { - plugins.push(new FriendlyErrorsWebpackPlugin()) - } - } else { - plugins.push(new webpack.IgnorePlugin(/react-hot-loader/)) - plugins.push( - // Minifies javascript bundles - new UglifyJSPlugin({ - exclude: /react\.js/, - parallel: true, - sourceMap: false, - uglifyOptions: { - compress: { - comparisons: false - } - } - }) - ) - plugins.push( - // Combines manifest.js commons.js and main.js into app.js in production - new CombineAssetsPlugin({ - input: ['manifest.js', 'react.js', 'commons.js', 'main.js'], - output: 'app.js' - }), - ) - // Implements scope hoisting which speeds up browser execution of javascript - plugins.push(new webpack.optimize.ModuleConcatenationPlugin()) - } - - const nodePathList = (process.env.NODE_PATH || '') - .split(process.platform === 'win32' ? ';' : ':') - .filter((p) => !!p) - +function babelConfig (dir, isServer) { const mainBabelOptions = { - cacheDirectory: true, - presets: [] + cacheDirectory: Boolean(process.env.BABEL_DISABLE_CACHE), + presets: [], + plugins: [ + !isServer && require.resolve('react-hot-loader/babel') + ].filter(Boolean) } const externalBabelConfig = findBabelConfig(dir) @@ -243,189 +52,279 @@ export default async function createCompiler (dir, { buildId, dev = false, quiet mainBabelOptions.presets.push(require.resolve('./babel/preset')) } - const devLoaders = dev ? [{ - test: /\.(js|jsx)(\?[^?]*)?$/, - loader: 'hot-self-accept-loader', - include: [ - join(dir, 'pages'), - nextPagesDir - ] - }, { - test: /\.(js|jsx)(\?[^?]*)?$/, - loader: 'react-hot-loader/webpack', - exclude: /node_modules/ - }] : [] - - const loaders = [{ - test: /\.json$/, - loader: 'json-loader' - }, { - test: /\.(js|jsx|json)(\?[^?]*)?$/, - loader: 'emit-file-loader', - include: [dir, nextPagesDir], - exclude (str) { - return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 - }, - options: { - name: 'dist/bundles/[path][name].[ext]', - // We need to strip off .jsx on the server. Otherwise require without .jsx doesn't work. - interpolateName: (name) => name.replace('.jsx', '.js'), - validateFileName (file) { - const cases = [{from: '.js', to: '.jsx'}, {from: '.jsx', to: '.js'}] - - for (const item of cases) { - const {from, to} = item - if (file.slice(-(from.length)) !== from) { - continue - } + return mainBabelOptions +} - const filePath = file.slice(0, -(from.length)) + to +function externalsConfig (dir, isServer) { + const externals = [] - if (existsSync(filePath)) { - throw new Error(`Both ${from} and ${to} file found. Please make sure you only have one of both.`) - } - } - }, - // By default, our babel config does not transpile ES2015 module syntax because - // webpack knows how to handle them. (That's how it can do tree-shaking) - // But Node.js doesn't know how to handle them. So, we have to transpile them here. - transform ({ content, sourceMap, interpolatedName }) { - // Only handle .js files - if (!(/\.(js|jsx)$/.test(interpolatedName))) { - return { content, sourceMap } - } + if (!isServer) { + return externals + } - const babelRuntimePath = require.resolve('babel-runtime/package').replace(/[\\/]package\.json$/, '') - const transpiled = babelCore.transform(content, { - babelrc: false, - sourceMaps: dev ? 'both' : false, - // Here we need to resolve all modules to the absolute paths. - // Earlier we did it with the babel-preset. - // But since we don't transpile ES2015 in the preset this is not resolving. - // That's why we need to do it here. - // See more: https://github.com/zeit/next.js/issues/951 - plugins: [ - require.resolve(join(__dirname, './babel/plugins/remove-dotjsx-from-import.js')), - [require.resolve('babel-plugin-transform-es2015-modules-commonjs')], - [ - require.resolve('babel-plugin-module-resolver'), - { - alias: { - 'babel-runtime': babelRuntimePath, - 'next/link': relativeResolve('../../lib/link'), - 'next/prefetch': relativeResolve('../../lib/prefetch'), - 'next/css': relativeResolve('../../lib/css'), - 'next/dynamic': relativeResolve('../../lib/dynamic'), - 'next/head': relativeResolve('../../lib/head'), - 'next/document': relativeResolve('../../server/document'), - 'next/router': relativeResolve('../../lib/router'), - 'next/error': relativeResolve('../../lib/error'), - 'styled-jsx/style': relativeResolve('styled-jsx/style') - } - } - ] - ], - inputSourceMap: sourceMap - }) + if (fs.existsSync(nextNodeModulesDir)) { + externals.push(nodeExternals({ + modulesDir: nextNodeModulesDir, + includeAbsolutePaths: true, + whitelist: [/\.(?!(?:js|json)$).{1,5}$/i] + })) + } - // Strip ?entry to map back to filesystem and work with iTerm, etc. - let { map } = transpiled - let output = transpiled.code + const dirNodeModules = path.join(dir, 'node_modules') + if (fs.existsSync(dirNodeModules)) { + nodeExternals({ + modulesDir: dirNodeModules, + includeAbsolutePaths: true, + whitelist: [/\.(?!(?:js|json)$).{1,5}$/i] + }) + } - if (map) { - let nodeMap = Object.assign({}, map) - nodeMap.sources = nodeMap.sources.map((source) => source.replace(/\?entry/, '')) - delete nodeMap.sourcesContent + return externals +} - // Output explicit inline source map that source-map-support can pickup via requireHook mode. - // Since these are not formal chunks, the devtool infrastructure in webpack does not output - // a source map for these files. - const sourceMapUrl = new Buffer(JSON.stringify(nodeMap), 'utf-8').toString('base64') - output = `${output}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${sourceMapUrl}` - } +export default async function getBaseWebpackConfig (dir, {dev = false, isServer = false, buildId, config}) { + const extractCSS = new ExtractTextPlugin({ + filename: 'static/style.css', + disable: dev + }) - return { - content: output, - sourceMap: transpiled.map - } - } + const cssLoader = { + loader: isServer ? 'css-loader/locals' : 'css-loader', + options: { + modules: false, + minimize: !dev, + sourceMap: dev, + importLoaders: 1, + ...(config.cssLoader || {}) } - }, { - loader: 'babel-loader', - include: nextPagesDir, - exclude (str) { - return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0 - }, + } + + const postcssLoader = { + loader: 'postcss-loader', options: { - babelrc: false, - cacheDirectory: true, - presets: [require.resolve('./babel/preset')] + plugins: () => {} } - }, { - test: /\.(js|jsx)(\?[^?]*)?$/, - loader: 'babel-loader', - include: [dir], - exclude (str) { - return /node_modules/.test(str) + } + + function cssLoaderConfig (loader = false) { + return [ + isServer && !cssLoader.options.modules && 'ignore-loader', + isServer && cssLoader.options.modules && cssLoader, + isServer && cssLoader.options.modules && postcssLoader, + isServer && cssLoader.options.modules && loader, + ...(!isServer ? extractCSS.extract({ + use: [cssLoader, postcssLoader, loader].filter(Boolean), + // Use style-loader in development + fallback: { + loader: 'style-loader', + options: { + sourceMap: true, + importLoaders: 1 + } + } + }) : []) + ].filter(Boolean) + } + + const babelLoaderOptions = babelConfig(dir, isServer) + + const defaultLoaders = { + babel: { + loader: 'babel-loader', + options: babelLoaderOptions }, - options: mainBabelOptions - }] + css: cssLoaderConfig(), + scss: cssLoaderConfig('sass-loader'), + less: cssLoaderConfig('less-loader') + } + + let totalPages let webpackConfig = { + devtool: dev ? 'cheap-module-source-map' : false, + name: isServer ? 'server' : 'client', + cache: true, + target: isServer ? 'node' : 'web', + externals: externalsConfig(dir, isServer), context: dir, - entry, + entry: async () => { + const pages = await getPages(dir, {dev, isServer}) + totalPages = Object.keys(pages).length + const mainJS = require.resolve(`../../client/next${dev ? '-dev' : ''}`) + const clientConfig = !isServer ? { + 'main.js': [ + dev && !isServer && path.join(__dirname, '..', '..', 'client', 'webpack-hot-middleware-client'), + dev && !isServer && path.join(__dirname, '..', '..', 'client', 'on-demand-entries-client'), + mainJS + ].filter(Boolean) + } : {} + return { + ...clientConfig, + ...pages + } + }, output: { - path: buildDir ? join(buildDir, '.next') : join(dir, config.distDir), + path: path.join(dir, '.next', isServer ? 'dist' : ''), // server compilation goes to `.next/dist` filename: '[name]', libraryTarget: 'commonjs2', publicPath: `/_next/webpack/`, - strictModuleExceptionHandling: true, - devtoolModuleFilenameTemplate ({ resourcePath }) { - const hash = createHash('sha1') - hash.update(Date.now() + '') - const id = hash.digest('hex').slice(0, 7) - - // append hash id for cache busting - return `webpack:///${resourcePath}?${id}` - }, // This saves chunks with the name given via require.ensure() - chunkFilename: '[name]-[chunkhash].js' + chunkFilename: '[name]-[chunkhash].js', + sourceMapFilename: '[file].map?[contenthash]' }, + performance: { hints: false }, resolve: { - alias: { - // This bypasses React's check for production mode. Since we know it is in production this way. - // This allows us to exclude React from being uglified. Saving multiple seconds per build. - 'react-dom': dev ? 'react-dom/cjs/react-dom.development.js' : 'react-dom/cjs/react-dom.production.min.js' - }, extensions: ['.js', '.jsx', '.json'], modules: [ nextNodeModulesDir, - 'node_modules', - ...nodePathList - ] + 'node_modules' + ], + alias: { + 'next': nextDir, + 'react-dom': dev ? 'react-dom/cjs/react-dom.development.js' : 'react-dom/cjs/react-dom.production.min.js' + } }, resolveLoader: { modules: [ nextNodeModulesDir, 'node_modules', - join(__dirname, 'loaders'), - ...nodePathList + path.join(__dirname, 'loaders') ] }, - plugins, module: { rules: [ - ...devLoaders, - ...loaders - ] + dev && !isServer && { + test: /\.(js|jsx)(\?[^?]*)?$/, + loader: 'hot-self-accept-loader', + include: [ + path.join(dir, 'pages'), + nextPagesDir + ] + }, + { + test: /\.+(js|jsx)$/, + include: [dir], + exclude: /node_modules/, + use: defaultLoaders.babel + }, + { + test: /\.css$/, + use: defaultLoaders.css + }, + { + test: /\.scss$/, + use: defaultLoaders.scss + }, + { + test: /\.less$/, + use: defaultLoaders.less + } + ].filter(Boolean) }, - devtool: dev ? 'cheap-module-inline-source-map' : false, - performance: { hints: false } + plugins: [ + new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), + dev && new webpack.NoEmitOnErrorsPlugin(), + dev && !isServer && new FriendlyErrorsWebpackPlugin(), + dev && new webpack.NamedModulesPlugin(), + dev && new webpack.HotModuleReplacementPlugin(), // Hot module replacement + dev && new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive + dev && new webpack.LoaderOptionsPlugin({ + options: { + context: dir, + customInterpolateName (url, name, opts) { + return interpolateNames.get(this.resourcePath) || url + } + } + }), + dev && new WriteFilePlugin({ + exitOnErrors: false, + log: false, + // required not to cache removed files + useHashIndex: false + }), + !dev && new webpack.IgnorePlugin(/react-hot-loader/), + !isServer && !dev && new UglifyJSPlugin({ + exclude: /react\.js/, + parallel: true, + sourceMap: false, + uglifyOptions: { + compress: { + comparisons: false + } + } + }), + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production') + }), + !isServer && new CombineAssetsPlugin({ + input: ['manifest.js', 'react.js', 'commons.js', 'main.js'], + output: 'app.js' + }), + !dev && new webpack.optimize.ModuleConcatenationPlugin(), + !isServer && extractCSS, + !isServer && new PagesPlugin(), + !isServer && new DynamicChunksPlugin(), + !isServer && new webpack.optimize.CommonsChunkPlugin({ + name: `commons`, + filename: `commons.js`, + minChunks (module, count) { + // We need to move react-dom explicitly into common chunks. + // Otherwise, if some other page or module uses it, it might + // included in that bundle too. + if (dev && module.context && module.context.indexOf(`${sep}react${sep}`) >= 0) { + return true + } + + if (dev && module.context && module.context.indexOf(`${sep}react-dom${sep}`) >= 0) { + return true + } + + // In the dev we use on-demand-entries. + // So, it makes no sense to use commonChunks based on the minChunks count. + // Instead, we move all the code in node_modules into each of the pages. + if (dev) { + return false + } + + // If there are one or two pages, only move modules to common if they are + // used in all of the pages. Otherwise, move modules used in at-least + // 1/2 of the total pages into commons. + if (totalPages <= 2) { + return count >= totalPages + } + return count >= totalPages * 0.5 + } + }), + !isServer && new webpack.optimize.CommonsChunkPlugin({ + name: 'react', + filename: 'react.js', + minChunks (module, count) { + if (dev) { + return false + } + + if (module.resource && module.resource.includes(`${sep}react-dom${sep}`) && count >= 0) { + return true + } + + if (module.resource && module.resource.includes(`${sep}react${sep}`) && count >= 0) { + return true + } + + return false + } + }), + !isServer && new webpack.optimize.CommonsChunkPlugin({ + name: 'manifest', + filename: 'manifest.js' + }) + + ].filter(Boolean) } - if (config.webpack) { - console.log(`> Using "webpack" config function defined in ${config.configOrigin}.`) - webpackConfig = await config.webpack(webpackConfig, { buildId, dev }) + if (typeof config.webpack === 'function') { + webpackConfig = config.webpack(webpackConfig, {dir, dev, isServer, buildId, config, defaultLoaders}) } + return webpackConfig } diff --git a/server/build/webpack/base.config.js b/server/build/webpack/base.config.js deleted file mode 100644 index 1764153fef11b..0000000000000 --- a/server/build/webpack/base.config.js +++ /dev/null @@ -1,330 +0,0 @@ -import path, {sep} from 'path' -import fs from 'fs' -import webpack from 'webpack' - -import nodeExternals from 'webpack-node-externals' -import UglifyJSPlugin from 'uglifyjs-webpack-plugin' -import CaseSensitivePathPlugin from 'case-sensitive-paths-webpack-plugin' -import WriteFilePlugin from 'write-file-webpack-plugin' -import FriendlyErrorsWebpackPlugin from 'friendly-errors-webpack-plugin' -import ExtractTextPlugin from 'extract-text-webpack-plugin' -import {getPages} from './utils' -import CombineAssetsPlugin from '../plugins/combine-assets-plugin' -import PagesPlugin from '../plugins/pages-plugin' -import DynamicChunksPlugin from '../plugins/dynamic-chunks-plugin' -import findBabelConfig from '../babel/find-config' - -const nextDir = path.join(__dirname, '..', '..', '..', '..') -const nextNodeModulesDir = path.join(nextDir, 'node_modules') -const nextPagesDir = path.join(nextDir, 'pages') -const defaultPages = [ - '_error.js', - '_document.js' -] -const interpolateNames = new Map(defaultPages.map((p) => { - return [path.join(nextPagesDir, p), `dist/bundles/pages/${p}`] -})) - -function babelConfig (dir, isServer) { - const mainBabelOptions = { - cacheDirectory: Boolean(process.env.BABEL_DISABLE_CACHE), - presets: [], - plugins: [ - !isServer && require.resolve('react-hot-loader/babel') - ].filter(Boolean) - } - - const externalBabelConfig = findBabelConfig(dir) - if (externalBabelConfig) { - console.log(`> Using external babel configuration`) - console.log(`> Location: "${externalBabelConfig.loc}"`) - // It's possible to turn off babelrc support via babelrc itself. - // In that case, we should add our default preset. - // That's why we need to do this. - const { options } = externalBabelConfig - mainBabelOptions.babelrc = options.babelrc !== false - } else { - mainBabelOptions.babelrc = false - } - - // Add our default preset if the no "babelrc" found. - if (!mainBabelOptions.babelrc) { - mainBabelOptions.presets.push(require.resolve('../babel/preset')) - } - - return mainBabelOptions -} - -function externalsConfig (dir, isServer) { - const externals = [] - - if (!isServer) { - return externals - } - - if (fs.existsSync(nextNodeModulesDir)) { - externals.push(nodeExternals({ - modulesDir: nextNodeModulesDir, - includeAbsolutePaths: true, - whitelist: [/\.(?!(?:js|json)$).{1,5}$/i] - })) - } - - const dirNodeModules = path.join(dir, 'node_modules') - if (fs.existsSync(dirNodeModules)) { - nodeExternals({ - modulesDir: dirNodeModules, - includeAbsolutePaths: true, - whitelist: [/\.(?!(?:js|json)$).{1,5}$/i] - }) - } - - return externals -} - -export default async function baseConfig (dir, {dev = false, isServer = false, buildId, config}) { - const extractCSS = new ExtractTextPlugin({ - filename: 'static/style.css', - disable: dev - }) - - const cssLoader = { - loader: isServer ? 'css-loader/locals' : 'css-loader', - options: { - modules: false, - minimize: !dev, - sourceMap: dev, - importLoaders: 1, - ...(config.cssLoader || {}) - } - } - - const postcssLoader = { - loader: 'postcss-loader', - options: { - plugins: () => {} - } - } - - function cssLoaderConfig (loader = false) { - return [ - isServer && !cssLoader.options.modules && 'ignore-loader', - isServer && cssLoader.options.modules && cssLoader, - isServer && cssLoader.options.modules && postcssLoader, - isServer && cssLoader.options.modules && loader, - ...(!isServer ? extractCSS.extract({ - use: [cssLoader, postcssLoader, loader].filter(Boolean), - // Use style-loader in development - fallback: { - loader: 'style-loader', - options: { - sourceMap: true, - importLoaders: 1 - } - } - }) : []) - ].filter(Boolean) - } - - const babelLoaderOptions = babelConfig(dir, isServer) - - const defaultLoaders = { - babel: { - loader: 'babel-loader', - options: babelLoaderOptions - }, - css: cssLoaderConfig(), - scss: cssLoaderConfig('sass-loader'), - less: cssLoaderConfig('less-loader') - } - - let totalPages - - let webpackConfig = { - devtool: dev ? 'cheap-module-source-map' : false, - name: isServer ? 'server' : 'client', - cache: true, - target: isServer ? 'node' : 'web', - externals: externalsConfig(dir, isServer), - context: dir, - entry: async () => { - const pages = await getPages(dir, {dev, isServer}) - totalPages = Object.keys(pages).length - const mainJS = require.resolve(`../../../client/next${dev ? '-dev' : ''}`) - const clientConfig = !isServer ? { - 'main.js': [ - dev && !isServer && path.join(__dirname, '..', '..', '..', 'client', 'webpack-hot-middleware-client'), - dev && !isServer && path.join(__dirname, '..', '..', '..', 'client', 'on-demand-entries-client'), - mainJS - ].filter(Boolean) - } : {} - return { - ...clientConfig, - ...pages - } - }, - output: { - path: path.join(dir, '.next', isServer ? 'dist' : ''), // server compilation goes to `.next/dist` - filename: '[name]', - libraryTarget: 'commonjs2', - publicPath: `/_next/webpack/`, - // This saves chunks with the name given via require.ensure() - chunkFilename: '[name]-[chunkhash].js', - sourceMapFilename: '[file].map?[contenthash]' - }, - performance: { hints: false }, - resolve: { - extensions: ['.js', '.jsx', '.json'], - modules: [ - nextNodeModulesDir, - 'node_modules' - ], - alias: { - 'next': nextDir, - 'react-dom': dev ? 'react-dom/cjs/react-dom.development.js' : 'react-dom/cjs/react-dom.production.min.js' - } - }, - resolveLoader: { - modules: [ - nextNodeModulesDir, - 'node_modules', - path.join(__dirname, '..', 'loaders') - ] - }, - module: { - rules: [ - dev && !isServer && { - test: /\.(js|jsx)(\?[^?]*)?$/, - loader: 'hot-self-accept-loader', - include: [ - path.join(dir, 'pages'), - nextPagesDir - ] - }, - { - test: /\.+(js|jsx)$/, - include: [dir], - exclude: /node_modules/, - use: defaultLoaders.babel - }, - { - test: /\.css$/, - use: defaultLoaders.css - }, - { - test: /\.scss$/, - use: defaultLoaders.scss - }, - { - test: /\.less$/, - use: defaultLoaders.less - } - ].filter(Boolean) - }, - plugins: [ - new webpack.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), - dev && new webpack.NoEmitOnErrorsPlugin(), - dev && !isServer && new FriendlyErrorsWebpackPlugin(), - dev && new webpack.NamedModulesPlugin(), - dev && new webpack.HotModuleReplacementPlugin(), // Hot module replacement - dev && new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive - dev && new webpack.LoaderOptionsPlugin({ - options: { - context: dir, - customInterpolateName (url, name, opts) { - return interpolateNames.get(this.resourcePath) || url - } - } - }), - dev && new WriteFilePlugin({ - exitOnErrors: false, - log: false, - // required not to cache removed files - useHashIndex: false - }), - !dev && new webpack.IgnorePlugin(/react-hot-loader/), - !isServer && !dev && new UglifyJSPlugin({ - exclude: /react\.js/, - parallel: true, - sourceMap: false, - uglifyOptions: { - compress: { - comparisons: false - } - } - }), - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production') - }), - !isServer && new CombineAssetsPlugin({ - input: ['manifest.js', 'react.js', 'commons.js', 'main.js'], - output: 'app.js' - }), - !dev && new webpack.optimize.ModuleConcatenationPlugin(), - !isServer && extractCSS, - !isServer && new PagesPlugin(), - !isServer && new DynamicChunksPlugin(), - !isServer && new webpack.optimize.CommonsChunkPlugin({ - name: `commons`, - filename: `commons.js`, - minChunks (module, count) { - // We need to move react-dom explicitly into common chunks. - // Otherwise, if some other page or module uses it, it might - // included in that bundle too. - if (dev && module.context && module.context.indexOf(`${sep}react${sep}`) >= 0) { - return true - } - - if (dev && module.context && module.context.indexOf(`${sep}react-dom${sep}`) >= 0) { - return true - } - - // In the dev we use on-demand-entries. - // So, it makes no sense to use commonChunks based on the minChunks count. - // Instead, we move all the code in node_modules into each of the pages. - if (dev) { - return false - } - - // If there are one or two pages, only move modules to common if they are - // used in all of the pages. Otherwise, move modules used in at-least - // 1/2 of the total pages into commons. - if (totalPages <= 2) { - return count >= totalPages - } - return count >= totalPages * 0.5 - } - }), - !isServer && new webpack.optimize.CommonsChunkPlugin({ - name: 'react', - filename: 'react.js', - minChunks (module, count) { - if (dev) { - return false - } - - if (module.resource && module.resource.includes(`${sep}react-dom${sep}`) && count >= 0) { - return true - } - - if (module.resource && module.resource.includes(`${sep}react${sep}`) && count >= 0) { - return true - } - - return false - } - }), - !isServer && new webpack.optimize.CommonsChunkPlugin({ - name: 'manifest', - filename: 'manifest.js' - }) - - ].filter(Boolean) - } - - if (typeof config.webpack === 'function') { - webpackConfig = config.webpack(webpackConfig, {dir, dev, isServer, buildId, config, defaultLoaders}) - } - - return webpackConfig -} diff --git a/server/hot-reloader.js b/server/hot-reloader.js index 7aa55d4c2820a..d957f4a0ed17c 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -3,7 +3,7 @@ import WebpackDevMiddleware from 'webpack-dev-middleware' import WebpackHotMiddleware from 'webpack-hot-middleware' import onDemandEntryHandler from './on-demand-entry-handler' import webpack from 'webpack' -import baseConfig from './build/webpack/base.config' +import getBaseWebpackConfig from './build/webpack' import clean from './build/clean' import getConfig from './config' import UUID from 'uuid' @@ -49,8 +49,8 @@ export default class HotReloader { await clean(this.dir) const configs = await Promise.all([ - baseConfig(this.dir, { dev: true, isServer: false, config: this.config }), - baseConfig(this.dir, { dev: true, isServer: true, config: this.config }) + getBaseWebpackConfig(this.dir, { dev: true, isServer: false, config: this.config }), + getBaseWebpackConfig(this.dir, { dev: true, isServer: true, config: this.config }) ]) const compiler = webpack(configs) @@ -79,8 +79,8 @@ export default class HotReloader { await clean(this.dir) const configs = await Promise.all([ - baseConfig(this.dir, { dev: true, isServer: false, config: this.conf }), - baseConfig(this.dir, { dev: true, isServer: true, config: this.conf }) + getBaseWebpackConfig(this.dir, { dev: true, isServer: false, config: this.conf }), + getBaseWebpackConfig(this.dir, { dev: true, isServer: true, config: this.conf }) ]) const compiler = webpack(configs) From 435b60d9f6f53b53fc40feee16ba77898c2ac223 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Thu, 18 Jan 2018 00:52:37 +0530 Subject: [PATCH 068/132] Make sure to only invalidate webpackDevMiddleware one after other. --- server/hot-reloader.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/server/hot-reloader.js b/server/hot-reloader.js index d957f4a0ed17c..c0c0d4fdb0742 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -273,10 +273,13 @@ export default class HotReloader { } async ensurePage (page) { - await Promise.all([ - this.onDemandEntriesClient.ensurePage(page), - this.onDemandEntriesServer.ensurePage(page) - ]) + // We need to do this one after another. + // Otherwise it'll mess up with webpack hash. + // (due to concurrent devMiddleware.invalidate() calls) + // TODO: In the future, we need handle both client and server using + // a single onDemandEntryHandler instance. + await this.onDemandEntriesClient.ensurePage(page) + await this.onDemandEntriesServer.ensurePage(page) } } From 1a2ab91efc1cd69fff0a4ede2cb528aebddc373f Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Thu, 18 Jan 2018 11:45:41 +0530 Subject: [PATCH 069/132] Allow babel-loder caching by default. --- server/build/webpack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index d2287b1c94d25..36b0ce6b582e9 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -27,7 +27,7 @@ const interpolateNames = new Map(defaultPages.map((p) => { function babelConfig (dir, isServer) { const mainBabelOptions = { - cacheDirectory: Boolean(process.env.BABEL_DISABLE_CACHE), + cacheDirectory: true, presets: [], plugins: [ !isServer && require.resolve('react-hot-loader/babel') From 495e0a4c65f78d7b4bda4f5b7d58b09481e56146 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 17 Jan 2018 14:06:17 +0100 Subject: [PATCH 070/132] Add comment about preact support --- client/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/index.js b/client/index.js index b85b222c2169b..2ef4c29e2256c 100644 --- a/client/index.js +++ b/client/index.js @@ -159,6 +159,7 @@ async function doRender ({ Component, props, hash, err, emitter: emitterProp = e let isInitialRender = true function renderReactElement (reactEl, domEl) { + // The check for `.hydrate` is there to support React alternatives like preact if (isInitialRender && typeof ReactDOM.hydrate === 'function') { ReactDOM.hydrate(reactEl, domEl) isInitialRender = false From 2a3aa745878537c04d43e9224cc7b66ece391eb0 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 17 Jan 2018 14:06:34 +0100 Subject: [PATCH 071/132] Bring back buildir replace --- server/build/index.js | 16 +++++++--------- server/build/webpack.js | 4 ++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/server/build/index.js b/server/build/index.js index 0254008db3987..618e8db3c6b76 100644 --- a/server/build/index.js +++ b/server/build/index.js @@ -2,17 +2,18 @@ import { tmpdir } from 'os' import { join } from 'path' import fs from 'mz/fs' import uuid from 'uuid' -// import del from 'del' +import del from 'del' import webpack from 'webpack' import getConfig from '../config' import getBaseWebpackConfig from './webpack' -// import replaceCurrentBuild from './replace' +import replaceCurrentBuild from './replace' import md5File from 'md5-file/promise' export default async function build (dir, conf = null) { const config = getConfig(dir, conf) const buildId = uuid.v4() const tempDir = tmpdir() + const buildDir = join(tempDir, buildId) try { await fs.access(tempDir, fs.constants.W_OK) @@ -23,15 +24,12 @@ export default async function build (dir, conf = null) { try { const configs = await Promise.all([ - getBaseWebpackConfig(dir, { buildId, isServer: false, config }), - getBaseWebpackConfig(dir, { buildId, isServer: true, config }) + getBaseWebpackConfig(dir, { buildId, buildDir, isServer: false, config }), + getBaseWebpackConfig(dir, { buildId, buildDir, isServer: true, config }) ]) await runCompiler(configs) - // await fs.writeFile(join(dir, '.next', 'server-stats.json'), JSON.stringify(serverStats), 'utf8') - // await fs.writeFile(join(dir, '.next', 'client-stats.json'), JSON.stringify(stats), 'utf8') - await writeBuildStats(dir) await writeBuildId(dir, buildId) } catch (err) { @@ -39,10 +37,10 @@ export default async function build (dir, conf = null) { throw err } - // await replaceCurrentBuild(dir, buildDir) + await replaceCurrentBuild(dir, buildDir) // no need to wait - // del(buildDir, { force: true }) + del(buildDir, { force: true }) } function runCompiler (compiler) { diff --git a/server/build/webpack.js b/server/build/webpack.js index 36b0ce6b582e9..28e309d0b1119 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -82,7 +82,7 @@ function externalsConfig (dir, isServer) { return externals } -export default async function getBaseWebpackConfig (dir, {dev = false, isServer = false, buildId, config}) { +export default async function getBaseWebpackConfig (dir, {dev = false, isServer = false, buildId, buildDir, config}) { const extractCSS = new ExtractTextPlugin({ filename: 'static/style.css', disable: dev @@ -164,7 +164,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer } }, output: { - path: path.join(dir, '.next', isServer ? 'dist' : ''), // server compilation goes to `.next/dist` + path: path.join(buildDir || dir, '.next', isServer ? 'dist' : ''), // server compilation goes to `.next/dist` filename: '[name]', libraryTarget: 'commonjs2', publicPath: `/_next/webpack/`, From 8e96607e74ca4b495c20cc661bd9edb597b415b1 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 01:29:22 +0100 Subject: [PATCH 072/132] Remove obsolete plugin --- server/build/plugins/watch-pages-plugin.js | 27 ---------------------- 1 file changed, 27 deletions(-) delete mode 100644 server/build/plugins/watch-pages-plugin.js diff --git a/server/build/plugins/watch-pages-plugin.js b/server/build/plugins/watch-pages-plugin.js deleted file mode 100644 index c258c3293cfed..0000000000000 --- a/server/build/plugins/watch-pages-plugin.js +++ /dev/null @@ -1,27 +0,0 @@ -import { resolve, join } from 'path' - -export default class WatchPagesPlugin { - constructor (dir) { - this.dir = resolve(dir, 'pages') - } - - apply (compiler) { - compiler.plugin('compilation', (compilation) => { - compilation.plugin('optimize-assets', (assets, callback) => { - // transpile pages/_document.js and descendants, - // but don't need the bundle file - delete assets[join('bundles', 'pages', '_document.js')] - callback() - }) - }) - - compiler.plugin('emit', (compilation, callback) => { - // watch the pages directory - compilation.contextDependencies = [ - ...compilation.contextDependencies, - this.dir - ] - callback() - }) - } -} From 6473226f62475b0be27cf121fa755b4f414f4f4d Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 01:31:39 +0100 Subject: [PATCH 073/132] Remove build replace, speed up build --- server/build/index.js | 16 +++------------- server/build/replace.js | 23 ----------------------- server/build/webpack.js | 4 ++-- 3 files changed, 5 insertions(+), 38 deletions(-) delete mode 100644 server/build/replace.js diff --git a/server/build/index.js b/server/build/index.js index 618e8db3c6b76..d469d103fdd86 100644 --- a/server/build/index.js +++ b/server/build/index.js @@ -1,22 +1,17 @@ -import { tmpdir } from 'os' import { join } from 'path' import fs from 'mz/fs' import uuid from 'uuid' -import del from 'del' import webpack from 'webpack' import getConfig from '../config' import getBaseWebpackConfig from './webpack' -import replaceCurrentBuild from './replace' import md5File from 'md5-file/promise' export default async function build (dir, conf = null) { const config = getConfig(dir, conf) const buildId = uuid.v4() - const tempDir = tmpdir() - const buildDir = join(tempDir, buildId) try { - await fs.access(tempDir, fs.constants.W_OK) + await fs.access(dir, fs.constants.W_OK) } catch (err) { console.error(`> Failed, build directory is not writeable. https://err.sh/zeit/next.js/build-dir-not-writeable`) throw err @@ -24,8 +19,8 @@ export default async function build (dir, conf = null) { try { const configs = await Promise.all([ - getBaseWebpackConfig(dir, { buildId, buildDir, isServer: false, config }), - getBaseWebpackConfig(dir, { buildId, buildDir, isServer: true, config }) + getBaseWebpackConfig(dir, { buildId, isServer: false, config }), + getBaseWebpackConfig(dir, { buildId, isServer: true, config }) ]) await runCompiler(configs) @@ -36,11 +31,6 @@ export default async function build (dir, conf = null) { console.error(`> Failed to build`) throw err } - - await replaceCurrentBuild(dir, buildDir) - - // no need to wait - del(buildDir, { force: true }) } function runCompiler (compiler) { diff --git a/server/build/replace.js b/server/build/replace.js deleted file mode 100644 index 22ff9e4a18f09..0000000000000 --- a/server/build/replace.js +++ /dev/null @@ -1,23 +0,0 @@ -import mv from 'mv' -import { join } from 'path' -import getConfig from '../config' - -export default async function replaceCurrentBuild (dir, buildDir) { - const dist = getConfig(dir).distDir - const _dir = join(dir, dist) - const _buildDir = join(buildDir, '.next') - const oldDir = join(buildDir, '.next.old') - - try { - await move(_dir, oldDir) - } catch (err) { - if (err.code !== 'ENOENT') throw err - } - await move(_buildDir, _dir) - return oldDir -} - -function move (from, to) { - return new Promise((resolve, reject) => - mv(from, to, err => err ? reject(err) : resolve())) -} diff --git a/server/build/webpack.js b/server/build/webpack.js index 28e309d0b1119..36b0ce6b582e9 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -82,7 +82,7 @@ function externalsConfig (dir, isServer) { return externals } -export default async function getBaseWebpackConfig (dir, {dev = false, isServer = false, buildId, buildDir, config}) { +export default async function getBaseWebpackConfig (dir, {dev = false, isServer = false, buildId, config}) { const extractCSS = new ExtractTextPlugin({ filename: 'static/style.css', disable: dev @@ -164,7 +164,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer } }, output: { - path: path.join(buildDir || dir, '.next', isServer ? 'dist' : ''), // server compilation goes to `.next/dist` + path: path.join(dir, '.next', isServer ? 'dist' : ''), // server compilation goes to `.next/dist` filename: '[name]', libraryTarget: 'commonjs2', publicPath: `/_next/webpack/`, From 30af0bf68cd5ca5a7ee743d5137273bbbe303db9 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 01:32:42 +0100 Subject: [PATCH 074/132] Resolve page entries like pages/day/index.js to pages/day.js --- server/build/webpack/utils.js | 63 ++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/server/build/webpack/utils.js b/server/build/webpack/utils.js index ca02abb725c18..ba99d319ac6d9 100644 --- a/server/build/webpack/utils.js +++ b/server/build/webpack/utils.js @@ -4,12 +4,12 @@ import glob from 'glob-promise' const nextPagesDir = path.join(__dirname, '..', '..', '..', 'pages') export async function getPages (dir, {dev, isServer}) { - const pageFiles = await getPageFiles(dir, {dev, isServer}) + const pageFiles = await getPagePaths(dir, {dev, isServer}) - return getPageEntries(pageFiles, {isServer}) + return getPageEntries(pageFiles, {dir, isServer}) } -async function getPageFiles (dir, {dev, isServer}) { +async function getPagePaths (dir, {dev, isServer}) { let pages if (dev) { @@ -21,24 +21,55 @@ async function getPageFiles (dir, {dev, isServer}) { return pages } -export function getPageEntries (pageFiles, {isServer}) { +// Convert page path into single entry +export function entry ({isServer}) { + return function createEntry (filePath, name) { + const parsedPath = path.parse(filePath) + let entryName = name || filePath + + // This makes sure we compile `pages/blog/index.js` to `pages/blog.js`. + // Excludes `pages/index.js` from this rule since we do want `/` to route to `pages/index.js` + if (parsedPath.dir !== 'pages' && parsedPath.name === 'index') { + entryName = `${parsedPath.dir}.js` + } + + // Makes sure supported extensions are stripped off. The outputted file should always be `.js` + entryName = entryName.replace(/\.+(jsx|tsx|ts)/, '.js') + + const bundlesDir = isServer ? '' : 'bundles' + return { + name: path.join(bundlesDir, entryName), + file: parsedPath.root ? filePath : `./${filePath}` + } + } +} + +// Convert page paths into entries +export function getPageEntries (pagePaths, {dir, isServer}) { const entries = {} - const bundleLocation = 'bundles' - for (const p of pageFiles) { - entries[path.join(bundleLocation, p.replace(/\.+(jsx|tsx|ts)/, '.js'))] = [`./${p}`] + + const createEntry = entry({isServer}) + + for (const filePath of pagePaths) { + const entry = createEntry(filePath) + entries[entry.name] = entry.file } - // The default pages (_document.js and _error.js) are only added when they're not provided by the user - const defaultPages = [ - '_error.js', - isServer && '_document.js' - ].filter(Boolean) - for (const p of defaultPages) { - const entryName = path.join(bundleLocation, 'pages', p) - if (!entries[entryName]) { - entries[entryName] = path.join(nextPagesDir, p) + const errorPagePath = path.join(nextPagesDir, '_error.js') + const errorPageEntry = createEntry(errorPagePath, 'pages/_error.js') // default error.js + if (!entries[errorPageEntry.name]) { + entries[errorPageEntry.name] = errorPageEntry.file + } + + if (isServer) { + const documentPagePath = path.join(nextPagesDir, '_document.js') + const documentPageEntry = createEntry(documentPagePath, 'pages/_document.js') + if (!entries[documentPageEntry.name]) { + entries[documentPageEntry.name] = documentPageEntry.file } } + console.log(entries) + return entries } From d82c5666b12234261a99881bb6621a86221504ec Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 10:27:58 +0100 Subject: [PATCH 075/132] Add componentDidCatch back --- lib/app.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/app.js b/lib/app.js index 63e46b22c80b5..bae48f0b97679 100644 --- a/lib/app.js +++ b/lib/app.js @@ -22,6 +22,12 @@ export default class App extends Component { } } + componentDidCatch (error, info) { + error.stack = `${error.stack}\n\n${info.componentStack}` + window.next.renderError(error) + this.setState({ hasError: true }) + } + render () { if (this.state.hasError) return null From 94fdee52e38d1a733b55a3b280b925fe4a360d22 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 10:28:08 +0100 Subject: [PATCH 076/132] Compile to bundles --- server/build/webpack/utils.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/build/webpack/utils.js b/server/build/webpack/utils.js index ba99d319ac6d9..3c0083b0cac66 100644 --- a/server/build/webpack/utils.js +++ b/server/build/webpack/utils.js @@ -36,9 +36,8 @@ export function entry ({isServer}) { // Makes sure supported extensions are stripped off. The outputted file should always be `.js` entryName = entryName.replace(/\.+(jsx|tsx|ts)/, '.js') - const bundlesDir = isServer ? '' : 'bundles' return { - name: path.join(bundlesDir, entryName), + name: path.join('bundles', entryName), file: parsedPath.root ? filePath : `./${filePath}` } } From bd27a7e79b210f09548c96ad0af867877634077f Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 10:48:00 +0100 Subject: [PATCH 077/132] Use config.distDir everywhere --- server/build/index.js | 14 +++++++------- server/build/webpack.js | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/server/build/index.js b/server/build/index.js index d469d103fdd86..4b7577bd5803b 100644 --- a/server/build/index.js +++ b/server/build/index.js @@ -25,8 +25,8 @@ export default async function build (dir, conf = null) { await runCompiler(configs) - await writeBuildStats(dir) - await writeBuildId(dir, buildId) + await writeBuildStats(dir, config) + await writeBuildId(dir, buildId, config) } catch (err) { console.error(`> Failed to build`) throw err @@ -53,21 +53,21 @@ function runCompiler (compiler) { }) } -async function writeBuildStats (dir) { +async function writeBuildStats (dir, config) { // Here we can't use hashes in webpack chunks. // That's because the "app.js" is not tied to a chunk. // It's created by merging a few assets. (commons.js and main.js) // So, we need to generate the hash ourself. const assetHashMap = { 'app.js': { - hash: await md5File(join(dir, '.next', 'app.js')) + hash: await md5File(join(dir, config.distDir, 'app.js')) } } - const buildStatsPath = join(dir, '.next', 'build-stats.json') + const buildStatsPath = join(dir, config.distDir, 'build-stats.json') await fs.writeFile(buildStatsPath, JSON.stringify(assetHashMap), 'utf8') } -async function writeBuildId (dir, buildId) { - const buildIdPath = join(dir, '.next', 'BUILD_ID') +async function writeBuildId (dir, buildId, config) { + const buildIdPath = join(dir, config.distDir, 'BUILD_ID') await fs.writeFile(buildIdPath, buildId, 'utf8') } diff --git a/server/build/webpack.js b/server/build/webpack.js index 36b0ce6b582e9..f42ba7a1ae179 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -164,7 +164,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer } }, output: { - path: path.join(dir, '.next', isServer ? 'dist' : ''), // server compilation goes to `.next/dist` + path: path.join(dir, config.distDir, isServer ? 'dist' : ''), // server compilation goes to `.next/dist` filename: '[name]', libraryTarget: 'commonjs2', publicPath: `/_next/webpack/`, From deff65aec9f5683b035d06be24d8feec96f60c7d Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 10:48:50 +0100 Subject: [PATCH 078/132] Make sure the file is an array --- server/build/webpack/utils.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/build/webpack/utils.js b/server/build/webpack/utils.js index 3c0083b0cac66..9ab17b88113de 100644 --- a/server/build/webpack/utils.js +++ b/server/build/webpack/utils.js @@ -38,7 +38,7 @@ export function entry ({isServer}) { return { name: path.join('bundles', entryName), - file: parsedPath.root ? filePath : `./${filePath}` + files: [parsedPath.root ? filePath : `./${filePath}`] // The entry always has to be an array. } } } @@ -51,20 +51,20 @@ export function getPageEntries (pagePaths, {dir, isServer}) { for (const filePath of pagePaths) { const entry = createEntry(filePath) - entries[entry.name] = entry.file + entries[entry.name] = entry.files } const errorPagePath = path.join(nextPagesDir, '_error.js') const errorPageEntry = createEntry(errorPagePath, 'pages/_error.js') // default error.js if (!entries[errorPageEntry.name]) { - entries[errorPageEntry.name] = errorPageEntry.file + entries[errorPageEntry.name] = errorPageEntry.files } if (isServer) { const documentPagePath = path.join(nextPagesDir, '_document.js') const documentPageEntry = createEntry(documentPagePath, 'pages/_document.js') if (!entries[documentPageEntry.name]) { - entries[documentPageEntry.name] = documentPageEntry.file + entries[documentPageEntry.name] = documentPageEntry.files } } From ef06a046ea5a7a9c801906b07ef220cfddda2466 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 10:51:15 +0100 Subject: [PATCH 079/132] Remove console.log --- server/build/webpack/utils.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/build/webpack/utils.js b/server/build/webpack/utils.js index 9ab17b88113de..f45ed8f00e957 100644 --- a/server/build/webpack/utils.js +++ b/server/build/webpack/utils.js @@ -68,7 +68,5 @@ export function getPageEntries (pagePaths, {dir, isServer}) { } } - console.log(entries) - return entries } From de8d0fb1de618afeab2d2d7091c98fea446205f5 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 11:16:11 +0100 Subject: [PATCH 080/132] Apply optimization to uglifyjs --- server/build/webpack.js | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index f42ba7a1ae179..cc47346a98ad0 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -249,7 +249,34 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer sourceMap: false, uglifyOptions: { compress: { - comparisons: false + arrows: false, + booleans: false, + cascade: false, + collapse_vars: false, + comparisons: false, + computed_props: false, + hoist_funs: false, + hoist_props: false, + hoist_vars: false, + if_return: false, + inline: false, + join_vars: false, + keep_infinity: true, + loops: false, + negate_iife: false, + properties: false, + reduce_funcs: false, + reduce_vars: false, + sequences: false, + side_effects: false, + switches: false, + top_retain: false, + toplevel: false, + typeofs: false, + unused: false, + conditionals: false, + dead_code: true, + evaluate: false } } }), From c80228b9756b62c757aa6590f99b0c929ece97a7 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 14:57:51 +0100 Subject: [PATCH 081/132] Add comment pointing to source --- server/on-demand-entry-handler.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/on-demand-entry-handler.js b/server/on-demand-entry-handler.js index f3c7bf6de7625..9e2054e315f08 100644 --- a/server/on-demand-entry-handler.js +++ b/server/on-demand-entry-handler.js @@ -215,6 +215,7 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { } } +// Based on https://github.com/webpack/webpack/blob/master/lib/DynamicEntryPlugin.js#L29-L37 function addEntry (compilation, context, name, entry) { return new Promise((resolve, reject) => { const dep = DynamicEntryPlugin.createDependency(entry, name) From 49e28085f3315a47c043551ba2c203f703eb85b1 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 14:59:20 +0100 Subject: [PATCH 082/132] Create entries the same way in dev and production --- server/on-demand-entry-handler.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/on-demand-entry-handler.js b/server/on-demand-entry-handler.js index 9e2054e315f08..6dc90a669b4ea 100644 --- a/server/on-demand-entry-handler.js +++ b/server/on-demand-entry-handler.js @@ -2,8 +2,9 @@ import DynamicEntryPlugin from 'webpack/lib/DynamicEntryPlugin' import { EventEmitter } from 'events' import { join, relative } from 'path' import { parse } from 'url' -import resolvePath from './resolve' import touch from 'touch' +import resolvePath from './resolve' +import {createEntry} from './build/webpack/utils' import { MATCH_ROUTE_NAME, IS_BUNDLED_PAGE } from './utils' const ADDED = Symbol('added') @@ -129,9 +130,8 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { page = normalizePage(page) const pagePath = join(dir, 'pages', page) - const pathname = await resolvePath(pagePath) - const name = join('bundles', relative(dir, pathname.replace(/\.+(jsx|tsx|ts)/, '.js'))) - const entry = [`${pathname}`] + const pathname = relative(dir, await resolvePath(pagePath)) + const {name, files} = createEntry(pathname) await new Promise((resolve, reject) => { const entryInfo = entries[page] @@ -150,7 +150,7 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { console.log(`> Building page: ${page}`) - entries[page] = { name, entry, pathname, status: ADDED } + entries[page] = { name, entry: files, pathname, status: ADDED } doneCallbacks.on(page, processCallback) invalidator.invalidate() From 7106affcb7410610b750fa9ee624bf78d92eddcb Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 14:59:40 +0100 Subject: [PATCH 083/132] Remove unused and broken pagesGlobPattern --- server/config.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/config.js b/server/config.js index 395b92c526ab5..e53b7ecf7f5e8 100644 --- a/server/config.js +++ b/server/config.js @@ -9,8 +9,7 @@ const defaultConfig = { distDir: '.next', assetPrefix: '', configOrigin: 'default', - useFileSystemPublicRoutes: true, - pagesGlobPattern: 'pages/**/*.+(js|jsx)' + useFileSystemPublicRoutes: true } export default function getConfig (dir, customConfig) { From a10c21e37ea2d153cfeba760203397c2d91cdd0e Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 15:00:28 +0100 Subject: [PATCH 084/132] day/index.js is automatically turned into day.js at build time --- server/build/webpack/utils.js | 36 ++++++++++++++++------------------- server/index.js | 7 ++----- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/server/build/webpack/utils.js b/server/build/webpack/utils.js index f45ed8f00e957..60e6490969fb9 100644 --- a/server/build/webpack/utils.js +++ b/server/build/webpack/utils.js @@ -6,7 +6,7 @@ const nextPagesDir = path.join(__dirname, '..', '..', '..', 'pages') export async function getPages (dir, {dev, isServer}) { const pageFiles = await getPagePaths(dir, {dev, isServer}) - return getPageEntries(pageFiles, {dir, isServer}) + return getPageEntries(pageFiles, {isServer}) } async function getPagePaths (dir, {dev, isServer}) { @@ -22,33 +22,29 @@ async function getPagePaths (dir, {dev, isServer}) { } // Convert page path into single entry -export function entry ({isServer}) { - return function createEntry (filePath, name) { - const parsedPath = path.parse(filePath) - let entryName = name || filePath - - // This makes sure we compile `pages/blog/index.js` to `pages/blog.js`. - // Excludes `pages/index.js` from this rule since we do want `/` to route to `pages/index.js` - if (parsedPath.dir !== 'pages' && parsedPath.name === 'index') { - entryName = `${parsedPath.dir}.js` - } +export function createEntry (filePath, name) { + const parsedPath = path.parse(filePath) + let entryName = name || filePath + + // This makes sure we compile `pages/blog/index.js` to `pages/blog.js`. + // Excludes `pages/index.js` from this rule since we do want `/` to route to `pages/index.js` + if (parsedPath.dir !== 'pages' && parsedPath.name === 'index') { + entryName = `${parsedPath.dir}.js` + } - // Makes sure supported extensions are stripped off. The outputted file should always be `.js` - entryName = entryName.replace(/\.+(jsx|tsx|ts)/, '.js') + // Makes sure supported extensions are stripped off. The outputted file should always be `.js` + entryName = entryName.replace(/\.+(jsx|tsx|ts)/, '.js') - return { - name: path.join('bundles', entryName), - files: [parsedPath.root ? filePath : `./${filePath}`] // The entry always has to be an array. - } + return { + name: path.join('bundles', entryName), + files: [parsedPath.root ? filePath : `./${filePath}`] // The entry always has to be an array. } } // Convert page paths into entries -export function getPageEntries (pagePaths, {dir, isServer}) { +export function getPageEntries (pagePaths, {isServer}) { const entries = {} - const createEntry = entry({isServer}) - for (const filePath of pagePaths) { const entry = createEntry(filePath) entries[entry.name] = entry.files diff --git a/server/index.js b/server/index.js index 804d034043319..d5841e4af453b 100644 --- a/server/index.js +++ b/server/index.js @@ -220,11 +220,8 @@ export default class Server { } } - let p = join(this.dir, this.dist, 'bundles', 'pages', paths.join('/')) - if (!fs.existsSync(`${p}.js`)) { - p = join(p, 'index') // It's possible to have index.js in a subfolder - } - await this.serveStatic(req, res, `${p}.js`) + const p = join(this.dir, this.dist, 'bundles', 'pages', paths.join('/'), '.js') + await this.serveStatic(req, res, p) }, '/_next/static/:path*': async (req, res, params) => { From fb7c8624d43be7d639be50eacebfd063e7a16d39 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 18 Jan 2018 16:00:21 +0100 Subject: [PATCH 085/132] Remove poweredByHeader option --- errors/powered-by-header-option-removed.md | 15 ++++++++++++++ server/config.js | 4 +++- server/index.js | 4 +--- .../integration/production/test/index.test.js | 20 ------------------- 4 files changed, 19 insertions(+), 24 deletions(-) create mode 100644 errors/powered-by-header-option-removed.md diff --git a/errors/powered-by-header-option-removed.md b/errors/powered-by-header-option-removed.md new file mode 100644 index 0000000000000..216fbda849f52 --- /dev/null +++ b/errors/powered-by-header-option-removed.md @@ -0,0 +1,15 @@ +# The poweredByHeader has been removed + +#### Why This Error Occurred + +Starting at Next.js version 5.0.0 the `poweredByHeader` option has been removed. + +#### Possible Ways to Fix It + +If you still want to remove `x-powered-by` you can use one of the custom-server examples. + +And then manually remove the header using `res.removeHeader('x-powered-by')` + +### Useful Links + +- [Custom Server documentation + examples](https://github.com/zeit/next.js#custom-server-and-routing) diff --git a/server/config.js b/server/config.js index e53b7ecf7f5e8..5aabc60bd9fbb 100644 --- a/server/config.js +++ b/server/config.js @@ -5,7 +5,6 @@ const cache = new Map() const defaultConfig = { webpack: null, webpackDevMiddleware: null, - poweredByHeader: true, distDir: '.next', assetPrefix: '', configOrigin: 'default', @@ -33,6 +32,9 @@ function loadConfig (dir, customConfig) { if (path && path.length) { const userConfigModule = require(path) userConfig = userConfigModule.default || userConfigModule + if (userConfig.poweredByHeader === true || userConfig.poweredByHeader === false) { + console.warn('> the `poweredByHeader` option has been removed https://err.sh/zeit/next.js/powered-by-header-option-removed') + } userConfig.configOrigin = 'next.config.js' } diff --git a/server/index.js b/server/index.js index d5841e4af453b..d760a48ea5262 100644 --- a/server/index.js +++ b/server/index.js @@ -301,10 +301,8 @@ export default class Server { return await this.render404(req, res, parsedUrl) } - if (this.config.poweredByHeader) { - res.setHeader('X-Powered-By', `Next.js ${pkg.version}`) - } const html = await this.renderToHTML(req, res, pathname, query) + res.setHeader('X-Powered-By', `Next.js ${pkg.version}`) return sendHTML(req, res, html, req.method, this.renderOpts) } diff --git a/test/integration/production/test/index.test.js b/test/integration/production/test/index.test.js index 217818f9d9a96..1916c81abf26e 100644 --- a/test/integration/production/test/index.test.js +++ b/test/integration/production/test/index.test.js @@ -145,26 +145,6 @@ describe('Production Usage', () => { await app.render(req, res, req.url) expect(headers['X-Powered-By']).toEqual(`Next.js ${pkg.version}`) }) - - it('should not set it when poweredByHeader==false', async () => { - const req = { url: '/stateless', headers: {} } - const originalConfigValue = app.config.poweredByHeader - app.config.poweredByHeader = false - const res = { - getHeader () { - return false - }, - setHeader (key, value) { - if (key === 'X-Powered-By') { - throw new Error('Should not set the X-Powered-By header') - } - }, - end () {} - } - - await app.render(req, res, req.url) - app.config.poweredByHeader = originalConfigValue - }) }) dynamicImportTests(context, (p, q) => renderViaHTTP(context.appPort, p, q)) From d948ef554ee09ba68f93522bb420b0fe4aaeba02 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Fri, 19 Jan 2018 14:27:19 +0530 Subject: [PATCH 086/132] Load pages with the correct path. --- server/index.js | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/server/index.js b/server/index.js index d760a48ea5262..bb1850da6d2c5 100644 --- a/server/index.js +++ b/server/index.js @@ -163,22 +163,13 @@ export default class Server { '/_next/:buildId/page/:path*.js.map': async (req, res, params) => { const paths = params.path || [''] - const page = `/${paths.join('/')}` + const page = paths.join('/') if (this.dev) { - try { - await this.hotReloader.ensurePage(page) - } catch (error) {} - - const compilationErr = await this.getCompilationError() - if (compilationErr) { - const customFields = { statusCode: 500 } - return await renderScriptError(req, res, page, compilationErr, customFields, this.renderOpts) - } + await this.hotReloader.ensurePage(page) } const dist = getConfig(this.dir).distDir - const path = join(this.dir, dist, 'bundles', 'pages', `${page}.js.map`) await serveStatic(req, res, path) }, @@ -197,7 +188,7 @@ export default class Server { '/_next/:buildId/page/:path*.js': async (req, res, params) => { const paths = params.path || [''] - const page = `/${paths.join('/')}` + const page = paths.join('/') if (!this.handleBuildId(params.buildId, res)) { const error = new Error('INVALID_BUILD_ID') @@ -220,7 +211,7 @@ export default class Server { } } - const p = join(this.dir, this.dist, 'bundles', 'pages', paths.join('/'), '.js') + const p = join(this.dir, this.dist, 'bundles', 'pages', `${page}.js`) await this.serveStatic(req, res, p) }, From 763a1d257d8cd47323cc41998ade1ac71a7eb35d Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 19 Jan 2018 10:29:28 +0100 Subject: [PATCH 087/132] Release 5.0.0-universal-alpha.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 94c97c1a95c9c..c58809b69c1d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.5", + "version": "5.0.0-universal-alpha.6", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 9b709c57dd1f2877d10adf421523424cc415514e Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 19 Jan 2018 11:20:53 +0100 Subject: [PATCH 088/132] Make sure react-dom/server can be overwritten by module-alias --- server/render.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/render.js b/server/render.js index f6b4a9f5b924c..af9605a18b5f6 100644 --- a/server/render.js +++ b/server/render.js @@ -1,6 +1,5 @@ import { join } from 'path' import { createElement } from 'react' -import { renderToString, renderToStaticMarkup } from 'react-dom/server' import send from 'send' import generateETag from 'etag' import fresh from 'fresh' @@ -76,6 +75,8 @@ async function doRender (req, res, pathname, query, { // the response might be finshed on the getinitialprops call if (res.finished) return + const { renderToString, renderToStaticMarkup } = require('react-dom/server') + const renderPage = (enhancer = Page => Page) => { const app = createElement(App, { Component: enhancer(Component), From 6b625517301bb3fbfc4ea6bd1929366c378bb322 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 19 Jan 2018 11:21:07 +0100 Subject: [PATCH 089/132] Only add react-hot-loader babel plugin in dev --- server/build/webpack.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index cc47346a98ad0..b45d4f6fd0e80 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -25,12 +25,12 @@ const interpolateNames = new Map(defaultPages.map((p) => { return [path.join(nextPagesDir, p), `dist/bundles/pages/${p}`] })) -function babelConfig (dir, isServer) { +function babelConfig (dir, {isServer, dev}) { const mainBabelOptions = { cacheDirectory: true, presets: [], plugins: [ - !isServer && require.resolve('react-hot-loader/babel') + dev && !isServer && require.resolve('react-hot-loader/babel') ].filter(Boolean) } @@ -126,7 +126,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer ].filter(Boolean) } - const babelLoaderOptions = babelConfig(dir, isServer) + const babelLoaderOptions = babelConfig(dir, {dev, isServer}) const defaultLoaders = { babel: { @@ -251,7 +251,6 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer compress: { arrows: false, booleans: false, - cascade: false, collapse_vars: false, comparisons: false, computed_props: false, From 4617987a5d8a75142913431024571dbc1aa1716e Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 19 Jan 2018 11:21:47 +0100 Subject: [PATCH 090/132] Release 5.0.0-universal-alpha.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c58809b69c1d9..4a4cadda602f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.6", + "version": "5.0.0-universal-alpha.7", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 6833e8bf7c2fe7fc077acaf14bb343a8544b3f5e Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 19 Jan 2018 11:40:44 +0100 Subject: [PATCH 091/132] Revert tests --- package.json | 2 +- server/render.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 4a4cadda602f3..d513869ac3b82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.7", + "version": "5.0.0-universal-alpha.9", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", diff --git a/server/render.js b/server/render.js index af9605a18b5f6..f6b4a9f5b924c 100644 --- a/server/render.js +++ b/server/render.js @@ -1,5 +1,6 @@ import { join } from 'path' import { createElement } from 'react' +import { renderToString, renderToStaticMarkup } from 'react-dom/server' import send from 'send' import generateETag from 'etag' import fresh from 'fresh' @@ -75,8 +76,6 @@ async function doRender (req, res, pathname, query, { // the response might be finshed on the getinitialprops call if (res.finished) return - const { renderToString, renderToStaticMarkup } = require('react-dom/server') - const renderPage = (enhancer = Page => Page) => { const app = createElement(App, { Component: enhancer(Component), From 516fa62e2c51bbf6335f5f5fbcae2782159cb111 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 19 Jan 2018 18:05:57 +0100 Subject: [PATCH 092/132] Release 5.0.0-universal-alpha.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d513869ac3b82..f38008721478c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.9", + "version": "5.0.0-universal-alpha.10", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 97f45e95cc4b849a830fd244d97c8ece8fe2f612 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Fri, 19 Jan 2018 23:19:05 +0530 Subject: [PATCH 093/132] Make sure next/head is working properly. --- server/build/webpack.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index b45d4f6fd0e80..004d930c7aa13 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -62,6 +62,17 @@ function externalsConfig (dir, isServer) { return externals } + // This will externalize all the 'next/xxx' modules to load from + // node_modules always. + // This is very useful in Next.js development where we use symlinked version + // of Next.js or using next/xxx inside test apps. + externals.push(function (context, request, callback) { + if (/^next\//.test(request)) { + return callback(null, `commonjs ${request}`) + } + callback() + }) + if (fs.existsSync(nextNodeModulesDir)) { externals.push(nodeExternals({ modulesDir: nextNodeModulesDir, @@ -180,7 +191,6 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer 'node_modules' ], alias: { - 'next': nextDir, 'react-dom': dev ? 'react-dom/cjs/react-dom.development.js' : 'react-dom/cjs/react-dom.production.min.js' } }, @@ -226,7 +236,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer dev && new webpack.NoEmitOnErrorsPlugin(), dev && !isServer && new FriendlyErrorsWebpackPlugin(), dev && new webpack.NamedModulesPlugin(), - dev && new webpack.HotModuleReplacementPlugin(), // Hot module replacement + dev && !isServer && new webpack.HotModuleReplacementPlugin(), // Hot module replacement dev && new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive dev && new webpack.LoaderOptionsPlugin({ options: { From e57c23676400e7158b251a41ab4f5f39875c645f Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Sat, 20 Jan 2018 00:06:13 +0530 Subject: [PATCH 094/132] Add wepack alias for 'next' back. --- server/build/webpack.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/build/webpack.js b/server/build/webpack.js index 004d930c7aa13..f5762c2de2517 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -191,6 +191,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer 'node_modules' ], alias: { + 'next': nextDir, 'react-dom': dev ? 'react-dom/cjs/react-dom.development.js' : 'react-dom/cjs/react-dom.production.min.js' } }, From 7ed60b7c41a62c89f9a5c8ed7dc6c775c8ab4431 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 19 Jan 2018 19:44:10 +0100 Subject: [PATCH 095/132] Make sure overriding className in next/head works --- lib/head.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/head.js b/lib/head.js index 3473332016067..c34e9b896f926 100644 --- a/lib/head.js +++ b/lib/head.js @@ -27,7 +27,7 @@ function reduceComponents (components) { .filter(unique()) .reverse() .map((c) => { - const className = (c.className ? c.className + ' ' : '') + 'next-head' + const className = (c.props && c.props.className ? c.props.className + ' ' : '') + 'next-head' return React.cloneElement(c, { className }) }) } From 4911d0a7b6ae1bcb7f414e493b5f57add11f3c20 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 19 Jan 2018 19:50:19 +0100 Subject: [PATCH 096/132] Alias react too --- server/build/webpack.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/build/webpack.js b/server/build/webpack.js index 004d930c7aa13..4526b3435d9d7 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -191,6 +191,10 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer 'node_modules' ], alias: { + next: nextDir, + // This bypasses React's check for production mode. Since we know it is in production this way. + // This allows us to exclude React from being uglified. Saving multiple seconds per build. + react: dev ? 'react/cjs/react.development.js' : 'eact/cjs/react.production.js', 'react-dom': dev ? 'react-dom/cjs/react-dom.development.js' : 'react-dom/cjs/react-dom.production.min.js' } }, From 8e9f8c7926969f59bffbd05049ba37e6d69277fb Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 19 Jan 2018 22:20:20 +0100 Subject: [PATCH 097/132] Add missing r --- server/build/webpack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 4526b3435d9d7..689652301597a 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -194,7 +194,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer next: nextDir, // This bypasses React's check for production mode. Since we know it is in production this way. // This allows us to exclude React from being uglified. Saving multiple seconds per build. - react: dev ? 'react/cjs/react.development.js' : 'eact/cjs/react.production.js', + react: dev ? 'react/cjs/react.development.js' : 'react/cjs/react.production.js', 'react-dom': dev ? 'react-dom/cjs/react-dom.development.js' : 'react-dom/cjs/react-dom.production.min.js' } }, From 7e9fa419833455807c07de7990d108cb8d2a2ee3 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 20 Jan 2018 00:07:48 +0100 Subject: [PATCH 098/132] Fragment fallback has to wrap the children --- server/document.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/document.js b/server/document.js index 05de031640c63..49eea8a5190c0 100644 --- a/server/document.js +++ b/server/document.js @@ -4,7 +4,7 @@ import htmlescape from 'htmlescape' import flush from 'styled-jsx/server' const Fragment = React.Fragment || function Fragment ({ children }) { - return children + return
{children}
} export default class Document extends Component { @@ -106,7 +106,6 @@ export class Main extends Component { render () { const { html, errorHtml } = this.context._documentProps - return (
From 1e6e8294370742401f5dee3202df2fe3c7a109ec Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 20 Jan 2018 13:39:40 +0100 Subject: [PATCH 099/132] Use min.js --- server/build/webpack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 689652301597a..774d0c7dd0660 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -194,7 +194,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer next: nextDir, // This bypasses React's check for production mode. Since we know it is in production this way. // This allows us to exclude React from being uglified. Saving multiple seconds per build. - react: dev ? 'react/cjs/react.development.js' : 'react/cjs/react.production.js', + react: dev ? 'react/cjs/react.development.js' : 'react/cjs/react.production.min.js', 'react-dom': dev ? 'react-dom/cjs/react-dom.development.js' : 'react-dom/cjs/react-dom.production.min.js' } }, From 3897e64d751a5e23ff662422b849b64d7a429470 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 20 Jan 2018 14:06:20 +0100 Subject: [PATCH 100/132] Remove css.js --- css.js | 1 - lib/css.js | 1 - 2 files changed, 2 deletions(-) delete mode 100644 css.js delete mode 100644 lib/css.js diff --git a/css.js b/css.js deleted file mode 100644 index e4d6d15f9f3b8..0000000000000 --- a/css.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./dist/lib/css') diff --git a/lib/css.js b/lib/css.js deleted file mode 100644 index b87b38863e4ad..0000000000000 --- a/lib/css.js +++ /dev/null @@ -1 +0,0 @@ -throw new Error(`'next/css' has been removed in Next.js 2.0. Please refer to the migration guide: https://github.com/zeit/next.js/wiki/Migrating-from-next-css`) From 9f4de5b01824a9dbb816f3b000d127895bacd97b Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 20 Jan 2018 14:25:20 +0100 Subject: [PATCH 101/132] Remove wallaby.js --- wallaby.js | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 wallaby.js diff --git a/wallaby.js b/wallaby.js deleted file mode 100644 index dedab25e4baf1..0000000000000 --- a/wallaby.js +++ /dev/null @@ -1,31 +0,0 @@ -module.exports = function (wallaby) { - return { - files: [ - 'server/**/*.js', - 'client/**/*.js', - 'lib/**/*.js', - 'dist/**/*.js', - 'test/**/*.*', - '!test/**/*.test.js' - ], - - tests: [ - 'test/**/*.test.js', - '!test/integration/**/*.test.js' - ], - - compilers: { - '**/*.js': wallaby.compilers.babel() - }, - - env: { - type: 'node', - runner: 'node', - params: { - env: 'NODE_PATH=test/lib' - } - }, - - testFramework: 'jest' - } -} From 0aa6aacc1882121fcd489014759290fe8be1b1fa Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 20 Jan 2018 14:49:46 +0100 Subject: [PATCH 102/132] Release 5.0.0-universal-alpha.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f38008721478c..cf3efe1fe8bc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.10", + "version": "5.0.0-universal-alpha.11", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From a13f3e4ab565df9e2c9a3dfc8eb4009c0c2e02ed Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sat, 20 Jan 2018 16:24:16 +0100 Subject: [PATCH 103/132] Resolve relative to workdir instead of next --- pages/_document.js | 2 +- pages/_error.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/_document.js b/pages/_document.js index 37050c9ac33a7..817d65956f1db 100644 --- a/pages/_document.js +++ b/pages/_document.js @@ -1 +1 @@ -module.exports = require('next/document') +module.exports = require('../server/document') diff --git a/pages/_error.js b/pages/_error.js index b60f10cf1b195..0235b026d2202 100644 --- a/pages/_error.js +++ b/pages/_error.js @@ -1 +1 @@ -module.exports = require('next/error') +module.exports = require('../lib/error') From 15d228097497c785e28d41b95ed17941ce64f5bc Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sun, 21 Jan 2018 22:40:10 +0100 Subject: [PATCH 104/132] Make sure we touch the right file --- server/on-demand-entry-handler.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/on-demand-entry-handler.js b/server/on-demand-entry-handler.js index 6dc90a669b4ea..e0df3a42eb9ff 100644 --- a/server/on-demand-entry-handler.js +++ b/server/on-demand-entry-handler.js @@ -130,8 +130,8 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { page = normalizePage(page) const pagePath = join(dir, 'pages', page) - const pathname = relative(dir, await resolvePath(pagePath)) - const {name, files} = createEntry(pathname) + const pathname = await resolvePath(pagePath) + const {name, files} = createEntry(relative(dir, pathname)) await new Promise((resolve, reject) => { const entryInfo = entries[page] From 280b9c765e607cf322243f39515dc2ef454454ed Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sun, 21 Jan 2018 23:06:08 +0100 Subject: [PATCH 105/132] Resolve next modules --- server/build/webpack.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/server/build/webpack.js b/server/build/webpack.js index 774d0c7dd0660..a81ce68a1f697 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -13,7 +13,9 @@ import CombineAssetsPlugin from './plugins/combine-assets-plugin' import PagesPlugin from './plugins/pages-plugin' import DynamicChunksPlugin from './plugins/dynamic-chunks-plugin' import findBabelConfig from './babel/find-config' +import rootModuleRelativePath from './root-module-relative-path' +const relativeResolve = rootModuleRelativePath(require) const nextDir = path.join(__dirname, '..', '..', '..') const nextNodeModulesDir = path.join(nextDir, 'node_modules') const nextPagesDir = path.join(nextDir, 'pages') @@ -30,6 +32,22 @@ function babelConfig (dir, {isServer, dev}) { cacheDirectory: true, presets: [], plugins: [ + isServer && [ + require.resolve('babel-plugin-module-resolver'), + { + alias: { + 'babel-runtime': relativeResolve('babel-runtime/package'), + 'next/link': relativeResolve('../../lib/link'), + 'next/prefetch': relativeResolve('../../lib/prefetch'), + 'next/dynamic': relativeResolve('../../lib/dynamic'), + 'next/head': relativeResolve('../../lib/head'), + 'next/document': relativeResolve('../../server/document'), + 'next/router': relativeResolve('../../lib/router'), + 'next/error': relativeResolve('../../lib/error'), + 'styled-jsx/style': relativeResolve('styled-jsx/style') + } + } + ], dev && !isServer && require.resolve('react-hot-loader/babel') ].filter(Boolean) } From 3479800365bd980c77a1e232c7cfd54b9d326496 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sun, 21 Jan 2018 23:06:37 +0100 Subject: [PATCH 106/132] Remove dotjsx removal plugins since we use webpack on the server --- .../babel/plugins/remove-dotjsx-from-import.js | 15 --------------- server/build/babel/preset.js | 1 - 2 files changed, 16 deletions(-) delete mode 100644 server/build/babel/plugins/remove-dotjsx-from-import.js diff --git a/server/build/babel/plugins/remove-dotjsx-from-import.js b/server/build/babel/plugins/remove-dotjsx-from-import.js deleted file mode 100644 index b43b61ba099d1..0000000000000 --- a/server/build/babel/plugins/remove-dotjsx-from-import.js +++ /dev/null @@ -1,15 +0,0 @@ -// This plugins removes the `.jsx` extension from import statements. Because we transpile .jsx files to .js in .next -// E.g. `import Hello from '../components/hello.jsx'` will become `import Hello from '../components/hello'` -module.exports = function ({types}) { - return { - name: 'remove-dotjsx-from-import', - visitor: { - ImportDeclaration (path) { - const value = path.node.source.value - if (value.slice(-4) === '.jsx') { - path.node.source = types.stringLiteral(value.slice(0, -4)) - } - } - } - } -} diff --git a/server/build/babel/preset.js b/server/build/babel/preset.js index 2a402b6f26684..59c6e95069d29 100644 --- a/server/build/babel/preset.js +++ b/server/build/babel/preset.js @@ -43,7 +43,6 @@ module.exports = (context, opts = {}) => ({ require.resolve('babel-preset-react') ], plugins: [ - require.resolve('./plugins/remove-dotjsx-from-import'), require.resolve('babel-plugin-react-require'), require.resolve('./plugins/handle-import'), require.resolve('babel-plugin-transform-object-rest-spread'), From 49b119bd60ab73cb9ac04097e9d7702a166f466f Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 22 Jan 2018 08:10:44 +0100 Subject: [PATCH 107/132] Revert "Resolve relative to workdir instead of next" This reverts commit a13f3e4ab565df9e2c9a3dfc8eb4009c0c2e02ed. --- pages/_document.js | 2 +- pages/_error.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/_document.js b/pages/_document.js index 817d65956f1db..37050c9ac33a7 100644 --- a/pages/_document.js +++ b/pages/_document.js @@ -1 +1 @@ -module.exports = require('../server/document') +module.exports = require('next/document') diff --git a/pages/_error.js b/pages/_error.js index 0235b026d2202..b60f10cf1b195 100644 --- a/pages/_error.js +++ b/pages/_error.js @@ -1 +1 @@ -module.exports = require('../lib/error') +module.exports = require('next/error') From 5650e50ce95a988a40d5937a4927dce10b950deb Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sun, 21 Jan 2018 23:06:37 +0100 Subject: [PATCH 108/132] Externalize any locally loaded module lives outside of app dir. --- server/build/webpack.js | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index a81ce68a1f697..4a40bd750280b 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -80,17 +80,6 @@ function externalsConfig (dir, isServer) { return externals } - // This will externalize all the 'next/xxx' modules to load from - // node_modules always. - // This is very useful in Next.js development where we use symlinked version - // of Next.js or using next/xxx inside test apps. - externals.push(function (context, request, callback) { - if (/^next\//.test(request)) { - return callback(null, `commonjs ${request}`) - } - callback() - }) - if (fs.existsSync(nextNodeModulesDir)) { externals.push(nodeExternals({ modulesDir: nextNodeModulesDir, @@ -108,6 +97,19 @@ function externalsConfig (dir, isServer) { }) } + // Externalize any locally loaded modules + // This is needed when developing Next.js and running tests inside Next.js + externals.push(function (context, request, callback) { + const actualPath = path.resolve(context, request) + // If the request is inside the app dir we don't need proceed + if (actualPath.startsWith(dir)) { + callback() + return + } + + callback(null, `commonjs ${require.resolve(actualPath)}`) + }) + return externals } From e7a938c01bdf0d5b2bc99f479e37b0ed9ad7a000 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 22 Jan 2018 10:35:23 +0100 Subject: [PATCH 109/132] Remove server aliases --- server/build/webpack.js | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 4a40bd750280b..e4023cc2d2ec0 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -13,9 +13,7 @@ import CombineAssetsPlugin from './plugins/combine-assets-plugin' import PagesPlugin from './plugins/pages-plugin' import DynamicChunksPlugin from './plugins/dynamic-chunks-plugin' import findBabelConfig from './babel/find-config' -import rootModuleRelativePath from './root-module-relative-path' -const relativeResolve = rootModuleRelativePath(require) const nextDir = path.join(__dirname, '..', '..', '..') const nextNodeModulesDir = path.join(nextDir, 'node_modules') const nextPagesDir = path.join(nextDir, 'pages') @@ -32,22 +30,6 @@ function babelConfig (dir, {isServer, dev}) { cacheDirectory: true, presets: [], plugins: [ - isServer && [ - require.resolve('babel-plugin-module-resolver'), - { - alias: { - 'babel-runtime': relativeResolve('babel-runtime/package'), - 'next/link': relativeResolve('../../lib/link'), - 'next/prefetch': relativeResolve('../../lib/prefetch'), - 'next/dynamic': relativeResolve('../../lib/dynamic'), - 'next/head': relativeResolve('../../lib/head'), - 'next/document': relativeResolve('../../server/document'), - 'next/router': relativeResolve('../../lib/router'), - 'next/error': relativeResolve('../../lib/error'), - 'styled-jsx/style': relativeResolve('styled-jsx/style') - } - } - ], dev && !isServer && require.resolve('react-hot-loader/babel') ].filter(Boolean) } @@ -97,19 +79,6 @@ function externalsConfig (dir, isServer) { }) } - // Externalize any locally loaded modules - // This is needed when developing Next.js and running tests inside Next.js - externals.push(function (context, request, callback) { - const actualPath = path.resolve(context, request) - // If the request is inside the app dir we don't need proceed - if (actualPath.startsWith(dir)) { - callback() - return - } - - callback(null, `commonjs ${require.resolve(actualPath)}`) - }) - return externals } From 827c8134ea882f23c3ff5d3e644e1aef33c0607a Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 22 Jan 2018 11:11:48 +0100 Subject: [PATCH 110/132] Check node_modules reliably --- package.json | 1 + server/build/webpack.js | 25 +++++++++++++++++-------- yarn.lock | 6 ++++++ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index cf3efe1fe8bc2..69bf0d13b5c91 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,7 @@ "prop-types-exact": "1.1.1", "react-hot-loader": "4.0.0-beta.14", "recursive-copy": "2.0.6", + "resolve": "1.5.0", "send": "0.16.1", "source-map-support": "0.5.0", "strip-ansi": "3.0.1", diff --git a/server/build/webpack.js b/server/build/webpack.js index e4023cc2d2ec0..f26765478e295 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -1,7 +1,7 @@ import path, {sep} from 'path' import fs from 'fs' import webpack from 'webpack' - +import resolve from 'resolve' import nodeExternals from 'webpack-node-externals' import UglifyJSPlugin from 'uglifyjs-webpack-plugin' import CaseSensitivePathPlugin from 'case-sensitive-paths-webpack-plugin' @@ -70,14 +70,23 @@ function externalsConfig (dir, isServer) { })) } - const dirNodeModules = path.join(dir, 'node_modules') - if (fs.existsSync(dirNodeModules)) { - nodeExternals({ - modulesDir: dirNodeModules, - includeAbsolutePaths: true, - whitelist: [/\.(?!(?:js|json)$).{1,5}$/i] + // This will externalize all the 'next/xxx' modules to load from + // node_modules always. + // This is very useful in Next.js development where we use symlinked version + // of Next.js or using next/xxx inside test apps. + externals.push((context, request, callback) => { + resolve(request, { basedir: dir }, (err, res) => { + if (err) { + return callback() + } + + if (res.match(/node_modules/)) { + return callback(null, `commonjs ${request}`) + } + + callback() }) - } + }) return externals } diff --git a/yarn.lock b/yarn.lock index ee407ca104056..191236679e368 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5114,6 +5114,12 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" +resolve@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + dependencies: + path-parse "^1.0.5" + resolve@^1.1.6, resolve@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" From aeea881fcdd415db4fee922f882545f3f5790e15 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 22 Jan 2018 11:12:38 +0100 Subject: [PATCH 111/132] Add symlink to next for tests --- test/.gitignore | 1 + test/node_modules/next | 1 + 2 files changed, 2 insertions(+) create mode 100644 test/.gitignore create mode 120000 test/node_modules/next diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000000000..cf4bab9ddde9f --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +!node_modules diff --git a/test/node_modules/next b/test/node_modules/next new file mode 120000 index 0000000000000..c25bddb6dd466 --- /dev/null +++ b/test/node_modules/next @@ -0,0 +1 @@ +../.. \ No newline at end of file From f9e971291cf074ff0841e297ec8bd0340467603a Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Tue, 23 Jan 2018 12:17:33 +0530 Subject: [PATCH 112/132] Make sure dynamic imports work locally. This is why we need it: https://github.com/webpack/webpack/blob/b545b519b2024e3f8be3041385bd326bf5d24449/lib/MainTemplate.js#L68 We need to have the finally clause in the above in __webpack_require__. webpack output option strictModuleExceptionHandling does that. --- server/build/webpack.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index f26765478e295..b226b45bb426b 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -179,7 +179,8 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer publicPath: `/_next/webpack/`, // This saves chunks with the name given via require.ensure() chunkFilename: '[name]-[chunkhash].js', - sourceMapFilename: '[file].map?[contenthash]' + sourceMapFilename: '[file].map?[contenthash]', + strictModuleExceptionHandling: true }, performance: { hints: false }, resolve: { From 6845af9235c1deeb9dd9c10bcc4e678284b131c5 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 23 Jan 2018 11:09:41 +0100 Subject: [PATCH 113/132] dynmaic -> dynamic --- test/integration/basic/test/dynamic.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/basic/test/dynamic.js b/test/integration/basic/test/dynamic.js index 1744e4a1c8265..7c83c7744e00e 100644 --- a/test/integration/basic/test/dynamic.js +++ b/test/integration/basic/test/dynamic.js @@ -11,17 +11,17 @@ export default (context, render) => { return cheerio.load(html) } - it('should render dynmaic import components', async () => { + it('should render dynamic import components', async () => { const $ = await get$('/dynamic/ssr') expect($('p').text()).toBe('Hello World 1') }) - it('should stop render dynmaic import components', async () => { + it('should stop render dynamic import components', async () => { const $ = await get$('/dynamic/no-ssr') expect($('p').text()).toBe('loading...') }) - it('should stop render dynmaic import components with custom loading', async () => { + it('should stop render dynamic import components with custom loading', async () => { const $ = await get$('/dynamic/no-ssr-custom-loading') expect($('p').text()).toBe('LOADING') }) From 89f55633121bb71140f60b0a60dbe90dcb2f0f5c Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 23 Jan 2018 14:12:25 +0100 Subject: [PATCH 114/132] Remove webpack-node-externals --- package.json | 1 - server/build/webpack.js | 12 +----------- yarn.lock | 4 ---- 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/package.json b/package.json index 69bf0d13b5c91..a61586016297a 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,6 @@ "webpack": "3.10.0", "webpack-dev-middleware": "1.12.0", "webpack-hot-middleware": "2.21.0", - "webpack-node-externals": "1.6.0", "write-file-webpack-plugin": "4.2.0", "xss-filters": "1.2.7" }, diff --git a/server/build/webpack.js b/server/build/webpack.js index b226b45bb426b..70f3824dace1e 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -1,8 +1,6 @@ import path, {sep} from 'path' -import fs from 'fs' import webpack from 'webpack' import resolve from 'resolve' -import nodeExternals from 'webpack-node-externals' import UglifyJSPlugin from 'uglifyjs-webpack-plugin' import CaseSensitivePathPlugin from 'case-sensitive-paths-webpack-plugin' import WriteFilePlugin from 'write-file-webpack-plugin' @@ -62,20 +60,12 @@ function externalsConfig (dir, isServer) { return externals } - if (fs.existsSync(nextNodeModulesDir)) { - externals.push(nodeExternals({ - modulesDir: nextNodeModulesDir, - includeAbsolutePaths: true, - whitelist: [/\.(?!(?:js|json)$).{1,5}$/i] - })) - } - // This will externalize all the 'next/xxx' modules to load from // node_modules always. // This is very useful in Next.js development where we use symlinked version // of Next.js or using next/xxx inside test apps. externals.push((context, request, callback) => { - resolve(request, { basedir: dir }, (err, res) => { + resolve(request, { basedir: dir, preserveSymlinks: true }, (err, res) => { if (err) { return callback() } diff --git a/yarn.lock b/yarn.lock index 191236679e368..1f2ed82a12094 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6040,10 +6040,6 @@ webpack-hot-middleware@2.21.0: querystring "^0.2.0" strip-ansi "^3.0.0" -webpack-node-externals@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.6.0.tgz#232c62ec6092b100635a3d29d83c1747128df9bd" - webpack-sources@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf" From c8f9c7099684538cbbb42c08c5c801dac3ab17d6 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Fri, 26 Jan 2018 11:47:42 +0530 Subject: [PATCH 115/132] Make sure dynamic imports support SSR. --- lib/dynamic.js | 5 +++ server/build/babel/plugins/handle-import.js | 39 ++++++++------------- server/build/plugins/nextjs-ssr-import.js | 29 +++++++++++++++ server/build/webpack.js | 2 ++ 4 files changed, 51 insertions(+), 24 deletions(-) create mode 100644 server/build/plugins/nextjs-ssr-import.js diff --git a/lib/dynamic.js b/lib/dynamic.js index 939e1114befa7..43d49999d4441 100644 --- a/lib/dynamic.js +++ b/lib/dynamic.js @@ -160,6 +160,11 @@ export function flushChunks () { } export class SameLoopPromise { + static resolve (value) { + const promise = new SameLoopPromise((done) => done(value)) + return promise + } + constructor (cb) { this.onResultCallbacks = [] this.onErrorCallbacks = [] diff --git a/server/build/babel/plugins/handle-import.js b/server/build/babel/plugins/handle-import.js index eb3d985a69854..86397e9e2e5c3 100644 --- a/server/build/babel/plugins/handle-import.js +++ b/server/build/babel/plugins/handle-import.js @@ -16,32 +16,23 @@ const TYPE_IMPORT = 'Import' const buildImport = (args) => (template(` ( - typeof require.resolveWeak !== 'function' ? - new (require('next/dynamic').SameLoopPromise)((resolve, reject) => { - eval('require.ensure = function (deps, callback) { callback(require) }') - require.ensure([], (require) => { + new (require('next/dynamic').SameLoopPromise)((resolve, reject) => { + const weakId = require.resolveWeak(SOURCE) + try { + const weakModule = __webpack_require__(weakId) + return resolve(weakModule) + } catch (err) {} + + require.ensure([], (require) => { + try { let m = require(SOURCE) m.__webpackChunkName = '${args.name}' - resolve(m); - }, 'chunks/${args.name}'); - }) - : - new (require('next/dynamic').SameLoopPromise)((resolve, reject) => { - const weakId = require.resolveWeak(SOURCE) - try { - const weakModule = __webpack_require__(weakId) - return resolve(weakModule) - } catch (err) {} - - require.ensure([], (require) => { - try { - let m = require(SOURCE) - resolve(m) - } catch(error) { - reject(error) - } - }, 'chunks/${args.name}'); - }) + resolve(m) + } catch(error) { + reject(error) + } + }, 'chunks/${args.name}'); + }) ) `)) diff --git a/server/build/plugins/nextjs-ssr-import.js b/server/build/plugins/nextjs-ssr-import.js new file mode 100644 index 0000000000000..d6de3ddb7d3d8 --- /dev/null +++ b/server/build/plugins/nextjs-ssr-import.js @@ -0,0 +1,29 @@ +import { join, sep } from 'path' + +// This plugin modifies the require-ensure code generated by Webpack +// to work with Next.js SSR +export default class NextJsSsrImportPlugin { + constructor ({ dir, dist }) { + this.dir = dir + this.dist = dist + } + + apply (compiler) { + compiler.plugin('compilation', (compilation) => { + compilation.mainTemplate.plugin('require-ensure', (code) => { + // Update to load chunks from our custom chunks directory + const chunksDirPath = join(this.dir, this.dist, 'dist') + let updatedCode = code.replace('require("./"', `require("${chunksDirPath}${sep}"`) + + // Replace a promise equivalent which runs in the same loop + // If we didn't do this webpack's module loading process block us from + // doing SSR for chunks + updatedCode = updatedCode.replace( + 'return Promise.resolve();', + `return require('next/dynamic').SameLoopPromise.resolve();` + ) + return updatedCode + }) + }) + } +} diff --git a/server/build/webpack.js b/server/build/webpack.js index 70f3824dace1e..53a7eee672547 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -9,6 +9,7 @@ import ExtractTextPlugin from 'extract-text-webpack-plugin' import {getPages} from './webpack/utils' import CombineAssetsPlugin from './plugins/combine-assets-plugin' import PagesPlugin from './plugins/pages-plugin' +import NextJsSsrImportPlugin from './plugins/nextjs-ssr-import' import DynamicChunksPlugin from './plugins/dynamic-chunks-plugin' import findBabelConfig from './babel/find-config' @@ -293,6 +294,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer !isServer && extractCSS, !isServer && new PagesPlugin(), !isServer && new DynamicChunksPlugin(), + isServer && new NextJsSsrImportPlugin({ dir, dist: config.distDir }), !isServer && new webpack.optimize.CommonsChunkPlugin({ name: `commons`, filename: `commons.js`, From 53c9a6b83a49b63222902f25c2b99cb4bc7e3f9e Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 26 Jan 2018 09:46:15 +0100 Subject: [PATCH 116/132] Remove css support in favor of next-css --- package.json | 1 - server/build/webpack.js | 62 +---------------------------------------- 2 files changed, 1 insertion(+), 62 deletions(-) diff --git a/package.json b/package.json index a61586016297a..2bdf7bc5cf069 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,6 @@ "cross-spawn": "5.1.0", "del": "3.0.0", "etag": "1.8.1", - "extract-text-webpack-plugin": "3.0.2", "find-up": "2.1.0", "fresh": "0.5.2", "friendly-errors-webpack-plugin": "1.6.1", diff --git a/server/build/webpack.js b/server/build/webpack.js index 53a7eee672547..7d54024b6f6b9 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -5,7 +5,6 @@ import UglifyJSPlugin from 'uglifyjs-webpack-plugin' import CaseSensitivePathPlugin from 'case-sensitive-paths-webpack-plugin' import WriteFilePlugin from 'write-file-webpack-plugin' import FriendlyErrorsWebpackPlugin from 'friendly-errors-webpack-plugin' -import ExtractTextPlugin from 'extract-text-webpack-plugin' import {getPages} from './webpack/utils' import CombineAssetsPlugin from './plugins/combine-assets-plugin' import PagesPlugin from './plugins/pages-plugin' @@ -83,59 +82,13 @@ function externalsConfig (dir, isServer) { } export default async function getBaseWebpackConfig (dir, {dev = false, isServer = false, buildId, config}) { - const extractCSS = new ExtractTextPlugin({ - filename: 'static/style.css', - disable: dev - }) - - const cssLoader = { - loader: isServer ? 'css-loader/locals' : 'css-loader', - options: { - modules: false, - minimize: !dev, - sourceMap: dev, - importLoaders: 1, - ...(config.cssLoader || {}) - } - } - - const postcssLoader = { - loader: 'postcss-loader', - options: { - plugins: () => {} - } - } - - function cssLoaderConfig (loader = false) { - return [ - isServer && !cssLoader.options.modules && 'ignore-loader', - isServer && cssLoader.options.modules && cssLoader, - isServer && cssLoader.options.modules && postcssLoader, - isServer && cssLoader.options.modules && loader, - ...(!isServer ? extractCSS.extract({ - use: [cssLoader, postcssLoader, loader].filter(Boolean), - // Use style-loader in development - fallback: { - loader: 'style-loader', - options: { - sourceMap: true, - importLoaders: 1 - } - } - }) : []) - ].filter(Boolean) - } - const babelLoaderOptions = babelConfig(dir, {dev, isServer}) const defaultLoaders = { babel: { loader: 'babel-loader', options: babelLoaderOptions - }, - css: cssLoaderConfig(), - scss: cssLoaderConfig('sass-loader'), - less: cssLoaderConfig('less-loader') + } } let totalPages @@ -210,18 +163,6 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer include: [dir], exclude: /node_modules/, use: defaultLoaders.babel - }, - { - test: /\.css$/, - use: defaultLoaders.css - }, - { - test: /\.scss$/, - use: defaultLoaders.scss - }, - { - test: /\.less$/, - use: defaultLoaders.less } ].filter(Boolean) }, @@ -291,7 +232,6 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer output: 'app.js' }), !dev && new webpack.optimize.ModuleConcatenationPlugin(), - !isServer && extractCSS, !isServer && new PagesPlugin(), !isServer && new DynamicChunksPlugin(), isServer && new NextJsSsrImportPlugin({ dir, dist: config.distDir }), From d6dee1e52cddee5ab8d7d18b1582ee7e928c5029 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sun, 28 Jan 2018 20:52:22 +0100 Subject: [PATCH 117/132] =?UTF-8?q?Make=20sure=20we=20load=20path=20from?= =?UTF-8?q?=20`/`=20since=20it=E2=80=99s=20included=20in=20the=20path=20ma?= =?UTF-8?q?tching?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/index.js b/server/index.js index bb1850da6d2c5..e8c6dd40b59e7 100644 --- a/server/index.js +++ b/server/index.js @@ -188,7 +188,7 @@ export default class Server { '/_next/:buildId/page/:path*.js': async (req, res, params) => { const paths = params.path || [''] - const page = paths.join('/') + const page = `/${paths.join('/')}` if (!this.handleBuildId(params.buildId, res)) { const error = new Error('INVALID_BUILD_ID') From ef5f3dea08c356f9ca0643a549ad4e7e9d68622d Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Sun, 28 Jan 2018 23:18:31 +0100 Subject: [PATCH 118/132] =?UTF-8?q?Catch=20when=20ensurepage=20couldn?= =?UTF-8?q?=E2=80=99t=20be=20fulfilled=20for=20`.js.map`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/index.js b/server/index.js index e8c6dd40b59e7..8cc04e4f3acde 100644 --- a/server/index.js +++ b/server/index.js @@ -163,10 +163,14 @@ export default class Server { '/_next/:buildId/page/:path*.js.map': async (req, res, params) => { const paths = params.path || [''] - const page = paths.join('/') + const page = `/${paths.join('/')}` if (this.dev) { - await this.hotReloader.ensurePage(page) + try { + await this.hotReloader.ensurePage(page) + } catch (err) { + await this.render404(req, res) + } } const dist = getConfig(this.dir).distDir From 96b99ac53e6a59298f30581a72af8bc2cc34c15e Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 29 Jan 2018 08:13:19 +0100 Subject: [PATCH 119/132] Register require cache flusher for both client and server --- server/hot-reloader.js | 26 ++++++++++++++------------ server/render.js | 8 -------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/server/hot-reloader.js b/server/hot-reloader.js index c0c0d4fdb0742..badfb2a1a057e 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -108,22 +108,24 @@ export default class HotReloader { } async prepareBuildTools (compiler) { - compiler.compilers[0].plugin('after-emit', (compilation, callback) => { - const { assets } = compilation + compiler.compilers.forEach((singleCompiler) => { + singleCompiler.plugin('after-emit', (compilation, callback) => { + const { assets } = compilation - if (this.prevAssets) { - for (const f of Object.keys(assets)) { - deleteCache(assets[f].existsAt) - } - for (const f of Object.keys(this.prevAssets)) { - if (!assets[f]) { - deleteCache(this.prevAssets[f].existsAt) + if (this.prevAssets) { + for (const f of Object.keys(assets)) { + deleteCache(assets[f].existsAt) + } + for (const f of Object.keys(this.prevAssets)) { + if (!assets[f]) { + deleteCache(this.prevAssets[f].existsAt) + } } } - } - this.prevAssets = assets + this.prevAssets = assets - callback() + callback() + }) }) compiler.compilers[0].plugin('done', (stats) => { diff --git a/server/render.js b/server/render.js index f6b4a9f5b924c..e56bdbb7b43f9 100644 --- a/server/render.js +++ b/server/render.js @@ -55,14 +55,6 @@ async function doRender (req, res, pathname, query, { const pagePath = join(dir, dist, 'dist', 'bundles', 'pages', page) const documentPath = join(dir, dist, 'dist', 'bundles', 'pages', '_document') - // Delete the require cache to facilitate hot reloading on the server side. - if (hotReloader) { - if (page === '/') { - delete require.cache[pagePath + 'index.js'] - } else { - delete require.cache[pagePath + '.js'] - } - } let [Component, Document] = await Promise.all([ requireModule(pagePath), requireModule(documentPath) From 440b39fb5dce9da3c7180ff6cf16a59e194dcbfc Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 29 Jan 2018 08:14:53 +0100 Subject: [PATCH 120/132] Add comment explaining this is to facilitate hot reloading --- server/hot-reloader.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/hot-reloader.js b/server/hot-reloader.js index badfb2a1a057e..969e83687a539 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -108,6 +108,7 @@ export default class HotReloader { } async prepareBuildTools (compiler) { + // This flushes require.cache after emitting the files. Providing 'hot reloading' of server files. compiler.compilers.forEach((singleCompiler) => { singleCompiler.plugin('after-emit', (compilation, callback) => { const { assets } = compilation From c73853cdab3b3b12f494f94940876d5adb9be4eb Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 29 Jan 2018 08:37:13 +0100 Subject: [PATCH 121/132] Only load module when needed --- bin/next-dev | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/next-dev b/bin/next-dev index 45d695ab34f6e..edf2255b85bac 100755 --- a/bin/next-dev +++ b/bin/next-dev @@ -4,7 +4,6 @@ import parseArgs from 'minimist' import { existsSync, readFileSync } from 'fs' import Server from '../server' import { printAndExit } from '../lib/utils' -import pkgUp from 'pkg-up' const argv = parseArgs(process.argv.slice(2), { alias: { @@ -63,7 +62,7 @@ srv.start(argv.port, argv.hostname) .catch((err) => { if (err.code === 'EADDRINUSE') { let errorMessage = `Port ${argv.port} is already in use.` - const pkgAppPath = pkgUp.sync('.') + const pkgAppPath = require('pkg-up').sync('.') const appPackage = JSON.parse(readFileSync(pkgAppPath, 'utf8')) const nextScript = Object.entries(appPackage.scripts).find(scriptLine => scriptLine[1] === 'next') if (nextScript) errorMessage += `\nUse \`npm run ${nextScript[0]} -- -p \`.` From 326910452f6524b3670d10de0e0531557bd7e7be Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 29 Jan 2018 08:38:47 +0100 Subject: [PATCH 122/132] Remove unused modules --- package.json | 4 ---- yarn.lock | 40 +++------------------------------------- 2 files changed, 3 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index 2bdf7bc5cf069..06ed88de80bce 100644 --- a/package.json +++ b/package.json @@ -51,13 +51,10 @@ "dependencies": { "ansi-html": "0.0.7", "babel-core": "6.26.0", - "babel-generator": "6.26.0", "babel-loader": "7.1.2", - "babel-plugin-module-resolver": "2.7.1", "babel-plugin-react-require": "3.0.0", "babel-plugin-syntax-dynamic-import": "6.18.0", "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", "babel-plugin-transform-object-rest-spread": "6.26.0", "babel-plugin-transform-react-jsx-source": "6.22.0", "babel-plugin-transform-react-remove-prop-types": "0.4.8", @@ -78,7 +75,6 @@ "hoist-non-react-statics": "2.3.1", "htmlescape": "1.1.1", "http-status": "1.0.1", - "ignore-loader": "0.1.2", "json-loader": "0.5.7", "loader-utils": "1.1.0", "md5-file": "3.2.3", diff --git a/yarn.lock b/yarn.lock index 1f2ed82a12094..566570e217d7c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -325,12 +325,6 @@ async@^2.0.0, async@^2.1.2, async@^2.1.4: dependencies: lodash "^4.14.0" -async@^2.4.1: - version "2.6.0" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" - dependencies: - lodash "^4.14.0" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -396,7 +390,7 @@ babel-eslint@8.0.1: babel-types "7.0.0-beta.0" babylon "7.0.0-beta.22" -babel-generator@6.26.0, babel-generator@^6.18.0, babel-generator@^6.26.0: +babel-generator@^6.18.0, babel-generator@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" dependencies: @@ -576,14 +570,6 @@ babel-plugin-jest-hoist@^21.2.0: version "21.2.0" resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-21.2.0.tgz#2cef637259bd4b628a6cace039de5fcd14dbb006" -babel-plugin-module-resolver@2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-2.7.1.tgz#18be3c42ddf59f7a456c9e0512cd91394f6e4be1" - dependencies: - find-babel-config "^1.0.1" - glob "^7.1.1" - resolve "^1.2.0" - babel-plugin-react-require@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/babel-plugin-react-require/-/babel-plugin-react-require-3.0.0.tgz#2e4e7b4496b93a654a1c80042276de4e4eeb20e3" @@ -721,7 +707,7 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-commonjs@6.26.0, babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" dependencies: @@ -2359,15 +2345,6 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" -extract-text-webpack-plugin@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz#5f043eaa02f9750a9258b78c0a6e0dc1408fb2f7" - dependencies: - async "^2.4.1" - loader-utils "^1.1.0" - schema-utils "^0.3.0" - webpack-sources "^1.0.1" - extract-zip@^1.6.5: version "1.6.5" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.5.tgz#99a06735b6ea20ea9b705d779acffcc87cff0440" @@ -2464,13 +2441,6 @@ finalhandler@~1.0.6: statuses "~1.3.1" unpipe "~1.0.0" -find-babel-config@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.1.0.tgz#acc01043a6749fec34429be6b64f542ebb5d6355" - dependencies: - json5 "^0.5.1" - path-exists "^3.0.0" - find-cache-dir@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" @@ -2992,10 +2962,6 @@ iferr@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" -ignore-loader@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463" - ignore@^3.0.9, ignore@^3.2.0: version "3.3.5" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.5.tgz#c4e715455f6073a8d7e5dae72d2fc9d71663dba6" @@ -5120,7 +5086,7 @@ resolve@1.5.0: dependencies: path-parse "^1.0.5" -resolve@^1.1.6, resolve@^1.2.0: +resolve@^1.1.6: version "1.4.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" dependencies: From e38c605c4198ae6c2fc59dffb77d60236bab5fa1 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 29 Jan 2018 08:43:10 +0100 Subject: [PATCH 123/132] Release 5.0.0-universal-alpha.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 06ed88de80bce..f7292f842958d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.11", + "version": "5.0.0-universal-alpha.12", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 01c84a1a428fac61b8bf63a9b19410d4114e7748 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 29 Jan 2018 09:27:56 +0100 Subject: [PATCH 124/132] Only log the `found babel` message once --- server/build/webpack.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 7d54024b6f6b9..7cec19120c964 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -34,8 +34,11 @@ function babelConfig (dir, {isServer, dev}) { const externalBabelConfig = findBabelConfig(dir) if (externalBabelConfig) { - console.log(`> Using external babel configuration`) - console.log(`> Location: "${externalBabelConfig.loc}"`) + // Log it out once + if (!isServer) { + console.log(`> Using external babel configuration`) + console.log(`> Location: "${externalBabelConfig.loc}"`) + } // It's possible to turn off babelrc support via babelrc itself. // In that case, we should add our default preset. // That's why we need to do this. From 91ce3f9945a59e756b7e6c5d5f608dd0867028d3 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Mon, 29 Jan 2018 22:20:01 +0530 Subject: [PATCH 125/132] Make sure ondemand entries working correctly. Now we are just using a single instance of OnDemandEntryHandler. --- server/build/webpack.js | 2 + server/hot-reloader.js | 33 ++----- server/on-demand-entry-handler.js | 149 ++++++++++++++++-------------- 3 files changed, 89 insertions(+), 95 deletions(-) diff --git a/server/build/webpack.js b/server/build/webpack.js index 7cec19120c964..7bb37db89c15f 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -10,6 +10,7 @@ import CombineAssetsPlugin from './plugins/combine-assets-plugin' import PagesPlugin from './plugins/pages-plugin' import NextJsSsrImportPlugin from './plugins/nextjs-ssr-import' import DynamicChunksPlugin from './plugins/dynamic-chunks-plugin' +import UnlinkFilePlugin from './plugins/unlink-file-plugin' import findBabelConfig from './babel/find-config' const nextDir = path.join(__dirname, '..', '..', '..') @@ -175,6 +176,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer dev && !isServer && new FriendlyErrorsWebpackPlugin(), dev && new webpack.NamedModulesPlugin(), dev && !isServer && new webpack.HotModuleReplacementPlugin(), // Hot module replacement + dev && new UnlinkFilePlugin(), dev && new CaseSensitivePathPlugin(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive dev && new webpack.LoaderOptionsPlugin({ options: { diff --git a/server/hot-reloader.js b/server/hot-reloader.js index 969e83687a539..ad19211967ec8 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -94,16 +94,14 @@ export default class HotReloader { await this.stop(oldWebpackDevMiddleware) } - assignBuildTools ({ webpackDevMiddleware, webpackHotMiddleware, onDemandEntriesClient, onDemandEntriesServer }) { + assignBuildTools ({ webpackDevMiddleware, webpackHotMiddleware, onDemandEntries }) { this.webpackDevMiddleware = webpackDevMiddleware this.webpackHotMiddleware = webpackHotMiddleware - this.onDemandEntriesClient = onDemandEntriesClient - this.onDemandEntriesServer = onDemandEntriesServer + this.onDemandEntries = onDemandEntries this.middlewares = [ webpackDevMiddleware, webpackHotMiddleware, - onDemandEntriesClient.middleware(), - onDemandEntriesServer.middleware() + onDemandEntries.middleware() ] } @@ -213,14 +211,7 @@ export default class HotReloader { heartbeat: 2500 }) - const onDemandEntriesClient = onDemandEntryHandler(webpackDevMiddleware, compiler.compilers[0], { - dir: this.dir, - dev: true, - reload: this.reload.bind(this), - ...this.config.onDemandEntries - }) - - const onDemandEntriesServer = onDemandEntryHandler(webpackDevMiddleware, compiler.compilers[1], { + const onDemandEntries = onDemandEntryHandler(webpackDevMiddleware, compiler.compilers, { dir: this.dir, dev: true, reload: this.reload.bind(this), @@ -230,8 +221,7 @@ export default class HotReloader { return { webpackDevMiddleware, webpackHotMiddleware, - onDemandEntriesClient, - onDemandEntriesServer + onDemandEntries } } @@ -244,10 +234,7 @@ export default class HotReloader { async getCompilationErrors () { // When we are reloading, we need to wait until it's reloaded properly. - await Promise.all([ - this.onDemandEntriesClient.waitUntilReloaded(), - this.onDemandEntriesServer.waitUntilReloaded() - ]) + await this.onDemandEntries.waitUntilReloaded() if (!this.compilationErrors) { this.compilationErrors = new Map() @@ -276,13 +263,7 @@ export default class HotReloader { } async ensurePage (page) { - // We need to do this one after another. - // Otherwise it'll mess up with webpack hash. - // (due to concurrent devMiddleware.invalidate() calls) - // TODO: In the future, we need handle both client and server using - // a single onDemandEntryHandler instance. - await this.onDemandEntriesClient.ensurePage(page) - await this.onDemandEntriesServer.ensurePage(page) + await this.onDemandEntries.ensurePage(page) } } diff --git a/server/on-demand-entry-handler.js b/server/on-demand-entry-handler.js index e0df3a42eb9ff..f723c95141f7a 100644 --- a/server/on-demand-entry-handler.js +++ b/server/on-demand-entry-handler.js @@ -11,7 +11,7 @@ const ADDED = Symbol('added') const BUILDING = Symbol('building') const BUILT = Symbol('built') -export default function onDemandEntryHandler (devMiddleware, compiler, { +export default function onDemandEntryHandler (devMiddleware, compilers, { dir, dev, reload, @@ -26,81 +26,90 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { let reloading = false let stopped = false let reloadCallbacks = new EventEmitter() + // Keep the names of compilers which are building pages at a given moment. + const currentBuilders = new Set() + + compilers.forEach(compiler => { + compiler.plugin('make', function (compilation, done) { + invalidator.startBuilding() + currentBuilders.add(compiler.name) + + const allEntries = Object.keys(entries).map((page) => { + const { name, entry } = entries[page] + entries[page].status = BUILDING + return addEntry(compilation, this.context, name, entry) + }) - compiler.plugin('make', function (compilation, done) { - invalidator.startBuilding() - - const allEntries = Object.keys(entries).map((page) => { - const { name, entry } = entries[page] - entries[page].status = BUILDING - return addEntry(compilation, this.context, name, entry) + Promise.all(allEntries) + .then(() => done()) + .catch(done) }) - Promise.all(allEntries) - .then(() => done()) - .catch(done) - }) + compiler.plugin('done', function (stats) { + // Wait until all the compilers mark the build as done. + currentBuilders.delete(compiler.name) + if (currentBuilders.size !== 0) return - compiler.plugin('done', function (stats) { - const { compilation } = stats - const hardFailedPages = compilation.errors - .filter(e => { - // Make sure to only pick errors which marked with missing modules - const hasNoModuleFoundError = /ENOENT/.test(e.message) || /Module not found/.test(e.message) - if (!hasNoModuleFoundError) return false + const { compilation } = stats + const hardFailedPages = compilation.errors + .filter(e => { + // Make sure to only pick errors which marked with missing modules + const hasNoModuleFoundError = /ENOENT/.test(e.message) || /Module not found/.test(e.message) + if (!hasNoModuleFoundError) return false - // The page itself is missing. So this is a failed page. - if (IS_BUNDLED_PAGE.test(e.module.name)) return true + // The page itself is missing. So this is a failed page. + if (IS_BUNDLED_PAGE.test(e.module.name)) return true - // No dependencies means this is a top level page. - // So this is a failed page. - return e.module.dependencies.length === 0 - }) - .map(e => e.module.chunks) - .reduce((a, b) => [...a, ...b], []) - .map(c => { - const pageName = MATCH_ROUTE_NAME.exec(c.name)[1] - return normalizePage(`/${pageName}`) + // No dependencies means this is a top level page. + // So this is a failed page. + return e.module.dependencies.length === 0 + }) + .map(e => e.module.chunks) + .reduce((a, b) => [...a, ...b], []) + .map(c => { + const pageName = MATCH_ROUTE_NAME.exec(c.name)[1] + return normalizePage(`/${pageName}`) + }) + + // Call all the doneCallbacks + Object.keys(entries).forEach((page) => { + const entryInfo = entries[page] + if (entryInfo.status !== BUILDING) return + + // With this, we are triggering a filesystem based watch trigger + // It'll memorize some timestamp related info related to common files used + // in the page + // That'll reduce the page building time significantly. + if (!touchedAPage) { + setTimeout(() => { + touch.sync(entryInfo.pathname) + }, 1000) + touchedAPage = true + } + + entryInfo.status = BUILT + entries[page].lastActiveTime = Date.now() + doneCallbacks.emit(page) }) - // Call all the doneCallbacks - Object.keys(entries).forEach((page) => { - const entryInfo = entries[page] - if (entryInfo.status !== BUILDING) return - - // With this, we are triggering a filesystem based watch trigger - // It'll memorize some timestamp related info related to common files used - // in the page - // That'll reduce the page building time significantly. - if (!touchedAPage) { - setTimeout(() => { - touch.sync(entryInfo.pathname) - }, 1000) - touchedAPage = true + invalidator.doneBuilding(compiler.name) + + if (hardFailedPages.length > 0 && !reloading) { + console.log(`> Reloading webpack due to inconsistant state of pages(s): ${hardFailedPages.join(', ')}`) + reloading = true + reload() + .then(() => { + console.log('> Webpack reloaded.') + reloadCallbacks.emit('done') + stop() + }) + .catch(err => { + console.error(`> Webpack reloading failed: ${err.message}`) + console.error(err.stack) + process.exit(1) + }) } - - entryInfo.status = BUILT - entries[page].lastActiveTime = Date.now() - doneCallbacks.emit(page) }) - - invalidator.doneBuilding() - - if (hardFailedPages.length > 0 && !reloading) { - console.log(`> Reloading webpack due to inconsistant state of pages(s): ${hardFailedPages.join(', ')}`) - reloading = true - reload() - .then(() => { - console.log('> Webpack reloaded.') - reloadCallbacks.emit('done') - stop() - }) - .catch(err => { - console.error(`> Webpack reloading failed: ${err.message}`) - console.error(err.stack) - process.exit(1) - }) - } }) const disposeHandler = setInterval(function () { @@ -143,7 +152,7 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { } if (entryInfo.status === BUILDING) { - doneCallbacks.on(page, processCallback) + doneCallbacks.once(page, handleCallback) return } } @@ -151,11 +160,11 @@ export default function onDemandEntryHandler (devMiddleware, compiler, { console.log(`> Building page: ${page}`) entries[page] = { name, entry: files, pathname, status: ADDED } - doneCallbacks.on(page, processCallback) + doneCallbacks.once(page, handleCallback) invalidator.invalidate() - function processCallback (err) { + function handleCallback (err) { if (err) return reject(err) resolve() } @@ -272,6 +281,7 @@ function sendJson (res, payload) { class Invalidator { constructor (devMiddleware) { this.devMiddleware = devMiddleware + // contains an array of types of compilers currently building this.building = false this.rebuildAgain = false } @@ -296,6 +306,7 @@ class Invalidator { doneBuilding () { this.building = false + if (this.rebuildAgain) { this.rebuildAgain = false this.invalidate() From a62b764ea8d8bc586c52199833bfc64d71f21c6f Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 29 Jan 2018 16:59:46 +0100 Subject: [PATCH 126/132] Better sourcemaps --- client/next-dev.js | 2 ++ package.json | 2 +- server/build/webpack.js | 7 +++---- server/index.js | 1 + yarn.lock | 12 ++++++------ 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/client/next-dev.js b/client/next-dev.js index f7c2386406354..7f5e13e0005f2 100644 --- a/client/next-dev.js +++ b/client/next-dev.js @@ -4,6 +4,8 @@ import ErrorDebugComponent from '../lib/error-debug' import initOnDemandEntries from './on-demand-entries-client' import initWebpackHMR from './webpack-hot-middleware-client' +require('@zeit/source-map-support/browser-source-map-support') + window.next = next initNext({ ErrorDebugComponent, stripAnsi }) diff --git a/package.json b/package.json index f7292f842958d..0a87404a6884e 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "bin/*": "standard" }, "dependencies": { + "@zeit/source-map-support": "0.6.0", "ansi-html": "0.0.7", "babel-core": "6.26.0", "babel-loader": "7.1.2", @@ -90,7 +91,6 @@ "recursive-copy": "2.0.6", "resolve": "1.5.0", "send": "0.16.1", - "source-map-support": "0.5.0", "strip-ansi": "3.0.1", "styled-jsx": "2.2.1", "touch": "3.1.0", diff --git a/server/build/webpack.js b/server/build/webpack.js index 7bb37db89c15f..d24feb9879911 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -98,7 +98,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer let totalPages let webpackConfig = { - devtool: dev ? 'cheap-module-source-map' : false, + devtool: dev ? 'source-map' : false, name: isServer ? 'server' : 'client', cache: true, target: isServer ? 'node' : 'web', @@ -127,8 +127,8 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer publicPath: `/_next/webpack/`, // This saves chunks with the name given via require.ensure() chunkFilename: '[name]-[chunkhash].js', - sourceMapFilename: '[file].map?[contenthash]', - strictModuleExceptionHandling: true + strictModuleExceptionHandling: true, + devtoolModuleFilenameTemplate: '[absolute-resource-path]' }, performance: { hints: false }, resolve: { @@ -294,7 +294,6 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer name: 'manifest', filename: 'manifest.js' }) - ].filter(Boolean) } diff --git a/server/index.js b/server/index.js index 8cc04e4f3acde..5a447c78d6ebe 100644 --- a/server/index.js +++ b/server/index.js @@ -1,3 +1,4 @@ +require('@zeit/source-map-support').install() import { resolve, join, sep } from 'path' import { parse as parseUrl } from 'url' import { parse as parseQs } from 'querystring' diff --git a/yarn.lock b/yarn.lock index 566570e217d7c..a62e413bfc733 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,6 +30,12 @@ dependencies: chokidar "^1.7.0" +"@zeit/source-map-support@0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@zeit/source-map-support/-/source-map-support-0.6.0.tgz#3808cbe343ae786a9a5cad06fd5a1aab210baea0" + dependencies: + source-map "^0.6.0" + abab@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" @@ -5312,12 +5318,6 @@ source-list-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" -source-map-support@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.0.tgz#2018a7ad2bdf8faf2691e5fddab26bed5a2bacab" - dependencies: - source-map "^0.6.0" - source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" From 415de61fced8404f86904da9adba11734380a486 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 29 Jan 2018 19:09:42 +0100 Subject: [PATCH 127/132] Release 5.0.0-universal-alpha.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a87404a6884e..4721a6f984b86 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.12", + "version": "5.0.0-universal-alpha.13", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 3de72fcbc783dfab10a517aa3a9b27713e42041e Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 29 Jan 2018 20:19:45 +0100 Subject: [PATCH 128/132] Lock uglify version to 1.1.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4721a6f984b86..08ff29697720e 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "strip-ansi": "3.0.1", "styled-jsx": "2.2.1", "touch": "3.1.0", - "uglifyjs-webpack-plugin": "^1.1.1", + "uglifyjs-webpack-plugin": "1.1.6", "unfetch": "3.0.0", "url": "0.11.0", "uuid": "3.1.0", From 256ad20a795faa4ccb21e848a16746d2bdce8f55 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 29 Jan 2018 20:48:34 +0100 Subject: [PATCH 129/132] Release 5.0.0-universal-alpha.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 08ff29697720e..e104dd62669b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "5.0.0-universal-alpha.13", + "version": "5.0.0-universal-alpha.14", "description": "Minimalistic framework for server-rendered React applications", "main": "./dist/server/next.js", "license": "MIT", From 563c9c3d5a2e73542c87b4618f0e15da370f4347 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Tue, 30 Jan 2018 11:49:02 +0530 Subject: [PATCH 130/132] Fix a typo. --- server/hot-reloader.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/hot-reloader.js b/server/hot-reloader.js index ad19211967ec8..b3c0f8cef08e4 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -79,8 +79,8 @@ export default class HotReloader { await clean(this.dir) const configs = await Promise.all([ - getBaseWebpackConfig(this.dir, { dev: true, isServer: false, config: this.conf }), - getBaseWebpackConfig(this.dir, { dev: true, isServer: true, config: this.conf }) + getBaseWebpackConfig(this.dir, { dev: true, isServer: false, config: this.config }), + getBaseWebpackConfig(this.dir, { dev: true, isServer: true, config: this.config }) ]) const compiler = webpack(configs) From 3b0d1f8a471b3a9418cfbda20a81e6a4393669a0 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Tue, 30 Jan 2018 18:04:28 +0530 Subject: [PATCH 131/132] Introduce multi-zones support for mircofrontends --- asset.js | 1 + client/index.js | 9 ++- client/on-demand-entries-client.js | 12 ++- client/webpack-hot-middleware-client.js | 14 +++- examples/hello-world/pages/about2.js | 3 + examples/hello-world/pages/day/index.js | 3 + examples/with-zones/README.md | 71 ++++++++++++++++ examples/with-zones/blog/.gitignore | 2 + examples/with-zones/blog/next.config.js | 6 ++ examples/with-zones/blog/now.json | 3 + examples/with-zones/blog/package.json | 14 ++++ examples/with-zones/blog/pages/blog.js | 5 ++ examples/with-zones/home/.gitignore | 2 + examples/with-zones/home/components/Header.js | 5 ++ examples/with-zones/home/next.config.js | 6 ++ examples/with-zones/home/now.json | 3 + examples/with-zones/home/package.json | 14 ++++ examples/with-zones/home/pages/about.js | 10 +++ examples/with-zones/home/pages/index.js | 15 ++++ examples/with-zones/home/static/nextjs.png | Bin 0 -> 70130 bytes examples/with-zones/home/static/zeit.png | Bin 0 -> 59856 bytes examples/with-zones/package.json | 20 +++++ examples/with-zones/rules-dev.json | 6 ++ examples/with-zones/rules-prod.json | 6 ++ lib/asset.js | 10 +++ lib/link.js | 1 + lib/router/router.js | 55 +++++++------ package.json | 1 + server/build/webpack.js | 2 +- server/hot-reloader.js | 12 ++- server/index.js | 23 ++---- server/utils.js | 34 ++++++++ yarn.lock | 76 ++++++++++++------ 33 files changed, 365 insertions(+), 79 deletions(-) create mode 100644 asset.js create mode 100644 examples/hello-world/pages/about2.js create mode 100644 examples/hello-world/pages/day/index.js create mode 100644 examples/with-zones/README.md create mode 100644 examples/with-zones/blog/.gitignore create mode 100644 examples/with-zones/blog/next.config.js create mode 100644 examples/with-zones/blog/now.json create mode 100644 examples/with-zones/blog/package.json create mode 100644 examples/with-zones/blog/pages/blog.js create mode 100644 examples/with-zones/home/.gitignore create mode 100644 examples/with-zones/home/components/Header.js create mode 100644 examples/with-zones/home/next.config.js create mode 100644 examples/with-zones/home/now.json create mode 100644 examples/with-zones/home/package.json create mode 100644 examples/with-zones/home/pages/about.js create mode 100644 examples/with-zones/home/pages/index.js create mode 100644 examples/with-zones/home/static/nextjs.png create mode 100644 examples/with-zones/home/static/zeit.png create mode 100644 examples/with-zones/package.json create mode 100644 examples/with-zones/rules-dev.json create mode 100644 examples/with-zones/rules-prod.json create mode 100644 lib/asset.js diff --git a/asset.js b/asset.js new file mode 100644 index 0000000000000..fd0bd5dbb15ec --- /dev/null +++ b/asset.js @@ -0,0 +1 @@ +module.exports = require('./dist/lib/asset') diff --git a/client/index.js b/client/index.js index 2ef4c29e2256c..78d953e5ae28f 100644 --- a/client/index.js +++ b/client/index.js @@ -6,6 +6,7 @@ import EventEmitter from '../lib/EventEmitter' import App from '../lib/app' import { loadGetInitialProps, getURL } from '../lib/utils' import PageLoader from '../lib/page-loader' +import * as asset from '../lib/asset' // Polyfill Promise globally // This is needed because Webpack2's dynamic loading(common chunks) code @@ -29,6 +30,9 @@ const { location } = window +// With this, static assets will work across zones +asset.setAssetPrefix(assetPrefix) + const asPath = getURL() const pageLoader = new PageLoader(buildId, assetPrefix) @@ -93,10 +97,7 @@ export default async ({ ErrorDebugComponent: passedDebugComponent, stripAnsi: pa } export async function render (props) { - // There are some errors we should ignore. - // Next.js rendering logic knows how to handle them. - // These are specially 404 errors - if (props.err && !props.err.ignore) { + if (props.err) { await renderError(props.err) return } diff --git a/client/on-demand-entries-client.js b/client/on-demand-entries-client.js index 8b5588d56297a..65ed2c2913989 100644 --- a/client/on-demand-entries-client.js +++ b/client/on-demand-entries-client.js @@ -3,6 +3,12 @@ import Router from '../lib/router' import fetch from 'unfetch' +const { + __NEXT_DATA__: { + assetPrefix + } +} = window + export default () => { Router.ready(() => { Router.router.events.on('routeChangeComplete', ping) @@ -10,16 +16,16 @@ export default () => { async function ping () { try { - const url = `/_next/on-demand-entries-ping?page=${Router.pathname}` + const url = `${assetPrefix}/_next/on-demand-entries-ping?page=${Router.pathname}` const res = await fetch(url, { - credentials: 'same-origin' + credentials: 'omit' }) const payload = await res.json() if (payload.invalid) { // Payload can be invalid even if the page is not exists. // So, we need to make sure it's exists before reloading. const pageRes = await fetch(location.href, { - credentials: 'same-origin' + credentials: 'omit' }) if (pageRes.status === 200) { location.reload() diff --git a/client/webpack-hot-middleware-client.js b/client/webpack-hot-middleware-client.js index 10dbf28dc191f..24477fe5da9fb 100644 --- a/client/webpack-hot-middleware-client.js +++ b/client/webpack-hot-middleware-client.js @@ -1,7 +1,19 @@ -import webpackHotMiddlewareClient from 'webpack-hot-middleware/client?overlay=false&reload=true&path=/_next/webpack-hmr' +import webpackHotMiddlewareClient from 'webpack-hot-middleware/client?autoConnect=false' import Router from '../lib/router' +const { + __NEXT_DATA__: { + assetPrefix + } +} = window + export default () => { + webpackHotMiddlewareClient.setOptionsAndConnect({ + overlay: false, + reload: true, + path: `${assetPrefix}/_next/webpack-hmr` + }) + const handlers = { reload (route) { if (route === '/_error') { diff --git a/examples/hello-world/pages/about2.js b/examples/hello-world/pages/about2.js new file mode 100644 index 0000000000000..44ce657168845 --- /dev/null +++ b/examples/hello-world/pages/about2.js @@ -0,0 +1,3 @@ +export default () => ( +
About 2
+) diff --git a/examples/hello-world/pages/day/index.js b/examples/hello-world/pages/day/index.js new file mode 100644 index 0000000000000..5a58100829934 --- /dev/null +++ b/examples/hello-world/pages/day/index.js @@ -0,0 +1,3 @@ +export default () => ( +
Hello Day
+) diff --git a/examples/with-zones/README.md b/examples/with-zones/README.md new file mode 100644 index 0000000000000..5349c81422e54 --- /dev/null +++ b/examples/with-zones/README.md @@ -0,0 +1,71 @@ +[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-zones) + +# Using multiple zones + +With Next.js you can use multiple apps as a single app using it's multi-zones feature. +This is an example showing how to use it. + +In this example, we've two apps: 'home' and 'blog'. +We also have a set of rules defined in `rules.json` for the proxy. + +Now let's start two of our app using: + +``` +npm run home +npm run blog +``` + +Then start the proxy: + +``` +npm run proxy +``` + +Now you can visit http://localhost:9000 and access and develop both apps a single app. + +### Proxy Rules + +This is the place we define rules for our proxy. Here are the rules(in `rules.json`) available for this app: + +```json +{ + "rules": [ + {"pathname": "/blog", "method":["GET", "POST", "OPTIONS"], "dest": "http://localhost:5000"}, + {"pathname": "/**", "dest": "http://localhost:4000"} + ] +} +``` + +These rules are based on ZEIT now [path alias](https://zeit.co/docs/features/path-aliases) rules and use [`micro-proxy`](https://github.com/zeit/micro-proxy) as the proxy. + +## Special Notes + +* All pages should be unique across zones. A page with the same name should not exist in multiple zones. Otherwise, there'll be unexpected behaviour in client side navigation. + * According to the above example, a page named `blog` should not be exist in the `home` zone. + +## Production Deployment + +Here's how are going to deploy this application into production. + +* Open the `now.json` file in both `blog` and `home` directories and change the aliases as you wish. +* Then update `rules-prod.json` accordingly. +* Now deploy both apps: + +~~~sh +cd home +now && now alias +cd ../blog +now && now alias +cd .. +~~~ + +* Finally, set the path alias rules with + +~~~sh +now alias with-zones.now.sh -r rules-prod.json +~~~ + +> You can use a domain name of your choice in the above command instead of `with-zones.now.sh`. + +That's it. +Now you can access the final app via: diff --git a/examples/with-zones/blog/.gitignore b/examples/with-zones/blog/.gitignore new file mode 100644 index 0000000000000..f74c78183c917 --- /dev/null +++ b/examples/with-zones/blog/.gitignore @@ -0,0 +1,2 @@ +.next +node_modules diff --git a/examples/with-zones/blog/next.config.js b/examples/with-zones/blog/next.config.js new file mode 100644 index 0000000000000..d930ee9c80d8c --- /dev/null +++ b/examples/with-zones/blog/next.config.js @@ -0,0 +1,6 @@ +const { NOW_URL } = process.env +const { alias } = require('./now.json') + +module.exports = { + assetPrefix: NOW_URL ? `https://${alias}` : 'http://localhost:5000' +} diff --git a/examples/with-zones/blog/now.json b/examples/with-zones/blog/now.json new file mode 100644 index 0000000000000..f575903587170 --- /dev/null +++ b/examples/with-zones/blog/now.json @@ -0,0 +1,3 @@ +{ + "alias": "with-zones-blog.now.sh" +} diff --git a/examples/with-zones/blog/package.json b/examples/with-zones/blog/package.json new file mode 100644 index 0000000000000..cc274c2fe3524 --- /dev/null +++ b/examples/with-zones/blog/package.json @@ -0,0 +1,14 @@ +{ + "name": "with-zones-blog", + "version": "1.0.0", + "scripts": { + "build": "next build", + "start": "next start -p 4000" + }, + "dependencies": { + "next": "zones", + "react": "^16.0.0", + "react-dom": "^16.0.0" + }, + "license": "ISC" +} diff --git a/examples/with-zones/blog/pages/blog.js b/examples/with-zones/blog/pages/blog.js new file mode 100644 index 0000000000000..1f8661265321f --- /dev/null +++ b/examples/with-zones/blog/pages/blog.js @@ -0,0 +1,5 @@ +export default () => ( +
+ This is our blog +
+) diff --git a/examples/with-zones/home/.gitignore b/examples/with-zones/home/.gitignore new file mode 100644 index 0000000000000..f74c78183c917 --- /dev/null +++ b/examples/with-zones/home/.gitignore @@ -0,0 +1,2 @@ +.next +node_modules diff --git a/examples/with-zones/home/components/Header.js b/examples/with-zones/home/components/Header.js new file mode 100644 index 0000000000000..b631afc81b5ce --- /dev/null +++ b/examples/with-zones/home/components/Header.js @@ -0,0 +1,5 @@ +export default () => ( +
+

The Company

+
+) diff --git a/examples/with-zones/home/next.config.js b/examples/with-zones/home/next.config.js new file mode 100644 index 0000000000000..e76728e674352 --- /dev/null +++ b/examples/with-zones/home/next.config.js @@ -0,0 +1,6 @@ +const { NOW_URL } = process.env +const { alias } = require('./now.json') + +module.exports = { + assetPrefix: NOW_URL ? `https://${alias}` : 'http://localhost:4000' +} diff --git a/examples/with-zones/home/now.json b/examples/with-zones/home/now.json new file mode 100644 index 0000000000000..f519fe4ca8ced --- /dev/null +++ b/examples/with-zones/home/now.json @@ -0,0 +1,3 @@ +{ + "alias": "with-zones-home.now.sh" +} diff --git a/examples/with-zones/home/package.json b/examples/with-zones/home/package.json new file mode 100644 index 0000000000000..f534c02a7a077 --- /dev/null +++ b/examples/with-zones/home/package.json @@ -0,0 +1,14 @@ +{ + "name": "with-zones-home", + "version": "1.0.0", + "scripts": { + "build": "next build", + "start": "next start -p 4000" + }, + "dependencies": { + "next": "zones", + "react": "^16.0.0", + "react-dom": "^16.0.0" + }, + "license": "ISC" +} diff --git a/examples/with-zones/home/pages/about.js b/examples/with-zones/home/pages/about.js new file mode 100644 index 0000000000000..79cbefd0edef6 --- /dev/null +++ b/examples/with-zones/home/pages/about.js @@ -0,0 +1,10 @@ +import asset from 'next/asset' +import Link from 'next/link' + +export default () => ( +
+

This is the about page.

+ + +
+) diff --git a/examples/with-zones/home/pages/index.js b/examples/with-zones/home/pages/index.js new file mode 100644 index 0000000000000..c251da2e5d428 --- /dev/null +++ b/examples/with-zones/home/pages/index.js @@ -0,0 +1,15 @@ +import Link from 'next/link' +import asset from 'next/asset' +import dynamic from 'next/dynamic' + +const Header = dynamic(import('../components/Header')) + +export default () => ( +
+
+

This is our homepage

+ + + +
+) diff --git a/examples/with-zones/home/static/nextjs.png b/examples/with-zones/home/static/nextjs.png new file mode 100644 index 0000000000000000000000000000000000000000..98cbbf09ade8691527aa8d9b0d8248740c6386bd GIT binary patch literal 70130 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
N_r5X5a-PH!bM2AgAujF9EkK$=mQ);>d^{d< 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 XF{?xTo&|`drfu7zyE$&-{y+X7x1QF( literal 0 HcmV?d00001 diff --git a/examples/with-zones/home/static/zeit.png b/examples/with-zones/home/static/zeit.png new file mode 100644 index 0000000000000000000000000000000000000000..8b80fabb35ed12ccbc4c67554c4387e68dbc580c GIT binary patch literal 59856 zcmeFZcOaGj`v;s8B`RdgtdEhcl95$HMP^3U5vh#K?1N5)?1mLWDI?>M?3odnm6^TC z-pBU5?{n^>e!t)I{Pq0XAK%Y6-1q%n*Y&zy*Xz3O+h1K(=@=Ok*?|KGj$ONYMf1P` z;waP7*ao32DNeQr_h?QVw`=~fC|5Fv<3Dfjw*Mgjnxd zzLNdltHM7D!GG`njQMZ+gf02E`@qKk84uoV{<$tdmVd|t$Ay2uNlN)IY{6XNU)24_ zdG=}JKhp4zH0);t|473>((osl{6`x8k%oO;;U8)EM;iW-27=TAscHX|hJQ-KzS#Ls zY51o!{1eFc0|fk!f283bY1p@ke@eqY((q4d_`BZuk2L%v4gW~Pet`H#8uru6|DP=x z?*)Zz`%BuCZ?eH~lQ0f?Dnth^pM=frBd4&}_PY3Zl$mK?kyAVGmm;{?0$oH&Y0|C` z^WY^Os(Jk6%*@QBu)U7e+U}x!9zOsUU6Lbr%b6N*bbB# z9K|>sEgT38-}*3Dwx8-<=L45oNH;0sPwS4J$y8gaeFf3s>S$4`?%pvfC1$EbrBIt? zPuo9_7X*#fkK;t52+`W4 z0U>j_z?>dKxW9v(A6X{F#KdI!edXTNgpMVdD?2$f6SZH&^0D7SeYN1>E=3yarabEWxD*n4+- zvLnMFT`&7x!UP%P_M3TBZTWRQ(x`00B=+d-4mODVarA|rf!)0HA#I!2LsfpYlRpw) zQxpD3!wxK)NY58GjbF4;!nZG@c9-KrJ32Z(*`CdB?#ebx)Jj%0M>gyq8$WauK7!o` z@fNQBSx!q!OQAB&@NJ9i9?HX8xCm=$d-CW&8f%etC~P7zh>3V_uk&JJ`Cy!Zg2Bh+r|9o&oFbU`ePo3aX%BW$ z5cbpC=$b%!C3$&y{#&2kTNX-uEu+8Y+q=R9FwCypl^4#y7qVRT^Q`LDs%!&p( ztCc_CwY7 zzV%}bNDPtWJrkaULV%wwKe%p+^O_psjFM}B-zjs#HdpJ`Ogbu0cI z0cG1y*d0vMU+Un*Z#J)B7HVTj95^grnN1nFpg|u0=F0C^^L8VI8=OwFSA2}o>EVG# z_<4=HW*So-cfQ)G(}?~Rx0-5^;(iArufX8xr{Q$@tg!vjqIHp;qByWAbTHTM5W4fj zdo$TPpjRjws{lI^`vNyOjaXvX2nC6wqoXZPmDG!l4EeEz0Ke!|Kw865ll?ga;Tt@R zFfz1#uFz7GrbTZ4jI^|**qY5pmMm0~|0r~vi2i7>?{yB4ogddGMA&Ob&R@8|rL87Y z1F-UpVCl+FlrIwjYU)bB0IzMckKqgny-CLaFm-z+SvKR^Q|Yy?)B5`QrW0>mGQVxo z?uV6daLb36=P6)wjg_0D&!b=vW-lyS61YE9=_6t{Sb_38Noeb=OMi5LFDD~c1i#|J z#&az}w{q^bpRaz-A#Xa~_*%5|a18+m0%#YgDoshG)$qIZ-q?dSh`AX>s|aIqK_d;-B;_cxQ6$%>|h7jfF1qH67?noohemtb&*x! zG2EEw8FFY3?H9frRE4yr$y%E8%d}7#yIPz1Si5kM{%7IURGNWgf&T( zY0TRoDAIQtxfnIA$h{>XpC%bNgX=dOVXC1`UjXJjvNf>h)jrLmMC377cuytff`D_c zeXWCvtt!FgJ^?4<>|yeOZ}TBbH!hXjT$?qRG!s4N)f_8fzxg}4Q>B!Qu=KF&fYR_@ zTZW@G7zZrI4A`_bCNY-8(C!O~h|65BgWzo&!VnG+?i(u8T*2?~!z(7=UUDwJZb5N5 zc;DTbR+8P+=tV6z-5N;RfoDP74`6)SlZ-&5a{0ewkmW_B7zgR1)eZx*-U9pFUcp?# z5t2bJ$1eB;&mhn=Bo1sRd%gE|PGc`-O^r?0oemAEW%DjE&a;Y#@$n7d9NH6yE7owg z$k7q+V!ikBGXajbC%K=p*xL-Sx4GJ<4#KA$Mxq$P%!u6T?$i{_w$2^% zn&=$;_R0)+hfog_7XdNfL-B>oNF5Fp-#O4AuH3h@ocf+~%XM-r5*f1Gd{KzpAp0<3 zql&><c}t;TroOou7+dpszf`K0{$^XKZh;(6n>Tz&$Ur$hiNX@8jy zW4U@*MF1_|@aQWwLCX++sgj4ke@^z~+tTHk?yu$oVAKzOx<0|1+0|R@^u|r`va(|* z_;h-5JB?3jC8?x#xziD%#Z7$>EcgU$r18^AxQ_?Vrx<7;=C(HoGt52dG_t ze~3JV6*{*`nE#y{!28mj+PrY5C+ACIQ?mGV{hONC%OMuJ^4w6*8M7a~z04poJ1)L@ zO=vQI{tRrZ|M|;|u*Ga43Xxs?<=%U1huy^J`1L5C96EOD5`n6O0l?9k{mh7)-g6@~ z@aBugo~!LMHd#+Ef`e;-P=_=2$4$caOp&dV-ger_P{luClw$$#Ev0;$KGTh*F}I)# z|8Xz$&3lQ>m12z<2=}N!+{6DuH!%(d>+<9<#-&enN%CB~vTiR{Q>)RehYb;~Jx>DS zT#nF3coX`mqr~k^nIC??^rO4G{=FPpoS^V_C&{qN!yrcm= z_`m2B;GgM@U2g*%J9gy=aWgowC^1{(BX`e|;3I=vf+WBiJrVV7Z-3@~Ai|7iFb98i^0icoXzB-i=wBr000Z|0DP?^p9Z$la3$U>P? z1WZcX7L9P=4pMyWNqfx4?x#k0Yk{U(6+@%x4xEN&O#xzAm@Kil!agg zD*zqB``d!>&ygcSNV~648q*GH*S|fj81(Eg8!9VID>@K=eC+CUz>MoFEj95IWoJX* zi}$>6{NhZOUcQZyOjYoiCm=^=rUX_H+Wh8XiP77MJ6^2k!;GG5iy}K>=j z1S&OfEC}r_3E5-&Tq4aZ2{ey50E)XjG8Awe_90uD>oaiG=F#{0IshojA_zh{_eBX~ z5HEqC&gac{8V=K^NF4Tt`z{@3p|R@B6mZ}QjZ_{aN3LI%+F5D+k*byKAaL85U^-vG zfzqms6V5jgf1pk@n9D8FTQfQKRma3`{yh>k7)h2p5q7jwB)-Q^(hY3&V*_GqM#3rA z)5 zfEe2{2`-f=_23T~*Whr}bp>30L!2N{glQ&x_`tc==Q04Lk!O-cbxBBehuC&G0E@Zx zg;sztv-JdEoowe9$>5otLJw?@i-BQo=~zW8v3Z`KE1J%<6tFddPo=^g_zg25t>8yM z5H@Nvzy8q^ZPQm&^Zwc^)8g5@w4J6dBKV1~z%jPp>7l_B`=508A3O+7N=o`1c+;pK z(bUvr|AmBpRJvb|aO|ldit*;AY{2JOuvE`C5?Q{@>3{Ud44BJ{tv7eU2nN2+=6tZL zXF#aL_ePT&H)0AEI=|nY51`V`)9t+HkZ4Zjh-!cCxTwFw9F#jq#H32U*7yWfnUJ$A|Od5^>eJ^+zQQfBI?{d)fvE<7C|g(Q*Xa6aAj~Z zF%-(F=$D@Dr$_IgWki1`hKD$Wj+6Ev!(1@Av(j>y)s-F6hJxmr^Wat9ghF@jxhcFW zi*gBrz`I^tzEupNQLuJq?`4wXQVSIfvR)|boZxbDfwpFt7A2S=cGD8gY~o-PxIlg1 z+M34r!QGebY}~4`47!H)3Of1sknmnThB#Cg4JUpv`qTwu5eCDxvb**f;Tip>hF;^|1~9mt^isTGp20Q^6xnA34~DVeVI@0B7&S= zFv!=}*LAr`tcP(dgP)w)V+H?T&>W^hf5r$xucE=Bqx%E3aKIEiL!Q1Mb=nxnl7Vd!|cCCjl;)h^YLvPKO z%kFN(?@6@$@NIumf!td~)_%5V9hPU?RF}5yWQDBF3&mKAXR?-oWvZmJ00FsYW_Hamp21SZWZeE!&zq zIbXJAGi&?xcs=hzJH|_NcfD3N!s*y6IFPJzf^+m-?XkgUXMQA1Cr|q5vUH?j4l9Ag z3n(;do)5b5e?5Ty1SP&Y#`v4j)}%p9qP%5G;g~yS=bSaD(4}kLe8%p-KXlm?&+>kX zQ-Hn98f~1%nGw|rc^5|Hg90vlDBZ&{}M^U(O$)`Oj`FTvu^!0>3x^oSlbv-~d|jp{LYO zb!$$!dzDszynyDkQpkHkW;2-uoSh|UnH^{Eb(s~A^nhHiqz5S$<>o06y;{81azt!; z3%c%}^!C;#Q**?v9_>!OfTUdQu;0SZ&5aZ!Xk?fryR-j!qXCEKa44r}pvR-CT*7HE zBd04(_feme_Q6d&9o|O!9L=aHrvCui%Yp#Ou}U#fT?|DMA>}-M!=T#97A) z4bGbf1bgjONg6o%w?zOC>Ch>^iO&-1xw1fU0g|8j4f4{ht)imjR0kpV9SONO_lU4x zbx@=(Nj-{BZhz5%+#9pN+asWQ*TtpZ?Vi+fTtRuXj-kMUrHABldr5o}!4q*rhDK5V`5t^ET# zeAYLh5oQ8E;;de-hS-;ajkT89QKhCMhZ3k(-pgX%)Ij16rtqAUKWV3Z_ACV}8Y z9=xat#G``@u>%|9Okc5!r*((mD{9x(cHNO!$L4F9f+R4({C$Kp>*ut80AUm zbHI($MB+fy0RhQIgBL*^u|5Ta%zayL3$6HM-T)Q4=mhj{%Esii{zn4rD!vB9)|fjF z0^or5lM?W{V3`!WK77;ADX7`qC{)RX=cNr+ zkw!KdfqzE(2`H`u@6fSwn?7-0*QEQih5Zi&`rM0OW8gsT3E6qPXTBA5s3}_L-tv{T z_`QvIry`G@Op?FRC&R~~{VJXX-nnAMI`$49?~cgb*D(bhG&AG&L9oB*e`Y z#g}m_@q6OyPxux95n}ZW5TskmdPE_&YI|D&;u>HiZpt$yaZ@V{!9j=Rkk`syL*5c}M;FE`pj% zfyB>+fd-!$4Su9wCf;1u|i=1LLkxN!#*&i*Fa&q z|Y|FxVAFeBlfMEMu8oPc3U2YDm4-NbQ2v!Mw)fDTdxOi&>)L7Zj2H+NQ{og z%cvl|6)mSA)Vd`Ffse4{FaL+bx2rlPKi(<)`2L-;AwoboPtk{p=gOd;?Dp+mpaA$t znZgx{=N!Q0&$g);;Dhc-;?31*?vn0DLoF(#K>KA`1U_)rROkYXCp7<~zI%;aB~D5L zqL+Hb&JTV%@rKB~ML^>JFksC*DJvj& z!m)_PnOa5Mz8pYr14>&zP=6J7oX<-to>84120U4{OqJxsWJ<-r?(D!RZ0? z5XOPz{-5u!ed|n>L)4Jr3dAN~9-AgF;^`Z^x;!Ko$v0{8;&%AH@?ewL07NtO3hZth z$d{RS1hgGYAcyW|XMvB#Y+nx!&_7G&aCRz`0tpK0+gaOYHAAK&5 zCqHt7PY{P$9;!nIV18CU=2T#)#8gTWVsZtAPeUpyQ1zT_i5>xtT+8BO*y}!> z@fYx#HB}aFA(vYZOI)2cYAO9u>{0^ z8-Wiy7b^8elsMtp*hK`8rGlwd#oxZ6>OUn1&>U>h*TFAO{s`dDA;ILx1%+$42MqpH z777MYd5;K;;ZN)gx*;Gf57aahubhj9p(EuzIE9zp9eDhABQ4n&kNJ^dkgu0za)~wZ z7zZ@Y-X>-*01_YmsNhGA0HS}nNgXfE)E$XMEq$xxQ$ouz5@#0A6+tAUUO49rjLr^F zRI<6fj0;j|1hKK(Sa_Gme5qOcM{N=*b5LmBAln|1-8BPD<@CmJF*sYj3du%SnBE@6 z!zVS4S=MW?t1F@hcII3}Q0oh4GfgaUf0avM25uBih^+|+5o%J4SD5XqsaRZpo+c)x zIhEBSvsGQ~Pi+RskHDyi89X;$h|4ITl<{*rhM4Zi2m}()G1<*m2heB9R9>Iu6a)zJ z*FbI1K>BSc+$Mv8Afgw)yON9_=;4(Fa86JG2f`gCR_sxnZLq7~24Rr*sEq_34ht(l zv4DDK3p=oFE=vt93FNsopslCA;BhKEHBAtkuculF;_d+U2c$l}yDf2jIQx?mLCE_a z^^Zh)6-J$rf(r+LV}a5b@dJF_2T1K8;46S4&TvM4fA`NG5WI82Afzz}p+7uphfDq~O9q*e!4_XAj22;q3Y|z5x!P z(7W8++zbw5Zn*>m0!Z3+5Dr1YDOvhm0GCkk`JahZ0x{yojT?|`82uOwH1ah#&7N+%7m)0(i80~Px&|@}N#Ny|Bha0xA zq|XisNlQ=92H{MNhIav!CaPt&W~ljeGx=9E0MER7bueaN`>xdXLe&xN_cVA{@dl35 zj%=C5$x*!jeb2e4Hl*#7E+C%}iwKokx*EhF@-9|6DhBsd5Ig}s8xSqw^#LHcyi${4 z^kegKRbpKQFmZ%zrg*+g#D2JX67+69Za;%R^gBpk0yEgI;}9$)R1y%13}Xqfr2dSs z+tO$OsOZ)gJ}rcS!x;n)%fqz>1fPSdi`$^L>vvsZ96ctsg~jlY_T3ja%`pZcJamTO zN;)DQYcnBIQviT0m{YAFktbnqMbC7`I++wSk-_Apil2ZK04f4>|-s>iK*C z#++Z_Qohw!fbI8aC=J?x*AooY?n$fi@#|qg_m_H*V*-d)_|Z&M3>U2RK$csi_)(h+ zH?2Bfu*ttB6OAAvlM5#SwFt`iz3quafKK({dT|HP*GWfru`)o#hKkLc5jptEM~Vlq zfT>;51CXJjHA#UTAHiHFvN(yPB6AD9FU#+-{5cCw69NKwP7cRK4!Hz&^p_`xl?3aSVBtFq zviOE+D`)80by+w)59-wAzx8s+sGErhVL-jU80yU|*7vZr!`CeyZ<9Qifpwi)kivC2 zt_px|$pb^$o@_+L+*!th5e7E?y+Tfe&aE&taP88s=-1G#XZeL6bbsywZ7pV?WX{6A7peC30FybzbtV>cB3y~e7v&^*7 z9ig0jCKoAa^bXXiia`7Ci&|+s#F2i6fc2!XG5&mFaNWCyjx!hFm86O-1jvO0sR8%c ziT8wW2~z~6PbQ@toB^87DZ_I zwbmGH*F^?{bm^i_reR?XwiGBT=wOnv)ePI3CloRTi^^qqXe17RGCNYKP#g!}A>9VG zXj6PaP((WrzLlZfGmIb72^&a^EP6R>=kU?e6#Tp?m`@ng(7vO*& z9DzCr7Awhxpk9|AreP->RVW;;Pl`cTgVjLu`PCHI6panhB_}T4}Qh>9J6D| zd$v}m4?{8=3mudTLwu9PtN#h)7;=v){;DDgFKqp;KW1ePB?UCFO;xcUMe2p}=SL^X>6*#15 z0rTISDK>%tuR@0ybfxi?bO*f1KSEiD90dKAw@ZP7KbxSbhu1yEW?}~BFRB4 z7cbZp4Eg@aqO3s%(xJ#uh9@pnzQ+Q4=RYn2L_j;>dtM+P1rXGL;|kD@--S|0YpVyi zNC$WF0vP&U8w89O(0x``$P43<&C`}}e;C60M8r>`FBjsZq2h5 z4xq=N;$HZP^?Kd16Hw*%LqyJT92%rp0ARN)@(jS`zJCKdG1&>%?Zw&=kh1WCx)dIu zN}+@R^CsUGIu1P{VTaMW_3q9xMW{VZo2qVSuJqa~t{Nc5A;VV%@V()d3cxV*e}_pz zPe>R=WMpK3&UV~{+D||^7r9VLmVSdlBzOc+FoQto5N+l4!Fg#aNhT1E*2jdrZ%tV= zfu|XHPx)3ESiS@J21O~&8ak~JAg!X8n;*M!2Ey$ zMQ9OsMVfS^-+~%k^a>ru_Oe}UzC>%cuMQY%dh>-#C854wuQ{RqP9&Pf@_J%K_(wzD zYq#9$o}@~R3WQ5JiJf;ia-HVK<^K**DG>V{IQ7i%raqB^;JZA;DN-K#OLA0{MdwNMn>WiWpYcCstz>@&}8O@e3rCrWTXQt{c1zrN=T zx?J|onvyuIKs#VSRAw<2snd96=7W%@g$t0CoXhvN%GG!-fctR^pQNo5%TnA6l_SPI zHAtRlr*aL{&>k}THJwS6qlvO0*%ZW_|7;3%C}GhQD3hd?=R^3}vXiBMMif@)Thz1) z;h(3YfHn)2&MThIEY|tp60Hc0@&3R-)<;Xbw$nAp(|l)RX&h@8k8@IGB)O|iB$zaX3K=nL0qOG`P(f4A{MtXs570^Suz4J3 zf#$;yiV*9ylgIjsmAviAHmh|#{^k`}f$%x9$+J^pZ*Q;_-6Aq8W$`*tB zv~`VYKv59h%KNy9Y)v{Yz!L#ojq-w+uZt;;^*q8kWb5X%@>811fy#Uvh7Z4WYFaOk zH}x^zixr_5y+=4xDn95;*M}x1acBCL50bea&bxOO`+7CTLc7d(Gr?Ft+hv+wXOLOJ zBMZ_;`+~*#yGlnng*cdj?LzjgVe*h{^rT**$EbuI?nh=aDbQuq_vJ8~R7ll$74Le+?*I4}-pf?~L%43sn>@U_xrxY2=!+Iq!i4d%RrW_>(7Vip=iYe}MyHVZ%bGq3!a=Rd2#-^Yf~I z2s!S7*W$W#C0(J-fPCi?w9m&j7su@gGir_B{p`_XW!x$a0_?~|lqxfTfsed{^qNNz zNz!HMdy8_WAtTeD8VYSadU}d(#9Yvj`E&F%kQXhdIDY?sJ9=P1pT5Z+9l59L|6_Gky14ui+w4;2xPG|l2;_~7Bn8h*6WlpC4H@V)1Z0>o z=y?$bwcZ(w?;st}ZoilBE0t<4Az3%ZOpGzlISnRt%du^~P? zP?~<&iS*uCpopf%`-vS#jZgTR=fG!&5Vl85mAx(@6O|I+MaQK`?SiZDv`m08AgmTb z#SaHTlRAn-*Rpz~UmSjR+SmJgtS~s6*Xoay|GTw!UwqB$1s~a;yX^ysJti7=Au#%TQlC z=%Ahd2hRrXfsuuqTDzcgvwH_*xNq-R|78=%VVTL=m@1qDfTy*1?=H`2W8Af|pgH;I zUY5jdaBbSh1N2w*d>5rS#%KySYv2df{ zhBzr^1E6Vv%~6$sM8}AzTs!bTIQmfFpdI1mc@cwx9zy-une}Z7Kj6aH5(-f+2TuKd#==7ir<1 zbLz#4JF!&NR=UkvA$yFR+O^;8CRL>q3{GB~eUDG9jXTB>w_?SFiXx|J2RG5j6S1ci z(d{=A=3_KgPwE-+-WEM4ljn52CdJ1`DUP4bRBs66gj%3v>3RH5C}D^2@6d*xV+!>A ziUnHn>GYf;C_Ar`y$==)-04gO$;(4g9TSxe8*vmNV|Hb=wVFBFe%p~{DnL&=*psftfb-1 zGvhLb4hA9)UZBs|iEX1!>8k&}y@*5hQlJ!lkZ{64HtGTG3bH3*d(kl@5)8cGn~yx2 zsb7>nTp7^4dogWOFnQ4Q_q2}4tSop1)Crt1Mccm9KGB3?n0n|rKYzSE6L~h640vK^ z^KAMgx2wjVf|;iWAPkQ$2J_A?GG2|MbJq7}>i;ZiaISRPXnsl+v^?Z~3m{lD5AKwu zo0++Ar;H+jx_AwZkL`&}Jk>DK2DF4KQprnVw9Jv=CG*;=^ods!Q4Z~D%C7Nhv4%4w z^oHLb^q05^%E}T#^wDb&2wYV=cMm^5L!8Fgcd~!M*Jf*N_Mogq2(ZoyOP&N}b^(4F zdcDd;|8JJR6JZ)A3bfx9DA{ZqNvL#0Q27GoH5pMzl`}~S85@1uYQpOaQ)Bcc z^WJ+~eG(I~Bb>v8*sQk<1u&~!s__HxQ|&-YffLlxB@Rch^e9BpN-Dj)3DaX`4wUJj zP3pm~9H{dAvZdcuDo#Sp4aRGq=86Y)Y_KmQOP-3D5|Aw20@`EIo%ORQ$n{O&*!VU0 zWUYNy>{+nyw7QR!Ir-@?cW)^@aSOWi?FqRcxv$evW4`jxfvFZYiT5GmKyR{j0X6^c zr}l$Dv@SdSUo#%!Tkuyyy(lF{8R+?)qR+G6OH5xH#K#sXjM zNQZDL+Vdf!6bvm;2gv>j*3d2}vl)qRh`pBb4b6CxXLoy(|E5;1RQXt^Uz&0e7 z6@%uv7h(HeVWk6EU6V}FQ5*?iD8qF`VWT@sl03lcSbpAJIH)(*tq?*L(7b#ww3+z0 zh~}fnvEO=q)Kv~V1I21ylE=Cc6>$ZQ>$iKZp6I04@0E zZc{-f1-iWZKq*0Fkb3++1arO!!|l)R)FVqu%p3f}pF%vCLxi!ZXBzDt_`I1yCfsF8 zpKipq^?ou}c4-u;ZCjbycgZ6Fm~**UwR~};AV>+F7%Ec)(%G%Aj)Sr1fmL$qJ|aI! z>l|MyyvP5PFLR9k%4my{^N#iE=}45gUQP1ikbi?x6rD%@pySgwvTb{y?{FT}ESwYm zn4}_l`vg{WIpyqq-2B(cAPKe)l=C~KLGN#stTir1eL9n%%-nIltRP$$+g5d=HqY{= zjnzQC?QPH1n$O&(4bKpe%apf#QjN($dVSBlr5eUpDiD)-df5Y9y0r#T)NdpGuMD!AC*um8;&$` zzU2Zw`p~YvMsU)*I5L;Srshi^b4@W~F1GHiF>&6vPPTl*5xR)$M1rW^$VxATy9wW6Luc@c+Pq-l=*z-Q zs*U{Vuj|JiW-%S!y#kuu1X1`W?2rp z@WqpKF89*6NMuMgCDtg=FoNoDOSzMZhh2)`8Wgf zt<4ivnxWDXGv+?ogZZv@v6%7~>fXy%I)o+UCddh9byRBA2jNyk#D}L3%no&r)S?mr z2gvFrvpX|FFXkx|sW5u~0?K;&R0{2gVfCH9;MO)}Ts#!<2eLn5Q`k8`8F)Ow{cWA!VvAwDF1}6zq0yp?c)s}3K@}G8PVrLn@2{) z{g`i8OW%7r@1*ZllQJ*9V-@ec?&m!zv*@pOpccoS!5K$ggYfh`-2{{WFo3byC^?(c@#-=EBt5tTV6=Ea=M|{ciz3359)z3QY zdi#`v5<`K*Vs={$P2!=|SY;XJHN8y}zD((C%jBU-i*}BrBJbS^?|#qU%1A`O{xTVK)AL61JgT8^6=8la*gT_sx=nZnfYQRE14tJSj2~Q6%2JNSu2*?vuLXvxVx5m_W?U}l#xv{lbpK0Nxkp)w=8Y|~Rb zcXK?M+mr6&>9UE>+qmo=k{agrcFOlA%tr|HDC!9AtXz*Wp2C?OD@h!9J!&rD$#Et) zK&|N$2^wS>e-|-g%`UiFN#-Ib#V^8NU`?JFX}aFuuv}Lwc+e0 zL9c16$|vGHil9#q#4-J`a309Q-Dnv9gDqTDYO#85JjRw4w(zyO5yMS8`&P>@<{_qY`302) zqa3QoODnQhe7SqA#E*AMm^3HmrH`x|4-_t0H99UxD>1OyVTL4n@*YfwNQ^Vw|6_@Y zAXGLrCf2dTXJ$A0LTS8wh62yF!Ff6Okb^ogN0RTLp6_Ij&>>xc)q96#t;({l1sb-z zYC+WMl+3;HoA20IqCd9>-Wcuab7&9G$@}C zY~7eIp@BhwpX67=l%{W~qd`<{A6Bv*BmJurwV*RVr?~rm!!trUW1v1w&r0UDty_aZ zQLCCPi~BwY*VYAKt-q@DoCpWjAm{_Af>bb8NCk_yNwhb9!l&?|Jzu=qm<2`trqjGs z&6H;BfH#RQUHOuy7q;d!M!#lLFu(4V`RXdyoKCOLxb8e?FD)uw`Kc@|x*rv^p{Ss* zz0pdbikYAeHa818WZ{e~tCnoi!6)z}R{Oh<#WQ;68c9;zRK;8qrN3C-iIM)T zW#3}Y#_ASefwsy6dSDLZo#h*HUIYl#GlzIcJq7zLj+w~o4(7z~Si8*Tb{^k}l0X6! z@kl*D&&{hPq|GzSJYi3D(@mg6`-#-L=g!dWQk~UbT3Qk&aYE@1gA&G$D4~Jrx@5(% zY;M2OW$8UgJIi;P*7;+8IyWGu7QJFYpn*^s)CGJMhhi@QCpCC{kSmqa5E0bq{aL+X zmmTnX*iWi!Wp+xptO?Z|==EV^LFWjHw)gIbSk1Du+Isnq;6% z_3T-}=XmCzcX>(7aXBwA4?S&Yksp_m-EgSbMFzb@I0t&l%WkusO$O}31Vb}fe0A}i zVcoN7)I`C2>{R}mF|tg&S?j@sN^65eoWZmt#ehURc3|s6l#H==^u|ycGNa|FO^f(Q z(A+)Qt=IB@NO}QcgL95g(2WVV$6w!8fU;x{=;Ze5%X`rC)qW6{a4GP8cX6xy5R~rN zb|5H_DOwUUrWW|)$!46Ab$6WSc3E`g@1Dr%g3eSKCuVGK&E`C6;$pFy=akm<214eX z#S4Lb+9?mb>I~EykN)Mj{ml6q&4Mx=>K3;BnP+J%k&9}RuBsKfVOUE^lvgoWM{S9> zwlF{=$LGoI)Kuo$$x8xjdiJY}1rtJF>9HpV))lefLp^>=`@o@N2!*g3PPHmn>R1Qu ztOKQs!M44#H5Tj1%{Z}62M9bGA#0oKoHy8#*B(uDOskihrz*^uO2lE9`a7*O^GyX% znk-A%{pFjjc2f5=k>k)uABvY-WXs)NC}!-_%Z3l2T#;*7pJanOv1&Muo%Y(5aHomV zAu@`#`|;Cdq8$3ur}dJNqXIqJlyU?F)$;cu3KZ6B66oZrPKHJ2>$k z_@YXNTqy$wm0^dFCJpy^nVF|}tbVKg*rsKTRD6MhewkxxPwnZs+|7c_Bh2X&S~)_8 zLNc}kI=ch*zOZdy!meVxOShon%+Gy^G5s0j>H&4JT(GMz02c4E*{6F8_p=4<_Ycnm z?|*D_s&S>~D0Xx(&Tsn`-IgaY0p^T>({Kwa$A{JtE(mIbCXap~J zrJ2;AgyI8fZ!Hb3%h{PjFAvEeBU$aNGS}=TNya7Y>io`GU>HQd)xMmU7B@>vns5^= z<1ei!ac=TE-H;qQ;skZ~JC(232tE3PYtNw43DxUXd{jk|tRTn0>-LibvhahhlSBDuZrff~$b0<~asKD{s+7r|hXUA`VXxmRJQ(@EuOg~jy z1xbb!BdxN$m%ecqgK|v7gZ(f;s{temzEh6TIPwa7#CxaH+sPo$ni1B&=sp~vKjld; zMDwK9ID(w6wmOZi#(+V5<6}N$sJKM8)$H%>Q4eW%6WXd;NjC4F+jg5v*gIbBH>Htn z<>0;HV(|9hmp{(Wp9VR91FvlWj<*2k5B1(2nRCK;80C9zt=Th+S(2s{3s1`8uXZ?rAn|RUM8A(=Dt|b&LH_lhJj#)N(euTs?LZdikaJ zT#MAJl|P>H5%QGur6iov52PJf62LLOE-R942j9RGwQX{dqWmcPUftLdOWI{}HtbM9 zmF4Z~k3NCgC7Uw$;?;~C`gj#t%ZBwA#xJz&+`r8liCmUG%%*HRyM<~m0pE})#sGQI zAqVFfz&QDfp~H0cZ-o*k9${;em8DN0lo9Y$gKTp6iBHQIX@Noce^keHb;^U@jLAru z+I+(>53MYL&+`<|i~8^>F_iJIzL`E(Oo7Z3Y)SSLpWE_^-gqNaE-G6v{yws0MrL&- z(q+;%p=lrVddX%s#U78%g>B+oghyDMWJT!^h2&(ymp6Qe!DS{bGz)?B+Jh&qL@3kM z4nEpom5EA67PUopd$6=PG7mgxz-%;*7>*O2R`OUk`Lyt5@L7wJ2%Xb(&5Pk`sg|Ak zRM8r9R!g_zsM^7c&Oq06+B7)wXWjYGx@~;4aAZ-~ghXcJo0{|H4&Gyl1h2fmQhJpr zjrT^8_#%TFZ6XEzCBv+WgWT~F&vcn(oUBUbN<+3*>}8^sC*_gxNRir9h2tLS%iQ*{ z^HLk+0uxoV&cKLWKqCs}A5qvGGUA3)Rspz(;){8-`}ND|P$>tvMxv)qBq&=jI5@1} zFRCbFH&LJ_kX4WIaQ(D;s?JKp09j@yZrp0+n(5e!K{=o@A4qUtmfky>Z7Iv1N z+?javZByadR`a5vxJh%BUll7~@1A(v+NL@=TdWjFC%6O~JcaW!idbvs(@vL&mQPqT zcPmA;01Lp-GlzB-+1=a%s@JsFW@|j6W}l`wkQiqzd)qnhhzcni%aGt@6q9FU(CaaM zpuHg;*?Y0tFXo&AT7gGhNbD+Yrgx3Ck*iAm;`S7F%)fJLL_9~uKx?&bv8*lKDd`J1 zg;AYG`@5;0(#e~n;;K#h_n3O8Kcj9#<%Qx`s*?VHVqe5fDE3_&Q_04~K2UEJvS}HR z6b-re1}O3tGz;X%)+<+jD3CR{1uj~>(UD%YSRFp4B+>th$+Ms!7c)VP*$9{Ky_cBp z80qM>Y4X}%nvR)Vut!X`U`Djlu+?+gU|`sFKh*xO;TCA2cj$}rOJ^UzRRuW=!q8f7 z0WQZ(pLi-|J(g7)Fk!gSW^agE)5B=&&?zzG4mFV3E)G#vy_CH3!Fz`X$764SX*>as}%p;OZP!tP5*;1=)?I&%Ui?)V|xZ`}f~1`tXR z;Rr7`bm#*kJ6DZGUR`@(lYk4AyUGB9Iz;h7LD)9wPaT zvp#lb-rKv&ukkkkps17sksMxbL^{-bs>kVMJopO?jG}omNz^)o%$Z%{B~6U0JZrcG zfXsB3zUw_xHJ81#Z;MKq?M5Y+fJ4@>VD0v%v>p_B-fNt|NlO61vhG6^@&31$xVkGt zGGf!}Cj}@(*t5zchX7DfB`Rkh8otU9$$mXZ@o*e*~hBnj<eK=iQp^ksEF4;<;abHEb%`!@8!(#$X$f<8+y8Te@q;7vm1udNT|2>vemDGF|y92*gp*rtRfMBU$byHIz(dBZty0oY zGUQ8@W^zr2UWUA3?k1{coy(|6cLsbHa#pZp;d0@=kF7zH`D{4q8nA6pk~TmCVK~1S z^mqDt*2M~fkUpSUA#~~^hMY?9T$bTWby7nQ)GgGIaq{@|Wn#g|)5gkWbg>(KneqJ% z66@_9yX0f7NBZAykHyAIaIH?H4;QtRnbKkbk-KBC;{zBfs3yomv}cXLa52^JjBLfOYTk9Hf{h@69&x@JV9q&INp+z7km;xN`z=tiA+8Ek{Th7 zs`;{z>vFU=1C^ogCxy|FSbklMrBw<9Xk$0?K6=G>+KI)golEtYJ=f~HycV@%Q&sjC zQ@Kh@kMDy1!mc+C^=FJF_cMG2J|OofC`UYn;eEZUR;B}z$w$PkftK*DA{Jq&Zns!L z;@426;A6JrQx#v$K@q~gQN778!OD${Y7vTc;~j8(CV})~tKDd}TD0<>@L)l$3$VuO zu+=;j3PU>nmS>gDqV-cV?69h|U2KNZMi8~IZTs#|_W^KoI!@g>oc)8Oe^1}5O+$&0 z^|v4|+cCZkBo*Z7z0OdUIr=k(HWjU99hxc(u55lx?Ex(xcPdKDgj>)D z=d$%%%;IWi+7|R0fU1N2f7*NZzohT}e|*)fl`XfGr!LcNuG~^1b8e!5ZEd+OOIGID zz(eJdmIr2v9L&nh!(ipiLkeqFW`cOg)Do~fkSEyYfetF3DN#@m5dr-?UuxTRUGLlX zFZj0KCIK&Aujljed_3-t`~Chv)}nYi6g7%gHQV)5n=T7nB*(o8c}cFa=~x70GnN*R zt|zwtgY^X@nNH}ea*rjl+PhADw44Oge{Wm^lvfW$99e81WY*SYJr)FR))s^Drc1Ly z-_)SDnwt6zcB@H>07R%0Z-^Wn(G!nNoI4Xp!E)zc?hC37s9HokFvOnDpQnF$$jUiW zksU!{u;$77#ToSCJy&4(dBx`MGq4M)uDv{rLznKx|K!z^e|>AZY5s?3&G%&9%^Yi# zx*;0uj~cEzzNv{FeX`I5bgIWvhRO92+nfPy?+<=$7rtH3)jTqFb*m!pQX8juO&;lB zQ`+TRk-BCK@KyiyzyroPI`enSEd2-sJN+88%)-0Gst2|<4|w_)ylt}|;U9pNI=1DH z6X&s?e`r{(VxtR=0L%j2zhw0#9!O`yucS}bKZ z>p<LLh|)yXl%3E zwQsySJfK4JtpUo1q?zz$_sp279zBUOERrkM^%6B3N4zpIBS{U)AohBp5+qnt7rpp6 zLlGT5aE{2`Z7;MjB2oVsxXk~U!KM0&wW4SFZ5CvUXgN5GWWf3JlYh8wN1-*jGxzJI zMGAm(keL-f1O(~V4Q2@pr8~0PUw32;ulb(Zj5~326j2itAD=OQhErNIf62@#q8-=b zYZP(iLTs-CJC$9NcoCgvwM$bGoH-UppKC)VPKurzb_U$lpn>*M2JBVousp`nCImP6 z_V*z3_PV^~-%E?&<%ZLJ52}cAqS$pNY>ad`cxJ;(#UoQw>&KTh$?JncCr-4)qO##r zPa4iYRGB#$7n%6@jk+*$n8QwJqP?>~jTwqRByJ0TR7@Nvc05nF@E;G>?vA;G#d)@> z&0_2C-l7yR5JOHh{ntu2sMT16QhnC?PZIn+lo)+__?@Mz1KoB2!SIMce_7V@6YsSb z!0Q{+x9i_OJ^LPJQB(Fq($cFWo?-l7l1KKjUX)BP-ugJ+*>nm8|iPk#V9K84g@ z$k1JZ3c%Y?)qBW)^)ljBSYHs=|7;RC2loLZS||EGfSv?j1WdL1Kc9u!3=SQoE0JRq zEB6|u2}lVfv(R5^0-VO`P>j0T)xvJS47p~8ZR%E4EpJh`-9}ELS;!9Y3ypZ@_Ls3% z+Nb;q$cvA2`E0z}{+#wi*I} zzi}sb_IziW{!c6Y;W$7hh=V2knVxU*cfaBc6sjJ!TsgF~N)a1gHXYZ`tA^oGo?8v} z-`OkPet!6BlUi2&iC0}rfM16(ANCCb)b^#bOccYphY)T7H~NRgF4t^1UBPnMS6h!(xzYcSu2M3rGg~Q5>8tjI-24ozTp+%ZOYO zc4R~04ix8U+lCUvV88$dkE*b}t@HAP-vXiu{yTr~9gsZ7B&h#z6f&7F=Dzm@XVUojY6W6H=?Ka~SZGAZ8g?d-m4+z*%!xS0 zpSI~PXq@Jb%Q?9zq-O`n1H^Y@a2VFDIpA0+>H~Gf&BoW&_0vNTQJ`<+$!iK01dT)b zM=222PY+ss0h)Q%UiGl`^P~g6=b%)N&zm_Ds})uA;}^ngt7Y1Fva=@5F?{rVLu{b_ zL6OP*W+|7pj_Pgck%MY~Wx;Q;{iEN%AjmdntAapTI;d{C zC~wh?%N++wu#>S(#=a1_6IuB8ZHdQ#;36e_woI-E*dfH%+ZI*7s*k$O_0kfdC*$BM z-a9{N><@mB6!z$+mJi#bLn{I-uQ%Jc2aOAj^M3a!p%@mfQx)t3sD74^+w(T#s0cq* z&eCP&WAQHw>8Q4wntYK$eR2Wls=E6Q*c9A*;fBRu7SZ31*BW3jKH>20Ifrnvr37NNr7 ziyxnl*#FH^dkJmpcb2#H;k`TyHAGYT&hvWM{v?pIwyoN=`uKEUk&Vm;As)U^ZI@HS z-7%S)IUg11>=02IXPfvJ-8`_zA>rQcaoe6R!>#)7dLU1-i7^(YK5FWf&c{!@n2`ch zuavMYD#Y0LpkbZRC4ARlt<}^cPn2dv227QX|Lb+^2Pd;8d^zZ@HK0@GU&#h87+E$P z#y5Yud#Az7U&3_WE^EKw=fh#isfJ?E%0^KY{zF%+Q79jTa|Na|tSeLHLM0wz4?AeUa!9(%8YQnl6&2}94G2%!ed&k^8Wv5u` zb-@gv9WQRt#l#kN+i+ujnc-mLiCipKQaxis^`>5vYjuP%9XgtH<$`xcZ9PH)oMU95 z4X_IK{>o{wp9!MQe%%xvl1l)58YmyS$OCJv%$8c)yQ2(rqx8b_-fc~9o4!4izJ}(k zjVMOb<$b=ERdv~t)CNA@mak^zwSQ_ET^7N)1_fX*OQKy6`!fbIS`m2m19yjnKN-*c z*srP(rkkqDri!<>rI_`=t1zQw;8rT8lf8sw{za`KNA$kC*s=$P7rrh)K3qC8HZ3i# zHNFFvt*I}eW?m9w4?lhN@b`ORb9GZ~L)uq^Q}1qf_KViWB;!-RhmTwUSW~dz3i{AV zrGuMCZ0dz*aia2jUF)C=7yfFnX_q!GoRH_ zNhZAk=;#o?A^hIdKif1_Y|->q`aT*k&}DYQV*kE2P$B9ZmywyW)z!T*9t%>{IYuP) zi(LlsHzEu2OcR@?YQKwO8hZt0e;YvgbN4!g`a=ImL-KHq*0N}APN47+wp}-J=eBm{ zz2(`B-0hqNX%;BmnP&}S*I z4oVLY#90Z}+vM-&zXof}AS`;TS}A-5YHG8Z)qv+Nhe#1CH|)r{^tY;y)T=4$2Pm9_ zQ%}Fvw2nT0q`kovt;VDLCih{Q3TV7PbVG+zEXGBeK_BoGHQb_g5NUN_WRF`-jUDN9 zQ=k$*{T(u<_x|{LrIChuCB-=WFWt;fsMwb6R-R&AW6L6tKXe_VXhxr}u)ymtLo}z$ zRun2ALe`fV*FenfbQm{&3B9X-XUiXL2-u7tm1Vff1l0puH_$~Iq1oGQ_|#qazTbiQiO5f%dhuZT*I0GvRZU)(8siek-2;_w`Rn<#80e?Y6@9@{VV}R z2%gZMJR77(2+2((iUQ$|O6N}4_|IS7XK6;9KP8rQHsGg?tpNd~*y$;{VkE4oiT_t1 zQHNbnWcQhZ-q?X#n^)k+BnW{>avOlo{iNufzbzgi1D74Data>1#q9Fx1cGR&;yY9h ziS>Zt9(U}Wqn@LcqV20FSn81AMz&q{#>N7v@*!3mj}#W2Oh=zaOVlJe8=k6ZmsOA5 zxD?aEzdzS_Er!w^G_J|56e@IjUAONpOS{XQcAh}jX6-ALI2h$fb_X^Mgr?%;W;LfdbBY{EEfzG`{@iyB)TXw+#5v0bHs?`a zYq-Y39*f`y5`I8T>L8h7+<0-(k)11r`TpBb{F<%D_kza;&g8@H+q(7RzPznV{XEc+ z(d|jfCT+_$Tt(f)USTC*;ZwziDK&E2{b=V{tY(74o+n0*-MB4rUb{(*J4%<6_p6H~ zy{F2!n%wlQRi@5$Tn$nPpJ6GF81>>U8j3cNpYYS%Gc1@<@hp^+DWEgP9ySWf2a=dr zko=my?$l&_w}e|yuEzgZ_dyaaXaJ30Ue0{&`njSq<6mt2ak%l~Xc#@DMbBjqml zv=hm%u)~NR#kPHWL*{=09J*Jd_vd5L_NRZYWRvSpR6XGf3YBij1TNm9h{}Hyft-yh zC+nUUDW33;SkWb}>v%9v3d=Wo{AfOzC3G|F+HPgopN+Plu+aIW*{PzYCgSkF#81fp z^St@ZN?SDJ8>pf2iIEE*B546=qqoLknIty4*LW(M;P&w%=Wz5t?VB1C)ty^NQ*)3% z#dlmY8oNe$d`A+kd;Vg&M`sz?0n4CN-Iw<~e!IR!?VKAQVVuKr`rt&d9*#=z3{Y~($Lh5kij_&+RoxWbqWYa)CE@2zLsQ4Lw z+C|n7cMv6s!Uoyb`0=NZSTo!a!6%+rdd!xRXgLil6a1fk>59?g$#Ht$mdfy{C@eT~n#>{#kcV&b6MRBIw52viS@+3=zBwXuu@ zzoyGXu8s@WMkxSay{_A|ou$1y>fta%9p0Q`{qU%=b6<~CME+UTlq|Z{JOAoBPf>S` z5A1&9xd@t>zR6k!mu-%NNbPZeV1^G^;bEJVLD6-pp#vi3o24w73&jBoC+ZS!$t-7e zU53<8b%I{__=>T+m5IY_1*RybAceivj+C%oZHb9IlHnq_vBN2+vv%l0+v8i*)5qvE zG%R}b0+DmTVJ@nS4in>C-D`#f>b#)}3qC*1n!yoW-*Uldod>FtFbVKQdp4Xlfx3>* zmm*)jXbt~@JfM{uY8ZxLM7SoOj(%4U{}O_5&rpib~0?3x!4@sME2!#|oX=<8pWwjh}KQx&6KxRcixi46gIPZb4s4#QJ_-< zGbTVY@?N2DNAfxW9Z@Yyckf6OZT*{nFET0}n(ONR^0HrW)J}$`ywMgsTztE7r|0R< zB;lLJn*T~Sf7%vtCB>k@M>k%=mVt>N`;%AN^1=0h6o3`1vfAUmTudKMf~-pcp4WLP z{vL?78;`6?d^L8C;{VnT%rRDwXS9C8qzH5r39l1l- zM%5pGb>N^+4SvcPU}hI_hubtVVdYrj>|ojlh1t6!h(U-bCV#rP26eN`zLF=fLXsE+5k*Z3Cr-RFFxcaToh2dr%otOYIubEX32)|+|w;MM3sED>2_uVQ?tNz=d zVQumyZ5rIvs>Hb@Gzj#oN}D#P7!mx0Y!or(Stg)!uxs$s>125^0vKu~b{= z0>t6BVO5--(B0$lXkBtdLN9(Qcc0JGBSQ3{ahx2bg-_L5QN6L+`Hy_#ag-Tl+qc3; z`~)=FRs*z)AHPPZ*LXoUkN6whbLr;o<&~WUwph!p@wIpNN|P-Qx{ozcJ`#@(Zts^y zz5gLyE4Z=W(E1V!34va2fY37DnwHXJgRareT!=Pc)lSe(4BSctD#mnDnv~>4Fb_7hN&@@~1$3CN2 z0Nw0*Eo}wi4n&!!YdWH#V8~sn`_w>i`_mF-qkiv}fupm+kDFQ+~>`BjQacfgM|%z1+MRFTobH2b5S%3n(iE=@M<+w#n>?ecd(J@mz*$=drgi{&7`3KV z2_N{LMlLCpJWAoybq9RlQ!Q+g{FWI)v6DA6RUmO1td6I5DzZ9T*LhLZp>jf1spJD( z_lIk-JnJL8E+oXj2G@59;v+gSCApo@^#vQ8;i!6KkWGRb6xf^Qeg%=yPrKnBrYtar z@vE~>If{`pln{~~%Xlyn_DHKp_2tgmZ$znjJr$|NV=)4(v;y4&%cK+^IE|wg5;-) z5Ahk$6|(EW#0(&1)$#K;mqr`J7xy^mZUw-)=FbgRG7M*QQ!WZJI!$!_s8{U*@m>Uy zJ;@ctk&eJl0%e%EVR}9@VrSfQO|iXHgy47wGwF>OJY4$f%63N*dplS^^&zO#HF_?S46x{5Zcf))zAj1`+>*_ z^tkS6f&IvyB}!%RyF2UC?=w+#-&NX_77m7OD*;45`&~Iq%*2UDPeN!Xb`4boG)@n$ zS3kATfY_kcOa(@VkVur8#+>4w^P)6#9s_Z@qlosx#5X7L&Kglza8&PoQiqXeX;|af zcdm)`Ay^iFy3dC9b|^CF><@S%*r=A2W{N? zeeLf<8}~k>Q+om{+%{`1c(wMow_qa5mc%P-<1C|_c49PXN(GuZ_L(fG5p*<`T20!0x_}Wd@Vuc(ZAS7RJR|wSHSts6hANludhqh&*Wxa}VJL0* z*{wbUsEZ)sG3Z@Bgsk*d;^6OZ!TRlOGiX#PY?NxdpG&eI8mIvH*6@JRcr5Y!BkN}F zi9qtN>vl07C<4=K0u|db*`qn4>lb}3V*|)r)}**cPD&NrxuJn-yXlC*4dLsRqr|aK zXl6Bv%Y=8;sSj0kCZ4_a+&Ku|tDOB|kQ`f&`?-g1enJRTt!IEkBr0MhFZ3&f6anl% z*JUr2-6^Y~5lhuT=qAwnjzs4}gh(8E6^7{qNA)md!5g5kACHrrxG?+Rkt*{IU>m47A{j}?`w ze@|ij%Q8n^K!Zu01~*4`Ck>l0lnE%V`mf5l>pabMnRrnz=6w75A}>HK6x`H}6C=>c zS6IK!ZSD~e0!gAJH*p77aX!%+R?4;1)$45OyvwfrzWbaJ&mJHy$xYXd1e@NKsESj( zPs7L9j`nI@6&44}Xwn?pM{9`_9BCI9;aMFA`x(#5(xzSc^>`6+auq zNgc-Dv+=Qymbmhxqf@Wg7`i)<{3SzS01yu|9CZb-`;rtU>}1oF`lee|aRb-e%VDUU z&kY#za7rwx7M1Ev^BD0RVE_?oY%012=t^yhkBp=iA^-4=s{n&l2F8TE|LY2$80QBX zk}NRO_RnQN1&IBZSRN}^`28x*r^*l=H#Q0h!!}<*^qz(yHp;h-K@8dJJ zcKx)eyfwumsK>VnxeKcan0k`Dt~7F>tbXUZ{M@ou>;3QUc5dYC2nywbv^M5hSTgJ^ zWpvMV(G|JjCh_;7Yne3)sb!F6j%=YwML)OQf9NExd)k@S}SV2eWJkV8av>%s_H2J3AWlWScrDroItp z&-d;$bx8PZ%mOGpz4n2uuy|i@bj*ouaXgw=_`n{%gk9Udch}h)3tgXxr9;|w*=BYR z(RTkP&Q3=E)E4ztkOUU^0CAe|QDk>y6C$x(*?Hjs#slRMjS4=~qFw;0sPhWVd1e7< z^IyD*oPE6vs*0fqI)-oS0ugkh-zt5&23QuXB|WyV-vEA*&ft3XP_pMRtZ(E(i1!+- ziB(;dd^jodg17yA_4tO8HjSd{4$W=dR#~(&YE3lLd1h4!$$2UuHo1FL=i~ekyr*nt> zWrulE#kcX?74$55cN5ZzYiGsw#XVkU!)J-YPfkAqjf!X%YGY83a$B}st4Vt(nsL@e zv}6{XrLd(MMKO(6q}1AV{p3ORH{sml^A)TwnoRPr7WVOT6E+>IiXtfywOQ;YrtE^f zNC!zRt3l7NcHwpZ4d($ZUX~>5)G~Ssnc>C((%DAcuW-y3zZV;(_Q;DMBD63av_~9f zr|Jne*fm2;pA3Yv-~10~de~H1*Zb~VJdVq+TlggLh8aGX<34GWl3T?$6_J}FxS+0( zthEN6fAK>%t3G{^`kXZ9Y5Oa#^MDhLWJj2~ooiJZV`HBX+!Tu?GAe~?grdCb5AM7m z*HEVW^YLZxhd}lt1Jz<^^55s_lD@NkU+d-N^AwQX&&p`d8IndI0M8*C#HaS$oaoY|22I@F|LZV+h0*^lg|5v zGF3;H5Q9*hMw=ZQ#nEcxIBKX}#0PP*ua#a6EQyy_v}Pt0Ce0a^5j*nsp*Z;fbd*<( zY89l2oieT*aEc{^Z9|E`g<=vY*eEYwuZ#U#;vWeXQ+QJ11n&6Dj3pB(v)@+(A0OC5 zu!yRmPVF)(#ykMB&#Z3V9u0j>(kVGtzAes*TIQo~O_ulQTf@b^Vmttp#*b#?A~Epi zm7sIB&1)0!S#koLH(N->2RLoRpJDlib@6?;qRHX-j#G2?K%veSc!jlJWRch}_|tiv zQ-K!zI!pmS3`Nr#M)!kpS#i)rr@z6^cOmX8D=FpI_n~!>vKlmr{Z>4UoPIlpxk$(@ z9q!3KJ|wVVnDyWXe~~!MJ-9dht!L9yKnugE4s)jtXrf*=^(*V4%=2e$zx0WS@7qUg zmku=W&lBmP^Sg`ea^eS^imKEum^Gzk4=nK5x(AUVLoXZhI|cHpX%3YXb@I&QHaySC zHb*%k?aUKLpZuZw!!gqM2RMIyX-nXl+FQmOmUwf(*$WZ?I29W02m@*1?p+2Hplv#v zI2)dLjn_{Mq9Kb4qCthuOg<4bTcLVfuOUZECQ{L!STcVwG`Cuo)$myD0$iaB4#anC zFJg0tqxw9@M-g%<7k_&iw+oIc!ds+BeYidyx$bd;B{Ht@uGH}?7IFk3gO0UfZ3rZ+fMPm)h z`F4Mt3qP#uy)iBxQB50OVwjby=iB9o?z5g)cHSBxe(>C*XhXh(=CNM={VBFl)zl*- zFXnP;TZ~mZ3#4P9`!fDcWQUw^S4!TpdA}Q*42c!N%q@dgD~oscQliyt^?fry768r$ zxgPgH`qX8d&9U??*!=}XI&JhF0V`)VO>5`~WCK--N4-Z1vx>}Mvx>o?uwuz{nyTAW zrc`&|#8k~}p`zclD?bqJe8yB!Ty3H3yl$EQEoZ8HC;}d5`7D`W!ON28kdTQ`c6zPW zLWv;7Pn__d^J8~Qd`oA8D~OIf^-bALjotz@H%_X7Vrb0@&7poH)JHI8P7^if1lz&X)^r$n}P7~aEqd%0aDC;^-Q$2WGU!ErV)_zcyiFHtL#=hnb zVb+P27n4fXIfTsloyig$S7m7}wz3#G+^82Q!E4 zO9f@uBx=X#v;3O{ZnpOteM)EUIEXtN97s&jgi>2m#f_i;p|qN(pX`G~wtHV&|Ck?z z%nTl-T)nak#{$Or@s%)U?tLy>-ML9(#vNiKS!wWLiV9>gi@*jQG4qFCMX$nk+vH3dD6D+r(;3 zRNyrWrgOW&ju+LJRngnx7zx48t4Sf5CUC##+{IQ~_5|c;a^O|!N(H+UTCd)ew@yJ- zjI;3{R{sJ*>&<+^T)xYOcF^~VRyDQ3?i=GXNYm2<^Goimh}5>EmxAgG+mpQ-bXvUc~f~rs;d}IP4~z^_&cW!wz-&ENi}ngzY?FHDq8ir zL9h|>K`&J*1(7jH0B-t2s z0#H>GYO;iUqB=Te*yL7z6|9sg+O0SHQUE@_%J<2+I4kfO%V)y85G z5k7T2(2T$bz&a!S+Dh8)cn8{PQ#X#^gmxOM{zUe%9x`w(uv}u6f}Qp;z4JW z-s!s5sT6cdM_Pt#8F|JwJESDFac9J+!2N8uh>n?yy7Sq?KXk20=xy_^o|CPNOT)Ev z-WH{!EfV~ap?>T_ZaDqfk791$-zfQhD7DN$T+RUGse0!vPs_vHt10^VWq%jPyKliN z{F;x`VuQGti~3QXV&GvciYsXePYSaw?9Sk|`7_394(XaUb1ZT?`HEb5LDhloRdTpP3rP|)r?MeCl@3GP%5y5( zZ9gh9nzIOz&`yn|q@UO|8u90v#7&>;pduZxW!`@6N$7YJy3a2|j{mwG(LO86|En*m z;oapL{p8VAn3LqXWXumu$(`9~B#lVb3RI>sn6h$8?I3*a>GRI$&??Y|x3@w?&kDRV z{QK4^H7yNk!WiJNdqVT6Q4lA90y_GCUH7lz^LsR$9hwSECGgfbfd&>HCGZUbWeWnmwH z1yRdQ-~FI37^!wT(}#9BUlVlZ7n^i>?c;I7N;Oc?N9#tPw5wD_w-Zt3{O&huaLuIoCLEo;K$_*u=2Du~oXIvEj9C0&ywsr+mFrl*z_4jYyg z4kcXt9gzNp;EW*rcN6{>c8(U5e~LTFv72HoE~MP@Ob>JzKmFo93v!?P?ERH4h2!tg z?H>8+_zD~bIpe*e?Klo%O)GWS`K-Q-cKi-9XiraA?xWCW!Hj40Ofn?Lc4~twGtA zKex)aU=CyW%29QPT+{U{%L7rldK0 z%<)7pNO}Sg?NF~Vot#yW#%*y>z7TjYJorw=a$_`aH82N_Q{VOF+$DmZOv>4N`8JT1 zrRrOe+FtCiErVkRn+Ue(Rm(EPk1yLFt%PNhs=L)3fGmIv-?8I#)-VBs=3Y}b^LuLK zMT2(N*m*cIrNG~itUH)FwH0UpU6c=x5&3;=cw?E9Ol!g~ZyohtFFKzddzxDImOG*A zC$Y3{LB*DX8B=>-vytmT=mu%BV$FA22r#)(54cbHZ6(o&@%)(mTLy0V!0yDpzebHD zg;3K2)qrjc^w5fD>4EUBm>`lp8%b+loN*yrNZN|fsz9J3vKsrAKF-kPffLYgJEZUW_v4};0rCx8G+o6SPqjvvNI|R<94M^c z_-Vc2XE0{norrr|H}AJ-OW*Bqy2KLL$+X_sQG*}*;NR5UjPfzZz!J+K=eq_pGr)iJ zx1TztadOuJGFJEvD|`jW?Wx)4e&POH zb0LSR#jLT&2oj4(F&6UcR#ZF3gdZ0RF9VR^XOr7zZF&>agLPn_dRR5#&g-RZ%LYr^ z2c!H6YW5!Azyu~Z$87|_lxQ3v7I(VUrXfu;gURMrz33zG#>Nx1Mmwan;O45MFA7_A zWXEv}ayha9J70TgE;HdqQNrVFao*20l7WYylpc+@>Mlx&(zPlva~OB7d@vs1ZCNko zB`Gef=V=5zYLnC5SO_8ZCMP_ZjgFw;(1)tKOnUB4_O{jnPdEw1%4hWWipSA^UFSC& z@?(4a3%E&H;M}Qi{q%dRCz&RPJqfPpPI1qu@jOq9WsbViYIaAFW`};zSTbr6o~WGJ zsmoW4_>*6AB`&~*#?+b{N7uHG<|q)pKt9}vqt6Dg=19j;J!uzO_V7sjK40Y6ReAY% z!)AdyJU~$3em2C?#-}`wt?zFa-^EHIJ04rGND_5ZmJkq^qV62Po-SGFZ%12A02*vI zcFj4nlkmY#$Ef{NS3AZ<)oo`Z_yuI0@a=7X? z-bO>Wv2+S_HUk=n*64#ZCRJl`4=HILmUn;&LH6-a2|tO1Cc6$= zB@hZukraao+gym)roks4;H@%9z`3Pj{`*Wgf?rE*Pyx?}ph@EtYmZXE!w%cV&yK|g z&4P?OmI^ZQlZ7@xQU2-{g9~WXG%6_Cx%=)(TUixi0gPrlYZ?@_iuIbqlLeiaJJ&Pr zFXgC7(0KAbV9D&X9M0En891?7YQ4TQMv5TOe7V5*gkz#nKI~I3Jf6_cM@7UR8z-Wo zL&14TYY8X3yZbaqu4@!`Qf^(FCDr#nmRAmafE$Hh!b-N3ZZ$UD|08L(YrG*ftOXy4 zf5o;49r5+(m0poM&@K?|cgHvGnEXFrvma|6e>zRW?RKvnP`t9?RY7)KG7v>hC!b%* z4mW%@b-rMcrmbE~pc_ZfzW~1ka>$7S=3Q}s4-r|k7;zn1T8fLM2k!$8Y<@rmOOvV%>K6_V1V2rV8uC+= z4V-~=8)Ix|0`)?b9fIjhoXW#RE{wq+ETC z-JIW`n@v0t^l0qVQt}938^|#_4mja%oc;ms1zBk6zV%vDA-R=ldX&~;vk9AXP2R_# z2^K#w1DCwd2Z+wC-Jxg!!e!A5G_&PSHYzn?syuf8cvsCV(bbJ}XVU3ax_5?w zI1EtY%LBrmYxMuR+*RLWerG-P$LYbH&FcUYXtNiJ!ji`q@OqBJ+79}$9YyVw`f1W! z1<=X5$8|V~{PshPH|Qw)3_8k={JRJZeo*1}15kYm&EGnl@060Uy7J~Z%okPhnnuQ& zxP=d?#zIqA$>V{0Lr(j*fg|3DM1!H=o$Y9};sj@{X&lR$eEBe-FATPLK2Ejg>$;8_ z&F>Z+X_to=nySiYO7*z>fT^Rjysi)V_9O*R>{$qo0a6G5uZQfl(bIj5U(p#Bv;AwB z&t2TI52pjuxCFF%FzPl$Z0)n*J%?1KMBvfBGk--YWCs~+2b@guLV>M3{poLsxyYBl zU0Aj}WL{mpuqTauc&a?32$^nr+}ZNNK7c`I1!C)vVsgw0TTilG(Cir;N_ipu;UDKa z^BC!C#;YQ(pxY%%zoyiXEKovpx~t~L)O49`3W>SfeijP5%943+OI<`$=f`5@<GIn{={;9Mmq{0E*{-vC{~VC)|VTzwJ40C@0kK@PEDqXWBLVPDx;YwH&*Mx zT)SQ{CSv_-?_ZzqAn^E?KTd51yBf6LK-KyXnoPCa-ru?Nw`>n=-LIf6cz@TI5nP2u z35w{CBE!c6H2~#7(R8!uvF08MSA9Cd5WEyahH-({1u6PoL_Y#3O~#rN-X)F4-(DfK z-W^;bw8~s}1eJt#6PX?yZT!F$Uv^{KZ)*GH(aFZQd zJar;D@Ak5u=!Xq2dClXI+vkCS4f0;$DB^JNNkHPYhUG7O{7izI@@aQ)HeQq6t*9Z1 zi59(*38iGimk}3;$JDP@v7Knj=_aNB6B}6%fsE1s%oQWln-ql#_@?~u_XQtYy%>7m zOK?QfrAUa~A-Om9vFtv(Ic5-GT#^S^;c)plj`l@oez}4J?3g6ZJfZx$SQ7~h6CNgN zs}l=PtPmQ(vI5xR9>aVE*ww&PADCn8Ss^s;{B!`8vB261jJ&N5IXj$AM<0XZB z`IdZ5e_C+p2-1xB?(O|~>oMnU91M=QbACr!`Nx;d;K3iC+<89phXL_7LU=dQ4PDTr zC3D*P9tNCsgH2$hEN@)*Jl*m*H!t^oj8HuxpDrPUn&TJiL{BBYlG_x;ReZBHfnmdz zx7A6Gbr6}ey$=#cRlSQhc@$}X?F)`p?W!h-vC4%RVZqiajI!&ldcL6-4D1#6bS=%( zFO6D`D__3inYbrZt)F^1$5m{vPq`z74zwk(&S z{6I*rV}y_8j}&NyI%WPycp}zKy#u@#sl;Q3o@J_)?IYs0lByCL^^;s*LO8Qu%bn=Z z)S~-^s)c@GORaiVRYma}ifuMWGbJ+*H01C4!(`aS_oNcHMFREnr3odD8-55zT9+2C ze=lCM8e;ufK?dg>ozeK_58~IYR&C#d{Y0zNUG?{E<9+q3jx^oQ&B%Ho8t2d_qy)Av zhP}OCSwYv1zR{8?Zaoq2*8FU}@_ck$$@iD30o1X6jH7n%mvtDxjvK0Qt4O0Sv^m`wz8 zLdakc^THKhYiN23BJ+&6*WOCXhJC;Isvhz|&tCkB{PpU^uU2dJ`1_7yW3+WW zil(YDeQ|u=F=M%86dA5^+XOJc|eRjfi|^bVf(V3xw+D>Kw3_5Vw7V zuZToFy;D*hv$J2cM=lZR+Dj^h`CV=1s(y(-yIju6>QqLK9<5`K>VZvf!kxt5Mxnup zNfP5f>Ju>7qRk&poi_kYfk*@inAySRHqZa?c7H*=W_$UWm}bSO1FqZbRe572ER6eM zIHx(Gg6?=VTg~JND0&=?bBa=hDc8+tZN9|mDP($`qtA3v@1m+myU6P=@y4Ax*o~-_ zAZ%t;C4MZ%p%h0SZHxde%q7=l1y0Y`#x0JF)a7SQGqKakg{;mnU*gWQ(%QS;<+{2_ zt;7<}>(}aubv@(y{!Wpj(A*sF$?;`1I*#cQ&@%IfX*P)oixUrBD)~F*5apo(5+?-l z!St+EtA!u_mZaKvhx*Chfl)&pR4YS+gA@w4JLvBQw!ITXKE?Fol4fmHy#aE#e~I6i zxz^l?m*&f)lnUDE6Ky&1&5c5Q1cz=ZSIgsMO8VmbMG^0|z}$lZo)e}+Nq3meNEJQZ z2K^J>gTx*yyg<5nQLg@dc7|N+8+K5jqT^+ZUN=dXIa#d15L6?UWJ-@5wDjKMOdh~AjDV4mdh-{{+wmQ+9oO8oUfPaWpeeATENaEPrS0gq+3&l6?lZ`I=ENHs#;pQgq;3N;dQJyQ9+ zQ;FZ-%pB!3JNAep`;JsTw0D%G(|L1LV_zwP1Jm;Fyf+*v0%Tr7(bZG!zx_*WMDx%~H4|7b$6P;|StsN0=F@Haxx-K`?e5CJ3M6@iOm; zadxK5@J>pVTX{xRwfG|?<>W%=fXH}CIDdIe}nsmvs4H33@ z&{qjrwHiT&bTPj|BiP>V|GnO(f5@NuG5BS~kEXyJ7Jub9XRcuOqw2R48VVB+Af(t) z?*&%;tW8nBR^zLrU)Ph{=^0gLy?OFi$_ZD#qm9&mC`NgUf6ErD1{&KOA_D z_?Z2nk{s1moV}Egn5||%yh)J}`oXI8RlBM4;gawUfAdJVI8CD43N{%c9Q$*N6qkCU zJ)qxlM?XJMU1u!xcjCTU2>0ynSfHdd?m1~MH{UEDW)U$>TDTLVcM*~SHNX-zZN7`Y zm59Dv8oyO!IEQ|RapvXQ;Kx}fF~G0}BQfYwiwn^cg&)LIk`_*sCmv?D`h#_#-(Sro z^}9%VuWxOUOHQz8$9)}-+Xm+tTv1TEPm|a=9T@*%4-gACrndCb-qB^t+CO6M~A!HKzE9rXQu$b}oi8eo6v3GeO9O))e zah!w;j`XUGthiWAD7n2aA`(fSj2&6fgK<`Jom9D9ycBNGrXZF+xUm@=`n0#Xz&UXK z`d{jo>KE>0Ow#<39M~oAVqQ4CT>J^K;+i`D3ar6j*gvwJuAY#FF?=xs#IVGiz%F0x z;v#(EWP2>VlE>~wOfN8e!1&6{YzMV4XD*kareJ6)aySAPsa&XamlZfv#iZ1U{Lr%} z4%&s$eC^OpR>Z~Dj!fm5rkF8~R>BqAfCJ0;VdhjQk5)k0To<{MqI)}-L5#CI(V|WjUxm-7;Bd=fS1(#&%($t#V zY&GU#=&9S@x`@OGbroel&F0Ihh=WW?ft0|@%2aJ7P9`j(>k@fkD6eL2j~uHU=|Z5J z6q$ZjS~?2tIg4R=d(y)DS`<7r@34%d@h2TJ*_O`)Yj~ zhWokC#3AJaAMp#e=5~AxTk(NZ!qE7;; zJXhsNVS|KpI5&}7B&aRoYXgQP@zUNFJ^my+j!xtmI6!xw;h>sgABEW_)a zmvhqd=MvXQ*T>)g;KQkfcSvB)OlMs}BIP0ZuWyq`8s=3pM(&H@!^2`dhoF7R zHhBSSX`$O~=h3Qqgz`8~M3`GOBbU(Z$d(JA6H+Ev4sc&3mo3?@{!z?}K#25s$yVh} zA5J*kVbRAs28Vc8;D==s`W=PZ?p*I`wi=ll-oDUV1^zIXua>Ky)QNeasiM9;Lcj8a z7!e92ohRwj-D9-GSLJxRdaKgw#Rp4g@C#+7eE6?IEl6%NC}VI)y*V?L;->qkc>hwq z{X6vAQqSE78I8gKSfmxEKvPRvL{%3m-c1 zVrAYGn(8?j178&AwdR?G(J_qqW@+33X7fVti%wAly5Dgue}NK-!Icx*`yF`aJ zvZ@YgejqNquAecypzp;~r1%{RN95v3rTN1{s6?TwB%IQ-ndkB)&S{4m!PhC0rQ)=} z!%{_axkA#|ppvmjI)sF#Do%ZqghoX3CZU>PdNuIew6a3Y4O}o?gp>EK7TQP2J^G&^ zUd9!Zt9#gj2_kMGC%>eQ80$6c5H5C=lxw}@{qgiz_89?O{YgKcC_$V}bd&e!5K>HE zezfdB9ZfADOe|3PSsFr*hEgRjhYMAr#BO$_^i|v|WeL${Hm9zurj?U6I+5WER|}YA zUt$c#Dsr?hEnI$m+=kuUst2jRhV2&4V&^VR$2?fiOL9_PU72DHoz+XT58wN+%x*wf zAF$SUWmNY+FYFE8@!S8`TYgKb+E{9_JfZOKPXcG+!M$s6W7}7zEC1(5`GXhCgTQ>` zrKyoCUkxR-xgbSv_gEgl{2y;PS6=~M*i#epzi(Kz+7T3Kx!I@x??;^gFPw-P{hx0D z7kLttsE)8_|M#QXzzb~ytxFSE|Le!Jzx{dHNleAk0Lp(Z7W|WI2A`K*dz7^@N%ud# zDhEW@j=JM3Q?>u&tLzMa2)4gq3kFI4*EhWP;qJ|U)aMaemIv4V#~a@BGx_7q1NooZ z_2z;6&*}l2?adDP-!1hfWW5Pl|9Kp}*&%Os$UkTFn=|Ci8S+o!`zFhJllJ}-9pBU; zZ|ac$h>mXx!~a`ezp2#!Beh(P9B^h5p!;D2+5ylGJV1I~Q7_stG@(=q&y{NYUt_n$gr1*dqkL*DF=H#-Dm h*#CcEoh+>TE3Ne@%V#v`E%4ugZ#};${W|#k{{y&Qn-u^6 literal 0 HcmV?d00001 diff --git a/examples/with-zones/package.json b/examples/with-zones/package.json new file mode 100644 index 0000000000000..3269a598f3f15 --- /dev/null +++ b/examples/with-zones/package.json @@ -0,0 +1,20 @@ +{ + "name": "with-zones", + "version": "1.0.0", + "scripts": { + "home": "next home -p 4000", + "home-build": "next build home", + "home-start": "next start home -p 4000", + "blog": "next blog -p 5000", + "blog-build": "next build blog", + "blog-start": "next start blog -p 5000", + "proxy": "micro-proxy -r rules-dev.json" + }, + "dependencies": { + "micro-proxy": "^1.0.0", + "next": "latest", + "react": "^16.0.0", + "react-dom": "^16.0.0" + }, + "license": "ISC" +} diff --git a/examples/with-zones/rules-dev.json b/examples/with-zones/rules-dev.json new file mode 100644 index 0000000000000..680a330286beb --- /dev/null +++ b/examples/with-zones/rules-dev.json @@ -0,0 +1,6 @@ +{ + "rules": [ + {"pathname": "/blog", "method":["GET", "POST", "OPTIONS"], "dest": "http://localhost:5000"}, + {"pathname": "/**", "dest": "http://localhost:4000"} + ] +} diff --git a/examples/with-zones/rules-prod.json b/examples/with-zones/rules-prod.json new file mode 100644 index 0000000000000..aa8f6da66c276 --- /dev/null +++ b/examples/with-zones/rules-prod.json @@ -0,0 +1,6 @@ +{ + "rules": [ + {"pathname": "/blog", "method":["GET", "POST", "OPTIONS"], "dest": "https://with-zones-blog.now.sh"}, + {"pathname": "/**", "dest": "https://with-zones-home.now.sh"} + ] +} diff --git a/lib/asset.js b/lib/asset.js new file mode 100644 index 0000000000000..f9dfe50c0a21a --- /dev/null +++ b/lib/asset.js @@ -0,0 +1,10 @@ +let assetPrefix + +export default function asset (path) { + const pathWithoutSlash = path.replace(/^\//, '') + return `${assetPrefix}/static/${pathWithoutSlash}` +} + +export function setAssetPrefix (url) { + assetPrefix = url +} diff --git a/lib/link.js b/lib/link.js index c8b9378eacabc..ac9862750c2d5 100644 --- a/lib/link.js +++ b/lib/link.js @@ -150,6 +150,7 @@ export default class Link extends Component { function isLocal (href) { const url = parse(href, false, true) const origin = parse(getLocationOrigin(), false, true) + return !url.host || (url.protocol === origin.protocol && url.host === origin.host) } diff --git a/lib/router/router.js b/lib/router/router.js index 222499aba40c6..f03107bfea435 100644 --- a/lib/router/router.js +++ b/lib/router/router.js @@ -129,7 +129,6 @@ export default class Router { } this.abortComponentLoad(as) - const { pathname, query } = parse(url, true) // If the url change is only related to a hash change // We should not proceed. We should only change the state. @@ -139,6 +138,8 @@ export default class Router { return } + const { pathname, query } = parse(url, true) + // If asked to change the current URL we should reload the current page // (not location.reload() but reload getInitalProps and other Next.js stuffs) // We also need to set the method = replaceState always @@ -209,10 +210,6 @@ export default class Router { this.components[route] = routeInfo } catch (err) { - if (err.cancelled) { - return { error: err } - } - if (err.buildIdMismatched) { // Now we need to reload the page or do the action asked by the user _notifyBuildIdMismatch(as) @@ -223,9 +220,21 @@ export default class Router { } if (err.statusCode === 404) { - // Indicate main error display logic to - // ignore rendering this error as a runtime error. - err.ignore = true + // If there's 404 error for the page, it could be due to two reasons. + // 1. Page is not exists + // 2. Page is exists in a different zone + // We are not sure whether this is actual 404 or exists in a different zone. + // So, doing a hard reload is the proper way to deal with this. + window.location.href = as + + // Changing the URL doesn't block executing the current code path. + // So, we need to mark it as a cancelled error and stop the routing logic. + err.cancelled = true + return { error: err } + } + + if (err.cancelled) { + return { error: err } } const Component = this.ErrorComponent @@ -301,29 +310,19 @@ export default class Router { cancelled = true } - try { - const Component = await this.fetchRoute(route) - - if (cancelled) { - const error = new Error(`Abort fetching component for route: "${route}"`) - error.cancelled = true - throw error - } + const Component = await this.fetchRoute(route) - if (cancel === this.componentLoadCancel) { - this.componentLoadCancel = null - } + if (cancelled) { + const error = new Error(`Abort fetching component for route: "${route}"`) + error.cancelled = true + throw error + } - return Component - } catch (err) { - // There's an error in loading the route. - // Usually this happens when there's a failure in the webpack build - // So in that case, we need to load the page with full SSR - // That'll clean the invalid exising client side information. - // (Like cached routes) - window.location.href = as - throw err + if (cancel === this.componentLoadCancel) { + this.componentLoadCancel = null } + + return Component } async getInitialProps (Component, ctx) { diff --git a/package.json b/package.json index e104dd62669b8..c51f0d6fe3a54 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "dynamic.js", "prefetch.js", "router.js", + "asset.js", "error.js" ], "bin": { diff --git a/server/build/webpack.js b/server/build/webpack.js index d24feb9879911..1fabfde4fe321 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -124,7 +124,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer path: path.join(dir, config.distDir, isServer ? 'dist' : ''), // server compilation goes to `.next/dist` filename: '[name]', libraryTarget: 'commonjs2', - publicPath: `/_next/webpack/`, + publicPath: `${config.assetPrefix}/_next/webpack/`, // This saves chunks with the name given via require.ensure() chunkFilename: '[name]-[chunkhash].js', strictModuleExceptionHandling: true, diff --git a/server/hot-reloader.js b/server/hot-reloader.js index b3c0f8cef08e4..fb4b92deb9be7 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -8,7 +8,8 @@ import clean from './build/clean' import getConfig from './config' import UUID from 'uuid' import { - IS_BUNDLED_PAGE + IS_BUNDLED_PAGE, + addCorsSupport } from './utils' export default class HotReloader { @@ -35,6 +36,15 @@ export default class HotReloader { } async run (req, res) { + // Usually CORS support is not needed for the hot-reloader (this is dev only feature) + // With when the app runs for multi-zones support behind a proxy, + // the current page is trying to access this URL via assetPrefix. + // That's when the CORS support is needed. + const { preflight } = addCorsSupport(req, res) + if (preflight) { + return + } + for (const fn of this.middlewares) { await new Promise((resolve, reject) => { fn(req, res, (err) => { diff --git a/server/index.js b/server/index.js index 5a447c78d6ebe..6b3493822e3c1 100644 --- a/server/index.js +++ b/server/index.js @@ -12,15 +12,11 @@ import { renderScriptError } from './render' import Router from './router' -import { getAvailableChunks } from './utils' +import { getAvailableChunks, isInternalUrl } from './utils' import getConfig from './config' // We need to go up one more level since we are in the `dist` directory import pkg from '../../package' - -const internalPrefixes = [ - /^\/_next\//, - /^\/static\// -] +import * as asset from '../lib/asset' const blockedPages = { '/_document': true, @@ -54,6 +50,9 @@ export default class Server { availableChunks: dev ? {} : getAvailableChunks(this.dir, this.dist) } + // With this, static assets will work across zones + asset.setAssetPrefix(this.config.assetPrefix) + this.defineRoutes() } @@ -289,7 +288,7 @@ export default class Server { } async render (req, res, pathname, query, parsedUrl) { - if (this.isInternalUrl(req)) { + if (isInternalUrl(req.url)) { return this.handleRequest(req, res, parsedUrl) } @@ -388,16 +387,6 @@ export default class Server { return true } - isInternalUrl (req) { - for (const prefix of internalPrefixes) { - if (prefix.test(req.url)) { - return true - } - } - - return false - } - readBuildId () { const buildIdPath = join(this.dir, this.dist, 'BUILD_ID') const buildId = fs.readFileSync(buildIdPath, 'utf8') diff --git a/server/utils.js b/server/utils.js index 66b87c0975453..3e546e8b3b8f3 100644 --- a/server/utils.js +++ b/server/utils.js @@ -20,3 +20,37 @@ export function getAvailableChunks (dir, dist) { return chunksMap } + +const internalPrefixes = [ + /^\/_next\//, + /^\/static\// +] + +export function isInternalUrl (url) { + for (const prefix of internalPrefixes) { + if (prefix.test(url)) { + return true + } + } + + return false +} + +export function addCorsSupport (req, res) { + if (!req.headers.origin) { + return { preflight: false } + } + + res.setHeader('Access-Control-Allow-Origin', req.headers.origin) + res.setHeader('Access-Control-Request-Method', req.headers.origin) + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET') + res.setHeader('Access-Control-Allow-Headers', req.headers.origin) + + if (req.method === 'OPTIONS') { + res.writeHead(200) + res.end() + return { preflight: true } + } + + return { preflight: false } +} diff --git a/yarn.lock b/yarn.lock index a62e413bfc733..98bccd3de9d74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -96,6 +96,10 @@ ajv-keywords@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.0.tgz#a296e17f7bfae7c1ce4f7e0de53d29cb32162df0" +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + ajv@^4.7.0, ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" @@ -1255,9 +1259,9 @@ builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" -cacache@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.1.tgz#3e05f6e616117d9b54665b1b20c8aeb93ea5d36f" +cacache@^10.0.1: + version "10.0.2" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.2.tgz#105a93a162bbedf3a25da42e1939ed99ffb145f8" dependencies: bluebird "^3.5.0" chownr "^1.0.1" @@ -1482,10 +1486,14 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@^2.9.0, commander@~2.11.0: +commander@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" +commander@~2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -5182,11 +5190,12 @@ sax@^1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" -schema-utils@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf" +schema-utils@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.3.tgz#e2a594d3395834d5e15da22b48be13517859458e" dependencies: ajv "^5.0.0" + ajv-keywords "^2.1.0" "semver@2 || 3 || 4 || 5", semver@^5.3.0: version "5.4.1" @@ -5228,6 +5237,10 @@ send@0.16.1: range-parser "~1.2.0" statuses "~1.3.1" +serialize-javascript@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.4.0.tgz#7c958514db6ac2443a8abc062dc9f7886a7f6005" + serve-static@1.12.6: version "1.12.6" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.6.tgz#b973773f63449934da54e5beba5e31d9f4211577" @@ -5800,11 +5813,11 @@ ua-parser-js@^0.7.9: version "0.7.17" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" -uglify-es@^3.1.3: - version "3.1.10" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.10.tgz#f1840c3b52771d17555a02ce158cf46f689384bd" +uglify-es@^3.3.4: + version "3.3.9" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" dependencies: - commander "~2.11.0" + commander "~2.13.0" source-map "~0.6.1" uglify-js@^2.6, uglify-js@^2.8.29: @@ -5820,6 +5833,19 @@ uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" +uglifyjs-webpack-plugin@1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.1.6.tgz#f4ba8449edcf17835c18ba6ae99b9d610857fb19" + dependencies: + cacache "^10.0.1" + find-cache-dir "^1.0.0" + schema-utils "^0.4.2" + serialize-javascript "^1.4.0" + source-map "^0.6.1" + uglify-es "^3.3.4" + webpack-sources "^1.1.0" + worker-farm "^1.5.2" + uglifyjs-webpack-plugin@^0.4.6: version "0.4.6" resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" @@ -5828,18 +5854,6 @@ uglifyjs-webpack-plugin@^0.4.6: uglify-js "^2.8.29" webpack-sources "^1.0.1" -uglifyjs-webpack-plugin@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.1.1.tgz#6167c5aae218ee8109de8920bb769b8acbc55d03" - dependencies: - cacache "^10.0.0" - find-cache-dir "^1.0.0" - schema-utils "^0.3.0" - source-map "^0.6.1" - uglify-es "^3.1.3" - webpack-sources "^1.0.1" - worker-farm "^1.4.1" - uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" @@ -6013,6 +6027,13 @@ webpack-sources@^1.0.1: source-list-map "^2.0.0" source-map "~0.5.3" +webpack-sources@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54" + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + webpack@3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.10.0.tgz#5291b875078cf2abf42bdd23afe3f8f96c17d725" @@ -6089,13 +6110,20 @@ wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" -worker-farm@^1.3.1, worker-farm@^1.4.1: +worker-farm@^1.3.1: version "1.5.0" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.0.tgz#adfdf0cd40581465ed0a1f648f9735722afd5c8d" dependencies: errno "^0.1.4" xtend "^4.0.1" +worker-farm@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.2.tgz#32b312e5dc3d5d45d79ef44acc2587491cd729ae" + dependencies: + errno "^0.1.4" + xtend "^4.0.1" + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" From 30186949ab6254f99769d5f04e1001fc93e234c8 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 30 Jan 2018 14:36:43 +0100 Subject: [PATCH 132/132] Add section on css --- readme.md | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/readme.md b/readme.md index d2fa37c23dfbb..54114c536aa33 100644 --- a/readme.md +++ b/readme.md @@ -164,6 +164,14 @@ export default () =>

hi there

To use more sophisticated CSS-in-JS solutions, you typically have to implement style flushing for server-side rendering. We enable this by allowing you to define your own [custom ``](#user-content-custom-document) component that wraps each page. +#### Importing CSS / Sass / Less files + +To support importing `.css` `.scss` or `.less` files you can use these modules, which configure sensible defaults for server rendered applications. + +- ![@zeit/next-css](https://github.com/zeit/next-plugins/tree/master/packages/next-css) +- ![@zeit/next-sass](https://github.com/zeit/next-plugins/tree/master/packages/next-sass) +- ![@zeit/next-less](https://github.com/zeit/next-plugins/tree/master/packages/next-less) + ### Static file serving (e.g.: images) Create a folder called `static` in your project root directory. From your code you can then reference those files with `/static/` URLs: @@ -1006,7 +1014,7 @@ In order to extend our usage of `webpack`, you can define a function that extend // (But you could use ES2015 features supported by your Node.js version) module.exports = { - webpack: (config, { buildId, dev }) => { + webpack: (config, { buildId, dev, isServer, defaultLoaders }) => { // Perform customizations to webpack config // Important: return the modified config @@ -1021,7 +1029,15 @@ module.exports = { } ``` -*Warning: Adding loaders to support new file types (css, less, svg, etc.) is __not__ recommended because only the client code gets bundled via webpack and thus it won't work on the initial server rendering. Babel plugins are a good alternative because they're applied consistently between server/client rendering (e.g. [babel-plugin-inline-react-svg](https://github.com/kesne/babel-plugin-inline-react-svg)).* +Some commonly asked for features are available as modules: + +- ![@zeit/next-css](https://github.com/zeit/next-plugins/tree/master/packages/next-css) +- ![@zeit/next-sass](https://github.com/zeit/next-plugins/tree/master/packages/next-sass) +- ![@zeit/next-less](https://github.com/zeit/next-plugins/tree/master/packages/next-less) +- ![@zeit/next-preact](https://github.com/zeit/next-plugins/tree/master/packages/next-preact) +- ![@zeit/next-typescript](https://github.com/zeit/next-plugins/tree/master/packages/next-typescript) + +*Warning: The `webpack` function is executed twice, once for the server and once for the client. This allows you to distinguish between client and server configuration using the `isServer` property* ### Customizing babel config @@ -1214,20 +1230,6 @@ If you want to create re-usable React components that you can embed in your Next Next.js bundles [styled-jsx](https://github.com/zeit/styled-jsx) supporting scoped css. However you can use any CSS-in-JS solution in your Next app by just including your favorite library [as mentioned before](#css-in-js) in the document. -
- How do I use CSS preprocessors like SASS / SCSS / LESS? - -Next.js bundles [styled-jsx](https://github.com/zeit/styled-jsx) supporting scoped css. However you can use any CSS preprocessor solution in your Next app by following one of these examples: - -- [with-external-scoped-css](./examples/with-external-scoped-css) -- [with-scoped-stylesheets-and-postcss](./examples/with-scoped-stylesheets-and-postcss) -- [with-global-stylesheet](./examples/with-global-stylesheet) -- [with-styled-jsx-scss](./examples/with-styled-jsx-scss) -- [with-styled-jsx-plugins](./examples/with-styled-jsx-plugins) - -
- -
What syntactic features are transpiled? How do I change them?