-
Notifications
You must be signed in to change notification settings - Fork 32
BRS 7 - Full SSR Hard Source and Loadable support #77
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 18 commits
5271192
a22a5a4
e9397e2
fcbd150
6efddf0
e1a1f1c
ace0ea8
e249d51
10a9395
84e8580
d9578f8
6cefe2f
722bc62
ed4062e
ad4c053
6f76253
83e5434
9cd3c7e
a3d057e
588ef25
2d52632
71ed294
21c0119
6d0ee70
b958eca
f4cb8c3
c084cf6
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 |
---|---|---|
@@ -0,0 +1,15 @@ | ||
'use strict'; | ||
|
||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const reactScriptsRoot = path.resolve(__dirname, '..'); | ||
const haveIsolatedDependencies = | ||
fs.existsSync(path.join(reactScriptsRoot, 'package-lock.json')) || | ||
fs.existsSync(path.join(reactScriptsRoot, 'yarn.lock')); | ||
|
||
module.exports = { | ||
root: haveIsolatedDependencies ? reactScriptsRoot : process.cwd(), | ||
directories: [], | ||
files: ['package-lock.json', 'yarn.lock'], | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,7 @@ const PnpWebpackPlugin = require('pnp-webpack-plugin'); | |
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); | ||
// const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin'); | ||
// const TerserPlugin = require('terser-webpack-plugin'); | ||
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | ||
// const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | ||
// const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); | ||
// const safePostCssParser = require('postcss-safe-parser'); | ||
// const ManifestPlugin = require('webpack-manifest-plugin'); | ||
|
@@ -35,6 +35,8 @@ const typescriptFormatter = require('react-dev-utils/typescriptFormatter'); | |
const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier'); | ||
// @remove-on-eject-end | ||
|
||
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin'); | ||
const LoadablePlugin = require('@loadable/webpack-plugin'); | ||
const sassFunctions = require('bpk-mixins/sass-functions'); | ||
// const camelCase = require('lodash/camelCase'); | ||
const pkgJson = require(paths.appPackageJson); | ||
|
@@ -54,6 +56,10 @@ const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; | |
// Some apps do not need the benefits of saving a web request, so not inlining the chunk | ||
// makes for a smoother build process. | ||
// const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false'; | ||
// We might not want to use the hard source plugin on environments that won't persist the cache for later | ||
const useHardSourceWebpackPlugin = | ||
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. Same here |
||
process.env.USE_HARD_SOURCE_WEBPACK_PLUGIN === 'true'; | ||
const environmentHash = require('./environmentHash'); | ||
|
||
// Check if TypeScript is setup | ||
const useTypeScript = fs.existsSync(paths.appTsConfig); | ||
|
@@ -82,7 +88,7 @@ module.exports = function(webpackEnv) { | |
: isEnvDevelopment && '/'; | ||
// Some apps do not use client-side routing with pushState. | ||
// For these, "homepage" can be set to "." to enable relative asset paths. | ||
const shouldUseRelativeAssetPaths = publicPath === './'; | ||
// const shouldUseRelativeAssetPaths = publicPath === './'; | ||
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. Could you confirm why this has been removed? 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. It was only used by |
||
|
||
// `publicUrl` is just like `publicPath`, but we will provide it to our app | ||
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. | ||
|
@@ -100,16 +106,16 @@ module.exports = function(webpackEnv) { | |
preProcessorOptions = {} | ||
) => { | ||
const loaders = [ | ||
isEnvDevelopment && require.resolve('style-loader'), | ||
isEnvProduction && { | ||
loader: MiniCssExtractPlugin.loader, | ||
options: Object.assign( | ||
{}, | ||
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined | ||
), | ||
}, | ||
// isEnvDevelopment && require.resolve('style-loader'), | ||
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. Could you confirm why this has been removed? 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. In standard CRA, in development, styles are served client-side only, via the Webpack dev server. The CSS is served inside the I didn't want to get into changing that - so in development, SSR should just ignore styles completely. |
||
// isEnvProduction && { | ||
// loader: MiniCssExtractPlugin.loader, | ||
// options: Object.assign( | ||
// {}, | ||
// shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined | ||
// ), | ||
// }, | ||
{ | ||
loader: require.resolve('css-loader'), | ||
loader: require.resolve('css-loader/locals'), | ||
options: cssOptions, | ||
}, | ||
{ | ||
|
@@ -171,8 +177,8 @@ module.exports = function(webpackEnv) { | |
// the line below with these two lines if you prefer the stock client: | ||
// require.resolve('webpack-dev-server/client') + '?/', | ||
// require.resolve('webpack/hot/dev-server'), | ||
isEnvDevelopment && | ||
require.resolve('react-dev-utils/webpackHotDevClient'), | ||
// isEnvDevelopment && | ||
// require.resolve('react-dev-utils/webpackHotDevClient'), | ||
// Finally, this is your app's code: | ||
// paths.appIndexJs, | ||
paths.appSsrJs, | ||
|
@@ -182,20 +188,20 @@ module.exports = function(webpackEnv) { | |
].filter(Boolean), | ||
output: { | ||
// The build folder. | ||
path: isEnvProduction ? paths.appBuild : undefined, | ||
path: paths.appBuildSsr, | ||
// Add /* filename */ comments to generated require()s in the output. | ||
pathinfo: isEnvDevelopment, | ||
// There will be one main bundle, and one file per asynchronous chunk. | ||
// In development, it does not produce real files. | ||
// filename: isEnvProduction | ||
// ? 'static/js/[name].[chunkhash:8].js' | ||
// : isEnvDevelopment && 'static/js/bundle.js', | ||
filename: 'ssr.js', | ||
filename: 'ssr.[hash:8].js', | ||
libraryTarget: 'commonjs2', | ||
// There are also additional JS chunk files if you use code splitting. | ||
chunkFilename: isEnvProduction | ||
? 'static/js/[name].[chunkhash:8].chunk.js' | ||
: isEnvDevelopment && 'static/js/[name].chunk.js', | ||
: isEnvDevelopment && 'static/js/[name].[chunkhash:8].chunk.js', | ||
// We inferred the "public path" (such as / or /my-project) from homepage. | ||
// We use "/" in development. | ||
publicPath: publicPath, | ||
|
@@ -344,6 +350,7 @@ module.exports = function(webpackEnv) { | |
], | ||
}, | ||
module: { | ||
noParse: /iconv-loader\.js$/, // https://github.com/webpack/webpack/issues/3078#issuecomment-400697407 | ||
strictExportPresence: true, | ||
rules: [ | ||
// Disable require.ensure as it's not a standard language feature. | ||
|
@@ -436,6 +443,7 @@ module.exports = function(webpackEnv) { | |
), | ||
// @remove-on-eject-end | ||
plugins: [ | ||
require.resolve('@loadable/babel-plugin'), | ||
[ | ||
require.resolve('babel-plugin-named-asset-import'), | ||
{ | ||
|
@@ -609,6 +617,20 @@ module.exports = function(webpackEnv) { | |
], | ||
}, | ||
plugins: [ | ||
useHardSourceWebpackPlugin && | ||
new HardSourceWebpackPlugin({ environmentHash }), | ||
useHardSourceWebpackPlugin && | ||
new HardSourceWebpackPlugin.ExcludeModulePlugin([ | ||
{ | ||
// HardSource works with mini-css-extract-plugin but due to how | ||
// mini-css emits assets, assets are not emitted on repeated builds with | ||
// mini-css and hard-source together. Ignoring the mini-css loader | ||
// modules, but not the other css loader modules, excludes the modules | ||
// that mini-css needs rebuilt to output assets every time. | ||
test: /mini-css-extract-plugin[\\/]dist[\\/]loader/, | ||
}, | ||
]), | ||
new LoadablePlugin(), | ||
// Generates an `index.html` file with the <script> injected. | ||
// new HtmlWebpackPlugin( | ||
// Object.assign( | ||
|
@@ -655,9 +677,12 @@ module.exports = function(webpackEnv) { | |
// It is absolutely essential that NODE_ENV is set to production | ||
// during a production build. | ||
// Otherwise React will be compiled in the very slow development mode. | ||
new webpack.DefinePlugin(env.stringified), | ||
new webpack.DefinePlugin({ | ||
...env.stringified, | ||
'typeof window': '"undefined"', | ||
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. Could you confirm what this is doing? 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. https://webpack.js.org/plugins/define-plugin/#usage - defining |
||
}), | ||
// This is necessary to emit hot updates (currently CSS only): | ||
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(), | ||
// isEnvDevelopment && new webpack.HotModuleReplacementPlugin(), | ||
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. Could you confirm why this has been removed? 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. As above re: styles, and I don't think https://webpack.js.org/concepts/hot-module-replacement/ is designed for the server. |
||
// Watcher doesn't work well if you mistype casing in a path so we use | ||
// a plugin that prints an error when you attempt to do this. | ||
// See https://github.com/facebook/create-react-app/issues/240 | ||
|
@@ -668,14 +693,14 @@ module.exports = function(webpackEnv) { | |
// See https://github.com/facebook/create-react-app/issues/186 | ||
isEnvDevelopment && | ||
new WatchMissingNodeModulesPlugin(paths.appNodeModules), | ||
isEnvProduction && | ||
new MiniCssExtractPlugin({ | ||
// Options similar to the same options in webpackOptions.output | ||
// both options are optional | ||
// filename: 'static/css/[name].[contenthash:8].css', | ||
filename: 'ssr.css', | ||
// chunkFilename: 'static/css/[name].[contenthash:8].chunk.css', | ||
}), | ||
// isEnvProduction && | ||
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. Could you confirm why this has been removed? Guessing it relates to the HardSourcePlugin? 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 the styles again. |
||
// new MiniCssExtractPlugin({ | ||
// // Options similar to the same options in webpackOptions.output | ||
// // both options are optional | ||
// // filename: 'static/css/[name].[contenthash:8].css', | ||
// filename: 'ssr.css', | ||
// // chunkFilename: 'static/css/[name].[contenthash:8].chunk.css', | ||
// }), | ||
// Generate a manifest file which contains a mapping of all asset filenames | ||
// to their corresponding output file so that tools can pick it up without | ||
// having to parse `index.html`. | ||
|
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.
Rather than an env variable this might be better as a config value instead?
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.
As it's experimental (mainly because mzgoddard/hard-source-webpack-plugin#419 + waiting for Webpack 5), I've found value in flipping it on/off at will - so was thinking the environment variables maybe gave more flexibility.
If there's cleaner way without needing to make a code change in the consuming project that would still be good.