From f56ebbaf700ce42e92bc5eadfe834e7e44747870 Mon Sep 17 00:00:00 2001
From: Oliver Curtis <8831547+olliecurtis@users.noreply.github.com>
Date: Mon, 14 Jun 2021 16:33:44 +0100
Subject: [PATCH 1/6] [NO JIRA]: Backport updates
---
packages/react-scripts/CHANGELOG.md | 7 ++++++-
packages/react-scripts/README.md | 2 +-
.../react-scripts/config/webpack.config.js | 18 ++++++++++++++----
.../react-scripts/config/webpack.config.ssr.js | 18 ++++++++++++++----
packages/react-scripts/package.json | 2 +-
.../scripts/utils/createJestConfig.js | 1 +
6 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md
index d7a1944f7e9..6f627935828 100644
--- a/packages/react-scripts/CHANGELOG.md
+++ b/packages/react-scripts/CHANGELOG.md
@@ -1,5 +1,9 @@
# `backpack-react-scripts` Change Log
+## 8.0.6
+
+- BACKPORT: Updated webpack paths to include the new `@skyscanner/bpk` foundations packages.
+
## 8.0.4
- Updated `bpk-mixins` to latest version `20.1.5`
@@ -11,7 +15,8 @@
- Downgraded `sass-loader` to `7.3.1` due to issues with `node-sass` and functional changes to options.
Rebased onto `upstream/master` v3.4.4 (6c009edface3ed63d0c7046f088c675a63c82fdb)
- - Update `resolve-url-loader` to `3.1.2` to resolve security vunerability
+
+- Update `resolve-url-loader` to `3.1.2` to resolve security vunerability
## 8.0.2
diff --git a/packages/react-scripts/README.md b/packages/react-scripts/README.md
index 4b2500f109b..ec9f0a85beb 100644
--- a/packages/react-scripts/README.md
+++ b/packages/react-scripts/README.md
@@ -23,7 +23,7 @@ npm start
- **`css.html` & `js.html`**: New files in the `build/` output folder. These are html partials that include `` and `` references to the various static assets output by webpack. Useful if automatic chunking is turned on and you don't want to worry about order.
- A bunch of configuration options via `"backpack-react-scripts"` field in `package.json`:
- `crossOriginLoading`: Modify the default behaviour, see [docs](https://webpack.js.org/configuration/output/#output-crossoriginloading).
- - `babelIncludePrefixes`: An array of module name prefixes to opt into babel compilation. Includes `["bpk-", "saddlebag-"]` by default.
+ - `babelIncludePrefixes`: An array of module name prefixes to opt into babel compilation. Includes `["@skyscanner/bpk-", "bpk-", "saddlebag-"]` by default.
- `enableAutomaticChunking`: Boolean, opt in to automatic chunking of vendor, common and app code.
- `vendorsChunkRegex`: String, Regex for picking what goes into the `vendors` chunk. See `cacheGroups` in webpack docs. Dependent on `enableAutomaticChunking` being enabled
- `amdExcludes`: Array of module names to exclude from AMD parsing. Incldues `["lodash"]` by default.
diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js
index c5bd3f16650..77bf5aa5f84 100644
--- a/packages/react-scripts/config/webpack.config.js
+++ b/packages/react-scripts/config/webpack.config.js
@@ -76,6 +76,7 @@ const sassModuleRegex = /\.module\.(scss|sass)$/;
// Backpack / saddlebag node module regexes
const backpackModulesRegex = /node_modules[\\/]bpk-/;
const saddlebagModulesRegex = /node_modules[\\/]saddlebag-/;
+const scopedBackpackModulesRegex = /node_modules[\\/]@skyscanner[\\/]bpk-/;
// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
@@ -440,6 +441,7 @@ module.exports = function(webpackEnv) {
paths.appSrc,
backpackModulesRegex,
saddlebagModulesRegex,
+ scopedBackpackModulesRegex,
...customModuleRegexes,
],
loader: require.resolve('babel-loader'),
@@ -539,7 +541,7 @@ module.exports = function(webpackEnv) {
{
test: {
and: [cssRegex, () => !cssModulesEnabled],
- exclude: [backpackModulesRegex],
+ exclude: [backpackModulesRegex, scopedBackpackModulesRegex],
},
exclude: cssModuleRegex,
use: getStyleLoaders({
@@ -561,7 +563,11 @@ module.exports = function(webpackEnv) {
and: [cssRegex, () => cssModulesEnabled],
},
{
- and: [cssRegex, backpackModulesRegex],
+ and: [
+ cssRegex,
+ backpackModulesRegex,
+ scopedBackpackModulesRegex,
+ ],
},
],
use: getStyleLoaders({
@@ -578,7 +584,7 @@ module.exports = function(webpackEnv) {
{
test: {
and: [sassRegex, () => !cssModulesEnabled],
- exclude: [backpackModulesRegex],
+ exclude: [backpackModulesRegex, scopedBackpackModulesRegex],
},
exclude: sassModuleRegex,
use: getStyleLoaders(
@@ -606,7 +612,11 @@ module.exports = function(webpackEnv) {
and: [sassRegex, () => cssModulesEnabled],
},
{
- and: [sassRegex, backpackModulesRegex],
+ and: [
+ sassRegex,
+ backpackModulesRegex,
+ scopedBackpackModulesRegex,
+ ],
},
],
use: getStyleLoaders(
diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js
index a99e2aedff3..8f41cb06bd8 100644
--- a/packages/react-scripts/config/webpack.config.ssr.js
+++ b/packages/react-scripts/config/webpack.config.ssr.js
@@ -73,6 +73,7 @@ const sassModuleRegex = /\.module\.(scss|sass)$/;
// Backpack / saddlebag node module regexes
const backpackModulesRegex = /node_modules[\\/]bpk-/;
const saddlebagModulesRegex = /node_modules[\\/]saddlebag-/;
+const scopedBackpackModulesRegex = /node_modules[\\/]@skyscanner[\\/]bpk-/;
// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
@@ -417,6 +418,7 @@ module.exports = function(webpackEnv) {
paths.appSrc,
backpackModulesRegex,
saddlebagModulesRegex,
+ scopedBackpackModulesRegex,
...customModuleRegexes,
],
loader: require.resolve('babel-loader'),
@@ -516,7 +518,7 @@ module.exports = function(webpackEnv) {
{
test: {
and: [cssRegex, () => !cssModulesEnabled],
- exclude: [backpackModulesRegex],
+ exclude: [backpackModulesRegex, scopedBackpackModulesRegex],
},
exclude: cssModuleRegex,
use: getStyleLoaders({
@@ -538,7 +540,11 @@ module.exports = function(webpackEnv) {
and: [cssRegex, () => cssModulesEnabled],
},
{
- and: [cssRegex, backpackModulesRegex],
+ and: [
+ cssRegex,
+ backpackModulesRegex,
+ scopedBackpackModulesRegex,
+ ],
},
],
use: getStyleLoaders({
@@ -555,7 +561,7 @@ module.exports = function(webpackEnv) {
{
test: {
and: [sassRegex, () => !cssModulesEnabled],
- exclude: [backpackModulesRegex],
+ exclude: [backpackModulesRegex, scopedBackpackModulesRegex],
},
exclude: sassModuleRegex,
use: getStyleLoaders(
@@ -583,7 +589,11 @@ module.exports = function(webpackEnv) {
and: [sassRegex, () => cssModulesEnabled],
},
{
- and: [sassRegex, backpackModulesRegex],
+ and: [
+ sassRegex,
+ backpackModulesRegex,
+ scopedBackpackModulesRegex,
+ ],
},
],
use: getStyleLoaders(
diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json
index 74ad521020a..316b0ef9a46 100644
--- a/packages/react-scripts/package.json
+++ b/packages/react-scripts/package.json
@@ -1,6 +1,6 @@
{
"name": "@skyscanner/backpack-react-scripts",
- "version": "8.0.4",
+ "version": "8.0.6",
"description": "Backpack configuration and scripts for Create React App.",
"repository": {
"type": "git",
diff --git a/packages/react-scripts/scripts/utils/createJestConfig.js b/packages/react-scripts/scripts/utils/createJestConfig.js
index 49f9c57ef3b..ff3935488d6 100644
--- a/packages/react-scripts/scripts/utils/createJestConfig.js
+++ b/packages/react-scripts/scripts/utils/createJestConfig.js
@@ -16,6 +16,7 @@ const pkgJson = require(paths.appPackageJson);
const bpkReactScriptsConfig = pkgJson['backpack-react-scripts'] || {};
const includePrefixes = bpkReactScriptsConfig.babelIncludePrefixes || [];
+includePrefixes.unshift('@skyscanner/bpk-');
includePrefixes.unshift('bpk-');
includePrefixes.unshift('saddlebag-');
From f6b5d72c49f50dfc509e7fd71bfb0dec915f99a3 Mon Sep 17 00:00:00 2001
From: Ollie Curtis <8831547+olliecurtis@users.noreply.github.com>
Date: Wed, 10 Jun 2020 12:26:26 +0100
Subject: [PATCH 2/6] [BPK-2599]: Backpackify
---
packages/react-scripts/package.json | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json
index 316b0ef9a46..012f24ae4f6 100644
--- a/packages/react-scripts/package.json
+++ b/packages/react-scripts/package.json
@@ -33,7 +33,11 @@
"babel-loader": "8.1.0",
"babel-plugin-named-asset-import": "^0.3.6",
"babel-preset-react-app": "^9.1.2",
+<<<<<<< HEAD
"bpk-mixins": "^20.1.5",
+=======
+ "bpk-mixins": "^19.1.20",
+>>>>>>> 1904fcb0 ([BPK-2599]: Backpackify)
"camelcase": "^5.3.1",
"case-sensitive-paths-webpack-plugin": "2.3.0",
"css-loader": "3.4.2",
From b650acb11fe58000f2d47e018b6289416859806d Mon Sep 17 00:00:00 2001
From: Ollie Curtis <8831547+olliecurtis@users.noreply.github.com>
Date: Tue, 25 Aug 2020 18:28:34 +0100
Subject: [PATCH 3/6] [no jira]: Full SSR, Hard Source plugin
---
packages/react-scripts/CHANGELOG.md | 11 +++
packages/react-scripts/README.md | 1 +
packages/react-scripts/bin/react-scripts.js | 9 +-
.../react-scripts/config/environmentHash.js | 15 ++++
packages/react-scripts/config/paths.js | 9 +-
.../react-scripts/config/webpack.config.js | 33 +++++++-
.../config/webpack.config.ssr.js | 83 +++++++++++++------
packages/react-scripts/package.json | 10 +--
packages/react-scripts/scripts/build.js | 14 ++--
packages/react-scripts/scripts/init.js | 1 +
packages/react-scripts/scripts/start-ssr.js | 62 ++++++++++++++
packages/react-scripts/scripts/start.js | 10 +++
.../react-scripts/scripts/utils/statusFile.js | 31 +++++++
13 files changed, 244 insertions(+), 45 deletions(-)
create mode 100644 packages/react-scripts/config/environmentHash.js
create mode 100644 packages/react-scripts/scripts/start-ssr.js
create mode 100644 packages/react-scripts/scripts/utils/statusFile.js
diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md
index 6f627935828..86396b7b11d 100644
--- a/packages/react-scripts/CHANGELOG.md
+++ b/packages/react-scripts/CHANGELOG.md
@@ -1,5 +1,16 @@
# `backpack-react-scripts` Change Log
+## 8.1.0 (Pending)
+
+- Added support for loadable components.
+- Added `start-ssr` command, to produce Node.js-compatible watched output. Several changes to SSR Webpack config to support.
+- Defined `typeof window` for browser and SSR environments, enabling dead code elimination (https://webpack.js.org/plugins/define-plugin/#usage)
+- SSR output always includes hash as part of filename
+- Added experimental support for https://github.com/mzgoddard/hard-source-webpack-plugin/, enabled by `USE_HARD_SOURCE_WEBPACK_PLUGIN=true` environment variable
+- `web` and `ssr` subpaths for each build's output
+- Output build 'status files' (`.build-status`, one for web, one for SSR), which can be watched by a Node.js server to know when builds are in progress or completed.
+- Added `ignoreCssWarnings` config item to allow the ability to supress CSS ordering issues when its safe to allow mixed order when it has not effect on output. https://github.com/webpack-contrib/mini-css-extract-plugin#remove-order-warnings
+
## 8.0.6
- BACKPORT: Updated webpack paths to include the new `@skyscanner/bpk` foundations packages.
diff --git a/packages/react-scripts/README.md b/packages/react-scripts/README.md
index ec9f0a85beb..1ec6a1063bb 100644
--- a/packages/react-scripts/README.md
+++ b/packages/react-scripts/README.md
@@ -32,6 +32,7 @@ npm start
- `cssModules`: Boolean, true by default.
- `sriEnabled`: Sets if SRI is to be used during build to add integrity hash for files, see [docs](https://github.com/waysact/webpack-subresource-integrity/blob/master/README.md).
- **Note** if this is enabled, `crossOriginLoading` value is overriden with `anonymous` in order for it to output with the integrity value.
+ - `ignoreCssWarnings`: Boolean, false by default. Allows the ability to supress CSS ordering issues when its safe to allow mixed order when it has not effect on output, see [docs](https://github.com/webpack-contrib/mini-css-extract-plugin#remove-order-warnings). False by default
## Releasing a new version of `backpack-react-scripts`
diff --git a/packages/react-scripts/bin/react-scripts.js b/packages/react-scripts/bin/react-scripts.js
index 7e6e290251a..1b2d36d222f 100755
--- a/packages/react-scripts/bin/react-scripts.js
+++ b/packages/react-scripts/bin/react-scripts.js
@@ -19,12 +19,17 @@ const spawn = require('react-dev-utils/crossSpawn');
const args = process.argv.slice(2);
const scriptIndex = args.findIndex(
- x => x === 'build' || x === 'eject' || x === 'start' || x === 'test'
+ x =>
+ x === 'build' ||
+ x === 'eject' ||
+ x === 'start' ||
+ x === 'start-ssr' ||
+ x === 'test'
);
const script = scriptIndex === -1 ? args[0] : args[scriptIndex];
const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : [];
-if (['build', 'eject', 'start', 'test'].includes(script)) {
+if (['build', 'eject', 'start', 'start-ssr', 'test'].includes(script)) {
const result = spawn.sync(
'node',
nodeArgs
diff --git a/packages/react-scripts/config/environmentHash.js b/packages/react-scripts/config/environmentHash.js
new file mode 100644
index 00000000000..2ff71f01c46
--- /dev/null
+++ b/packages/react-scripts/config/environmentHash.js
@@ -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'],
+};
diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js
index 3b4a304055b..9ab55e2d93a 100644
--- a/packages/react-scripts/config/paths.js
+++ b/packages/react-scripts/config/paths.js
@@ -60,7 +60,8 @@ const resolveModule = (resolveFn, filePath) => {
module.exports = {
dotenv: resolveApp('.env'),
appPath: resolveApp('.'),
- appBuild: resolveApp('build'),
+ appBuildWeb: resolveApp('build/web'),
+ appBuildSsr: resolveApp('build/ssr'),
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
@@ -83,7 +84,8 @@ const resolveOwn = relativePath => path.resolve(__dirname, '..', relativePath);
module.exports = {
dotenv: resolveApp('.env'),
appPath: resolveApp('.'),
- appBuild: resolveApp('build'),
+ appBuildWeb: resolveApp('build/web'),
+ appBuildSsr: resolveApp('build/ssr'),
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
@@ -119,7 +121,8 @@ if (
module.exports = {
dotenv: resolveOwn(`${templatePath}/.env`),
appPath: resolveApp('.'),
- appBuild: resolveOwn('../../build'),
+ appBuildWeb: resolveOwn('../../build/web'),
+ appBuildSsr: resolveOwn('../../build/ssr'),
appPublic: resolveOwn(`${templatePath}/public`),
appHtml: resolveOwn(`${templatePath}/public/index.html`),
appIndexJs: resolveModule(resolveOwn, `${templatePath}/src/index`),
diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js
index 77bf5aa5f84..aa0d5adf215 100644
--- a/packages/react-scripts/config/webpack.config.js
+++ b/packages/react-scripts/config/webpack.config.js
@@ -40,6 +40,9 @@ const postcssNormalize = require('postcss-normalize');
const appPackageJson = require(paths.appPackageJson);
+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 bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {};
@@ -51,6 +54,7 @@ const customModuleRegexes = bpkReactScriptsConfig.babelIncludePrefixes
const cssModulesEnabled = bpkReactScriptsConfig.cssModules !== false;
const crossOriginLoading = bpkReactScriptsConfig.crossOriginLoading || false;
const sriEnabled = bpkReactScriptsConfig.sriEnabled || false;
+const supressCssWarnings = bpkReactScriptsConfig.ignoreCssWarnings || false;
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
@@ -58,6 +62,11 @@ const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
// 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 =
+ process.env.USE_HARD_SOURCE_WEBPACK_PLUGIN === 'true';
+const environmentHash = require('./environmentHash');
+
// const isExtendingEslintConfig = process.env.EXTEND_ESLINT === 'true';
const imageInlineSizeLimit = parseInt(
@@ -196,7 +205,7 @@ module.exports = function(webpackEnv) {
output: {
crossOriginLoading: sriEnabled ? 'anonymous' : crossOriginLoading,
// The build folder.
- path: isEnvProduction ? paths.appBuild : undefined,
+ path: paths.appBuildWeb,
// Add /* filename */ comments to generated require()s in the output.
pathinfo: isEnvDevelopment,
// There will be one main bundle, and one file per asynchronous chunk.
@@ -375,6 +384,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.
@@ -471,6 +481,7 @@ module.exports = function(webpackEnv) {
),
// @remove-on-eject-end
plugins: [
+ require.resolve('@loadable/babel-plugin'),
[
require.resolve('babel-plugin-named-asset-import'),
{
@@ -656,6 +667,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