From c6f0eb2fcfbb6c895b9ea0d457b1229b3cc010d7 Mon Sep 17 00:00:00 2001 From: Dhruv Parmar Date: Sun, 16 Jul 2017 22:37:51 +0530 Subject: [PATCH 1/3] Move webpack manifest out from index chunk Enables index chunk hash to become independent of children chunk hashes. The manifest is inlined with every server rendered route in production mode. --- config/values.js | 4 ++ internal/webpack/configFactory.js | 12 +++++ package.json | 3 +- .../middleware/reactApplication/ServerHTML.js | 15 +++++- .../getClientBundleEntryAssets.js | 48 ++++++++++++------- 5 files changed, 64 insertions(+), 18 deletions(-) diff --git a/config/values.js b/config/values.js index f25a330a..39b240f7 100644 --- a/config/values.js +++ b/config/values.js @@ -117,6 +117,10 @@ const values = { // containing details of all output files for a bundle? bundleAssetsFileName: 'assets.json', + // What should we name the manifest generated by chunk-manifest-webpack-plugin + // containing mappings for chunk ids and names? + bundleManifestFileName: 'manifest.json', + // node_modules are not included in any bundles that target "node" as a // runtime (e.g.. the server bundle) as including them often breaks builds // due to thinks like require statements containing expressions.. diff --git a/internal/webpack/configFactory.js b/internal/webpack/configFactory.js index a7060c5c..dd5076f6 100644 --- a/internal/webpack/configFactory.js +++ b/internal/webpack/configFactory.js @@ -5,6 +5,7 @@ import nodeExternals from 'webpack-node-externals'; import path from 'path'; import webpack from 'webpack'; import WebpackMd5Hash from 'webpack-md5-hash'; +import ChunkManifestWebpackPlugin from 'chunk-manifest-webpack-plugin'; import { happyPackPlugin, log } from '../utils'; import { ifElse } from '../../shared/utils/logic'; @@ -233,6 +234,17 @@ export default function webpackConfigFactory(buildOptions) { // even though 1 or 2 may have only changed. ifClient(() => new WebpackMd5Hash()), + // Since chunk-manifest-webpack-plugin doesn't work with webpack-dev-server + // https://github.com/soundcloud/chunk-manifest-webpack-plugin/issues/26 + // we generate manifest only in production mode. + // Also this optimisation is to prevent better long term caching of + // index chunk which can be compromised in development mode. + ifProdClient(() => new ChunkManifestWebpackPlugin({ + filename: config('bundleManifestFileName'), + manifestVariable: 'webpackManifest', + inlineManifest: false, + })), + // These are process.env flags that you can use in your code in order to // have advanced control over what is included/excluded in your bundles. // For example you may only want certain parts of your code to be diff --git a/package.json b/package.json index 65873d52..217ae9cb 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "modernizr": "3.5.0", "normalize.css": "7.0.0", "offline-plugin": "4.8.3", - "pretty-error": "2.1.1", + "pretty-error": "2.1.1", "prop-types": "15.5.10", "react": "15.6.1", "react-async-bootstrapper": "1.1.1", @@ -98,6 +98,7 @@ "babel-template": "6.26.0", "chokidar": "1.7.0", "css-loader": "0.28.7", + "chunk-manifest-webpack-plugin": "1.1.0", "enzyme": "2.9.1", "enzyme-to-json": "2.0.0", "eslint": "4.7.2", diff --git a/server/middleware/reactApplication/ServerHTML.js b/server/middleware/reactApplication/ServerHTML.js index 847160c7..fc7b795b 100644 --- a/server/middleware/reactApplication/ServerHTML.js +++ b/server/middleware/reactApplication/ServerHTML.js @@ -13,7 +13,10 @@ import serialize from 'serialize-javascript'; import config from '../../../config'; import ifElse from '../../../shared/utils/logic/ifElse'; import removeNil from '../../../shared/utils/arrays/removeNil'; -import getClientBundleEntryAssets from './getClientBundleEntryAssets'; +import { + getClientBundleEntryAssets, + getClientWebpackManifest, +} from './getClientBundleEntryAssets'; import ClientConfig from '../../../config/components/ClientConfig'; import HTML from '../../../shared/components/HTML'; @@ -27,6 +30,11 @@ function KeyedComponent({ children }) { // Resolve the assets (js/css) for the client bundle's entry chunk. const clientEntryAssets = getClientBundleEntryAssets(); +// Resolve the webpack manifest. Useful only in production mode. +const clientWebpackManifest = process.env.BUILD_FLAG_IS_DEV === 'false' ? + getClientWebpackManifest() : {}; + + function stylesheetTag(stylesheetFilePath) { return ( @@ -46,6 +54,10 @@ function ServerHTML(props) { const inlineScript = body =>