diff --git a/build/webpack.js b/build/webpack.js index dc2695f0..725d2ffb 100644 --- a/build/webpack.js +++ b/build/webpack.js @@ -41,7 +41,7 @@ function externalsConfig (dir, isServer) { } // Webpack itself has to be compiled because it doesn't always use module relative paths - if (res.match(/node_modules[/\\]webpack/)) { + if (res.match(/node_modules[/\\]webpack/) || res.match(/node_modules[/\\]css-loader/)) { return callback() } @@ -59,7 +59,6 @@ function externalsConfig (dir, isServer) { function optimizationConfig ({dir, dev, isServer, totalPages}) { if (isServer) { return { - // runtimeChunk: 'single', splitChunks: false, minimize: false } @@ -69,7 +68,12 @@ function optimizationConfig ({dir, dev, isServer, totalPages}) { runtimeChunk: { name: CLIENT_STATIC_FILES_RUNTIME_WEBPACK }, - splitChunks: false + splitChunks: { + cacheGroups: { + default: false, + vendors: false + } + } } if (dev) { @@ -79,21 +83,14 @@ function optimizationConfig ({dir, dev, isServer, totalPages}) { // Only enabled in production // This logic will create a commons bundle // with modules that are used in 50% of all pages - return { - ...config, - splitChunks: { - chunks: 'all', - cacheGroups: { - default: false, - vendors: false, - commons: { - name: 'commons', - chunks: 'all', - minChunks: totalPages > 2 ? totalPages * 0.5 : 2 - } - } - } + config.splitChunks.chunks = 'all' + config.splitChunks.cacheGroups.commons = { + name: 'commons', + chunks: 'all', + minChunks: totalPages > 2 ? totalPages * 0.5 : 2 } + + return config } type BaseConfigContext = {| diff --git a/build/webpack/plugins/build-manifest-plugin.js b/build/webpack/plugins/build-manifest-plugin.js index 9959614d..473474ee 100644 --- a/build/webpack/plugins/build-manifest-plugin.js +++ b/build/webpack/plugins/build-manifest-plugin.js @@ -8,7 +8,7 @@ export default class BuildManifestPlugin { apply (compiler: any) { compiler.hooks.emit.tapAsync('NextJsBuildManifest', (compilation, callback) => { const {chunks} = compilation - const assetMap = {pages: {}, css: []} + const assetMap = {pages: {}} const mainJsChunk = chunks.find((c) => c.name === CLIENT_STATIC_FILES_RUNTIME_MAIN) const mainJsFiles = mainJsChunk && mainJsChunk.files.length > 0 ? mainJsChunk.files.filter((file) => /\.js$/.test(file)) : [] @@ -35,12 +35,16 @@ export default class BuildManifestPlugin { } for (const file of chunk.files) { - // Only `.js` files are added for now. In the future we can also handle other file types. - if (/\.map$/.test(file) || /\.hot-update\.js$/.test(file) || !/\.js$/.test(file)) { + if (/\.map$/.test(file) || /\.hot-update\.js$/.test(file)) { continue } - // These are manually added to _document.js + // Only `.js` and `.css` files are added for now. In the future we can also handle other file types. + if (!/\.js$/.test(file) && !/\.css$/.test(file)) { + continue + } + + // The page bundles are manually added to _document.js as they need extra properties if (IS_BUNDLED_PAGE_REGEX.exec(file)) { continue } @@ -52,35 +56,6 @@ export default class BuildManifestPlugin { assetMap.pages[`/${pagePath.replace(/\\/g, '/')}`] = [...filesForEntry, ...mainJsFiles] } - for (const chunk of chunks) { - if (!chunk.name || !chunk.files) { - continue - } - - const files = [] - - for (const file of chunk.files) { - if (/\.map$/.test(file)) { - continue - } - - if (/\.hot-update\.js$/.test(file)) { - continue - } - - if (/\.css$/.exec(file)) { - assetMap.css.push(file) - continue - } - - files.push(file) - } - - if (files.length > 0) { - assetMap[chunk.name] = files - } - } - if (typeof assetMap.pages['/index'] !== 'undefined') { assetMap.pages['/'] = assetMap.pages['/index'] } diff --git a/build/webpack/plugins/nextjs-ssr-module-cache.js b/build/webpack/plugins/nextjs-ssr-module-cache.js index 176c910f..c09b3651 100644 --- a/build/webpack/plugins/nextjs-ssr-module-cache.js +++ b/build/webpack/plugins/nextjs-ssr-module-cache.js @@ -1,6 +1,7 @@ import webpack from 'webpack' import { RawSource } from 'webpack-sources' import { join, relative, dirname } from 'path' +import {IS_BUNDLED_PAGE_REGEX} from '../../../lib/constants' const SSR_MODULE_CACHE_FILENAME = 'ssr-module-cache.js' @@ -31,7 +32,14 @@ export default class NextJsSsrImportPlugin { compilation.mainTemplate.hooks.localVars.intercept({ register (tapInfo) { if (tapInfo.name === 'MainTemplate') { + const originalFn = tapInfo.fn tapInfo.fn = (source, chunk) => { + // If the chunk is not part of the pages directory we have to keep the original behavior, + // otherwise webpack will error out when the file is used before the compilation finishes + // this is the case with mini-css-extract-plugin + if (!IS_BUNDLED_PAGE_REGEX.exec(chunk.name)) { + return originalFn(source, chunk) + } const pagePath = join(outputPath, dirname(chunk.name)) const relativePathToBaseDir = relative(pagePath, join(outputPath, SSR_MODULE_CACHE_FILENAME)) // Make sure even in windows, the path looks like in unix diff --git a/package.json b/package.json index 120e7cc0..47c34a04 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "unfetch": "3.0.0", "url": "0.11.0", "uuid": "3.1.0", - "webpack": "4.16.1", + "webpack": "4.16.3", "webpack-dev-middleware": "3.1.3", "webpack-hot-middleware": "2.22.2", "webpack-sources": "1.1.0", @@ -112,7 +112,8 @@ "@taskr/clear": "1.1.0", "@taskr/esnext": "1.1.0", "@taskr/watch": "1.1.0", - "@zeit/next-css": "0.0.7", + "@zeit/next-css": "0.2.1-canary.1", + "@zeit/next-sass": "0.2.1-canary.1", "@zeit/next-typescript": "1.1.0", "babel-eslint": "8.2.2", "babel-jest": "21.2.0", @@ -135,6 +136,7 @@ "mkdirp": "0.5.1", "node-fetch": "1.7.3", "node-notifier": "5.1.2", + "node-sass": "4.9.2", "nyc": "11.2.1", "react": "16.4.0", "react-dom": "16.4.0", diff --git a/server/document.js b/server/document.js index b77ab3e5..70c8a635 100644 --- a/server/document.js +++ b/server/document.js @@ -49,15 +49,41 @@ export class Head extends Component { return null } - return files.map((file) => ( - { + // Only render .js files here + if(!/\.js$/.exec(file)) { + return null + } + + return - )) + }) + } + + getCssLinks () { + const { assetPrefix, files } = this.context._documentProps + if(!files || files.length === 0) { + return null + } + + return files.map((file) => { + // Only render .css files here + if(!/\.css$/.exec(file)) { + return null + } + + return + }) } getPreloadDynamicChunks () { @@ -85,6 +111,7 @@ export class Head extends Component { {this.getPreloadDynamicChunks()} {this.getPreloadMainLinks()} + {this.getCssLinks()} {styles || null} {this.props.children} @@ -122,14 +149,19 @@ export class NextScript extends Component { return null } - return files.map((file) => ( -