-
-
Notifications
You must be signed in to change notification settings - Fork 27k
[WIP] Split vendor bundle #2310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
76cd9ea
fa83243
812e209
b7a0757
9345cfa
90ade1b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,8 +12,11 @@ | |
|
||
const autoprefixer = require('autoprefixer'); | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
const webpack = require('webpack'); | ||
const NameAllModulesPlugin = require('name-all-modules-plugin'); | ||
const HtmlWebpackPlugin = require('html-webpack-plugin'); | ||
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin'); | ||
const ExtractTextPlugin = require('extract-text-webpack-plugin'); | ||
const ManifestPlugin = require('webpack-manifest-plugin'); | ||
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); | ||
|
@@ -53,6 +56,18 @@ const extractTextPluginOptions = shouldUseRelativeAssetPaths | |
? // Making sure that the publicPath goes back to to build folder. | ||
{ publicPath: Array(cssFilename.split('/').length).join('../') } | ||
: {}; | ||
// Check if vendor file exists | ||
const checkIfVendorFileExists = fs.existsSync(paths.appVendorJs); | ||
// If the vendor file exists, add an entry point for vendor, | ||
// and a seperate entry for polyfills and app index file, | ||
// otherwise keep only polyfills and app index. | ||
const appEntryFiles = [require.resolve('./polyfills'), paths.appIndexJs]; | ||
const entryFiles = checkIfVendorFileExists | ||
? { | ||
vendor: paths.appVendorJs, | ||
main: appEntryFiles, | ||
} | ||
: appEntryFiles; | ||
|
||
// This is the production configuration. | ||
// It compiles slowly and is focused on producing a fast and minimal bundle. | ||
|
@@ -63,8 +78,8 @@ module.exports = { | |
// We generate sourcemaps in production. This is slow but gives good results. | ||
// You can exclude the *.map files from the build during deployment. | ||
devtool: 'source-map', | ||
// In production, we only want to load the polyfills and the app code. | ||
entry: [require.resolve('./polyfills'), paths.appIndexJs], | ||
// Add the entry point based on whether vendor file exists. | ||
entry: entryFiles, | ||
output: { | ||
// The build folder. | ||
path: paths.appBuild, | ||
|
@@ -250,6 +265,41 @@ module.exports = { | |
], | ||
}, | ||
plugins: [ | ||
// configuration for vendor splitting and long term caching | ||
// more info: https://medium.com/webpack/predictable-long-term-caching-with-webpack-d3eee1d3fa31 | ||
new webpack.NamedModulesPlugin(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just in case - webpack docs recommend adding also |
||
new webpack.NamedChunksPlugin(chunk => { | ||
if (chunk.name) { | ||
return chunk.name; | ||
} | ||
return chunk.modules | ||
.map(m => path.relative(m.context, m.request)) | ||
.join('_'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the only thing to keep in mind here is, that this could potentially become a length string, so it might make sense to cut the string at a certain point or use a hash digest or something similar. the most brutal way would be to
|
||
}), | ||
new webpack.optimize.CommonsChunkPlugin( | ||
// Check if vendor file exists, if it does, | ||
// generate a seperate chucks for vendor | ||
// else don't generate any common chunck | ||
checkIfVendorFileExists | ||
? { | ||
name: 'vendor', | ||
minChunks: Infinity, | ||
} | ||
: { names: [] } | ||
), | ||
// We need to extract out the runtime into a separate manifest file. | ||
// more info: https://webpack.js.org/guides/code-splitting-libraries/#manifest-file | ||
new webpack.optimize.CommonsChunkPlugin( | ||
// Check if vendor file exists, if it does, | ||
// generate a seperate chucks for manifest file | ||
// else don't generate any common chunck | ||
checkIfVendorFileExists | ||
? { | ||
name: 'manifest', | ||
} | ||
: { names: [] } | ||
), | ||
new NameAllModulesPlugin(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there is an issue with the plugin that could hurt hashing. didn't have time to elaborate approach though :( timse/name-all-modules-plugin#1 |
||
// Makes some environment variables available in index.html. | ||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.: | ||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> | ||
|
@@ -273,6 +323,11 @@ module.exports = { | |
minifyURLs: true, | ||
}, | ||
}), | ||
// This ensures that the browser will load the scripts in parallel, | ||
// but execute them in the order they appear in the document. | ||
new ScriptExtHtmlWebpackPlugin({ | ||
defaultAttribute: 'defer', | ||
}), | ||
// Makes some environment variables available to the JS code, for example: | ||
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`. | ||
// It is absolutely essential that NODE_ENV was set to production here. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This way vendor bundle does not get the polyfills. Polyfills should the first thing that run from our bundles, else we could get issue similar to this facebook/react#8379 (comment) for promises and fetch. I think we need another check here / move this to a resolver function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@viankakrisna yup makes sense. external libs that depends on promise might get this issue. Plus polyfills are vendor libs.
can't we simply do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking about something like this https://github.com/viankakrisna/create-react-app/blob/cb34a1baf21497ad1de7eb314d9ba97a89f1c0be/packages/react-dev-utils/webpackAutoDllCompiler.js#L82-L111 I feel that ejected users should not be bothered by an optional feature checks when they ejected.