From ce77eab4912b41c844e508a6abe4ce1cf2c2f90f 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 01/29] Backpackify --- .github/workflows/build-brs.yml | 50 + .github/workflows/build.yml | 6 +- .github/workflows/lint.yml | 6 +- README.md | 222 +---- .../package.json | 1 + packages/babel-preset-react-app/package.json | 1 + .../confusing-browser-globals/package.json | 1 + packages/cra-template-typescript/package.json | 1 + packages/cra-template/package.json | 1 + packages/create-react-app/package.json | 1 + packages/eslint-config-react-app/package.json | 1 + packages/react-app-polyfill/package.json | 1 + packages/react-dev-utils/package.json | 1 + packages/react-error-overlay/package.json | 1 + packages/react-scripts/CHANGELOG.md | 556 +++++++++++ packages/react-scripts/README.md | 37 +- packages/react-scripts/config/css.html | 5 + packages/react-scripts/config/js.html | 3 + packages/react-scripts/config/paths.js | 3 + .../react-scripts/config/webpack.config.js | 210 +++- .../config/webpack.config.ssr.js | 908 ++++++++++++++++++ .../docs/migrating-from-v6-to-v7.md | 181 ++++ .../docs/migrating-from-v7-to-v8.md | 83 ++ .../docs/migrating-from-v8-to-v9.md | 40 + packages/react-scripts/docs/updating-brs.md | 81 ++ packages/react-scripts/package.json | 37 +- packages/react-scripts/scripts/build.js | 35 +- packages/react-scripts/scripts/init.js | 34 +- .../scripts/utils/createJestConfig.js | 29 +- .../scripts/utils/verifyPackageTree.js | 2 - tasks/e2e-installs.sh | 95 +- tasks/e2e-kitchensink.sh | 2 +- tasks/e2e-simple.sh | 88 +- tasks/local-registry.sh | 2 +- tasks/publish.sh | 9 +- 35 files changed, 2324 insertions(+), 410 deletions(-) create mode 100644 .github/workflows/build-brs.yml create mode 100644 packages/react-scripts/CHANGELOG.md create mode 100644 packages/react-scripts/config/css.html create mode 100644 packages/react-scripts/config/js.html create mode 100644 packages/react-scripts/config/webpack.config.ssr.js create mode 100644 packages/react-scripts/docs/migrating-from-v6-to-v7.md create mode 100644 packages/react-scripts/docs/migrating-from-v7-to-v8.md create mode 100644 packages/react-scripts/docs/migrating-from-v8-to-v9.md create mode 100644 packages/react-scripts/docs/updating-brs.md diff --git a/.github/workflows/build-brs.yml b/.github/workflows/build-brs.yml new file mode 100644 index 000000000..b08074b6f --- /dev/null +++ b/.github/workflows/build-brs.yml @@ -0,0 +1,50 @@ +name: Build BRS + +on: + push: + branches: [fork] + pull_request: + branches: [fork] + +defaults: + run: + shell: bash -l {0} + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + + - name: nvm install + run: nvm install lts/erbium + + - name: Run simple + run: | + nvm use lts/erbium + tasks/e2e-simple.sh + + - name: Run Installs + run: | + nvm use lts/erbium + tasks/e2e-installs.sh + + ## For now we don't need to worry about Kitchensink as this is also failing upstream and the functions is executes are not relevant + + # - name: Run Kitchensink + # shell: bash -l {0} + # run: | + # nvm use lts/erbium + # tasks/e2e-kitchensink.sh + + # - name: Run Kitchensink Eject + # shell: bash -l {0} + # run: | + # nvm use lts/erbium + # tasks/e2e-kitchensink-eject.sh + + # - name: Run Behaviour + # shell: bash -l {0} + # run: | + # nvm use lts/erbium + # tasks/e2e-behavior.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7b94526e8..a7f66cab6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,10 @@ name: Build -on: [push] +on: + push: + branches: [fork] + pull_request: + branches: [fork] jobs: build: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a2e7567d1..7dae7aa40 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,6 +1,10 @@ name: Lint -on: [push] +on: + push: + branches: [fork] + pull_request: + branches: [fork] jobs: lint: diff --git a/README.md b/README.md index f688165eb..a82b4b29a 100644 --- a/README.md +++ b/README.md @@ -1,220 +1,12 @@ -# Create React App [](https://dev.azure.com/facebook/create-react-app/_build/latest?definitionId=1&branchName=master) [](https://github.com/facebook/create-react-app/blob/master/CONTRIBUTING.md) +# `backpack-react-scripts` [](https://travis-ci.org/Skyscanner/backpack-react-scripts) -<img alt="Logo" align="right" src="https://create-react-app.dev/img/logo.svg" width="20%" /> +**âš ï¸ This is a fork of Facebook's [Create React App](https://github.com/facebook/create-react-app).** -Create React apps with no build configuration. +Specifically, it is a fork of the [`react-scripts`](https://github.com/facebook/create-react-app/tree/master/packages/react-scripts) package. It adds Backpack component support and server-side rendering functionality (amongst other things). -- [Creating an App](#creating-an-app) – How to create a new app. -- [User Guide](https://facebook.github.io/create-react-app/) – How to develop apps bootstrapped with Create React App. +In order to benefit from the ongoing open source development of create-react-app, this fork is kept up-to-date with the upstream repo. To aid this, we have preserved the existing repo structure, including all of the source code for the other packages that live alongside [`react-scripts`](https://github.com/facebook/create-react-app/tree/master/packages/react-scripts). **We do not modify any source code outside of [`react-scripts`](https://github.com/facebook/create-react-app/tree/master/packages/react-scripts).** -Create React App works on macOS, Windows, and Linux.<br> -If something doesn’t work, please [file an issue](https://github.com/facebook/create-react-app/issues/new).<br> -If you have questions or need help, please ask in [GitHub Discussions](https://github.com/facebook/create-react-app/discussions). +Files of interest: -## Quick Overview - -```sh -npx create-react-app my-app -cd my-app -npm start -``` - -If you've previously installed `create-react-app` globally via `npm install -g create-react-app`, we recommend you uninstall the package using `npm uninstall -g create-react-app` or `yarn global remove create-react-app` to ensure that npx always uses the latest version. - -_([npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) comes with npm 5.2+ and higher, see [instructions for older npm versions](https://gist.github.com/gaearon/4064d3c23a77c74a3614c498a8bb1c5f))_ - -Then open [http://localhost:3000/](http://localhost:3000/) to see your app.<br> -When you’re ready to deploy to production, create a minified bundle with `npm run build`. - -<p align='center'> -<img src='https://cdn.jsdelivr.net/gh/facebook/create-react-app@27b42ac7efa018f2541153ab30d63180f5fa39e0/screencast.svg' width='600' alt='npm start'> -</p> - -### Get Started Immediately - -You **don’t** need to install or configure tools like webpack or Babel.<br> -They are preconfigured and hidden so that you can focus on the code. - -Create a project, and you’re good to go. - -## Creating an App - -**You’ll need to have Node 10.16.0 or later version on your local development machine** (but it’s not required on the server). We recommend using the latest LTS version. You can use [nvm](https://github.com/creationix/nvm#installation) (macOS/Linux) or [nvm-windows](https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows) to switch Node versions between different projects. - -To create a new app, you may choose one of the following methods: - -### npx - -```sh -npx create-react-app my-app -``` - -_([npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) is a package runner tool that comes with npm 5.2+ and higher, see [instructions for older npm versions](https://gist.github.com/gaearon/4064d3c23a77c74a3614c498a8bb1c5f))_ - -### npm - -```sh -npm init react-app my-app -``` - -_`npm init <initializer>` is available in npm 6+_ - -### Yarn - -```sh -yarn create react-app my-app -``` - -_[`yarn create <starter-kit-package>`](https://yarnpkg.com/lang/en/docs/cli/create/) is available in Yarn 0.25+_ - -It will create a directory called `my-app` inside the current folder.<br> -Inside that directory, it will generate the initial project structure and install the transitive dependencies: - -``` -my-app -├── README.md -├── node_modules -├── package.json -├── .gitignore -├── public -│ ├── favicon.ico -│ ├── index.html -│ └── manifest.json -└── src - ├── App.css - ├── App.js - ├── App.test.js - ├── index.css - ├── index.js - ├── logo.svg - └── serviceWorker.js - └── setupTests.js -``` - -No configuration or complicated folder structures, only the files you need to build your app.<br> -Once the installation is done, you can open your project folder: - -```sh -cd my-app -``` - -Inside the newly created project, you can run some built-in commands: - -### `npm start` or `yarn start` - -Runs the app in development mode.<br> -Open [http://localhost:3000](http://localhost:3000) to view it in the browser. - -The page will automatically reload if you make changes to the code.<br> -You will see the build errors and lint warnings in the console. - -<p align='center'> -<img src='https://cdn.jsdelivr.net/gh/marionebl/create-react-app@9f6282671c54f0874afd37a72f6689727b562498/screencast-error.svg' width='600' alt='Build errors'> -</p> - -### `npm test` or `yarn test` - -Runs the test watcher in an interactive mode.<br> -By default, runs tests related to files changed since the last commit. - -[Read more about testing.](https://facebook.github.io/create-react-app/docs/running-tests) - -### `npm run build` or `yarn build` - -Builds the app for production to the `build` folder.<br> -It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.<br> - -Your app is ready to be deployed. - -## User Guide - -You can find detailed instructions on using Create React App and many tips in [its documentation](https://facebook.github.io/create-react-app/). - -## How to Update to New Versions? - -Please refer to the [User Guide](https://facebook.github.io/create-react-app/docs/updating-to-new-releases) for this and other information. - -## Philosophy - -- **One Dependency:** There is only one build dependency. It uses webpack, Babel, ESLint, and other amazing projects, but provides a cohesive curated experience on top of them. - -- **No Configuration Required:** You don't need to configure anything. A reasonably good configuration of both development and production builds is handled for you so you can focus on writing code. - -- **No Lock-In:** You can “eject†to a custom setup at any time. Run a single command, and all the configuration and build dependencies will be moved directly into your project, so you can pick up right where you left off. - -## What’s Included? - -Your environment will have everything you need to build a modern single-page React app: - -- React, JSX, ES6, TypeScript and Flow syntax support. -- Language extras beyond ES6 like the object spread operator. -- Autoprefixed CSS, so you don’t need `-webkit-` or other prefixes. -- A fast interactive unit test runner with built-in support for coverage reporting. -- A live development server that warns about common mistakes. -- A build script to bundle JS, CSS, and images for production, with hashes and sourcemaps. -- An offline-first [service worker](https://developers.google.com/web/fundamentals/getting-started/primers/service-workers) and a [web app manifest](https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/), meeting all the [Progressive Web App](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) criteria. (_Note: Using the service worker is opt-in as of `react-scripts@2.0.0` and higher_) -- Hassle-free updates for the above tools with a single dependency. - -Check out [this guide](https://github.com/nitishdayal/cra_closer_look) for an overview of how these tools fit together. - -The tradeoff is that **these tools are preconfigured to work in a specific way**. If your project needs more customization, you can ["eject"](https://facebook.github.io/create-react-app/docs/available-scripts#npm-run-eject) and customize it, but then you will need to maintain this configuration. - -## Popular Alternatives - -Create React App is a great fit for: - -- **Learning React** in a comfortable and feature-rich development environment. -- **Starting new single-page React applications.** -- **Creating examples** with React for your libraries and components. - -Here are a few common cases where you might want to try something else: - -- If you want to **try React** without hundreds of transitive build tool dependencies, consider [using a single HTML file or an online sandbox instead](https://reactjs.org/docs/try-react.html). - -- If you need to **integrate React code with a server-side template framework** like Rails, Django or Symfony, or if you’re **not building a single-page app**, consider using [nwb](https://github.com/insin/nwb), or [Neutrino](https://neutrino.js.org/) which are more flexible. For Rails specifically, you can use [Rails Webpacker](https://github.com/rails/webpacker). For Symfony, try [Symfony's webpack Encore](https://symfony.com/doc/current/frontend/encore/reactjs.html). - -- If you need to **publish a React component**, [nwb](https://github.com/insin/nwb) can [also do this](https://github.com/insin/nwb#react-components-and-libraries), as well as [Neutrino's react-components preset](https://neutrino.js.org/packages/react-components/). - -- If you want to do **server rendering** with React and Node.js, check out [Next.js](https://nextjs.org/) or [Razzle](https://github.com/jaredpalmer/razzle). Create React App is agnostic of the backend, and only produces static HTML/JS/CSS bundles. - -- If your website is **mostly static** (for example, a portfolio or a blog), consider using [Gatsby](https://www.gatsbyjs.org/) or [Next.js](https://nextjs.org/). Unlike Create React App, Gatsby pre-renders the website into HTML at build time. Next.js supports both server rendering and pre-rendering. - -- Finally, if you need **more customization**, check out [Neutrino](https://neutrino.js.org/) and its [React preset](https://neutrino.js.org/packages/react/). - -All of the above tools can work with little to no configuration. - -If you prefer configuring the build yourself, [follow this guide](https://reactjs.org/docs/add-react-to-an-existing-app.html). - -## React Native - -Looking for something similar, but for React Native?<br> -Check out [Expo CLI](https://github.com/expo/expo-cli). - -## Contributing - -We'd love to have your helping hand on `create-react-app`! See [CONTRIBUTING.md](CONTRIBUTING.md) for more information on what we're looking for and how to get started. - -## Supporting Create React App - -Create React App is a community maintained project and all contributors are volunteers. If you'd like to support the future development of Create React App then please consider donating to our [Open Collective](https://opencollective.com/create-react-app). - -## Credits - -This project exists thanks to all the people who [contribute](CONTRIBUTING.md).<br> -<a href="https://github.com/facebook/create-react-app/graphs/contributors"><img src="https://opencollective.com/create-react-app/contributors.svg?width=890&button=false" /></a> - -Thanks to [Netlify](https://www.netlify.com/) for hosting our documentation. - -## Acknowledgements - -We are grateful to the authors of existing related projects for their ideas and collaboration: - -- [@eanplatter](https://github.com/eanplatter) -- [@insin](https://github.com/insin) -- [@mxstbr](https://github.com/mxstbr) - -## License - -Create React App is open source software [licensed as MIT](https://github.com/facebook/create-react-app/blob/master/LICENSE). The Create React App logo is licensed under a [Creative Commons Attribution 4.0 International license](https://creativecommons.org/licenses/by/4.0/). +- [`react-scripts` README](packages/react-scripts/README.md) +- [`react-scripts` CHANGELOG](packages/react-scripts/CHANGELOG.md) diff --git a/packages/babel-plugin-named-asset-import/package.json b/packages/babel-plugin-named-asset-import/package.json index e80440a08..29d9fa59a 100644 --- a/packages/babel-plugin-named-asset-import/package.json +++ b/packages/babel-plugin-named-asset-import/package.json @@ -1,6 +1,7 @@ { "name": "babel-plugin-named-asset-import", "version": "0.3.7", + "private": true, "description": "Babel plugin for named asset imports in Create React App", "repository": { "type": "git", diff --git a/packages/babel-preset-react-app/package.json b/packages/babel-preset-react-app/package.json index 986836e2a..e260f2576 100644 --- a/packages/babel-preset-react-app/package.json +++ b/packages/babel-preset-react-app/package.json @@ -1,6 +1,7 @@ { "name": "babel-preset-react-app", "version": "10.0.0", + "private": true, "description": "Babel preset used by Create React App", "repository": { "type": "git", diff --git a/packages/confusing-browser-globals/package.json b/packages/confusing-browser-globals/package.json index d6abc2dc6..d9e1f7569 100644 --- a/packages/confusing-browser-globals/package.json +++ b/packages/confusing-browser-globals/package.json @@ -1,6 +1,7 @@ { "name": "confusing-browser-globals", "version": "1.0.10", + "private": true, "description": "A list of browser globals that are often used by mistake instead of local variables", "license": "MIT", "main": "index.js", diff --git a/packages/cra-template-typescript/package.json b/packages/cra-template-typescript/package.json index d2bd82433..178c09e9c 100644 --- a/packages/cra-template-typescript/package.json +++ b/packages/cra-template-typescript/package.json @@ -1,6 +1,7 @@ { "name": "cra-template-typescript", "version": "1.1.2", + "private": true, "keywords": [ "react", "create-react-app", diff --git a/packages/cra-template/package.json b/packages/cra-template/package.json index fe933d404..112739c69 100644 --- a/packages/cra-template/package.json +++ b/packages/cra-template/package.json @@ -1,6 +1,7 @@ { "name": "cra-template", "version": "1.1.2", + "private": true, "keywords": [ "react", "create-react-app", diff --git a/packages/create-react-app/package.json b/packages/create-react-app/package.json index b83da7dfe..57ec34a0e 100644 --- a/packages/create-react-app/package.json +++ b/packages/create-react-app/package.json @@ -1,6 +1,7 @@ { "name": "create-react-app", "version": "4.0.3", + "private": true, "keywords": [ "react" ], diff --git a/packages/eslint-config-react-app/package.json b/packages/eslint-config-react-app/package.json index 6177cc62d..9c6a90a7f 100644 --- a/packages/eslint-config-react-app/package.json +++ b/packages/eslint-config-react-app/package.json @@ -1,6 +1,7 @@ { "name": "eslint-config-react-app", "version": "6.0.0", + "private": true, "description": "ESLint configuration used by Create React App", "repository": { "type": "git", diff --git a/packages/react-app-polyfill/package.json b/packages/react-app-polyfill/package.json index 32b5343a6..8a50f04f2 100644 --- a/packages/react-app-polyfill/package.json +++ b/packages/react-app-polyfill/package.json @@ -1,6 +1,7 @@ { "name": "react-app-polyfill", "version": "2.0.0", + "private": true, "description": "Polyfills for various browsers including commonly used language features", "repository": { "type": "git", diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json index 77a41ebe5..a95666686 100644 --- a/packages/react-dev-utils/package.json +++ b/packages/react-dev-utils/package.json @@ -1,6 +1,7 @@ { "name": "react-dev-utils", "version": "11.0.3", + "private": true, "description": "webpack utilities used by Create React App", "repository": { "type": "git", diff --git a/packages/react-error-overlay/package.json b/packages/react-error-overlay/package.json index 137ceb7f2..f6172af87 100644 --- a/packages/react-error-overlay/package.json +++ b/packages/react-error-overlay/package.json @@ -1,6 +1,7 @@ { "name": "react-error-overlay", "version": "6.0.9", + "private": true, "description": "An overlay for displaying stack frames.", "main": "lib/index.js", "sideEffects": false, diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md new file mode 100644 index 000000000..8d66cd930 --- /dev/null +++ b/packages/react-scripts/CHANGELOG.md @@ -0,0 +1,556 @@ +# `backpack-react-scripts` Change Log + +## 9.0.3 + +- Rebased onto `upstream/master` v4.0.3 (f92c37a6e6636ed1650ffd976c6881f59b1be803) + +## 9.0.2 + +- Rebased onto `upstream/master` v4.0.1 (de8b2b3f2d0a699284420c19d5b4db0be776e0cf) +- Bumped `@svgr/webpack` to v5.5.0 + +## 9.0.1 + +- Fixed an issue where eslint was being shipped, which is not required due to our own linting package. + +## 9.0.0 + +With this change its is only breaking due to the requirement of needing `Jest` to be upgraded to `26.6.0`, nothing else should affect from a consumer perspective. + +### Breaking + +- Rebased onto `upstream/master` v4.0.0 (ed958938f642007645dd5ac3466db36202f8754e). +- This release rebases `backpack-react-scripts` on top of `create-react-app` v4! The major changes have been summarised in the following blog post: + [Create React App 4.0](https://github.com/facebook/create-react-app/blob/master/CHANGELOG.md#400-2020-10-23) + +- **The only breaking change is the requirement of Jest to be upgraded. Please follow [this guide](./docs/migrating-from-v8-to-v9.md) when upgrading.** + +## 8.0.5 + +- Updated `bpk-mixins` to latest version + +## 8.0.4 + +- Updated `bpk-mixins` to latest version `20.1.5` + +## 8.0.3 + +### Fixed + +- 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 + +## 8.0.2 + +### Fixed + +- Updated `lodash` to latest to resolve vunerabilites. + +## 8.0.1 + +### Fixed + +- Update `terser-webpack-plugin` to `2.3.8` to resolve security vunerability +- Update `webpack-dev-server` to `3.11.0` to resolve security vunerability + +## 8.0.0 + +### Breaking + +- Rebased onto `upstream/master` v3.4.1 (d2f813f8897ffcd2f0b0d2da75d0c44924c92f4d). +- This release rebases `backpack-react-scripts` on top of `create-react-app` v3! The major changes have been summarised in the following blog post: + [Create React App 3.0](https://github.com/facebook/create-react-app/blob/master/CHANGELOG.md#300-april-22-2019) +- **Some of these changes are breaking. Please follow [this guide](./migrating-from-v7-to-v8.md) when upgrading.** + +## 7.0.5 - 2020-01-10 + +### Fixed + +- Reverted change introducted in `7.0.4` that unlocked `babel-loader` version which was causing issues when running BRS scripts + +## 7.0.4 + +### Fixed + +- Unlocked `babel-loader` version to allow in range versions. + +## 7.0.3 (November 18, 2019) + +- Add the ability to split vendor chunks using `vendorChunkRegex`. Anything that matches the regex will be put in the vendors chunk. [See PR from banana project](https://github.skyscannertools.net/dingo/banana/blob/2c5bf3f89bc0d1fec29e7fae27dd5988e99dedec/packages/webapp/package.json#L151) + +## 7.0.1 - 2019-09-18 + +### Fixed + +- Update `node-sass` to `4.12.0` to support Node 12 rollout. +- Update `fsevents` to `1.2.9` to support Node 12 rollout. + +## 7.0.0 - 2019-01-11 + +### Breaking + +- Rebased onto `upstream/master` v2.1.2 (3e1dc990130c45f57c647e847682ded0ba352c7b) +- This release rebases `backpack-react-scripts` on top of `create-react-app` v2! The major changes have been summarised in the following blog post: + [Create React App 2.0: Babel 7, Sass, and More.](https://reactjs.org/blog/2018/10/01/create-react-app-v2.html) +- **Some of these changes are breaking. Please follow [this guide](./migrating-from-v6-to-v7.md) when upgrading.** + +## 6.0.0 - 2018-11-02 + +### Breaking + +- Add css modules to `.css` imports. This is only valid for projects using css modules + +## 5.2.1 - 2018-09-10 + +### Fixed + +- Remove peer dependency warnings +- Remove usage of `bpk-component-grid` + +## 5.2.0 - 2018-09-06 + +### Added + +- Rebased onto `upstream/master` v1.1.5 (dc74990b89b5c6e143b522c759be3dac2c286514) +- Upgraded dependencies, mostly `eslint` based. + +## 5.1.1 - 2018-04-11 + +### Fixed + +- `backpack-react-scripts` listed inside of `devDependencies` instead of `dependencies` +- `registerServiceWorker.js` no longer appears in project output + +## 5.1.0 - 2018-04-10 + +### Added + +- Rebased onto `upstream/master` v1.1.4 (dfbc71ce2ae07547a8544cce14a1a23fac99e071) + +## 5.0.10 - 2018-03-21 + +### Fixed + +- New `disablePolyfills` config in `package.json`. You can opt out of including polyfills from the output bundle like so: + +```json + "backpack-react-scripts": { + "disablePolyfills": true + } +``` + +## 5.0.9 - 2018-03-14 + +### Fixed + +- New `crossOriginLoading` config in `package.json`. You can configure cross-origin loading of dynamic chunks: + +```json + "backpack-react-scripts": { + "crossOriginLoading": "anonymous" + } +``` + +## 5.0.8 - 2018-03-07 + +### Fixed + +- New `amdExcludes` config in `package.json`. You can now disable AMD parsing for specific modules like so: + +```json + "backpack-react-scripts": { + "amdExcludes": [ + "globalize" + ] + } +``` + +## 5.0.7 - 2018-03-06 + +### Fixed + +- Use `package.json` name field as value for `output.jsonpFunction`, this is important for when multiple webpack runtimes from different compilation are used on the same page + +## 5.0.6 - 2018-01-31 + +### Fixed + +- CSS Modules hashing now uses `package.json` name field as a salt + +## 5.0.5 - 2018-01-15 + +### Fixed + +- Added `saddlebag-` prefix to the jest config + +## 5.0.4 - 2018-01-11 + +### Added + +- Added `saddlebag-` prefix for saddlebag modules + +## 5.0.3 - 2017-12-21 + +### Fixed + +- Rebased onto `upstream/master` v1.0.17 (4b55193f0ad479f26b0f5e153bb4b152a1ee03e7) +- Peer dependency issues with `postcss-less` & `sugarss` + +## 5.0.2 - 2017-11-03 + +### Fixed + +- Scope the disabling of AMD for `lodash` only + +## 5.0.1 - 2017-11-02 + +### Fixed + +- Prevent lodash imports from leaking on to the global scope, see https://github.com/webpack/webpack/issues/3017#issuecomment-285954512 +- Upgraded `stylelint` to `^8.2.0` and `stylelint-config-skyscanner` to `^1.0.1` + +## 5.0.0 - 2017-10-30 + +### Breaking + +- Upgraded [`eslint-config-skyscanner`](https://github.com/Skyscanner/eslint-config-skyscanner/blob/master/changelog.md#300---upgraded-esling-config-airbnb-peer-dependencies) to `3.0.0`. + +## 4.0.8 - 2017-10-12 + +### Fixed + +- Rebased onto `upstream/master` (b2c0b3f74b47f0f85e3f17f7d3249b7e536cda05) +- Locked `react` & `react-dom` versions to `^15.0.0` for now + +## 4.0.7 - 2017-08-24 + +### Fixed + +- Fixed issue with classnames not being hashed correctly for projects using CSS Modules + +## 4.0.6 - 2017-08-22 + +### Fixed + +- Upgraded sass-loader to 6.0.6 which fixes peer dependency warning with webpack (caused shrinkwraps to fail) +- Upgraded bpk-mixins to 16.3.1 + +## 4.0.5 - 2017-08-17 + +### Fixed + +- Rebased onto `upstream/master` (e8a3e4b2995f4c6e49c0a7ed653a1646a7b5e515) + +## 4.0.3 - 2017-08-10 + +### Fixed + +- Production and SSR builds will now use `optimize-css-assets-webpack-plugin` with `cssnano` to optimize output CSS. This gets rid of duplication of global CSS constructs such as keyframes. + +## 4.0.2 - 2017-07-28 + +### Fixed + +- Deprecated BpkHeading and BpkParagraph +- Added BpkText component +- Updated all other Backpack dependencies to latest versions + +## 4.0.1 - 2017-07-27 + +### Fixed + +- Updated eslint-plugin-import to 2.7.0 to fix `npm shrinkwrap --save-dev` + +## 4.0.0 - 2017-07-27 + +### Changed + +- Updated stylelint to 8.0.0 and stylelint-config-skyscanner to 1.0.0 + +## 3.0.1 - 2017-07-12 + +### Fixed + +- Mocked CSS Modules for Jest, so snapshot tests include the original class names + +## 3.0.0 - 2017-07-11 + +### Changed + +- Enabled [CSS Modules](https://github.com/css-modules/css-modules) by default + - You can use the config option `cssModules` to opt out: + ``` + "backpack-react-scripts": { + "cssModules": false + } + ``` + In this case, Sass files will not be treated as CSS Modules by default. However, you can opt-in on a + per-file basis using the naming convention: `*.module.scss`. + - Backpack components will _always_ be treated as CSS Modules, even if you opt out + - All Backpack components need to be on these versions (or higher) to work: + - bpk-component-accordion@1.1.0 + - bpk-component-autosuggest@3.0.13 + - bpk-component-badge@0.1.0 + - bpk-component-banner-alert@1.1.0 + - bpk-component-barchart@0.1.0 + - bpk-component-blockquote@0.1.0 + - bpk-component-breakpoint@0.1.22 + - bpk-component-button@1.6.33 + - bpk-component-calendar@3.3.0 + - bpk-component-card@0.1.0 + - bpk-component-checkbox@1.2.0 + - bpk-component-close-button@0.1.0 + - bpk-component-code@0.1.0 + - bpk-component-content-container@1.1.0 + - bpk-component-datepicker@6.1.1 + - bpk-component-fieldset@0.3.1 + - bpk-component-form-validation@0.1.0 + - bpk-component-grid-toggle@0.1.0 + - bpk-component-grid@1.1.0 + - bpk-component-heading@2.1.0 + - bpk-component-horizontal-nav@0.1.0 + - bpk-component-icon@3.7.0 + - bpk-component-input@3.2.1 + - bpk-component-label@3.2.0 + - bpk-component-link@0.6.0 + - bpk-component-list@0.1.0 + - bpk-component-loading-button@0.1.0 + - bpk-component-modal@1.1.0 + - bpk-component-nudger@0.1.0 + - bpk-component-panel@0.1.0 + - bpk-component-paragraph@0.3.0 + - bpk-component-popover@1.1.0 + - bpk-component-progress@0.1.0 + - bpk-component-radio@1.1.0 + - bpk-component-router-link@0.2.0 + - bpk-component-rtl-toggle@0.0.73 + - bpk-component-select@2.1.0 + - bpk-component-spinner@2.1.0 + - bpk-component-star-rating@0.0.3 + - bpk-component-table@0.1.0 + - bpk-component-textarea@0.1.0 + - bpk-component-ticket@0.1.0 + - bpk-component-tooltip@1.1.0 + - bpk-react-utils@2.0.0 + +## 2.0.3 - 2017-07-010 + +### Fixed + +- Rebased onto `upstream/master` (f495c15578403cf2dbac211493ae8fb6ac742415) + +## 2.0.1 - 2017-07-04 + +### Changed + +- Replaced the "babelIncludeRegex" config option in `package.json` with "babelIncludePrefixes". You can now + enable transpilation for your dependencies by adding package prefixes like so: + ``` + { + ... + "backpack-react-scripts": { + "babelIncludePrefixes": [ + "my-module-prefix-", + "some-dependency" + ] + } + } + ``` + +### Changed + +- Upgraded `eslint-config-skyscanner` to `2.0.0` which uses the `babel-eslint` parse + +## 1.0.1 - 2017-06-12 + +### Added + +- Added `babel-eslint` as dependency so it can be used with ESLint when dynamic `import()` statements are used + +### Changed + +- Upgraded `eslint-config-skyscanner` to `2.0.0` which uses the `babel-eslint` parse + +## 1.0.0 - 2017-05-29 + +### Changed + +- Rebased from `upstream/master` (fbaeff2d6ef83ae5dc8213150e0fa6589ed29150) +- TLDR; this upgrades the upstream dependency `react-scripts` to `^1.0.0` - please read the [blog post](https://facebook.github.io/react/blog/2017/05/18/whats-new-in-create-react-app.html) for a summary of the new features this brings +- This is a major release, meaning there are a few breaking changes (summarised below). Please refer to the [`react-scripts` changelog](https://github.com/facebookincubator/create-react-app/blob/master/CHANGELOG.md#100-may-18-2017) for detailed migration documentations. + - [Ensure application and test files reside in src/](https://github.com/facebookincubator/create-react-app/blob/master/CHANGELOG.md#ensure-application-and-test-files-reside-in-src) + - [You can no longer import file content](https://github.com/facebookincubator/create-react-app/blob/master/CHANGELOG.md#you-can-no-longer-import-file-content) + - [Confusing window globals can no longer be used without window qualifier](https://github.com/facebookincubator/create-react-app/blob/master/CHANGELOG.md#confusing-window-globals-can-no-longer-be-used-without-window-qualifier) + - [Jest snapshot format has changed](https://github.com/facebookincubator/create-react-app/blob/master/CHANGELOG.md#how-do-i-make-my-tests-work-with-jest-20) + +## 0.0.19 - 2017-05-02 + +### Added + +- The ability to configure "babelIncludeRegex" in package json + +## 0.0.18 - 2017-04-10 + +### Added + +- Support for new `bpk-icon` mixin from `bpk-mixins` + +## 0.0.17 - 2017-04-06 + +### Fixed + +- Rebased from `upstream/0.9.x` (ebebe80383eb15b4759a0cd5ea12015eaac94c0e) +- Now moves `react` and `react-dom` from dependencies to devDependencies + +## 0.0.16 - 2017-03-30 + +### Added + +- Upgrading `eslint-config-skyscanner` to v1.1.0 +- Upgrading `stylelint-config-skyscanner` to v0.1.3 +- Upgrading `eslint-plugin-react` to v6.10.3 as [undelying issue](https://github.com/yannickcr/eslint-plugin-react/issues/1117) which caused it to be pinned was resolved +- Upgrading `node-sass` to v4.5.0 to make it compatible with latest version of `bpk-mixins` +- Upgrading all Backpack dev dependencies: + - `bpk-component-button` to v1.6.6 + - `bpk-component-code` to v0.0.58 + - `bpk-component-grid` to v1.0.8 + - `bpk-component-heading` to v1.2.7 + - `bpk-component-paragraph` to v0.2.1 + - `bpk-mixins` to v11.0.2 + - `bpk-stylesheets` to v3.2.16 +- Upgrading `detect-port` to v1.1.1 + +## 0.0.15 - 2017-03-27 + +### Added + +- The ability to lint SCSS with `stylelint-config-skyscanner` + - run `npm run lint:scss` or just `npm run lint` for both JS and SCSS linting +- The ability to automatically fix many SCSS linting issues using `stylefmt` + - run `npm run lint:scss:fix` +- The ability to automatically fix many JS linting issues using `eslint --fix` + - run `npm run lint:js:fix` + +## 0.0.14 - 2017-03-20 + +### Added + +- Upgrading `eslint-config-skyscanner` to v1.0.0 + +### Fixed + +- Pinning `eslint-plugin-react` to 6.10.0 to fix indent bug + +## 0.0.13 - 2017-03-09 + +### Added + +- The ability to configure "ssrExternals" in package json + +## 0.0.12 - 2017-03-01 + +### Fixed + +- The backpack module regex now works on windows + +## 0.0.11 - 2017-02-27 + +### Changed + +- Removed backpack logo usage from output template + +### Added + +- There is now an `.editorconfig` in the output template + +## 0.0.10 - 2017-01-05 + +### Changed + +- Rebased from `upstream/master` (4d7b7544e74db1aaca22e847b233ed1f3b95b72b) + - Updates `babel-jest` && `jest` packages to 18.0.0 +- Upgraded `eslint` & `eslint-plugin-react` to 3.12.2 & 6.8.0 respectively + +### Added + +- Added ability to configure "externals" in package json + +## 0.0.9 - 2016-12-20 + +### Added + +- Server Side Rendering support (proof of concept): + - `webpack.config.ssr.js`: This is a duplicate of `webpack.config.prod.js` modified to target a server side node environment + - `build.js` now checks if an `ssr.js` file exists at the app root, if so it will compile it in parallel with the optimized browser bundle leaving an + `ssr.js` file in the build directory ready to be required on the server + - See the [readme](https://github.com/Skyscanner/backpack-react-scripts/tree/master/packages/react-scripts/template#server-side-rendering-ssr) for detailed instructions. + +## 0.0.8 + +### Changed + +- Rebased from `upstream/master` (94c912dc60561c931232caf9cf5442082711227c) + - Mostly bug fixes and dependency upgrades, see [create-react-app's changelog](https://github.com/facebookincubator/create-react-app/blob/master/CHANGELOG.md) + (between versions `v0.8.0` -> `v0.8.4`) + +## 0.0.7 + +### Fixed + +- Added base stylesheet scripts to the template so that hover effects work + +## 0.0.6 + +### Changed + +- Removed eslint from webpack to a separate `npm run lint` task +- Swapped out `eslint-config-react-app` in favour of `eslint-config-skyscanner` + +### Added + +- A `backpack-react-scripts` specific readme + +## 0.0.5 + +### Fixed + +- Rebased from `upstream/master` (bcc469c9a5c7916ec10786f133769cdda2c80188) + - Most notable change is Yarn support + +## 0.0.4 + +### Fixed + +- Reverted nested components dir + +## 0.0.3 + +### Added + +- New Backpack template + - Backpack stylesheet and Sass mixin integration + - Backpack button, code, grid, heading & paragraph components integration + - `.eslintrc` for editor integration + - Nested components into `src/components/` dir + +## 0.0.2 + +### Fixed + +- Removed `bundledDependencies` + +## 0.0.1 + +### Changed + +- Customised `react-scripts` package to be `backpack-react-scripts` +- Marked all other packages as private + +### Added + +- Sass stylesheet support +- Babel will now compile imports from the `node_modules` folder that match `/bpk-*` +- Drone build configuration diff --git a/packages/react-scripts/README.md b/packages/react-scripts/README.md index d6de290ff..0236deb06 100644 --- a/packages/react-scripts/README.md +++ b/packages/react-scripts/README.md @@ -1,7 +1,34 @@ -# react-scripts +# backpack-react-scripts -This package includes scripts and configuration used by [Create React App](https://github.com/facebook/create-react-app).<br> -Please refer to its documentation: +### **Important:** The currently supported version of **CRA** by `backpack-react-scripts` is up to `v4.0.3`. Versions above this may not work. -- [Getting Started](https://facebook.github.io/create-react-app/docs/getting-started) – How to create a new app. -- [User Guide](https://facebook.github.io/create-react-app/) – How to develop apps bootstrapped with Create React App. +This package is a fork of [Create React App](https://github.com/facebookincubator/create-react-app) (specifically the +`react-scripts` package). It's intended to be used in conjuction with `create-react-app` like so: + +```sh +npx create-react-app@4.0.3 my-app --scripts-version=@skyscanner/backpack-react-scripts --template @skyscanner/backpack --use-npm + +# start your app development like you normally would with `create-react-app` +cd my-app +npm start +``` + +## What is different in our fork? + +- Compilation of uncompiled Backpack components (specifically JSX). +- Skyscanner specific template with Backpack components integrated out of the box. Published as `@skyscanner/cra-template-backpack` +- CSS Modules enabled by default for all `.css` & `.scss` files. +- Ability to create a bundle for server side rending. +- Automatic chunking is disabled by default. +- **`css.html` & `js.html`**: New files in the `build/` output folder. These are html partials that include `<script />` and `<link />` 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. + - `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. + - `externals`: exposing the Webpack config to modify externals, see [docs](https://webpack.js.org/configuration/externals/). + - `ssrExternals`: Similar to above, but for `ssr.js` only. + - `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. diff --git a/packages/react-scripts/config/css.html b/packages/react-scripts/config/css.html new file mode 100644 index 000000000..6c3a62d81 --- /dev/null +++ b/packages/react-scripts/config/css.html @@ -0,0 +1,5 @@ +<% _.each(htmlWebpackPlugin.files.css, file => { %><link + rel="stylesheet" + href="<%= file %>" +/> +<% }); %> diff --git a/packages/react-scripts/config/js.html b/packages/react-scripts/config/js.html new file mode 100644 index 000000000..af2a17b3e --- /dev/null +++ b/packages/react-scripts/config/js.html @@ -0,0 +1,3 @@ +<% _.each(htmlWebpackPlugin.files.js, file => { %> +<script src="<%= file %>"></script> +<% }); %> diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index 67ba927fc..d19fb7550 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -76,6 +76,7 @@ module.exports = { appNodeModules: resolveApp('node_modules'), swSrc: resolveModule(resolveApp, 'src/service-worker'), publicUrlOrPath, + appSsrJs: resolveApp('src/ssr.js'), }; // @remove-on-eject-begin @@ -99,6 +100,7 @@ module.exports = { appNodeModules: resolveApp('node_modules'), swSrc: resolveModule(resolveApp, 'src/service-worker'), publicUrlOrPath, + appSsrJs: resolveApp('src/ssr.js'), // These properties only exist before ejecting: ownPath: resolveOwn('.'), ownNodeModules: resolveOwn('node_modules'), // This is empty on npm 3 @@ -135,6 +137,7 @@ if ( appNodeModules: resolveOwn('node_modules'), swSrc: resolveModule(resolveOwn, `${templatePath}/src/service-worker`), publicUrlOrPath, + appSsrJs: resolveOwn(`${templatePath}/src/ssr.js`), // These properties only exist before ejecting: ownPath: resolveOwn('.'), ownNodeModules: resolveOwn('node_modules'), diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 26c2a65aa..121b987bb 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -21,12 +21,13 @@ 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'); +const SubresourceIntegrityPlugin = require('webpack-subresource-integrity'); const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent'); -const ESLintPlugin = require('eslint-webpack-plugin'); +// const ESLintPlugin = require('eslint-webpack-plugin'); const paths = require('./paths'); const modules = require('./modules'); const getClientEnvironment = require('./env'); @@ -41,6 +42,18 @@ const postcssNormalize = require('postcss-normalize'); const appPackageJson = require(paths.appPackageJson); +const sassFunctions = require('bpk-mixins/sass-functions'); +const camelCase = require('lodash/camelCase'); +const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; +const customModuleRegexes = bpkReactScriptsConfig.babelIncludePrefixes + ? bpkReactScriptsConfig.babelIncludePrefixes.map( + prefix => new RegExp(`node_modules[\\/]${prefix}`) + ) + : []; +const cssModulesEnabled = bpkReactScriptsConfig.cssModules !== false; +const crossOriginLoading = bpkReactScriptsConfig.crossOriginLoading || false; +const sriEnabled = bpkReactScriptsConfig.sriEnabled || false; + // Source maps are resource heavy and can cause out of memory issue for large source files. const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; @@ -55,8 +68,9 @@ const reactRefreshOverlayEntry = require.resolve( // makes for a smoother build process. const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false'; -const emitErrorsAsWarnings = process.env.ESLINT_NO_DEV_ERRORS === 'true'; -const disableESLintPlugin = process.env.DISABLE_ESLINT_PLUGIN === 'true'; +// Disabling as they are not currently used in the code see L874 +// const emitErrorsAsWarnings = process.env.ESLINT_NO_DEV_ERRORS === 'true'; +// const disableESLintPlugin = process.env.DISABLE_ESLINT_PLUGIN === 'true'; const imageInlineSizeLimit = parseInt( process.env.IMAGE_INLINE_SIZE_LIMIT || '10000' @@ -87,6 +101,10 @@ const hasJsxRuntime = (() => { } })(); +// Backpack / saddlebag node module regexes +const backpackModulesRegex = /node_modules[\\/]bpk-/; +const saddlebagModulesRegex = /node_modules[\\/]saddlebag-/; + // This is the production and development configuration. // It is focused on developer experience, fast rebuilds, and a minimal bundle. module.exports = function (webpackEnv) { @@ -107,7 +125,11 @@ module.exports = function (webpackEnv) { const shouldUseReactRefresh = env.raw.FAST_REFRESH; // common function to get style loaders - const getStyleLoaders = (cssOptions, preProcessor) => { + const getStyleLoaders = ( + cssOptions, + preProcessor, + preProcessorOptions = {} + ) => { const loaders = [ isEnvDevelopment && require.resolve('style-loader'), isEnvProduction && { @@ -160,7 +182,10 @@ module.exports = function (webpackEnv) { { loader: require.resolve(preProcessor), options: { - sourceMap: true, + ...preProcessorOptions, + ...{ + sourceMap: true, + }, }, } ); @@ -205,6 +230,7 @@ module.exports = function (webpackEnv) { ] : paths.appIndexJs, output: { + crossOriginLoading: sriEnabled ? 'anonymous' : crossOriginLoading, // The build folder. path: isEnvProduction ? paths.appBuild : undefined, // Add /* filename */ comments to generated require()s in the output. @@ -234,7 +260,8 @@ module.exports = function (webpackEnv) { (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')), // Prevents conflicts when multiple webpack runtimes (from different apps) // are used on the same page. - jsonpFunction: `webpackJsonp${appPackageJson.name}`, + // jsonpFunction: `webpackJsonp${appPackageJson.name}`, + jsonpFunction: camelCase(appPackageJson.name + 'JsonpCallback'), // this defaults to 'window', but by setting it to 'this' then // module chunks which are built will work in web workers as well. globalObject: 'this', @@ -306,17 +333,36 @@ module.exports = function (webpackEnv) { // Automatically split vendor and commons // https://twitter.com/wSokra/status/969633336732905474 // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 - splitChunks: { - chunks: 'all', - name: isEnvDevelopment, - }, + // splitChunks: { + // chunks: 'all', + // name: false, + // }, + splitChunks: bpkReactScriptsConfig.enableAutomaticChunking + ? { + chunks: 'all', + name: isEnvDevelopment, + cacheGroups: bpkReactScriptsConfig.vendorsChunkRegex + ? { + vendors: { + test: new RegExp(bpkReactScriptsConfig.vendorsChunkRegex), + }, + } + : {}, + } + : {}, // Keep the runtime chunk separated to enable long term caching // https://twitter.com/wSokra/status/969679223278505985 // https://github.com/facebook/create-react-app/issues/5358 - runtimeChunk: { - name: entrypoint => `runtime-${entrypoint.name}`, - }, + // runtimeChunk: { + // name: entrypoint => `runtime-${entrypoint.name}`, + // }, + runtimeChunk: bpkReactScriptsConfig.enableAutomaticChunking + ? { + name: entrypoint => `runtime-${entrypoint.name}`, + } + : false, }, + externals: isEnvProduction ? bpkReactScriptsConfig.externals || {} : {}, resolve: { // This allows you to set a fallback for where webpack should look for modules. // We placed these paths second because we want `node_modules` to "win" @@ -388,6 +434,16 @@ module.exports = function (webpackEnv) { name: 'static/media/[name].[hash:8].[ext]', }, }, + { + test: new RegExp( + `(^|/)(${(bpkReactScriptsConfig.amdExcludes || []) + .concat('lodash') + .join('|')})(/|.|$)` + ), + parser: { + amd: false, + }, + }, // "url" loader works like "file" loader except that it embeds assets // smaller than specified limit in bytes as data URLs to avoid requests. // A missing `test` is equivalent to a match. @@ -403,7 +459,12 @@ module.exports = function (webpackEnv) { // The preset includes JSX, Flow, TypeScript, and some ESnext features. { test: /\.(js|mjs|jsx|ts|tsx)$/, - include: paths.appSrc, + include: [ + paths.appSrc, + backpackModulesRegex, + saddlebagModulesRegex, + ...customModuleRegexes, + ], loader: require.resolve('babel-loader'), options: { customize: require.resolve( @@ -509,7 +570,10 @@ module.exports = function (webpackEnv) { // of CSS. // By default we support CSS Modules with the extension .module.css { - test: cssRegex, + test: { + and: [cssRegex, () => !cssModulesEnabled], + exclude: [backpackModulesRegex], + }, exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, @@ -526,7 +590,15 @@ module.exports = function (webpackEnv) { // Adds support for CSS Modules (https://github.com/css-modules/css-modules) // using the extension .module.css { - test: cssModuleRegex, + test: [ + cssModuleRegex, + { + and: [cssRegex, () => cssModulesEnabled], + }, + { + and: [cssRegex, backpackModulesRegex], + }, + ], use: getStyleLoaders({ importLoaders: 1, sourceMap: isEnvProduction @@ -541,7 +613,10 @@ module.exports = function (webpackEnv) { // By default we support SASS Modules with the // extensions .module.scss or .module.sass { - test: sassRegex, + test: { + and: [sassRegex, () => !cssModulesEnabled], + exclude: [backpackModulesRegex], + }, exclude: sassModuleRegex, use: getStyleLoaders( { @@ -550,7 +625,10 @@ module.exports = function (webpackEnv) { ? shouldUseSourceMap : isEnvDevelopment, }, - 'sass-loader' + 'sass-loader', + { + functions: sassFunctions, + } ), // Don't consider CSS imports dead code even if the // containing package claims to have no side effects. @@ -561,7 +639,15 @@ module.exports = function (webpackEnv) { // Adds support for CSS Modules, but using SASS // using the extension .module.scss or .module.sass { - test: sassModuleRegex, + test: [ + sassModuleRegex, + { + and: [sassRegex, () => cssModulesEnabled], + }, + { + and: [sassRegex, backpackModulesRegex], + }, + ], use: getStyleLoaders( { importLoaders: 3, @@ -572,7 +658,10 @@ module.exports = function (webpackEnv) { getLocalIdent: getCSSModuleLocalIdent, }, }, - 'sass-loader' + 'sass-loader', + { + functions: sassFunctions, + } ), }, // "file" loader makes sure those assets get served by WebpackDevServer. @@ -624,6 +713,26 @@ module.exports = function (webpackEnv) { : undefined ) ), + new HtmlWebpackPlugin( + Object.assign( + {}, + { + inject: false, + filename: 'css.html', + template: path.resolve(__dirname, './css.html'), + } + ) + ), + new HtmlWebpackPlugin( + Object.assign( + {}, + { + inject: false, + filename: 'js.html', + template: path.resolve(__dirname, './js.html'), + } + ) + ), // Inlines the webpack runtime script. This script is too small to warrant // a network request. // https://github.com/facebook/create-react-app/issues/5358 @@ -703,6 +812,15 @@ module.exports = function (webpackEnv) { }; }, }), + // Calculate and inject Subresource Integrity (SRI) hashes + // https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity + // This is a security feature that enables browsers to verify that resources + // they fetch (for example, from a CDN) are delivered without unexpected manipulation. + sriEnabled && + new SubresourceIntegrityPlugin({ + enabled: true, + hashFuncNames: ['sha384'], + }), // Moment.js is an extremely popular library that bundles large locale files // by default due to how webpack interprets its code. This is a practical // solution that requires the user to opt into importing specific locales. @@ -753,31 +871,33 @@ module.exports = function (webpackEnv) { // The formatter is invoked directly in WebpackDevServerUtils during development formatter: isEnvProduction ? typescriptFormatter : undefined, }), - !disableESLintPlugin && - new ESLintPlugin({ - // Plugin options - extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'], - formatter: require.resolve('react-dev-utils/eslintFormatter'), - eslintPath: require.resolve('eslint'), - failOnError: !(isEnvDevelopment && emitErrorsAsWarnings), - context: paths.appSrc, - cache: true, - cacheLocation: path.resolve( - paths.appNodeModules, - '.cache/.eslintcache' - ), - // ESLint class options - cwd: paths.appPath, - resolvePluginsRelativeTo: __dirname, - baseConfig: { - extends: [require.resolve('eslint-config-react-app/base')], - rules: { - ...(!hasJsxRuntime && { - 'react/react-in-jsx-scope': 'error', - }), - }, - }, - }), + // For now we keep this disabled but in a future update we should review if just setting disableESLintPlugin works + // but needs research into the dependencies being installed if they clash with the Skyscanner config + // !disableESLintPlugin && + // new ESLintPlugin({ + // // Plugin options + // extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'], + // formatter: require.resolve('react-dev-utils/eslintFormatter'), + // eslintPath: require.resolve('eslint'), + // failOnError: !(isEnvDevelopment && emitErrorsAsWarnings), + // context: paths.appSrc, + // cache: true, + // cacheLocation: path.resolve( + // paths.appNodeModules, + // '.cache/.eslintcache' + // ), + // // ESLint class options + // cwd: paths.appPath, + // resolvePluginsRelativeTo: __dirname, + // baseConfig: { + // extends: [require.resolve('eslint-config-react-app/base')], + // rules: { + // ...(!hasJsxRuntime && { + // 'react/react-in-jsx-scope': 'error', + // }), + // }, + // }, + // }), ].filter(Boolean), // Some libraries import Node modules but don't use them in the browser. // Tell webpack to provide empty mocks for them so importing them works. diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js new file mode 100644 index 000000000..331f2ca9f --- /dev/null +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -0,0 +1,908 @@ +// @remove-on-eject-begin +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +// @remove-on-eject-end +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const webpack = require('webpack'); +const resolve = require('resolve'); +const PnpWebpackPlugin = require('pnp-webpack-plugin'); +// const HtmlWebpackPlugin = require('html-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 OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); +// const safePostCssParser = require('postcss-safe-parser'); +// const ManifestPlugin = require('webpack-manifest-plugin'); +// const SubresourceIntegrityPlugin = require('webpack-subresource-integrity'); +// const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); +// const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); +const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); +const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); +const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent'); +// const ESLintPlugin = require('eslint-webpack-plugin'); +const paths = require('./paths'); +const modules = require('./modules'); +const getClientEnvironment = require('./env'); +const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin'); +const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin'); +const typescriptFormatter = require('react-dev-utils/typescriptFormatter'); +const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); +// @remove-on-eject-begin +const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier'); +// @remove-on-eject-end +const postcssNormalize = require('postcss-normalize'); + +const appPackageJson = require(paths.appPackageJson); + +const sassFunctions = require('bpk-mixins/sass-functions'); +// const camelCase = require('lodash/camelCase'); +const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; +const customModuleRegexes = bpkReactScriptsConfig.babelIncludePrefixes + ? bpkReactScriptsConfig.babelIncludePrefixes.map( + prefix => new RegExp(`node_modules[\\/]${prefix}`) + ) + : []; +const cssModulesEnabled = bpkReactScriptsConfig.cssModules !== false; +// const crossOriginLoading = bpkReactScriptsConfig.crossOriginLoading || false; +// const sriEnabled = bpkReactScriptsConfig.sriEnabled || false; + +// Source maps are resource heavy and can cause out of memory issue for large source files. +const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; + +const webpackDevClientEntry = require.resolve( + 'react-dev-utils/webpackHotDevClient' +); +const reactRefreshOverlayEntry = require.resolve( + 'react-dev-utils/refreshOverlayInterop' +); + +// 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'; + +const imageInlineSizeLimit = parseInt( + process.env.IMAGE_INLINE_SIZE_LIMIT || '10000' +); + +// Check if TypeScript is setup +const useTypeScript = fs.existsSync(paths.appTsConfig); + +// Get the path to the uncompiled service worker (if it exists). +// const swSrc = paths.swSrc; + +// style files regexes +const cssRegex = /\.css$/; +const cssModuleRegex = /\.module\.css$/; +const sassRegex = /\.(scss|sass)$/; +const sassModuleRegex = /\.module\.(scss|sass)$/; + +const hasJsxRuntime = (() => { + if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') { + return false; + } + + try { + require.resolve('react/jsx-runtime'); + return true; + } catch (e) { + return false; + } +})(); + +// Backpack / saddlebag node module regexes +const backpackModulesRegex = /node_modules[\\/]bpk-/; +const saddlebagModulesRegex = /node_modules[\\/]saddlebag-/; + +// This is the production and development configuration. +// It is focused on developer experience, fast rebuilds, and a minimal bundle. +module.exports = function (webpackEnv) { + const isEnvDevelopment = webpackEnv === 'development'; + const isEnvProduction = webpackEnv === 'production'; + + // Variable used for enabling profiling in Production + // passed into alias object. Uses a flag if passed into the build command + const isEnvProductionProfile = + isEnvProduction && process.argv.includes('--profile'); + + // We will provide `paths.publicUrlOrPath` to our app + // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. + // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz. + // Get environment variables to inject into our app. + const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1)); + + const shouldUseReactRefresh = env.raw.FAST_REFRESH; + + // common function to get style loaders + const getStyleLoaders = ( + cssOptions, + preProcessor, + preProcessorOptions = {} + ) => { + const loaders = [ + isEnvDevelopment && require.resolve('style-loader'), + isEnvProduction && { + loader: MiniCssExtractPlugin.loader, + // css is located in `static/css`, use '../../' to locate index.html folder + // in production `paths.publicUrlOrPath` can be a relative path + options: paths.publicUrlOrPath.startsWith('.') + ? { publicPath: '../../' } + : {}, + }, + { + loader: require.resolve('css-loader'), + options: cssOptions, + }, + { + // Options for PostCSS as we reference these options twice + // Adds vendor prefixing based on your specified browser support in + // package.json + loader: require.resolve('postcss-loader'), + options: { + // Necessary for external CSS imports to work + // https://github.com/facebook/create-react-app/issues/2677 + ident: 'postcss', + plugins: () => [ + require('postcss-flexbugs-fixes'), + require('postcss-preset-env')({ + autoprefixer: { + flexbox: 'no-2009', + }, + stage: 3, + }), + // Adds PostCSS Normalize as the reset css with default options, + // so that it honors browserslist config in package.json + // which in turn let's users customize the target behavior as per their needs. + postcssNormalize(), + ], + sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, + }, + }, + ].filter(Boolean); + if (preProcessor) { + loaders.push( + { + loader: require.resolve('resolve-url-loader'), + options: { + sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, + root: paths.appSrc, + }, + }, + { + loader: require.resolve(preProcessor), + options: { + ...preProcessorOptions, + ...{ + sourceMap: true, + }, + }, + } + ); + } + return loaders; + }; + + return { + target: 'node', + mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development', + // Stop compilation early in production + bail: isEnvProduction, + devtool: isEnvProduction + ? shouldUseSourceMap + ? 'source-map' + : false + : isEnvDevelopment && 'cheap-module-source-map', + // These are the "entry points" to our application. + // This means they will be the "root" imports that are included in JS bundle. + entry: + isEnvDevelopment && !shouldUseReactRefresh + ? [ + // Include an alternative client for WebpackDevServer. A client's job is to + // connect to WebpackDevServer by a socket and get notified about changes. + // When you save a file, the client will either apply hot updates (in case + // of CSS changes), or refresh the page (in case of JS changes). When you + // make a syntax error, this client will display a syntax error overlay. + // Note: instead of the default WebpackDevServer client, we use a custom one + // to bring better experience for Create React App users. You can replace + // 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'), + // + // When using the experimental react-refresh integration, + // the webpack plugin takes care of injecting the dev client for us. + webpackDevClientEntry, + // Finally, this is your app's code: + // paths.appIndexJs, + paths.appSsrJs, + // We include the app code last so that if there is a runtime error during + // initialization, it doesn't blow up the WebpackDevServer client, and + // changing JS code would still trigger a refresh. + ] + : paths.appSsrJs, + output: { + // crossOriginLoading: sriEnabled ? 'anonymous' : crossOriginLoading, + // The build folder. + path: isEnvProduction ? paths.appBuild : undefined, + // 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].[contenthash:8].js' + // : isEnvDevelopment && 'static/js/bundle.js', + // TODO: remove this when upgrading to webpack 5 + futureEmitAssets: true, + filename: 'ssr.js', + libraryTarget: 'commonjs2', + // There are also additional JS chunk files if you use code splitting. + chunkFilename: isEnvProduction + ? 'static/js/[name].[contenthash:8].chunk.js' + : isEnvDevelopment && 'static/js/[name].chunk.js', + // webpack uses `publicPath` to determine where the app is being served from. + // It requires a trailing slash, or the file assets will get an incorrect path. + // We inferred the "public path" (such as / or /my-project) from homepage. + publicPath: paths.publicUrlOrPath, + // Point sourcemap entries to original disk location (format as URL on Windows) + devtoolModuleFilenameTemplate: isEnvProduction + ? info => + path + .relative(paths.appSrc, info.absoluteResourcePath) + .replace(/\\/g, '/') + : isEnvDevelopment && + (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')), + // Prevents conflicts when multiple webpack runtimes (from different apps) + // are used on the same page. + // jsonpFunction: `webpackJsonp${appPackageJson.name}`, + // jsonpFunction: camelCase(appPackageJson.name + 'JsonpCallback'), + // this defaults to 'window', but by setting it to 'this' then + // module chunks which are built will work in web workers as well. + // globalObject: 'this', + }, + optimization: { + // minimize: isEnvProduction, + minimize: false, + // minimizer: [ + // // This is only used in production mode + // new TerserPlugin({ + // terserOptions: { + // parse: { + // // We want terser to parse ecma 8 code. However, we don't want it + // // to apply any minification steps that turns valid ecma 5 code + // // into invalid ecma 5 code. This is why the 'compress' and 'output' + // // sections only apply transformations that are ecma 5 safe + // // https://github.com/facebook/create-react-app/pull/4234 + // ecma: 8, + // }, + // compress: { + // ecma: 5, + // warnings: false, + // // Disabled because of an issue with Uglify breaking seemingly valid code: + // // https://github.com/facebook/create-react-app/issues/2376 + // // Pending further investigation: + // // https://github.com/mishoo/UglifyJS2/issues/2011 + // comparisons: false, + // // Disabled because of an issue with Terser breaking valid code: + // // https://github.com/facebook/create-react-app/issues/5250 + // // Pending further investigation: + // // https://github.com/terser-js/terser/issues/120 + // inline: 2, + // }, + // mangle: { + // safari10: true, + // }, + // // Added for profiling in devtools + // keep_classnames: isEnvProductionProfile, + // keep_fnames: isEnvProductionProfile, + // output: { + // ecma: 5, + // comments: false, + // // Turned on because emoji and regex is not minified properly using default + // // https://github.com/facebook/create-react-app/issues/2488 + // ascii_only: true, + // }, + // }, + // sourceMap: shouldUseSourceMap, + // }), + // // This is only used in production mode + // new OptimizeCSSAssetsPlugin({ + // cssProcessorOptions: { + // parser: safePostCssParser, + // map: shouldUseSourceMap + // ? { + // // `inline: false` forces the sourcemap to be output into a + // // separate file + // inline: false, + // // `annotation: true` appends the sourceMappingURL to the end of + // // the css file, helping the browser find the sourcemap + // annotation: true, + // } + // : false, + // }, + // cssProcessorPluginOptions: { + // preset: ['default', { minifyFontValues: { removeQuotes: false } }], + // }, + // }), + // ], + // Automatically split vendor and commons + // https://twitter.com/wSokra/status/969633336732905474 + // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 + // splitChunks: { + // chunks: 'all', + // name: false, + // }, + // splitChunks: bpkReactScriptsConfig.enableAutomaticChunking + // ? { + // chunks: 'all', + // name: false, + // cacheGroups: bpkReactScriptsConfig.vendorsChunkRegex + // ? { + // vendors: { + // test: new RegExp(bpkReactScriptsConfig.vendorsChunkRegex), + // }, + // } + // : {}, + // } + // : {}, + // Keep the runtime chunk separated to enable long term caching + // https://twitter.com/wSokra/status/969679223278505985 + // https://github.com/facebook/create-react-app/issues/5358 + // runtimeChunk: { + // name: entrypoint => `runtime-${entrypoint.name}`, + // }, + // runtimeChunk: bpkReactScriptsConfig.enableAutomaticChunking + // ? { + // name: entrypoint => `runtime-${entrypoint.name}`, + // } + // : false, + runtimeChunk: false, + }, + externals: bpkReactScriptsConfig.ssrExternals || [], + resolve: { + // This allows you to set a fallback for where webpack should look for modules. + // We placed these paths second because we want `node_modules` to "win" + // if there are any conflicts. This matches Node resolution mechanism. + // https://github.com/facebook/create-react-app/issues/253 + modules: ['node_modules', paths.appNodeModules].concat( + modules.additionalModulePaths || [] + ), + // These are the reasonable defaults supported by the Node ecosystem. + // We also include JSX as a common component filename extension to support + // some tools, although we do not recommend using it, see: + // https://github.com/facebook/create-react-app/issues/290 + // `web` extension prefixes have been added for better support + // for React Native Web. + extensions: paths.moduleFileExtensions + .map(ext => `.${ext}`) + .filter(ext => useTypeScript || !ext.includes('ts')), + alias: { + // Support React Native Web + // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ + 'react-native': 'react-native-web', + // Allows for better profiling with ReactDevTools + ...(isEnvProductionProfile && { + 'react-dom$': 'react-dom/profiling', + 'scheduler/tracing': 'scheduler/tracing-profiling', + }), + ...(modules.webpackAliases || {}), + }, + plugins: [ + // Adds support for installing with Plug'n'Play, leading to faster installs and adding + // guards against forgotten dependencies and such. + PnpWebpackPlugin, + // Prevents users from importing files from outside of src/ (or node_modules/). + // This often causes confusion because we only process files within src/ with babel. + // To fix this, we prevent you from importing files out of src/ -- if you'd like to, + // please link the files into your node_modules/ and let module-resolution kick in. + // Make sure your source files are compiled, as they will not be processed in any way. + new ModuleScopePlugin(paths.appSrc, [ + paths.appPackageJson, + reactRefreshOverlayEntry, + ]), + ], + }, + resolveLoader: { + plugins: [ + // Also related to Plug'n'Play, but this time it tells webpack to load its loaders + // from the current package. + PnpWebpackPlugin.moduleLoader(module), + ], + }, + module: { + strictExportPresence: true, + rules: [ + // Disable require.ensure as it's not a standard language feature. + { parser: { requireEnsure: false } }, + { + // "oneOf" will traverse all following loaders until one will + // match the requirements. When no loader matches it will fall + // back to the "file" loader at the end of the loader list. + oneOf: [ + // TODO: Merge this config once `image/avif` is in the mime-db + // https://github.com/jshttp/mime-db + { + test: [/\.avif$/], + loader: require.resolve('url-loader'), + options: { + limit: imageInlineSizeLimit, + mimetype: 'image/avif', + name: 'static/media/[name].[hash:8].[ext]', + }, + }, + { + test: new RegExp( + `(^|/)(${(bpkReactScriptsConfig.amdExcludes || []) + .concat('lodash') + .join('|')})(/|.|$)` + ), + parser: { + amd: false, + }, + }, + // "url" loader works like "file" loader except that it embeds assets + // smaller than specified limit in bytes as data URLs to avoid requests. + // A missing `test` is equivalent to a match. + { + test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], + loader: require.resolve('url-loader'), + options: { + limit: imageInlineSizeLimit, + name: 'static/media/[name].[hash:8].[ext]', + }, + }, + // Process application JS with Babel. + // The preset includes JSX, Flow, TypeScript, and some ESnext features. + { + test: /\.(js|mjs|jsx|ts|tsx)$/, + include: [ + paths.appSrc, + backpackModulesRegex, + saddlebagModulesRegex, + ...customModuleRegexes, + ], + loader: require.resolve('babel-loader'), + options: { + customize: require.resolve( + 'babel-preset-react-app/webpack-overrides' + ), + // @remove-on-eject-begin + babelrc: false, + configFile: false, + presets: [ + [ + require.resolve('babel-preset-react-app'), + { + runtime: hasJsxRuntime ? 'automatic' : 'classic', + }, + ], + ], + // Make sure we have a unique cache identifier, erring on the + // side of caution. + // We remove this when the user ejects because the default + // is sane and uses Babel options. Instead of options, we use + // the react-scripts and babel-preset-react-app versions. + cacheIdentifier: getCacheIdentifier( + isEnvProduction + ? 'production' + : isEnvDevelopment && 'development', + [ + 'babel-plugin-named-asset-import', + 'babel-preset-react-app', + 'react-dev-utils', + 'react-scripts', + ] + ), + // @remove-on-eject-end + plugins: [ + [ + require.resolve('babel-plugin-named-asset-import'), + { + loaderMap: { + svg: { + ReactComponent: + '@svgr/webpack?-svgo,+titleProp,+ref![path]', + }, + }, + }, + ], + isEnvDevelopment && + shouldUseReactRefresh && + require.resolve('react-refresh/babel'), + ].filter(Boolean), + // This is a feature of `babel-loader` for webpack (not Babel itself). + // It enables caching results in ./node_modules/.cache/babel-loader/ + // directory for faster rebuilds. + cacheDirectory: true, + // See #6846 for context on why cacheCompression is disabled + cacheCompression: false, + compact: isEnvProduction, + }, + }, + // Process any JS outside of the app with Babel. + // Unlike the application JS, we only compile the standard ES features. + { + test: /\.(js|mjs)$/, + exclude: /@babel(?:\/|\\{1,2})runtime/, + loader: require.resolve('babel-loader'), + options: { + babelrc: false, + configFile: false, + compact: false, + presets: [ + [ + require.resolve('babel-preset-react-app/dependencies'), + { helpers: true }, + ], + ], + cacheDirectory: true, + // See #6846 for context on why cacheCompression is disabled + cacheCompression: false, + // @remove-on-eject-begin + cacheIdentifier: getCacheIdentifier( + isEnvProduction + ? 'production' + : isEnvDevelopment && 'development', + [ + 'babel-plugin-named-asset-import', + 'babel-preset-react-app', + 'react-dev-utils', + 'react-scripts', + ] + ), + // @remove-on-eject-end + // Babel sourcemaps are needed for debugging into node_modules + // code. Without the options below, debuggers like VSCode + // show incorrect code and set breakpoints on the wrong lines. + sourceMaps: shouldUseSourceMap, + inputSourceMap: shouldUseSourceMap, + }, + }, + // "postcss" loader applies autoprefixer to our CSS. + // "css" loader resolves paths in CSS and adds assets as dependencies. + // "style" loader turns CSS into JS modules that inject <style> tags. + // In production, we use MiniCSSExtractPlugin to extract that CSS + // to a file, but in development "style" loader enables hot editing + // of CSS. + // By default we support CSS Modules with the extension .module.css + { + test: { + and: [cssRegex, () => !cssModulesEnabled], + exclude: [backpackModulesRegex], + }, + exclude: cssModuleRegex, + use: getStyleLoaders({ + importLoaders: 1, + sourceMap: isEnvProduction + ? shouldUseSourceMap + : isEnvDevelopment, + }), + // Don't consider CSS imports dead code even if the + // containing package claims to have no side effects. + // Remove this when webpack adds a warning or an error for this. + // See https://github.com/webpack/webpack/issues/6571 + sideEffects: true, + }, + // Adds support for CSS Modules (https://github.com/css-modules/css-modules) + // using the extension .module.css + { + test: [ + cssModuleRegex, + { + and: [cssRegex, () => cssModulesEnabled], + }, + { + and: [cssRegex, backpackModulesRegex], + }, + ], + use: getStyleLoaders({ + importLoaders: 1, + sourceMap: isEnvProduction + ? shouldUseSourceMap + : isEnvDevelopment, + modules: { + getLocalIdent: getCSSModuleLocalIdent, + }, + }), + }, + // Opt-in support for SASS (using .scss or .sass extensions). + // By default we support SASS Modules with the + // extensions .module.scss or .module.sass + { + test: { + and: [sassRegex, () => !cssModulesEnabled], + exclude: [backpackModulesRegex], + }, + exclude: sassModuleRegex, + use: getStyleLoaders( + { + importLoaders: 3, + sourceMap: isEnvProduction + ? shouldUseSourceMap + : isEnvDevelopment, + }, + 'sass-loader', + { + functions: sassFunctions, + } + ), + // Don't consider CSS imports dead code even if the + // containing package claims to have no side effects. + // Remove this when webpack adds a warning or an error for this. + // See https://github.com/webpack/webpack/issues/6571 + sideEffects: true, + }, + // Adds support for CSS Modules, but using SASS + // using the extension .module.scss or .module.sass + { + test: [ + sassModuleRegex, + { + and: [sassRegex, () => cssModulesEnabled], + }, + { + and: [sassRegex, backpackModulesRegex], + }, + ], + use: getStyleLoaders( + { + importLoaders: 3, + sourceMap: isEnvProduction + ? shouldUseSourceMap + : isEnvDevelopment, + modules: { + getLocalIdent: getCSSModuleLocalIdent, + }, + }, + 'sass-loader', + { + functions: sassFunctions, + } + ), + }, + // "file" loader makes sure those assets get served by WebpackDevServer. + // When you `import` an asset, you get its (virtual) filename. + // In production, they would get copied to the `build` folder. + // This loader doesn't use a "test" so it will catch all modules + // that fall through the other loaders. + { + loader: require.resolve('file-loader'), + // Exclude `js` files to keep "css" loader working as it injects + // its runtime that would otherwise be processed through "file" loader. + // Also exclude `html` and `json` extensions so they get processed + // by webpacks internal loaders. + exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/], + options: { + name: 'static/media/[name].[hash:8].[ext]', + }, + }, + // ** STOP ** Are you adding a new loader? + // Make sure to add the new loader(s) before the "file" loader. + ], + }, + ], + }, + plugins: [ + // Generates an `index.html` file with the <script> injected. + // new HtmlWebpackPlugin( + // Object.assign( + // {}, + // { + // inject: true, + // template: paths.appHtml, + // }, + // isEnvProduction + // ? { + // minify: { + // removeComments: true, + // collapseWhitespace: true, + // removeRedundantAttributes: true, + // useShortDoctype: true, + // removeEmptyAttributes: true, + // removeStyleLinkTypeAttributes: true, + // keepClosingSlash: true, + // minifyJS: true, + // minifyCSS: true, + // minifyURLs: true, + // }, + // } + // : undefined + // ) + // ), + // new HtmlWebpackPlugin( + // Object.assign( + // {}, + // { + // inject: false, + // filename: 'css.html', + // template: path.resolve(__dirname, './css.html'), + // } + // ) + // ), + // new HtmlWebpackPlugin( + // Object.assign( + // {}, + // { + // inject: false, + // filename: 'js.html', + // template: path.resolve(__dirname, './js.html'), + // } + // ) + // ), + // Inlines the webpack runtime script. This script is too small to warrant + // a network request. + // https://github.com/facebook/create-react-app/issues/5358 + // isEnvProduction && + // shouldInlineRuntimeChunk && + // new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]), + // Makes some environment variables available in index.html. + // The public URL is available as %PUBLIC_URL% in index.html, e.g.: + // <link rel="icon" href="%PUBLIC_URL%/favicon.ico"> + // It will be an empty string unless you specify "homepage" + // in `package.json`, in which case it will be the pathname of that URL. + // new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw), + // This gives some necessary context to module not found errors, such as + // the requesting resource. + new ModuleNotFoundPlugin(paths.appPath), + // 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 is set to production + // during a production build. + // Otherwise React will be compiled in the very slow development mode. + new webpack.DefinePlugin(env.stringified), + // This is necessary to emit hot updates (CSS and Fast Refresh): + isEnvDevelopment && new webpack.HotModuleReplacementPlugin(), + // Experimental hot reloading for React . + // https://github.com/facebook/react/tree/master/packages/react-refresh + isEnvDevelopment && + shouldUseReactRefresh && + new ReactRefreshWebpackPlugin({ + overlay: { + entry: webpackDevClientEntry, + // The expected exports are slightly different from what the overlay exports, + // so an interop is included here to enable feedback on module-level errors. + module: reactRefreshOverlayEntry, + // Since we ship a custom dev client and overlay integration, + // the bundled socket handling logic can be eliminated. + sockIntegration: false, + }, + }), + // 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 + isEnvDevelopment && new CaseSensitivePathsPlugin(), + // If you require a missing module and then `npm install` it, you still have + // to restart the development server for webpack to discover it. This plugin + // makes the discovery automatic so you don't have to restart. + // 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', + }), + // Generate an asset manifest file with the following content: + // - "files" key: Mapping of all asset filenames to their corresponding + // output file so that tools can pick it up without having to parse + // `index.html` + // - "entrypoints" key: Array of files which are included in `index.html`, + // can be used to reconstruct the HTML if necessary + // new ManifestPlugin({ + // fileName: 'asset-manifest.json', + // publicPath: paths.publicUrlOrPath, + // generate: (seed, files, entrypoints) => { + // const manifestFiles = files.reduce((manifest, file) => { + // manifest[file.name] = file.path; + // return manifest; + // }, seed); + // const entrypointFiles = entrypoints.main.filter( + // fileName => !fileName.endsWith('.map') + // ); + + // return { + // files: manifestFiles, + // entrypoints: entrypointFiles, + // }; + // }, + // }), + // Calculate and inject Subresource Integrity (SRI) hashes + // https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity + // This is a security feature that enables browsers to verify that resources + // they fetch (for example, from a CDN) are delivered without unexpected manipulation. + // sriEnabled && + // new SubresourceIntegrityPlugin({ + // enabled: true, + // hashFuncNames: ['sha384'], + // }), + // Moment.js is an extremely popular library that bundles large locale files + // by default due to how webpack interprets its code. This is a practical + // solution that requires the user to opt into importing specific locales. + // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack + // You can remove this if you don't use Moment.js: + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + // Generate a service worker script that will precache, and keep up to date, + // the HTML & assets that are part of the webpack build. + // isEnvProduction && + // fs.existsSync(swSrc) && + // new WorkboxWebpackPlugin.InjectManifest({ + // swSrc, + // dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./, + // exclude: [/\.map$/, /asset-manifest\.json$/, /LICENSE/], + // }), + // TypeScript type checking + useTypeScript && + new ForkTsCheckerWebpackPlugin({ + typescript: resolve.sync('typescript', { + basedir: paths.appNodeModules, + }), + async: isEnvDevelopment, + checkSyntacticErrors: true, + resolveModuleNameModule: process.versions.pnp + ? `${__dirname}/pnpTs.js` + : undefined, + resolveTypeReferenceDirectiveModule: process.versions.pnp + ? `${__dirname}/pnpTs.js` + : undefined, + tsconfig: paths.appTsConfig, + reportFiles: [ + // This one is specifically to match during CI tests, + // as micromatch doesn't match + // '../cra-template-typescript/template/src/App.tsx' + // otherwise. + '../**/src/**/*.{ts,tsx}', + '**/src/**/*.{ts,tsx}', + '!**/src/**/__tests__/**', + '!**/src/**/?(*.)(spec|test).*', + '!**/src/setupProxy.*', + '!**/src/setupTests.*', + ], + silent: true, + // The formatter is invoked directly in WebpackDevServerUtils during development + formatter: isEnvProduction ? typescriptFormatter : undefined, + }), + // new ESLintPlugin({ + // // Plugin options + // extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'], + // formatter: require.resolve('react-dev-utils/eslintFormatter'), + // eslintPath: require.resolve('eslint'), + // context: paths.appSrc, + // // ESLint class options + // cwd: paths.appPath, + // resolvePluginsRelativeTo: __dirname, + // baseConfig: { + // extends: [require.resolve('eslint-config-react-app/base')], + // rules: { + // ...(!hasJsxRuntime && { + // 'react/react-in-jsx-scope': 'error', + // }), + // }, + // }, + // }), + ].filter(Boolean), + // Some libraries import Node modules but don't use them in the browser. + // Tell webpack to provide empty mocks for them so importing them works. + // node: { + // module: 'empty', + // dgram: 'empty', + // dns: 'mock', + // fs: 'empty', + // http2: 'empty', + // net: 'empty', + // tls: 'empty', + // child_process: 'empty', + // }, + // Turn off performance processing because we utilize + // our own hints via the FileSizeReporter + performance: false, + }; +}; diff --git a/packages/react-scripts/docs/migrating-from-v6-to-v7.md b/packages/react-scripts/docs/migrating-from-v6-to-v7.md new file mode 100644 index 000000000..9624bc9b6 --- /dev/null +++ b/packages/react-scripts/docs/migrating-from-v6-to-v7.md @@ -0,0 +1,181 @@ +# Migrating from v6 to v7 + +Inside any created `backpack-react-scripts` project that has not been ejected, run: + +``` +npm install --save backpack-react-scripts@^7 +``` + +## Breaking Changes + +Like any major release, `backpack-react-scripts@7` contains a few breaking changes. At least one of them will affect every user, so please scan over these sections to see what is relevant to you. + +### ESLint and Stylelint are no longer included by default, you have to manage them yourself + +We have decoupled ESLint and Stylelint from this release. This is because the rate at which our configs (`eslint-config-skyscanner` and `stylelint-config-skyscanner`) change is much faster than the underlying functionality of `create-react-app`, causing unecessary churn. + +That means that your `npm run lint:js` and `npm run lint:scss` scripts will no longer work if on `eslint-config-skyscanner@^4` or `stylelint-config-skyscanner@^1`. + +If on these older versions of our Skyscanner linting configurations and you do not wish to upgrade in this change you will need to install their peer dependencies. It is however recommended to upgrade to the latest of each, where not only will this not be a problem but you will benefit from the latest linting features and improvements. + +If you do not wish to upgrade then you can install the required peer dependencies using: + +ESLint + +**Note:** `eslint-config-skyscanner-with-prettier` does not require peer dependencies, but has been deprecated in favour of `eslint-config-skyscanner` coming with Prettier inbuild by default from [`v5`](https://github.com/Skyscanner/eslint-config-skyscanner/blob/master/CHANGELOG.md). + +``` +npx install-peerdeps --dev eslint-config-skyscanner@^4 +``` + +Stylelint + +``` +npx install-peerdeps --dev stylelint-config-skyscanner@^1 +``` + +### Polyfills for IE 9, IE 10, and IE 11 are no longer included by default (but you can opt in!) + +We have dropped default support for Internet Explorer 9, 10, and 11. If you still need to support these browsers, follow the instructions below. + +First, install `react-app-polyfill`: + +``` +npm install react-app-polyfill +``` + +Next, place one of the following lines at the very top of `src/index.js`: + +``` +import 'react-app-polyfill/ie9'; // For IE 9-11 support +import 'react-app-polyfill/ie11'; // For IE 11 support +``` + +You can read more about [these polyfills here](https://github.com/facebook/create-react-app/tree/master/packages/react-app-polyfill). + +### Dynamic `import()` of a CommonJS module now has a `.default` property + +[Webpack 4 changed the behavior of import()](https://medium.com/webpack/webpack-4-import-and-commonjs-d619d626b655) to be closer in line with the specification. + +Previously, importing a CommonJS module did not require you specify the default export. In most cases, this is now required. +If you see errors in your application about `... is not a function`, you likely need to update your dynamic import, e.g.: + +``` +const throttle = await import('lodash/throttle'); +// replace with +const throttle = await import('lodash/throttle').then(m => m.default); +``` + +### `require.ensure()` is superseded by dynamic `import()` + +We previously allowed code splitting with a webpack-specific directive, `require.ensure()`. It is now disabled in favor of `import()`. To switch to `import()`, follow the examples below: + +Single Module + +``` +require.ensure(['module-a'], function() { + var a = require('module-a'); + // ... +}); + +// Replace with: +import('module-a').then(a => { + // ... +}); +``` + +Multiple Module + +``` +require.ensure(['module-a', 'module-b'], function() { + var a = require('module-a'); + var b = require('module-b'); + // ... +}); + +// Replace with: +Promise.all([import('module-a'), import('module-b')]).then(([a, b]) => { + // ... +}); +``` + +### The default Jest environment was changed to `jsdom` + +Look at the `test` entry in the `scripts` section of your package.json. +Here's a table how to change it from "before" and "after", depending on what you have there: + +| 6.x (if you have this...) | 7.x (...change it to this!) | +| -------------------------------- | ------------------------------- | +| `react-scripts test --env=jsdom` | `react-scripts test` | +| `react-scripts test` | `react-scripts test --env=node` | + +### Object proxy configuration is superseded by `src/setupProxy.js` + +To check if action is required, look for the `proxy` key in `package.json` and follow this: + +1. I couldn't find a `proxy` key in `package.json` + - No action is required! +2. The value of `proxy` is a string (e.g. `http://localhost:5000`) + - No action is required! +3. The value of `proxy` is an object + - Follow the migration instructions below. + +**It's worth highlighting: if your `proxy` field is a `string`, e.g. `http://localhost:5000`, or you don't have it, skip this section. This feature is still supported and has the same behavior.** + +If your `proxy` is an object, that means you are using the advanced proxy configuration. It has become fully customizable so we removed the limited support for the object-style configuration. Here's how to recreate it. + +First, install `http-proxy-middleware` using npm or Yarn: + +``` +npm install http-proxy-middleware +``` + +Next, create `src/setupProxy.js` and place the following contents in it: + +``` +const proxy = require('http-proxy-middleware'); + +module.exports = function(app) { + // ... +}; +``` + +Now, migrate each entry in your `proxy` object one by one, e.g.: + +``` +"proxy": { + "/api": { + "target": "http://localhost:5000/" + }, + "/*.svg": { + "target": "http://localhost:5000/" + } +} +``` + +Place entries into `src/setupProxy.js` like so: + +``` +const proxy = require('http-proxy-middleware'); + +module.exports = function(app) { + app.use(proxy('/api', { target: 'http://localhost:5000/' })); + app.use(proxy('/*.svg', { target: 'http://localhost:5000/' })); +}; +``` + +You can also use completely custom logic there now! This wasn't possible before. + +### `.mjs` file extension support is removed + +Change the extension of any files in your project using `.mjs` to `.js`. + +It was removed because of inconsistent support from underlying tools. We will add it back after it stops being experimental, and Jest gets built-in support for it. + +### `PropTypes` definitions are now removed in production + +Normally, this shouldn't affect your logic and should make the resulting bundle smaller. However, you may be relying on PropTypes definition for production logic. This is not recommended, and will break now. If a library does it, one possible solution is to file an issue in it with a proposal to use a different field (not propTypes) to signal that the declaration needs to be retained. + +### Node 6 is no longer supported + +Please upgrade to Node 8 (LTS) or later. diff --git a/packages/react-scripts/docs/migrating-from-v7-to-v8.md b/packages/react-scripts/docs/migrating-from-v7-to-v8.md new file mode 100644 index 000000000..618f6e227 --- /dev/null +++ b/packages/react-scripts/docs/migrating-from-v7-to-v8.md @@ -0,0 +1,83 @@ +# Migrating from v7 to v8 + +Inside any created `backpack-react-scripts` project that has not been ejected, run: + +``` +npm install --save-dev @skyscanner/backpack-react-scripts@^8.0.0 +``` + +## Breaking Changes + +Like any major release, `backpack-react-scripts@8` contains a few breaking changes. At least one of them will affect every user, so please scan over these sections to see what is relevant to you. + +### Upgrade to Jest 24 + +With this version brings the use of Jest `24.9.0`. Major Jest changes in [Jest v24](https://github.com/facebook/jest/blob/master/CHANGELOG.md#2400) + +You will be required to upgrade to Jest 24 due to some incompatibilies with using mixed versions in BRS and your app, please ensure you upgrade your projects Jest version when you upgrade BRS. + +If you encounter this error during build time then you will be required to make the move to Jest `24`. + +```sh +There might be a problem with the project dependency tree. +It is likely not a bug in Create React App, but something you need to fix locally. + +The backpack-react-scripts package provided by Create React App requires a dependency: + + "babel-jest": "^24.9.0" +``` + +### **New structure in `asset-manifest.json`** + +All asset paths have been moved under the files key in `asset-manifest.json`. + +This will require you to make changes to how you access files from the `asset-manifest` file. + +If in your files you currently use the import similar to the following: + +``` +require('../../client/build/asset-manifest.json') +``` + +with the new version you will need to change it to the following so that it will correctly select the files generated: + +``` +require('../../client/build/asset-manifest.json').files +``` + +If you are mocking using these files in jest you will need to change the structure from: + +``` +jest.mock('../../../client/build/asset-manifest.json', () => ({ 'main.js': 'main.js', 'main.css': 'main.css' })); +``` + +to + +``` +jest.mock('../../../client/build/asset-manifest.json', () => ({ files: { 'main.js': 'main.js', 'main.css': 'main.css' } })); +``` + +## New features + +### SRI (Subresource Integrity) Support + +Backpack React Scripts now has the ability to support [SRI (Subresource Integrity)](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) that allows for browsers to verify that resources they fetch (for example, from a CDN) are delivered without unexpected manipulation. + +To use this and opt-in a new config option has been added - `sriEnabled`. +This flag sets if SRI is to be used during build to add integrity hash for files. + +- **Note** if this is enabled, `crossOriginLoading` value is overriden with `anonymous` in order for it to output with the integrity value. + +By default this feature is disabled and can be opted in should you wish to use this. + +### Templating + +With this version brings in a feature of create-react-app which is called `templates` this allows you to specify a custom template that will be used for the base of the webapp on generation in which we have created a standard template here under [cra-template-backpack](https://github.com/Skyscanner/cra-template-backpack/) - this repo contains the base standard Backpackified template as in BRS 7 but now separated. + +As templates are the default method when creating react apps our command for running now looks like the following: + +```sh +npx create-react-app my-app --scripts-version=@skyscanner/backpack-react-scripts --template @skyscanner/cra-template-backpack --use-npm +``` + +Where `@skyscanner/cra-template-backpack` is published to the NPM repository diff --git a/packages/react-scripts/docs/migrating-from-v8-to-v9.md b/packages/react-scripts/docs/migrating-from-v8-to-v9.md new file mode 100644 index 000000000..71befeaad --- /dev/null +++ b/packages/react-scripts/docs/migrating-from-v8-to-v9.md @@ -0,0 +1,40 @@ +# Migrating from v8 to v9 + +Inside any created `backpack-react-scripts` project that has not been ejected, run: + +``` +npm install --save-dev @skyscanner/backpack-react-scripts@ +``` + +## Breaking Changes + +Like any major release, `backpack-react-scripts@9` contains a few breaking changes. At least one of them will affect every user, so please scan over these sections to see what is relevant to you. + +### Upgrade to Jest 26 + +With this version brings the use of Jest `26.6.0`. Major Jest changes in [Jest v26](https://github.com/facebook/jest/blob/master/CHANGELOG.md#2600) + +The main breaking feature is `resetMocks` is now set to `true` by default in the Jest config. + +**Note:** + +You will be required to upgrade to Jest 26 due to some incompatibilies with using mixed versions in BRS and your app, please ensure you upgrade your projects Jest version when you upgrade BRS. + +If you encounter this error during build time then you will be required to make the move to Jest `26`. + +```sh +There might be a problem with the project dependency tree. +It is likely not a bug in Create React App, but something you need to fix locally. + +The backpack-react-scripts package provided by Create React App requires a dependency: + + "babel-jest": "^26.6.0" +``` + +### Service works + +BRS now uses the Workbox InjectManifest plugin over the GenerateSW plugin + +## New features + +A full list of new features and links can be found [here](https://github.com/facebook/create-react-app/releases/tag/v4.0.0) diff --git a/packages/react-scripts/docs/updating-brs.md b/packages/react-scripts/docs/updating-brs.md new file mode 100644 index 000000000..f8d022e36 --- /dev/null +++ b/packages/react-scripts/docs/updating-brs.md @@ -0,0 +1,81 @@ +# Updating Backpack React Scripts. + +## Keeping this fork updated + +We wish to keep this fork updated with the upstream repo to benefit from the ongoing open source development +of `create-react-app`. To keep this fork up to date, please follow the steps below: + +1. Ensure `master` is in sync with `upstream/master`: + + ```sh + git checkout master + git remote add upstream git@github.com:facebook/create-react-app.git + git fetch upstream + git reset --hard upstream/master + git push --force-with-lease + ``` + +1. Rebase `fork` on top of a **tagged release** on `master`: + + ```sh + git checkout fork + git rebase <commit> + ``` + + > **Note:** `<commit>` should be the SHA-1 of the latest upstream release - _not_ the latest commit i.e. `upstream/master` + +1. Pair with someone else to fix any conflicts and cross examine changes in upstream with changes in our fork. + + > This is the most time consuming part. Take care to make sure you are not regressing any functionality that we have added in our fork. + + 1. When rebasing its important to note the `webpack.config.ssr.js` file is an exact copy of the `webpack.config.js` file with components commented out that are not required for SSR. + + When rebasing its important to do a comparison between these files to ensure that new functionality is available to SSR and enabled where necessary. + + 2. The `package.json` files will all be marked as private for each of the packages except `react-scripts/package.json` this is to prevent lerna from trying to publish new versions of these packages and cause the task to fail due to permissions, as it tries to push to the facebook npms. + +1. Re-name your local, rebased `fork` branch to something else and push it to origin. This will ensure it runs through CI and you can verify your changes. + + ```sh + git branch -m <branch> + git push origin <branch> + ``` + +1. Finally, when we are confident that the rebase has been successful, re-name your branch back to `fork` and push it to origin: + + ```sh + git branch -m fork + git push --force-with-lease + ``` + +## Releasing a new version of `backpack-react-scripts` + +1. Ensure you have run `npm install` in `root`, `packages/react-error-overlay` and `packages/react-scripts` + + - When doing this make sure you remove the `package-lock.json` files that are created in as we don't want these to be published and checked into git. + +2. Create a new version that you wish to publish by running the following command. Use the [CHANGELOG.md](./CHANGELOG.md) to decide on the nature of the changes since the last release. + + ``` + (cd packages/react-scripts && npm version major|minor|patch) + ``` + + - This will create a new commit which you will need to push to fork but place it on the last commit by running: + + ``` + gcn! && ggf + ``` + +3. To publish a new version of `backpack-react-scripts`, run the following command: + + ``` + npm run publish + ``` + + - If you want to be extra careful, you can publish a prerelease by running this instead: + + ``` + npm run publish -- --canary + ``` + +4. Update the [CHANGELOG.md](./CHANGELOG.md) with the new version, taking care to follow the format of previous releases. diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index ffae0fa30..0652163b0 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,19 +1,16 @@ { - "name": "react-scripts", - "version": "4.0.3", - "description": "Configuration and scripts for Create React App.", + "name": "@skyscanner/backpack-react-scripts", + "version": "9.0.3", + "description": "Backpack configuration and scripts for Create React App.", "repository": { "type": "git", - "url": "https://github.com/facebook/create-react-app.git", + "url": "https://github.com/Skyscanner/backpack-react-scripts.git", "directory": "packages/react-scripts" }, "license": "MIT", "engines": { "node": "^10.12.0 || >=12.0.0" }, - "bugs": { - "url": "https://github.com/facebook/create-react-app/issues" - }, "files": [ "bin", "config", @@ -39,21 +36,12 @@ "babel-plugin-named-asset-import": "^0.3.7", "babel-preset-react-app": "^10.0.0", "bfj": "^7.0.2", + "bpk-mixins": "^20.1.7", "camelcase": "^6.1.0", "case-sensitive-paths-webpack-plugin": "2.3.0", "css-loader": "4.3.0", "dotenv": "8.2.0", "dotenv-expand": "5.1.0", - "eslint": "^7.11.0", - "eslint-config-react-app": "^6.0.0", - "eslint-plugin-flowtype": "^5.2.0", - "eslint-plugin-import": "^2.22.1", - "eslint-plugin-jest": "^24.1.0", - "eslint-plugin-jsx-a11y": "^6.3.1", - "eslint-plugin-react": "^7.21.5", - "eslint-plugin-react-hooks": "^4.2.0", - "eslint-plugin-testing-library": "^3.9.2", - "eslint-webpack-plugin": "^2.5.2", "file-loader": "6.1.1", "fs-extra": "^9.0.1", "html-webpack-plugin": "4.5.0", @@ -62,7 +50,9 @@ "jest-circus": "26.6.0", "jest-resolve": "26.6.0", "jest-watch-typeahead": "0.6.1", + "lodash": "^4.17.20", "mini-css-extract-plugin": "0.11.3", + "node-sass": "^4.12.0", "optimize-css-assets-webpack-plugin": "5.0.4", "pnp-webpack-plugin": "1.6.4", "postcss-flexbugs-fixes": "4.2.1", @@ -76,7 +66,7 @@ "react-refresh": "^0.8.3", "resolve": "1.18.1", "resolve-url-loader": "^3.1.2", - "sass-loader": "^10.0.5", + "sass-loader": "7.3.1", "semver": "7.3.2", "style-loader": "1.3.0", "terser-webpack-plugin": "4.2.3", @@ -85,11 +75,12 @@ "webpack": "4.44.2", "webpack-dev-server": "3.11.1", "webpack-manifest-plugin": "2.2.0", + "webpack-subresource-integrity": "^1.4.1", "workbox-webpack-plugin": "5.1.4" }, "devDependencies": { - "react": "^17.0.1", - "react-dom": "^17.0.1" + "react": "16.2.0", + "react-dom": "16.2.0" }, "optionalDependencies": { "fsevents": "^2.1.3" @@ -114,5 +105,9 @@ "last 1 firefox version", "last 1 safari version" ] - } + }, + "publishConfig": { + "access": "public" + }, + "gitHead": "fb27e351ae2e450ddc5ff72008ea7d3559a261c4" } diff --git a/packages/react-scripts/scripts/build.js b/packages/react-scripts/scripts/build.js index de2ff505e..31c966d02 100644 --- a/packages/react-scripts/scripts/build.js +++ b/packages/react-scripts/scripts/build.js @@ -37,6 +37,7 @@ const fs = require('fs-extra'); const bfj = require('bfj'); const webpack = require('webpack'); const configFactory = require('../config/webpack.config'); +const ssrConfigFactory = require('../config/webpack.config.ssr'); const paths = require('../config/paths'); const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages'); @@ -65,6 +66,11 @@ const writeStatsJson = argv.indexOf('--stats') !== -1; // Generate configuration const config = configFactory('production'); +const ssrConfig = ssrConfigFactory('production'); + +// If an SSR entry file is found, lets make use of webpacks multi-compiler +// functionality to bundle it in parallel +const compileSsr = fs.existsSync(paths.appSsrJs); // We require that you explicitly set browsers and do not fall back to // browserslist defaults. @@ -86,6 +92,26 @@ checkBrowsers(paths.appPath, isInteractive) }) .then( ({ stats, previousFileSizes, warnings }) => { + // We don't want to make too many changes as it makes syncing back + // with upstream a pain. The rest of the code in this function relies on + // `config` and `stats` being an object as opposed to an array (from + // webpack's multi-compiler feature.) + if (compileSsr) { + stats = stats.stats[0]; + } + + // The SSR config still omits a css file - it's not yet possible to omit + // file output in ExtractTextPlugin. This is not needed so lets clean + // it up to avoid confusion. + const ssrCssPath = path.join(paths.appBuild, 'ssr.css'); + const ssrCssMapPath = path.join(paths.appBuild, 'ssr.css.map'); + if (fs.existsSync(ssrCssPath)) { + fs.unlinkSync(ssrCssPath); + } + if (fs.existsSync(ssrCssMapPath)) { + fs.unlinkSync(ssrCssMapPath); + } + if (warnings.length) { console.log(chalk.yellow('Compiled with warnings.\n')); console.log(warnings.join('\n\n')); @@ -152,7 +178,14 @@ checkBrowsers(paths.appPath, isInteractive) function build(previousFileSizes) { console.log('Creating an optimized production build...'); - const compiler = webpack(config); + let finalConfig = config; + + if (compileSsr) { + finalConfig = [config, ssrConfig]; + } + + let compiler = webpack(finalConfig); + return new Promise((resolve, reject) => { compiler.run((err, stats) => { let messages; diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index 7b9958e81..116053aaa 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -211,9 +211,9 @@ module.exports = function ( } // Setup the eslint config - appPackage.eslintConfig = { - extends: 'react-app', - }; + // appPackage.eslintConfig = { + // extends: 'react-app', + // }; // Setup the browsers list appPackage.browserslist = defaultBrowsers; @@ -293,11 +293,11 @@ module.exports = function ( if (useYarn) { command = 'yarnpkg'; remove = 'remove'; - args = ['add']; + args = ['add', `--dev`]; } else { command = 'npm'; remove = 'uninstall'; - args = ['install', '--save', verbose && '--verbose'].filter(e => e); + args = ['install', '--save-dev', verbose && '--verbose'].filter(e => e); } // Install additional template dependencies, if present. @@ -316,20 +316,24 @@ module.exports = function ( // Install react and react-dom for backward compatibility with old CRA cli // which doesn't install react and react-dom along with react-scripts if (!isReactInstalled(appPackage)) { - args = args.concat(['react', 'react-dom']); + args = args.concat(['react@16.2.0', 'react-dom@16.2.0']); } // Install template dependencies, and react and react-dom if missing. - if ((!isReactInstalled(appPackage) || templateName) && args.length > 1) { - console.log(); - console.log(`Installing template dependencies using ${command}...`); + // if ((!isReactInstalled(appPackage) || templateName) && args.length > 1) { + // console.log(); + // console.log(`Installing template dependencies using ${command}...`); + console.log( + `Installing ${chalk.cyan('Backpack')} dependencies using ${command}` + ); + console.log(); - const proc = spawn.sync(command, args, { stdio: 'inherit' }); - if (proc.status !== 0) { - console.error(`\`${command} ${args.join(' ')}\` failed`); - return; - } + let proc = spawn.sync(command, args, { stdio: 'inherit' }); + if (proc.status !== 0) { + console.error(`\`${command} ${args.join(' ')}\` failed`); + return; } + //} if (args.find(arg => arg.includes('typescript'))) { console.log(); @@ -340,7 +344,7 @@ module.exports = function ( console.log(`Removing template package using ${command}...`); console.log(); - const proc = spawn.sync(command, [remove, templateName], { + proc = spawn.sync(command, [remove, templateName], { stdio: 'inherit', }); if (proc.status !== 0) { diff --git a/packages/react-scripts/scripts/utils/createJestConfig.js b/packages/react-scripts/scripts/utils/createJestConfig.js index ca316aab5..f20d314c9 100644 --- a/packages/react-scripts/scripts/utils/createJestConfig.js +++ b/packages/react-scripts/scripts/utils/createJestConfig.js @@ -12,6 +12,17 @@ const chalk = require('react-dev-utils/chalk'); const paths = require('../../config/paths'); const modules = require('../../config/modules'); +const pkgJson = require(paths.appPackageJson); +const bpkReactScriptsConfig = pkgJson['backpack-react-scripts'] || {}; + +const includePrefixes = bpkReactScriptsConfig.babelIncludePrefixes || []; +includePrefixes.unshift('bpk-'); +includePrefixes.unshift('saddlebag-'); + +const transformIgnorePattern = `[/\\\\]node_modules[/\\\\](?!${includePrefixes.join( + '|' +)}).+\\.(js|jsx|mjs)$`; + module.exports = (resolve, rootDir, isEjecting) => { // Use this instead of `paths.testsSetup` to avoid putting // an absolute filename into configuration after ejecting. @@ -41,22 +52,24 @@ module.exports = (resolve, rootDir, isEjecting) => { testEnvironment: 'jsdom', testRunner: require.resolve('jest-circus/runner'), transform: { - '^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': resolve( - 'config/jest/babelTransform.js' - ), - '^.+\\.css$': resolve('config/jest/cssTransform.js'), - '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': resolve( + '^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': resolve('config/jest/babelTransform.js'), + // '^.+\\.css$': resolve('config/jest/cssTransform.js'), + // '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': resolve( + '^(?!.*\\.(js|jsx|ts|tsx|json)$)': resolve( 'config/jest/fileTransform.js' ), }, transformIgnorePatterns: [ - '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$', - '^.+\\.module\\.(css|sass|scss)$', + // '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$', + // '^.+\\.module\\.(css|sass|scss)$', + transformIgnorePattern, + '^.+\\.(css|sass|scss)$', ], modulePaths: modules.additionalModulePaths || [], moduleNameMapper: { '^react-native$': 'react-native-web', - '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy', + // '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy', + '^.+\\.(css|sass|scss)$': 'identity-obj-proxy', ...(modules.jestAliases || {}), }, moduleFileExtensions: [...paths.moduleFileExtensions, 'node'].filter( diff --git a/packages/react-scripts/scripts/utils/verifyPackageTree.js b/packages/react-scripts/scripts/utils/verifyPackageTree.js index 210043ff7..f0c0aaf7d 100644 --- a/packages/react-scripts/scripts/utils/verifyPackageTree.js +++ b/packages/react-scripts/scripts/utils/verifyPackageTree.js @@ -21,10 +21,8 @@ function verifyPackageTree() { // These are packages most likely to break in practice. // See https://github.com/facebook/create-react-app/issues/1795 for reasons why. // I have not included Babel here because plugins typically don't import Babel (so it's not affected). - 'babel-eslint', 'babel-jest', 'babel-loader', - 'eslint', 'jest', 'webpack', 'webpack-dev-server', diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index a430227c2..71deca7b8 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -109,11 +109,11 @@ npx create-react-app --version # ****************************************************************************** cd "$temp_app_path" -npx create-react-app test-app-dist-tag --scripts-version=@latest +npx create-react-app test-app-dist-tag --scripts-version=@skyscanner/backpack-react-scripts --template @skyscanner/backpack cd test-app-dist-tag # Check corresponding scripts version is installed and no TypeScript is present. -exists node_modules/react-scripts +exists node_modules/@skyscanner/backpack-react-scripts ! exists node_modules/typescript ! exists src/index.tsx exists src/index.js @@ -124,12 +124,12 @@ checkDependencies # ****************************************************************************** cd "$temp_app_path" -npx create-react-app test-app-version-number --scripts-version=1.0.17 +npx create-react-app test-app-version-number --scripts-version=backpack-react-scripts@8.0.0-beta.41a3a687f --template @skyscanner/backpack cd test-app-version-number # Check corresponding scripts version is installed. -exists node_modules/react-scripts -grep '"version": "1.0.17"' node_modules/react-scripts/package.json +exists node_modules/backpack-react-scripts +grep '"version": "8.0.0-beta.41a3a687f"' node_modules/backpack-react-scripts/package.json checkDependencies # ****************************************************************************** @@ -137,64 +137,64 @@ checkDependencies # ****************************************************************************** cd "$temp_app_path" -npx create-react-app test-use-npm-flag --use-npm --scripts-version=1.0.17 +npx create-react-app test-use-npm-flag --use-npm --scripts-version=@skyscanner/backpack-react-scripts --template @skyscanner/backpack cd test-use-npm-flag # Check corresponding scripts version is installed. -exists node_modules/react-scripts +exists node_modules/@skyscanner/backpack-react-scripts [ ! -e "yarn.lock" ] && echo "yarn.lock correctly does not exist" -grep '"version": "1.0.17"' node_modules/react-scripts/package.json +grep '"version": "9.0.3"' node_modules/@skyscanner/backpack-react-scripts/package.json checkDependencies # ****************************************************************************** # Test typescript setup # ****************************************************************************** +# TEMP: Removed this as we don't support TS currently in Backpack so not important and not worth the failing builds for. +# cd "$temp_app_path" +# npx create-react-app test-app-typescript --template typescript +# cd test-app-typescript -cd "$temp_app_path" -npx create-react-app test-app-typescript --template typescript -cd test-app-typescript - -# Check corresponding template is installed. -exists node_modules/react-scripts -exists node_modules/typescript -exists src/index.tsx -exists tsconfig.json -exists src/react-app-env.d.ts -checkTypeScriptDependencies - -# Check that the TypeScript template passes smoke tests, build, and normal tests -yarn start --smoke-test -yarn build -CI=true yarn test +# # Check corresponding template is installed. +# exists node_modules/react-scripts +# exists node_modules/typescript +# exists src/index.tsx +# exists tsconfig.json +# exists src/react-app-env.d.ts +# checkTypeScriptDependencies -# Check eject behaves and works +# # Check that the TypeScript template passes smoke tests, build, and normal tests +# yarn start --smoke-test +# yarn build +# CI=true yarn test -# Eject... -echo yes | npm run eject +# # Check eject behaves and works -# Temporary workaround for https://github.com/facebook/create-react-app/issues/6099 -rm yarn.lock -yarn add @babel/plugin-transform-react-jsx-source @babel/plugin-syntax-jsx @babel/plugin-transform-react-jsx @babel/plugin-transform-react-jsx-self +# # Eject... +# echo yes | npm run eject -# Ensure env file still exists -exists src/react-app-env.d.ts +# # Temporary workaround for https://github.com/facebook/create-react-app/issues/6099 +# rm yarn.lock +# yarn add @babel/plugin-transform-react-jsx-source @babel/plugin-syntax-jsx @babel/plugin-transform-react-jsx @babel/plugin-transform-react-jsx-self @babel/helper-create-regexp-features-plugin -# Check that the TypeScript template passes ejected smoke tests, build, and normal tests -yarn start --smoke-test -yarn build -CI=true yarn test +# # Ensure env file still exists +# exists src/react-app-env.d.ts + +# # Check that the TypeScript template passes ejected smoke tests, build, and normal tests +# yarn start --smoke-test +# yarn build +# CI=true yarn test # ****************************************************************************** # Test --scripts-version with a tarball url # ****************************************************************************** cd "$temp_app_path" -npx create-react-app test-app-tarball-url --scripts-version=https://registry.npmjs.org/react-scripts/-/react-scripts-1.0.17.tgz +npx create-react-app test-app-tarball-url --scripts-version=https://registry.npmjs.org/@skyscanner/backpack-react-scripts/-/backpack-react-scripts-8.0.1.tgz --template @skyscanner/backpack cd test-app-tarball-url # Check corresponding scripts version is installed. -exists node_modules/react-scripts -grep '"version": "1.0.17"' node_modules/react-scripts/package.json +exists node_modules/@skyscanner/backpack-react-scripts +grep '"version": "8.0.1"' node_modules/@skyscanner/backpack-react-scripts/package.json checkDependencies # ****************************************************************************** @@ -276,13 +276,16 @@ yarn start --smoke-test # ****************************************************************************** # Test when PnP is enabled # ****************************************************************************** -cd "$temp_app_path" -npx create-react-app test-app-pnp --use-pnp -cd test-app-pnp -! exists node_modules -exists .pnp.js -yarn start --smoke-test -yarn build + +# TEMP: Removed as its a yarn feature and we don't support yarn for projects + +# cd "$temp_app_path" +# npx create-react-app test-app-pnp --scripts-version=@skyscanner/backpack-react-scripts --template @skyscanner/backpack --use-pnp +# cd test-app-pnp +# ! exists node_modules +# exists .pnp.js +# yarn start --smoke-test +# yarn build # Cleanup cleanup diff --git a/tasks/e2e-kitchensink.sh b/tasks/e2e-kitchensink.sh index f2e8f9a52..52627be46 100755 --- a/tasks/e2e-kitchensink.sh +++ b/tasks/e2e-kitchensink.sh @@ -93,7 +93,7 @@ publishToLocalRegistry # Install the app in a temporary location cd $temp_app_path -npx create-react-app test-kitchensink --template=file:"$root_path"/packages/react-scripts/fixtures/kitchensink +npx create-react-app test-kitchensink --scripts-version=@skyscanner/backpack-react-scripts --template=file:"$root_path"/packages/react-scripts/fixtures/kitchensink # Install the test module cd "$temp_module_path" diff --git a/tasks/e2e-simple.sh b/tasks/e2e-simple.sh index 7cf89bb5b..ddded5e7d 100755 --- a/tasks/e2e-simple.sh +++ b/tasks/e2e-simple.sh @@ -88,13 +88,14 @@ yarn startLocalRegistry "$root_path"/tasks/verdaccio.yaml # Lint own code -./node_modules/.bin/eslint --max-warnings 0 packages/babel-preset-react-app/ -./node_modules/.bin/eslint --max-warnings 0 packages/confusing-browser-globals/ -./node_modules/.bin/eslint --max-warnings 0 packages/create-react-app/ -./node_modules/.bin/eslint --max-warnings 0 packages/eslint-config-react-app/ -./node_modules/.bin/eslint --max-warnings 0 packages/react-dev-utils/ -./node_modules/.bin/eslint --max-warnings 0 packages/react-error-overlay/src/ -./node_modules/.bin/eslint --max-warnings 0 packages/react-scripts/ +# TEMP: Removed this as it is currently failing upstream so will be re-enabled once upstream issues resolved +# ./node_modules/.bin/eslint --max-warnings 0 packages/babel-preset-react-app/ +# ./node_modules/.bin/eslint --max-warnings 0 packages/confusing-browser-globals/ +# ./node_modules/.bin/eslint --max-warnings 0 packages/create-react-app/ +# ./node_modules/.bin/eslint --max-warnings 0 packages/eslint-config-react-app/ +# ./node_modules/.bin/eslint --max-warnings 0 packages/react-dev-utils/ +# ./node_modules/.bin/eslint --max-warnings 0 packages/react-error-overlay/src/ +# ./node_modules/.bin/eslint --max-warnings 0 packages/react-scripts/ cd packages/react-error-overlay/ yarn test @@ -127,7 +128,7 @@ yarn build exists build/*.html exists build/static/js/*.js exists build/static/css/*.css -exists build/static/media/*.svg +# exists build/static/media/*.svg exists build/favicon.ico # Run tests with CI flag @@ -147,7 +148,7 @@ publishToLocalRegistry # Install the app in a temporary location cd $temp_app_path -npx create-react-app test-app +npx create-react-app test-app --scripts-version=@skyscanner/backpack-react-scripts --template @skyscanner/backpack # TODO: verify we installed prerelease @@ -235,7 +236,7 @@ yarn build exists build/*.html exists build/static/js/*.js exists build/static/css/*.css -exists build/static/media/*.svg +# exists build/static/media/*.svg exists build/favicon.ico # Run tests with CI flag @@ -252,45 +253,44 @@ verify_env_url # Test reliance on webpack internals verify_module_scope + +# DISABLED: The below test is disabled due to an issue that exists post ejecting in upstream CRA, once this has been resolved we can enable the below + # ****************************************************************************** # Finally, let's check that everything still works after ejecting. # ****************************************************************************** # Eject... -echo yes | npm run eject - -# Temporary workaround for https://github.com/facebook/create-react-app/issues/6099 -rm yarn.lock -yarn add @babel/plugin-transform-react-jsx-source @babel/plugin-syntax-jsx @babel/plugin-transform-react-jsx @babel/plugin-transform-react-jsx-self - -# Test ejected files were staged -test -n "$(git diff --staged --name-only)" - -# Test the build -yarn build -# Check for expected output -exists build/*.html -exists build/static/js/*.js -exists build/static/css/*.css -exists build/static/media/*.svg -exists build/favicon.ico - -# Run tests, overriding the watch option to disable it. -# `CI=true yarn test` won't work here because `yarn test` becomes just `jest`. -# We should either teach Jest to respect CI env variable, or make -# `scripts/test.js` survive ejection (right now it doesn't). -yarn test --watch=no -# Uncomment when snapshot testing is enabled by default: -# exists src/__snapshots__/App.test.js.snap - -# Test the server -yarn start --smoke-test - -# Test environment handling -verify_env_url - -# Test reliance on webpack internals -verify_module_scope +# echo yes | npm run eject + +# # Test ejected files were staged +# test -n "$(git diff --staged --name-only)" + +# # Test the build +# yarn build +# # Check for expected output +# exists build/*.html +# exists build/static/js/*.js +# exists build/static/css/*.css +# # exists build/static/media/*.svg +# exists build/favicon.ico + +# # Run tests, overriding the watch option to disable it. +# # `CI=true yarn test` won't work here because `yarn test` becomes just `jest`. +# # We should either teach Jest to respect CI env variable, or make +# # `scripts/test.js` survive ejection (right now it doesn't). +# yarn test --watch=no +# # Uncomment when snapshot testing is enabled by default: +# # exists src/__snapshots__/App.test.js.snap + +# # Test the server +# yarn start --smoke-test + +# # Test environment handling +# verify_env_url + +# # Test reliance on webpack internals +# verify_module_scope # Cleanup cleanup diff --git a/tasks/local-registry.sh b/tasks/local-registry.sh index 34bdd260c..edf63004e 100644 --- a/tasks/local-registry.sh +++ b/tasks/local-registry.sh @@ -26,5 +26,5 @@ function stopLocalRegistry { function publishToLocalRegistry { git clean -df - ./tasks/publish.sh prerelease --yes --force-publish=* --no-git-tag-version --no-commit-hooks --no-push --exact --dist-tag=latest + ./tasks/publish.sh --force-publish=* --no-git-tag-version --no-commit-hooks --no-push --exact --dist-tag=latest } diff --git a/tasks/publish.sh b/tasks/publish.sh index f5ed3838c..c0bb4c232 100755 --- a/tasks/publish.sh +++ b/tasks/publish.sh @@ -26,9 +26,10 @@ set -x cd .. root_path=$PWD -if [ -z $CI ]; then - yarn compile:lockfile -fi +# As we don't use yarn we ignore this as it otherwise causes issues with the release +# if [ -z $CI ]; then +# yarn compile:lockfile +# fi if [ -n "$(git status --porcelain)" ]; then echo "Your git status is not clean. Aborting."; @@ -48,4 +49,4 @@ if [ -z $CI ]; then fi # Go! -NPM_CONFIG_OTP="$otp" ./node_modules/.bin/lerna publish "$@" +NPM_CONFIG_OTP="$otp" ./node_modules/.bin/lerna publish from-package "$@" -- GitLab From cb6ab318acb8a15f38ad9fc268e8b7ea61746bf3 Mon Sep 17 00:00:00 2001 From: jayson991 <jaysonwu991@outlook.com> Date: Fri, 14 May 2021 19:49:57 +0800 Subject: [PATCH 02/29] [LEOP-21]: Add `cache-loader` to speed up local development (#92) * Backpackify * add cache-loader to speed up local development * add cache-loader to speed up local development * restore link style of paths.js and webpack.config.js in react-scripts * restore link style of paths.js and webpack.config.js in react-scripts again * restore link style of paths.js and webpack.config.js in react-scripts again 2x * restore link style of paths.js and webpack.config.js in react-scripts again 3x * restore link style of paths.js and webpack.config.js in react-scripts again 4x * restore link style of paths.js and webpack.config.js in react-scripts * update CHANGELOG and the version of @skyscanner/backpack-react-scripts to v9.0.4 * add cache-loader to webpack SSR config but comment that out to not use * change BRS version to v9.1.0 since it is a mirror change * restore build-brs.yml formation as fork branch * add blank space to build-brs.yml to restore formation Co-authored-by: Ollie Curtis <8831547+olliecurtis@users.noreply.github.com> Co-authored-by: Jayson Wu <jayson.wu@skyscanner.net> --- packages/react-scripts/CHANGELOG.md | 4 + packages/react-scripts/config/paths.js | 2 + .../react-scripts/config/webpack.config.js | 204 ++++++++++-------- .../config/webpack.config.ssr.js | 202 +++++++++-------- packages/react-scripts/package.json | 1 + 5 files changed, 236 insertions(+), 177 deletions(-) diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 8d66cd930..761f39d4d 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,5 +1,9 @@ # `backpack-react-scripts` Change Log +## 9.1.0 - UNRELEASED + +Add `cache-loader` to speed up local development + ## 9.0.3 - Rebased onto `upstream/master` v4.0.3 (f92c37a6e6636ed1650ffd976c6881f59b1be803) diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index d19fb7550..41f1bdbf0 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -106,6 +106,7 @@ module.exports = { ownNodeModules: resolveOwn('node_modules'), // This is empty on npm 3 appTypeDeclarations: resolveApp('src/react-app-env.d.ts'), ownTypeDeclarations: resolveOwn('lib/react-app.d.ts'), + cacheLoaderDir: resolveOwn('.cache/cache-loader'), }; const ownPackageJson = require('../package.json'); @@ -143,6 +144,7 @@ if ( ownNodeModules: resolveOwn('node_modules'), appTypeDeclarations: resolveOwn(`${templatePath}/src/react-app-env.d.ts`), ownTypeDeclarations: resolveOwn('lib/react-app.d.ts'), + cacheLoaderDir: resolveOwn('.cache/cache-loader'), }; } // @remove-on-eject-end diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 121b987bb..a7ec7be78 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -140,6 +140,12 @@ module.exports = function (webpackEnv) { ? { publicPath: '../../' } : {}, }, + isEnvDevelopment && { + loader: require.resolve('cache-loader'), + options: { + cacheDirectory: paths.cacheLoaderDir, + }, + }, { loader: require.resolve('css-loader'), options: cssOptions, @@ -465,102 +471,122 @@ module.exports = function (webpackEnv) { saddlebagModulesRegex, ...customModuleRegexes, ], - loader: require.resolve('babel-loader'), - options: { - customize: require.resolve( - 'babel-preset-react-app/webpack-overrides' - ), - presets: [ - [ - require.resolve('babel-preset-react-app'), - { - runtime: hasJsxRuntime ? 'automatic' : 'classic', - }, - ], - ], - // @remove-on-eject-begin - babelrc: false, - configFile: false, - // Make sure we have a unique cache identifier, erring on the - // side of caution. - // We remove this when the user ejects because the default - // is sane and uses Babel options. Instead of options, we use - // the react-scripts and babel-preset-react-app versions. - cacheIdentifier: getCacheIdentifier( - isEnvProduction - ? 'production' - : isEnvDevelopment && 'development', - [ - 'babel-plugin-named-asset-import', - 'babel-preset-react-app', - 'react-dev-utils', - 'react-scripts', - ] - ), - // @remove-on-eject-end - plugins: [ - [ - require.resolve('babel-plugin-named-asset-import'), - { - loaderMap: { - svg: { - ReactComponent: - '@svgr/webpack?-svgo,+titleProp,+ref![path]', + use: [ + isEnvDevelopment && { + loader: require.resolve('cache-loader'), + options: { + cacheDirectory: paths.cacheLoaderDir, + }, + }, + { + loader: require.resolve('babel-loader'), + options: { + customize: require.resolve( + 'babel-preset-react-app/webpack-overrides', + ), + presets: [ + [ + require.resolve('babel-preset-react-app'), + { + runtime: hasJsxRuntime ? 'automatic' : 'classic', }, - }, - }, - ], - isEnvDevelopment && - shouldUseReactRefresh && - require.resolve('react-refresh/babel'), - ].filter(Boolean), - // This is a feature of `babel-loader` for webpack (not Babel itself). - // It enables caching results in ./node_modules/.cache/babel-loader/ - // directory for faster rebuilds. - cacheDirectory: true, - // See #6846 for context on why cacheCompression is disabled - cacheCompression: false, - compact: isEnvProduction, - }, + ], + ], + // @remove-on-eject-begin + babelrc: false, + configFile: false, + // Make sure we have a unique cache identifier, erring on the + // side of caution. + // We remove this when the user ejects because the default + // is sane and uses Babel options. Instead of options, we use + // the react-scripts and babel-preset-react-app versions. + cacheIdentifier: getCacheIdentifier( + isEnvProduction + ? 'production' + : isEnvDevelopment && 'development', + [ + 'babel-plugin-named-asset-import', + 'babel-preset-react-app', + 'react-dev-utils', + 'react-scripts', + ], + ), + // @remove-on-eject-end + plugins: [ + [ + require.resolve('babel-plugin-named-asset-import'), + { + loaderMap: { + svg: { + ReactComponent: + '@svgr/webpack?-svgo,+titleProp,+ref![path]', + }, + }, + }, + ], + isEnvDevelopment && + shouldUseReactRefresh && + require.resolve('react-refresh/babel'), + ].filter(Boolean), + // This is a feature of `babel-loader` for webpack (not Babel itself). + // It enables caching results in ./node_modules/.cache/babel-loader/ + // directory for faster rebuilds. + cacheDirectory: true, + // See #6846 for context on why cacheCompression is disabled + cacheCompression: false, + compact: isEnvProduction, + }, + }, + ].filter(Boolean), }, // Process any JS outside of the app with Babel. // Unlike the application JS, we only compile the standard ES features. { test: /\.(js|mjs)$/, exclude: /@babel(?:\/|\\{1,2})runtime/, - loader: require.resolve('babel-loader'), - options: { - babelrc: false, - configFile: false, - compact: false, - presets: [ - [ - require.resolve('babel-preset-react-app/dependencies'), - { helpers: true }, - ], - ], - cacheDirectory: true, - // See #6846 for context on why cacheCompression is disabled - cacheCompression: false, - // @remove-on-eject-begin - cacheIdentifier: getCacheIdentifier( - isEnvProduction - ? 'production' - : isEnvDevelopment && 'development', - [ - 'babel-plugin-named-asset-import', - 'babel-preset-react-app', - 'react-dev-utils', - 'react-scripts', - ] - ), - // @remove-on-eject-end - // Babel sourcemaps are needed for debugging into node_modules - // code. Without the options below, debuggers like VSCode - // show incorrect code and set breakpoints on the wrong lines. - sourceMaps: shouldUseSourceMap, - inputSourceMap: shouldUseSourceMap, - }, + use: [ + isEnvDevelopment && { + loader: require.resolve('cache-loader'), + options: { + cacheDirectory: paths.cacheLoaderDir, + }, + }, + { + loader: require.resolve('babel-loader'), + options: { + babelrc: false, + configFile: false, + compact: false, + presets: [ + [ + require.resolve('babel-preset-react-app/dependencies'), + { helpers: true }, + ], + ], + cacheDirectory: true, + // See #6846 for context on why cacheCompression is disabled + cacheCompression: false, + // @remove-on-eject-begin + cacheIdentifier: getCacheIdentifier( + isEnvProduction + ? 'production' + : isEnvDevelopment && 'development', + [ + 'babel-plugin-named-asset-import', + 'babel-preset-react-app', + 'react-dev-utils', + 'react-scripts', + ], + ), + // @remove-on-eject-end + // Babel sourcemaps are needed for debugging into node_modules + // code. Without the options below, debuggers like VSCode + // show incorrect code and set breakpoints on the wrong lines. + sourceMaps: shouldUseSourceMap, + inputSourceMap: shouldUseSourceMap, + }, + }, + ].filter(Boolean), }, // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index 331f2ca9f..7208ff9fb 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -136,6 +136,12 @@ module.exports = function (webpackEnv) { ? { publicPath: '../../' } : {}, }, + // isEnvDevelopment && { + // loader: require.resolve('cache-loader'), + // options: { + // cacheDirectory: paths.cacheLoaderDir, + // }, + // }, { loader: require.resolve('css-loader'), options: cssOptions, @@ -467,102 +473,122 @@ module.exports = function (webpackEnv) { saddlebagModulesRegex, ...customModuleRegexes, ], - loader: require.resolve('babel-loader'), - options: { - customize: require.resolve( - 'babel-preset-react-app/webpack-overrides' - ), - // @remove-on-eject-begin - babelrc: false, - configFile: false, - presets: [ - [ - require.resolve('babel-preset-react-app'), - { - runtime: hasJsxRuntime ? 'automatic' : 'classic', - }, - ], - ], - // Make sure we have a unique cache identifier, erring on the - // side of caution. - // We remove this when the user ejects because the default - // is sane and uses Babel options. Instead of options, we use - // the react-scripts and babel-preset-react-app versions. - cacheIdentifier: getCacheIdentifier( - isEnvProduction - ? 'production' - : isEnvDevelopment && 'development', - [ - 'babel-plugin-named-asset-import', - 'babel-preset-react-app', - 'react-dev-utils', - 'react-scripts', - ] - ), - // @remove-on-eject-end - plugins: [ - [ - require.resolve('babel-plugin-named-asset-import'), - { - loaderMap: { - svg: { - ReactComponent: - '@svgr/webpack?-svgo,+titleProp,+ref![path]', + use: [ + // isEnvDevelopment && { + // loader: require.resolve('cache-loader'), + // options: { + // cacheDirectory: paths.cacheLoaderDir, + // }, + // }, + { + loader: require.resolve('babel-loader'), + options: { + customize: require.resolve( + 'babel-preset-react-app/webpack-overrides' + ), + // @remove-on-eject-begin + babelrc: false, + configFile: false, + presets: [ + [ + require.resolve('babel-preset-react-app'), + { + runtime: hasJsxRuntime ? 'automatic' : 'classic', }, - }, - }, - ], - isEnvDevelopment && - shouldUseReactRefresh && - require.resolve('react-refresh/babel'), + ], + ], + // Make sure we have a unique cache identifier, erring on the + // side of caution. + // We remove this when the user ejects because the default + // is sane and uses Babel options. Instead of options, we use + // the react-scripts and babel-preset-react-app versions. + cacheIdentifier: getCacheIdentifier( + isEnvProduction + ? 'production' + : isEnvDevelopment && 'development', + [ + 'babel-plugin-named-asset-import', + 'babel-preset-react-app', + 'react-dev-utils', + 'react-scripts', + ] + ), + // @remove-on-eject-end + plugins: [ + [ + require.resolve('babel-plugin-named-asset-import'), + { + loaderMap: { + svg: { + ReactComponent: + '@svgr/webpack?-svgo,+titleProp,+ref![path]', + }, + }, + }, + ], + isEnvDevelopment && + shouldUseReactRefresh && + require.resolve('react-refresh/babel'), + ].filter(Boolean), + // This is a feature of `babel-loader` for webpack (not Babel itself). + // It enables caching results in ./node_modules/.cache/babel-loader/ + // directory for faster rebuilds. + cacheDirectory: true, + // See #6846 for context on why cacheCompression is disabled + cacheCompression: false, + compact: isEnvProduction, + }, + }, ].filter(Boolean), - // This is a feature of `babel-loader` for webpack (not Babel itself). - // It enables caching results in ./node_modules/.cache/babel-loader/ - // directory for faster rebuilds. - cacheDirectory: true, - // See #6846 for context on why cacheCompression is disabled - cacheCompression: false, - compact: isEnvProduction, - }, }, // Process any JS outside of the app with Babel. // Unlike the application JS, we only compile the standard ES features. { test: /\.(js|mjs)$/, exclude: /@babel(?:\/|\\{1,2})runtime/, - loader: require.resolve('babel-loader'), - options: { - babelrc: false, - configFile: false, - compact: false, - presets: [ - [ - require.resolve('babel-preset-react-app/dependencies'), - { helpers: true }, - ], - ], - cacheDirectory: true, - // See #6846 for context on why cacheCompression is disabled - cacheCompression: false, - // @remove-on-eject-begin - cacheIdentifier: getCacheIdentifier( - isEnvProduction - ? 'production' - : isEnvDevelopment && 'development', - [ - 'babel-plugin-named-asset-import', - 'babel-preset-react-app', - 'react-dev-utils', - 'react-scripts', - ] - ), - // @remove-on-eject-end - // Babel sourcemaps are needed for debugging into node_modules - // code. Without the options below, debuggers like VSCode - // show incorrect code and set breakpoints on the wrong lines. - sourceMaps: shouldUseSourceMap, - inputSourceMap: shouldUseSourceMap, - }, + use: [ + // isEnvDevelopment && { + // loader: require.resolve('cache-loader'), + // options: { + // cacheDirectory: paths.cacheLoaderDir, + // }, + // }, + { + loader: require.resolve('babel-loader'), + options: { + babelrc: false, + configFile: false, + compact: false, + presets: [ + [ + require.resolve('babel-preset-react-app/dependencies'), + { helpers: true }, + ], + ], + cacheDirectory: true, + // See #6846 for context on why cacheCompression is disabled + cacheCompression: false, + // @remove-on-eject-begin + cacheIdentifier: getCacheIdentifier( + isEnvProduction + ? 'production' + : isEnvDevelopment && 'development', + [ + 'babel-plugin-named-asset-import', + 'babel-preset-react-app', + 'react-dev-utils', + 'react-scripts', + ] + ), + // @remove-on-eject-end + // Babel sourcemaps are needed for debugging into node_modules + // code. Without the options below, debuggers like VSCode + // show incorrect code and set breakpoints on the wrong lines. + sourceMaps: shouldUseSourceMap, + inputSourceMap: shouldUseSourceMap, + }, + }, + ].filter(Boolean), }, // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 0652163b0..6aeba656c 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -37,6 +37,7 @@ "babel-preset-react-app": "^10.0.0", "bfj": "^7.0.2", "bpk-mixins": "^20.1.7", + "cache-loader": "^4.1.0", "camelcase": "^6.1.0", "case-sensitive-paths-webpack-plugin": "2.3.0", "css-loader": "4.3.0", -- GitLab From b2a21aacf5fae18d7df08b53433527ae69c19894 Mon Sep 17 00:00:00 2001 From: jayson991 <jaysonwu991@outlook.com> Date: Fri, 14 May 2021 20:27:19 +0800 Subject: [PATCH 03/29] [LEOP-23]: Add thread-loader to speed up webpack workflow (#93) * Backpackify * add thread-loader to webpack config * add thread-loader to webpack SSR config but comment that out to not use * add CHANGELOG and upgrade version to v9.1.1 * restore build-brs.yml formation as fork branch Co-authored-by: Ollie Curtis <8831547+olliecurtis@users.noreply.github.com> Co-authored-by: Jayson Wu <jayson.wu@skyscanner.net> --- packages/react-scripts/CHANGELOG.md | 3 ++- .../react-scripts/config/webpack.config.js | 19 +++++++++++++++++++ .../config/webpack.config.ssr.js | 19 +++++++++++++++++++ packages/react-scripts/package.json | 1 + 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 761f39d4d..6da52b0c3 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -2,7 +2,8 @@ ## 9.1.0 - UNRELEASED -Add `cache-loader` to speed up local development +- Add `thread-loader` to speed up webpack workflow by bundling in parallels +- Add `cache-loader` to speed up local development ## 9.0.3 diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index a7ec7be78..ea70bd147 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -40,6 +40,17 @@ const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier'); // @remove-on-eject-end const postcssNormalize = require('postcss-normalize'); +const threadLoader = require('thread-loader'); + +// This boots the max number of workers in the pool and loads specified modules into the node.js module cache. +const jsWorkerPool = { + // can be set to Infinity for watching builds to keep workers alive + poolTimeout: 2000, +}; + +// To prevent the high delay when booting workers it possible to warmup the worker pool. +threadLoader.warmup(jsWorkerPool, ['babel-loader']); + const appPackageJson = require(paths.appPackageJson); const sassFunctions = require('bpk-mixins/sass-functions'); @@ -472,6 +483,10 @@ module.exports = function (webpackEnv) { ...customModuleRegexes, ], use: [ + { + loader: require.resolve('thread-loader'), + options: jsWorkerPool, + }, isEnvDevelopment && { loader: require.resolve('cache-loader'), options: { @@ -545,6 +560,10 @@ module.exports = function (webpackEnv) { test: /\.(js|mjs)$/, exclude: /@babel(?:\/|\\{1,2})runtime/, use: [ + { + loader: require.resolve('thread-loader'), + options: jsWorkerPool, + }, isEnvDevelopment && { loader: require.resolve('cache-loader'), options: { diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index 7208ff9fb..7845402ec 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -40,6 +40,17 @@ const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier'); // @remove-on-eject-end const postcssNormalize = require('postcss-normalize'); +// const threadLoader = require('thread-loader'); + +// // This boots the max number of workers in the pool and loads specified modules into the node.js module cache. +// const jsWorkerPool = { +// // can be set to Infinity for watching builds to keep workers alive +// poolTimeout: 2000, +// }; + +// // To prevent the high delay when booting workers it possible to warmup the worker pool. +// threadLoader.warmup(jsWorkerPool, ['babel-loader']); + const appPackageJson = require(paths.appPackageJson); const sassFunctions = require('bpk-mixins/sass-functions'); @@ -474,6 +485,10 @@ module.exports = function (webpackEnv) { ...customModuleRegexes, ], use: [ + // { + // loader: require.resolve('thread-loader'), + // options: jsWorkerPool, + // }, // isEnvDevelopment && { // loader: require.resolve('cache-loader'), // options: { @@ -547,6 +562,10 @@ module.exports = function (webpackEnv) { test: /\.(js|mjs)$/, exclude: /@babel(?:\/|\\{1,2})runtime/, use: [ + // { + // loader: require.resolve('thread-loader'), + // options: jsWorkerPool, + // }, // isEnvDevelopment && { // loader: require.resolve('cache-loader'), // options: { diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 6aeba656c..042b1e5c4 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -71,6 +71,7 @@ "semver": "7.3.2", "style-loader": "1.3.0", "terser-webpack-plugin": "4.2.3", + "thread-loader": "^3.0.3", "ts-pnp": "1.2.0", "url-loader": "4.1.1", "webpack": "4.44.2", -- GitLab From 73cfa32bb56a14b8f61e32baf9ca7f7d5c82349f Mon Sep 17 00:00:00 2001 From: Oliver Curtis <8831547+olliecurtis@users.noreply.github.com> Date: Fri, 14 May 2021 18:26:56 +0100 Subject: [PATCH 04/29] Publish 9.1.0 --- packages/react-scripts/CHANGELOG.md | 2 +- packages/react-scripts/package.json | 2 +- tasks/e2e-installs.sh | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 6da52b0c3..c155dccc3 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,6 +1,6 @@ # `backpack-react-scripts` Change Log -## 9.1.0 - UNRELEASED +## 9.1.0 - Add `thread-loader` to speed up webpack workflow by bundling in parallels - Add `cache-loader` to speed up local development diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 042b1e5c4..31e38670c 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@skyscanner/backpack-react-scripts", - "version": "9.0.3", + "version": "9.1.0", "description": "Backpack configuration and scripts for Create React App.", "repository": { "type": "git", diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index 71deca7b8..b3325087d 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -137,13 +137,13 @@ checkDependencies # ****************************************************************************** cd "$temp_app_path" -npx create-react-app test-use-npm-flag --use-npm --scripts-version=@skyscanner/backpack-react-scripts --template @skyscanner/backpack +npx create-react-app test-use-npm-flag --use-npm --scripts-version=@skyscanner/backpack-react-scripts@9.1.0 --template @skyscanner/backpack cd test-use-npm-flag # Check corresponding scripts version is installed. exists node_modules/@skyscanner/backpack-react-scripts [ ! -e "yarn.lock" ] && echo "yarn.lock correctly does not exist" -grep '"version": "9.0.3"' node_modules/@skyscanner/backpack-react-scripts/package.json +grep '"version": "9.1.0"' node_modules/@skyscanner/backpack-react-scripts/package.json checkDependencies # ****************************************************************************** -- GitLab From 914c6be8c8be69509d7589a5088a8818ec51a6dc Mon Sep 17 00:00:00 2001 From: jayson991 <jaysonwu991@outlook.com> Date: Mon, 24 May 2021 18:04:10 +0800 Subject: [PATCH 05/29] Optimize thread loader to fix build storybook failed (#94) * Backpackify * optimize the usage of thread-loader to fix build:storybook running failed * restore formation of build-brs.yml file * restore react-scripts version to v9.1.0 to make pipeline run normal Co-authored-by: Ollie Curtis <8831547+olliecurtis@users.noreply.github.com> Co-authored-by: Jayson Wu <jayson.wu@skyscanner.net> --- packages/react-scripts/CHANGELOG.md | 4 + .../react-scripts/config/webpack.config.js | 87 ++++++++++++++++--- .../config/webpack.config.ssr.js | 87 ++++++++++++++++--- packages/react-scripts/package.json | 2 +- 4 files changed, 159 insertions(+), 21 deletions(-) diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index c155dccc3..aa9c31bfa 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,5 +1,9 @@ # `backpack-react-scripts` Change Log +## 9.1.1 + +- Optimize the usage of `thread-loader` to fix `build:storybook` running failed + ## 9.1.0 - Add `thread-loader` to speed up webpack workflow by bundling in parallels diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index ea70bd147..e759455f8 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -40,17 +40,19 @@ const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier'); // @remove-on-eject-end const postcssNormalize = require('postcss-normalize'); -const threadLoader = require('thread-loader'); - -// This boots the max number of workers in the pool and loads specified modules into the node.js module cache. +// thread-loader options const jsWorkerPool = { + // name of the pool + // can be used to create different pools with elsewise identical options + name: 'js-pool', + // can be set to Infinity for watching builds to keep workers alive poolTimeout: 2000, + // number of jobs a worker processes in parallel + // defaults to 20 + workerParallelJobs: 50, }; -// To prevent the high delay when booting workers it possible to warmup the worker pool. -threadLoader.warmup(jsWorkerPool, ['babel-loader']); - const appPackageJson = require(paths.appPackageJson); const sassFunctions = require('bpk-mixins/sass-functions'); @@ -482,6 +484,75 @@ module.exports = function (webpackEnv) { saddlebagModulesRegex, ...customModuleRegexes, ], + loader: require.resolve('babel-loader'), + options: { + customize: require.resolve( + 'babel-preset-react-app/webpack-overrides', + ), + presets: [ + [ + require.resolve('babel-preset-react-app'), + { + runtime: hasJsxRuntime ? 'automatic' : 'classic', + }, + ], + ], + // @remove-on-eject-begin + babelrc: false, + configFile: false, + // Make sure we have a unique cache identifier, erring on the + // side of caution. + // We remove this when the user ejects because the default + // is sane and uses Babel options. Instead of options, we use + // the react-scripts and babel-preset-react-app versions. + cacheIdentifier: getCacheIdentifier( + isEnvProduction + ? 'production' + : isEnvDevelopment && 'development', + [ + 'babel-plugin-named-asset-import', + 'babel-preset-react-app', + 'react-dev-utils', + 'react-scripts', + ], + ), + // @remove-on-eject-end + plugins: [ + [ + require.resolve('babel-plugin-named-asset-import'), + { + loaderMap: { + svg: { + ReactComponent: + '@svgr/webpack?-svgo,+titleProp,+ref![path]', + }, + }, + }, + ], + isEnvDevelopment && + shouldUseReactRefresh && + require.resolve('react-refresh/babel'), + ].filter(Boolean), + // This is a feature of `babel-loader` for webpack (not Babel itself). + // It enables caching results in ./node_modules/.cache/babel-loader/ + // directory for faster rebuilds. + cacheDirectory: true, + // See #6846 for context on why cacheCompression is disabled + cacheCompression: false, + compact: isEnvProduction, + }, + }, + // Process application JS with Babel but without `.storybook` folder. + // The preset includes JSX, Flow, TypeScript, and some ESnext features. + { + test: /\.(js|mjs|jsx|ts|tsx)$/, + exclude: /\.storybook/, + include: [ + paths.appSrc, + backpackModulesRegex, + saddlebagModulesRegex, + ...customModuleRegexes, + ], use: [ { loader: require.resolve('thread-loader'), @@ -560,10 +631,6 @@ module.exports = function (webpackEnv) { test: /\.(js|mjs)$/, exclude: /@babel(?:\/|\\{1,2})runtime/, use: [ - { - loader: require.resolve('thread-loader'), - options: jsWorkerPool, - }, isEnvDevelopment && { loader: require.resolve('cache-loader'), options: { diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index 7845402ec..5c67a6ca6 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -40,17 +40,19 @@ const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier'); // @remove-on-eject-end const postcssNormalize = require('postcss-normalize'); -// const threadLoader = require('thread-loader'); - -// // This boots the max number of workers in the pool and loads specified modules into the node.js module cache. +// // thread-loader options // const jsWorkerPool = { +// // name of the pool +// // can be used to create different pools with elsewise identical options +// name: 'js-pool', + // // can be set to Infinity for watching builds to keep workers alive // poolTimeout: 2000, +// // number of jobs a worker processes in parallel +// // defaults to 20 +// workerParallelJobs: 50, // }; -// // To prevent the high delay when booting workers it possible to warmup the worker pool. -// threadLoader.warmup(jsWorkerPool, ['babel-loader']); - const appPackageJson = require(paths.appPackageJson); const sassFunctions = require('bpk-mixins/sass-functions'); @@ -484,6 +486,75 @@ module.exports = function (webpackEnv) { saddlebagModulesRegex, ...customModuleRegexes, ], + loader: require.resolve('babel-loader'), + options: { + customize: require.resolve( + 'babel-preset-react-app/webpack-overrides' + ), + // @remove-on-eject-begin + babelrc: false, + configFile: false, + presets: [ + [ + require.resolve('babel-preset-react-app'), + { + runtime: hasJsxRuntime ? 'automatic' : 'classic', + }, + ], + ], + // Make sure we have a unique cache identifier, erring on the + // side of caution. + // We remove this when the user ejects because the default + // is sane and uses Babel options. Instead of options, we use + // the react-scripts and babel-preset-react-app versions. + cacheIdentifier: getCacheIdentifier( + isEnvProduction + ? 'production' + : isEnvDevelopment && 'development', + [ + 'babel-plugin-named-asset-import', + 'babel-preset-react-app', + 'react-dev-utils', + 'react-scripts', + ] + ), + // @remove-on-eject-end + plugins: [ + [ + require.resolve('babel-plugin-named-asset-import'), + { + loaderMap: { + svg: { + ReactComponent: + '@svgr/webpack?-svgo,+titleProp,+ref![path]', + }, + }, + }, + ], + isEnvDevelopment && + shouldUseReactRefresh && + require.resolve('react-refresh/babel'), + ].filter(Boolean), + // This is a feature of `babel-loader` for webpack (not Babel itself). + // It enables caching results in ./node_modules/.cache/babel-loader/ + // directory for faster rebuilds. + cacheDirectory: true, + // See #6846 for context on why cacheCompression is disabled + cacheCompression: false, + compact: isEnvProduction, + }, + }, + // Process application JS with Babel but without `.storybook` folder. + // The preset includes JSX, Flow, TypeScript, and some ESnext features. + { + test: /\.(js|mjs|jsx|ts|tsx)$/, + exclude: /\.storybook/, + include: [ + paths.appSrc, + backpackModulesRegex, + saddlebagModulesRegex, + ...customModuleRegexes, + ], use: [ // { // loader: require.resolve('thread-loader'), @@ -562,10 +633,6 @@ module.exports = function (webpackEnv) { test: /\.(js|mjs)$/, exclude: /@babel(?:\/|\\{1,2})runtime/, use: [ - // { - // loader: require.resolve('thread-loader'), - // options: jsWorkerPool, - // }, // isEnvDevelopment && { // loader: require.resolve('cache-loader'), // options: { diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 31e38670c..538895fde 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@skyscanner/backpack-react-scripts", - "version": "9.1.0", + "version": "9.1.1", "description": "Backpack configuration and scripts for Create React App.", "repository": { "type": "git", -- GitLab From 07fd1c8019245dfd6f42be1dfc60083e5735d970 Mon Sep 17 00:00:00 2001 From: Ollie Curtis <8831547+olliecurtis@users.noreply.github.com> Date: Mon, 14 Jun 2021 15:19:38 +0100 Subject: [PATCH 06/29] [NO JIRA]: Adding new paths for scoped Backpack packages (#97) --- packages/react-scripts/CHANGELOG.md | 8 ++ packages/react-scripts/README.md | 2 +- .../react-scripts/config/webpack.config.js | 29 ++++--- .../config/webpack.config.ssr.js | 77 +++++++++++-------- packages/react-scripts/package.json | 4 +- .../scripts/utils/createJestConfig.js | 5 +- 6 files changed, 79 insertions(+), 46 deletions(-) diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index aa9c31bfa..726535f3b 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,5 +1,13 @@ # `backpack-react-scripts` Change Log +## 9.1.3 + +- Fixed an issue where webpack paths in SSR were not being utilised. + +## 9.1.2 + +- Updated webpack paths to include the new `@skyscanner/bpk` foundations packages. + ## 9.1.1 - Optimize the usage of `thread-loader` to fix `build:storybook` running failed diff --git a/packages/react-scripts/README.md b/packages/react-scripts/README.md index 0236deb06..477f21c22 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 `<script />` and `<link />` 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 e759455f8..623153ca3 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -117,6 +117,7 @@ const hasJsxRuntime = (() => { // 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. @@ -482,12 +483,13 @@ module.exports = function (webpackEnv) { paths.appSrc, backpackModulesRegex, saddlebagModulesRegex, + scopedBackpackModulesRegex, ...customModuleRegexes, ], loader: require.resolve('babel-loader'), options: { customize: require.resolve( - 'babel-preset-react-app/webpack-overrides', + 'babel-preset-react-app/webpack-overrides' ), presets: [ [ @@ -514,7 +516,7 @@ module.exports = function (webpackEnv) { 'babel-preset-react-app', 'react-dev-utils', 'react-scripts', - ], + ] ), // @remove-on-eject-end plugins: [ @@ -551,6 +553,7 @@ module.exports = function (webpackEnv) { paths.appSrc, backpackModulesRegex, saddlebagModulesRegex, + scopedBackpackModulesRegex, ...customModuleRegexes, ], use: [ @@ -568,7 +571,7 @@ module.exports = function (webpackEnv) { loader: require.resolve('babel-loader'), options: { customize: require.resolve( - 'babel-preset-react-app/webpack-overrides', + 'babel-preset-react-app/webpack-overrides' ), presets: [ [ @@ -595,7 +598,7 @@ module.exports = function (webpackEnv) { 'babel-preset-react-app', 'react-dev-utils', 'react-scripts', - ], + ] ), // @remove-on-eject-end plugins: [ @@ -662,7 +665,7 @@ module.exports = function (webpackEnv) { 'babel-preset-react-app', 'react-dev-utils', 'react-scripts', - ], + ] ), // @remove-on-eject-end // Babel sourcemaps are needed for debugging into node_modules @@ -684,7 +687,7 @@ module.exports = function (webpackEnv) { { test: { and: [cssRegex, () => !cssModulesEnabled], - exclude: [backpackModulesRegex], + exclude: [backpackModulesRegex, scopedBackpackModulesRegex], }, exclude: cssModuleRegex, use: getStyleLoaders({ @@ -708,7 +711,11 @@ module.exports = function (webpackEnv) { and: [cssRegex, () => cssModulesEnabled], }, { - and: [cssRegex, backpackModulesRegex], + and: [ + cssRegex, + backpackModulesRegex, + scopedBackpackModulesRegex, + ], }, ], use: getStyleLoaders({ @@ -727,7 +734,7 @@ module.exports = function (webpackEnv) { { test: { and: [sassRegex, () => !cssModulesEnabled], - exclude: [backpackModulesRegex], + exclude: [backpackModulesRegex, scopedBackpackModulesRegex], }, exclude: sassModuleRegex, use: getStyleLoaders( @@ -757,7 +764,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 5c67a6ca6..0704bf15d 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -113,6 +113,7 @@ const hasJsxRuntime = (() => { // 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. @@ -484,6 +485,7 @@ module.exports = function (webpackEnv) { paths.appSrc, backpackModulesRegex, saddlebagModulesRegex, + scopedBackpackModulesRegex, ...customModuleRegexes, ], loader: require.resolve('babel-loader'), @@ -532,9 +534,9 @@ module.exports = function (webpackEnv) { }, ], isEnvDevelopment && - shouldUseReactRefresh && - require.resolve('react-refresh/babel'), - ].filter(Boolean), + shouldUseReactRefresh && + require.resolve('react-refresh/babel'), + ].filter(Boolean), // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. @@ -553,6 +555,7 @@ module.exports = function (webpackEnv) { paths.appSrc, backpackModulesRegex, saddlebagModulesRegex, + scopedBackpackModulesRegex, ...customModuleRegexes, ], use: [ @@ -613,9 +616,9 @@ module.exports = function (webpackEnv) { }, ], isEnvDevelopment && - shouldUseReactRefresh && - require.resolve('react-refresh/babel'), - ].filter(Boolean), + shouldUseReactRefresh && + require.resolve('react-refresh/babel'), + ].filter(Boolean), // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. @@ -686,7 +689,7 @@ module.exports = function (webpackEnv) { { test: { and: [cssRegex, () => !cssModulesEnabled], - exclude: [backpackModulesRegex], + exclude: [backpackModulesRegex, scopedBackpackModulesRegex], }, exclude: cssModuleRegex, use: getStyleLoaders({ @@ -710,12 +713,16 @@ module.exports = function (webpackEnv) { and: [cssRegex, () => cssModulesEnabled], }, { - and: [cssRegex, backpackModulesRegex], + and: [ + cssRegex, + backpackModulesRegex, + scopedBackpackModulesRegex, + ], }, ], use: getStyleLoaders({ importLoaders: 1, - sourceMap: isEnvProduction + sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, modules: { @@ -729,15 +736,15 @@ module.exports = function (webpackEnv) { { test: { and: [sassRegex, () => !cssModulesEnabled], - exclude: [backpackModulesRegex], + exclude: [backpackModulesRegex, scopedBackpackModulesRegex], }, exclude: sassModuleRegex, use: getStyleLoaders( { importLoaders: 3, - sourceMap: isEnvProduction - ? shouldUseSourceMap - : isEnvDevelopment, + sourceMap: isEnvProduction + ? shouldUseSourceMap + : isEnvDevelopment, }, 'sass-loader', { @@ -759,7 +766,11 @@ module.exports = function (webpackEnv) { and: [sassRegex, () => cssModulesEnabled], }, { - and: [sassRegex, backpackModulesRegex], + and: [ + sassRegex, + backpackModulesRegex, + scopedBackpackModulesRegex, + ], }, ], use: getStyleLoaders( @@ -870,7 +881,7 @@ module.exports = function (webpackEnv) { new webpack.DefinePlugin(env.stringified), // This is necessary to emit hot updates (CSS and Fast Refresh): isEnvDevelopment && new webpack.HotModuleReplacementPlugin(), - // Experimental hot reloading for React . + // Experimental hot reloading for React . // https://github.com/facebook/react/tree/master/packages/react-refresh isEnvDevelopment && shouldUseReactRefresh && @@ -982,24 +993,24 @@ module.exports = function (webpackEnv) { // The formatter is invoked directly in WebpackDevServerUtils during development formatter: isEnvProduction ? typescriptFormatter : undefined, }), - // new ESLintPlugin({ - // // Plugin options - // extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'], - // formatter: require.resolve('react-dev-utils/eslintFormatter'), - // eslintPath: require.resolve('eslint'), - // context: paths.appSrc, - // // ESLint class options - // cwd: paths.appPath, - // resolvePluginsRelativeTo: __dirname, - // baseConfig: { - // extends: [require.resolve('eslint-config-react-app/base')], - // rules: { - // ...(!hasJsxRuntime && { - // 'react/react-in-jsx-scope': 'error', - // }), - // }, - // }, - // }), + // new ESLintPlugin({ + // // Plugin options + // extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'], + // formatter: require.resolve('react-dev-utils/eslintFormatter'), + // eslintPath: require.resolve('eslint'), + // context: paths.appSrc, + // // ESLint class options + // cwd: paths.appPath, + // resolvePluginsRelativeTo: __dirname, + // baseConfig: { + // extends: [require.resolve('eslint-config-react-app/base')], + // rules: { + // ...(!hasJsxRuntime && { + // 'react/react-in-jsx-scope': 'error', + // }), + // }, + // }, + // }), ].filter(Boolean), // Some libraries import Node modules but don't use them in the browser. // Tell webpack to provide empty mocks for them so importing them works. diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 538895fde..5a9ca453a 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@skyscanner/backpack-react-scripts", - "version": "9.1.1", + "version": "9.1.3", "description": "Backpack configuration and scripts for Create React App.", "repository": { "type": "git", @@ -36,7 +36,7 @@ "babel-plugin-named-asset-import": "^0.3.7", "babel-preset-react-app": "^10.0.0", "bfj": "^7.0.2", - "bpk-mixins": "^20.1.7", + "bpk-mixins": "^21.0.0", "cache-loader": "^4.1.0", "camelcase": "^6.1.0", "case-sensitive-paths-webpack-plugin": "2.3.0", diff --git a/packages/react-scripts/scripts/utils/createJestConfig.js b/packages/react-scripts/scripts/utils/createJestConfig.js index f20d314c9..6f554265b 100644 --- a/packages/react-scripts/scripts/utils/createJestConfig.js +++ b/packages/react-scripts/scripts/utils/createJestConfig.js @@ -17,6 +17,7 @@ const bpkReactScriptsConfig = pkgJson['backpack-react-scripts'] || {}; const includePrefixes = bpkReactScriptsConfig.babelIncludePrefixes || []; includePrefixes.unshift('bpk-'); +includePrefixes.unshift('@skyscanner/bpk-'); includePrefixes.unshift('saddlebag-'); const transformIgnorePattern = `[/\\\\]node_modules[/\\\\](?!${includePrefixes.join( @@ -52,7 +53,9 @@ module.exports = (resolve, rootDir, isEjecting) => { testEnvironment: 'jsdom', testRunner: require.resolve('jest-circus/runner'), transform: { - '^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': resolve('config/jest/babelTransform.js'), + '^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': resolve( + 'config/jest/babelTransform.js' + ), // '^.+\\.css$': resolve('config/jest/cssTransform.js'), // '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': resolve( '^(?!.*\\.(js|jsx|ts|tsx|json)$)': resolve( -- GitLab From 042cb434372b96fa819276a0989a0043454e24ab Mon Sep 17 00:00:00 2001 From: Oliver Curtis <8831547+olliecurtis@users.noreply.github.com> Date: Tue, 29 Jun 2021 17:29:02 +0100 Subject: [PATCH 07/29] [NO JIRA]: Add ignoreCssWarnings option --- packages/react-scripts/CHANGELOG.md | 4 ++++ packages/react-scripts/README.md | 1 + packages/react-scripts/config/webpack.config.js | 2 ++ packages/react-scripts/config/webpack.config.ssr.js | 2 ++ packages/react-scripts/package.json | 2 +- 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 726535f3b..22f0430df 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,5 +1,9 @@ # `backpack-react-scripts` Change Log +## 9.2.0 + +- 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 + ## 9.1.3 - Fixed an issue where webpack paths in SSR were not being utilised. diff --git a/packages/react-scripts/README.md b/packages/react-scripts/README.md index 477f21c22..4f4e65630 100644 --- a/packages/react-scripts/README.md +++ b/packages/react-scripts/README.md @@ -32,3 +32,4 @@ 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 diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 623153ca3..2ab863ab5 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -66,6 +66,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'; @@ -910,6 +911,7 @@ module.exports = function (webpackEnv) { // both options are optional filename: 'static/css/[name].[contenthash:8].css', chunkFilename: 'static/css/[name].[contenthash:8].chunk.css', + ignoreOrder: supressCssWarnings, }), // Generate an asset manifest file with the following content: // - "files" key: Mapping of all asset filenames to their corresponding diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index 0704bf15d..dae49c11c 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -66,6 +66,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'; @@ -913,6 +914,7 @@ module.exports = function (webpackEnv) { // filename: 'static/css/[name].[contenthash:8].css', filename: 'ssr.css', // chunkFilename: 'static/css/[name].[contenthash:8].chunk.css', + // ignoreOrder: supressCssWarnings, }), // Generate an asset manifest file with the following content: // - "files" key: Mapping of all asset filenames to their corresponding diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 5a9ca453a..a1948a11f 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@skyscanner/backpack-react-scripts", - "version": "9.1.3", + "version": "9.2.0", "description": "Backpack configuration and scripts for Create React App.", "repository": { "type": "git", -- GitLab From efda24916006cb48f98526f64d08ea56e1d154bf Mon Sep 17 00:00:00 2001 From: Jayson Wu <jaysonwu@skyscanner.net> Date: Mon, 19 Jul 2021 19:43:13 +0800 Subject: [PATCH 08/29] [LEOP-55]: Apply cache-loader on CI (#99) * apply cache-loader on ci * fix spell of cache-loader * only using SHOULD_USE_CACHE_LOADER to control and restore formation * restore webpack config formation Co-authored-by: Jayson Wu <jayson.wu@skyscanner.net> --- packages/react-scripts/CHANGELOG.md | 6 + packages/react-scripts/config/paths.js | 6 +- .../react-scripts/config/webpack.config.js | 136 +++++++++--------- .../config/webpack.config.ssr.js | 134 +++++++++-------- packages/react-scripts/package.json | 2 +- 5 files changed, 143 insertions(+), 141 deletions(-) diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 22f0430df..87308d378 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,5 +1,11 @@ # `backpack-react-scripts` Change Log +## 9.3.0 + +- Apply `cache-loader` on CI + - Put `cache-loader` before `sass-loader` since `sass-loader` is the most expensive + - Add `SHOULD_USE_CACHE_LOADER` to control if use `cache-loader` or not since not all the web projects at Skyscanner have applied the cache strategy + ## 9.2.0 - 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 diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index 41f1bdbf0..577b5cc85 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -106,7 +106,8 @@ module.exports = { ownNodeModules: resolveOwn('node_modules'), // This is empty on npm 3 appTypeDeclarations: resolveApp('src/react-app-env.d.ts'), ownTypeDeclarations: resolveOwn('lib/react-app.d.ts'), - cacheLoaderDir: resolveOwn('.cache/cache-loader'), + // Make all the caches (Babel-loader, Cache-loader & Terser-webpack-plugin) in one single folder + cacheLoaderDir: resolveApp('./node_modules/.cache/cache-loader'), }; const ownPackageJson = require('../package.json'); @@ -144,7 +145,8 @@ if ( ownNodeModules: resolveOwn('node_modules'), appTypeDeclarations: resolveOwn(`${templatePath}/src/react-app-env.d.ts`), ownTypeDeclarations: resolveOwn('lib/react-app.d.ts'), - cacheLoaderDir: resolveOwn('.cache/cache-loader'), + // Make all the caches (Babel-loader, Cache-loader & Terser-webpack-plugin) in one single folder + cacheLoaderDir: resolveApp('./node_modules/.cache/cache-loader'), }; } // @remove-on-eject-end diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 2ab863ab5..f4f85b6c0 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -139,6 +139,10 @@ module.exports = function (webpackEnv) { const shouldUseReactRefresh = env.raw.FAST_REFRESH; + // SHOULD_USE_CACHE_LOADER - this environment variable is not from Create React App side, it shouldn't be added to `env.js` file to get its value, and it should be deleted when cache strategy is ready for all the web teams at Skyscanner + // Warning: cache-loader won't be needed when webpack 5 is there + const shouldUseCacheLoader = process.env.SHOULD_USE_CACHE_LOADER; + // common function to get style loaders const getStyleLoaders = ( cssOptions, @@ -155,12 +159,6 @@ module.exports = function (webpackEnv) { ? { publicPath: '../../' } : {}, }, - isEnvDevelopment && { - loader: require.resolve('cache-loader'), - options: { - cacheDirectory: paths.cacheLoaderDir, - }, - }, { loader: require.resolve('css-loader'), options: cssOptions, @@ -193,22 +191,32 @@ module.exports = function (webpackEnv) { ].filter(Boolean); if (preProcessor) { loaders.push( - { - loader: require.resolve('resolve-url-loader'), - options: { - sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, - root: paths.appSrc, + ...[ + { + loader: require.resolve('resolve-url-loader'), + options: { + sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, + root: paths.appSrc, + }, }, - }, - { - loader: require.resolve(preProcessor), - options: { - ...preProcessorOptions, - ...{ - sourceMap: true, + // Because sass-loader is the most expensive, so put cache-loader here to only cache sass-loader + // Note that there is an overhead for saving the reading and saving the cache file, so only use this loader to cache expensive loaders. + shouldUseCacheLoader && { + loader: require.resolve('cache-loader'), + options: { + cacheDirectory: paths.cacheLoaderDir, }, }, - } + { + loader: require.resolve(preProcessor), + options: { + ...preProcessorOptions, + ...{ + sourceMap: true, + }, + }, + }, + ].filter(Boolean), ); } return loaders; @@ -562,12 +570,6 @@ module.exports = function (webpackEnv) { loader: require.resolve('thread-loader'), options: jsWorkerPool, }, - isEnvDevelopment && { - loader: require.resolve('cache-loader'), - options: { - cacheDirectory: paths.cacheLoaderDir, - }, - }, { loader: require.resolve('babel-loader'), options: { @@ -634,49 +636,39 @@ module.exports = function (webpackEnv) { { test: /\.(js|mjs)$/, exclude: /@babel(?:\/|\\{1,2})runtime/, - use: [ - isEnvDevelopment && { - loader: require.resolve('cache-loader'), - options: { - cacheDirectory: paths.cacheLoaderDir, - }, - }, - { - loader: require.resolve('babel-loader'), - options: { - babelrc: false, - configFile: false, - compact: false, - presets: [ - [ - require.resolve('babel-preset-react-app/dependencies'), - { helpers: true }, - ], - ], - cacheDirectory: true, - // See #6846 for context on why cacheCompression is disabled - cacheCompression: false, - // @remove-on-eject-begin - cacheIdentifier: getCacheIdentifier( - isEnvProduction - ? 'production' - : isEnvDevelopment && 'development', - [ - 'babel-plugin-named-asset-import', - 'babel-preset-react-app', - 'react-dev-utils', - 'react-scripts', - ] - ), - // @remove-on-eject-end - // Babel sourcemaps are needed for debugging into node_modules - // code. Without the options below, debuggers like VSCode - // show incorrect code and set breakpoints on the wrong lines. - sourceMaps: shouldUseSourceMap, - inputSourceMap: shouldUseSourceMap, - }, - }, - ].filter(Boolean), + loader: require.resolve('babel-loader'), + options: { + babelrc: false, + configFile: false, + compact: false, + presets: [ + [ + require.resolve('babel-preset-react-app/dependencies'), + { helpers: true }, + ], + ], + cacheDirectory: true, + // See #6846 for context on why cacheCompression is disabled + cacheCompression: false, + // @remove-on-eject-begin + cacheIdentifier: getCacheIdentifier( + isEnvProduction + ? 'production' + : isEnvDevelopment && 'development', + [ + 'babel-plugin-named-asset-import', + 'babel-preset-react-app', + 'react-dev-utils', + 'react-scripts', + ] + ), + // @remove-on-eject-end + // Babel sourcemaps are needed for debugging into node_modules + // code. Without the options below, debuggers like VSCode + // show incorrect code and set breakpoints on the wrong lines. + sourceMaps: shouldUseSourceMap, + inputSourceMap: shouldUseSourceMap, + }, }, // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. @@ -740,7 +732,9 @@ module.exports = function (webpackEnv) { exclude: sassModuleRegex, use: getStyleLoaders( { - importLoaders: 3, + // When using sass-loader, the total count of loaders is up to 4 including cache-loader below the css-loader + // When not using sass-loader, the total count of loaders is 3 not including cache-loader below the css-loader + importLoaders: shouldUseCacheLoader ? 4 : 3, sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, @@ -774,7 +768,9 @@ module.exports = function (webpackEnv) { ], use: getStyleLoaders( { - importLoaders: 3, + // When using sass-loader, the total count of loaders is up to 4 including cache-loader below the css-loader + // When not using sass-loader, the total count of loaders is 3 not including cache-loader below the css-loader + importLoaders: shouldUseCacheLoader ? 4 : 3, sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index dae49c11c..c503a0eee 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -135,6 +135,10 @@ module.exports = function (webpackEnv) { const shouldUseReactRefresh = env.raw.FAST_REFRESH; + // SHOULD_USE_CACHE_LOADER - this environment variable is not from Create React App side, it shouldn't be added to `env.js` file to get its value, and it should be deleted when cache strategy is ready for all the web teams at Skyscanner + // Warning: cache-loader won't be needed when webpack 5 is there + // const shouldUseCacheLoader = process.env.SHOULD_USE_CACHE_LOADER; + // common function to get style loaders const getStyleLoaders = ( cssOptions, @@ -151,12 +155,6 @@ module.exports = function (webpackEnv) { ? { publicPath: '../../' } : {}, }, - // isEnvDevelopment && { - // loader: require.resolve('cache-loader'), - // options: { - // cacheDirectory: paths.cacheLoaderDir, - // }, - // }, { loader: require.resolve('css-loader'), options: cssOptions, @@ -189,22 +187,32 @@ module.exports = function (webpackEnv) { ].filter(Boolean); if (preProcessor) { loaders.push( - { - loader: require.resolve('resolve-url-loader'), - options: { - sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, - root: paths.appSrc, + ...[ + { + loader: require.resolve('resolve-url-loader'), + options: { + sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, + root: paths.appSrc, + }, }, - }, - { - loader: require.resolve(preProcessor), - options: { - ...preProcessorOptions, - ...{ - sourceMap: true, + // Because sass-loader is the most expensive, so put cache-loader here to only cache sass-loader + // Note that there is an overhead for saving the reading and saving the cache file, so only use this loader to cache expensive loaders. + // shouldUseCacheLoader && { + // loader: require.resolve('cache-loader'), + // options: { + // cacheDirectory: paths.cacheLoaderDir, + // }, + // }, + { + loader: require.resolve(preProcessor), + options: { + ...preProcessorOptions, + ...{ + sourceMap: true, + }, }, }, - } + ].filter(Boolean), ); } return loaders; @@ -564,12 +572,6 @@ module.exports = function (webpackEnv) { // loader: require.resolve('thread-loader'), // options: jsWorkerPool, // }, - // isEnvDevelopment && { - // loader: require.resolve('cache-loader'), - // options: { - // cacheDirectory: paths.cacheLoaderDir, - // }, - // }, { loader: require.resolve('babel-loader'), options: { @@ -636,49 +638,39 @@ module.exports = function (webpackEnv) { { test: /\.(js|mjs)$/, exclude: /@babel(?:\/|\\{1,2})runtime/, - use: [ - // isEnvDevelopment && { - // loader: require.resolve('cache-loader'), - // options: { - // cacheDirectory: paths.cacheLoaderDir, - // }, - // }, - { - loader: require.resolve('babel-loader'), - options: { - babelrc: false, - configFile: false, - compact: false, - presets: [ - [ - require.resolve('babel-preset-react-app/dependencies'), - { helpers: true }, - ], - ], - cacheDirectory: true, - // See #6846 for context on why cacheCompression is disabled - cacheCompression: false, - // @remove-on-eject-begin - cacheIdentifier: getCacheIdentifier( - isEnvProduction - ? 'production' - : isEnvDevelopment && 'development', - [ - 'babel-plugin-named-asset-import', - 'babel-preset-react-app', - 'react-dev-utils', - 'react-scripts', - ] - ), - // @remove-on-eject-end - // Babel sourcemaps are needed for debugging into node_modules - // code. Without the options below, debuggers like VSCode - // show incorrect code and set breakpoints on the wrong lines. - sourceMaps: shouldUseSourceMap, - inputSourceMap: shouldUseSourceMap, - }, - }, - ].filter(Boolean), + loader: require.resolve('babel-loader'), + options: { + babelrc: false, + configFile: false, + compact: false, + presets: [ + [ + require.resolve('babel-preset-react-app/dependencies'), + { helpers: true }, + ], + ], + cacheDirectory: true, + // See #6846 for context on why cacheCompression is disabled + cacheCompression: false, + // @remove-on-eject-begin + cacheIdentifier: getCacheIdentifier( + isEnvProduction + ? 'production' + : isEnvDevelopment && 'development', + [ + 'babel-plugin-named-asset-import', + 'babel-preset-react-app', + 'react-dev-utils', + 'react-scripts', + ] + ), + // @remove-on-eject-end + // Babel sourcemaps are needed for debugging into node_modules + // code. Without the options below, debuggers like VSCode + // show incorrect code and set breakpoints on the wrong lines. + sourceMaps: shouldUseSourceMap, + inputSourceMap: shouldUseSourceMap, + }, }, // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. @@ -742,6 +734,9 @@ module.exports = function (webpackEnv) { exclude: sassModuleRegex, use: getStyleLoaders( { + // When using sass-loader, the total count of loaders is up to 4 including cache-loader below the css-loader + // When not using sass-loader, the total count of loaders is 3 not including cache-loader below the css-loader + // importLoaders: shouldUseCacheLoader ? 4 : 3, importLoaders: 3, sourceMap: isEnvProduction ? shouldUseSourceMap @@ -776,6 +771,9 @@ module.exports = function (webpackEnv) { ], use: getStyleLoaders( { + // When using sass-loader, the total count of loaders is up to 4 including cache-loader below the css-loader + // When not using sass-loader, the total count of loaders is 3 not including cache-loader below the css-loader + // importLoaders: shouldUseCacheLoader ? 4 : 3, importLoaders: 3, sourceMap: isEnvProduction ? shouldUseSourceMap diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index a1948a11f..b2371e0fc 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@skyscanner/backpack-react-scripts", - "version": "9.2.0", + "version": "9.3.0", "description": "Backpack configuration and scripts for Create React App.", "repository": { "type": "git", -- GitLab From 2ce55dea85dd04751077ac74ec13696f7cbd7c3a Mon Sep 17 00:00:00 2001 From: Jayson Wu <jaysonwu@skyscanner.net> Date: Tue, 31 Aug 2021 17:09:08 +0800 Subject: [PATCH 09/29] [LEOP-166]: Move cache-loader above resolve-url-loader to get the best performance (#102) * Move cache-loader above resolve-url-loader to get the best performance Co-authored-by: Jayson Wu <jayson.wu@skyscanner.net> --- packages/react-scripts/CHANGELOG.md | 6 +++++ .../react-scripts/config/webpack.config.js | 22 +++++++++---------- .../config/webpack.config.ssr.js | 22 +++++++++---------- packages/react-scripts/package.json | 2 +- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 87308d378..719aa6124 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,5 +1,11 @@ # `backpack-react-scripts` Change Log +## 9.3.1 + +- Move `cache-loader` above `resolve-url-loader` to get the best performance + - Note that there is an overhead for saving the reading and saving the cache file, so only use this loader to cache expensive loaders. It is said that `cache-loader` shouldn't deal with all the loaders and only the expensive parts. + - Moving `cache-loader` above resolve-url-loader is because cache files it generates after this operation are small and it is faster to read the cache files, and it saves more time than `cache-loader` below resolve-url-loader, we can still speed up the process of compiling sass to css since sass-loader is the most expensive + ## 9.3.0 - Apply `cache-loader` on CI diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index f4f85b6c0..bae2d8c85 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -192,6 +192,12 @@ module.exports = function (webpackEnv) { if (preProcessor) { loaders.push( ...[ + shouldUseCacheLoader && { + loader: require.resolve('cache-loader'), + options: { + cacheDirectory: paths.cacheLoaderDir, + }, + }, { loader: require.resolve('resolve-url-loader'), options: { @@ -199,14 +205,6 @@ module.exports = function (webpackEnv) { root: paths.appSrc, }, }, - // Because sass-loader is the most expensive, so put cache-loader here to only cache sass-loader - // Note that there is an overhead for saving the reading and saving the cache file, so only use this loader to cache expensive loaders. - shouldUseCacheLoader && { - loader: require.resolve('cache-loader'), - options: { - cacheDirectory: paths.cacheLoaderDir, - }, - }, { loader: require.resolve(preProcessor), options: { @@ -732,8 +730,8 @@ module.exports = function (webpackEnv) { exclude: sassModuleRegex, use: getStyleLoaders( { - // When using sass-loader, the total count of loaders is up to 4 including cache-loader below the css-loader - // When not using sass-loader, the total count of loaders is 3 not including cache-loader below the css-loader + // When using cache-loader, the total count of loaders is up to 4 including cache-loader below the css-loader + // When not using cache-loader, the total count of loaders is 3 not including cache-loader below the css-loader importLoaders: shouldUseCacheLoader ? 4 : 3, sourceMap: isEnvProduction ? shouldUseSourceMap @@ -768,8 +766,8 @@ module.exports = function (webpackEnv) { ], use: getStyleLoaders( { - // When using sass-loader, the total count of loaders is up to 4 including cache-loader below the css-loader - // When not using sass-loader, the total count of loaders is 3 not including cache-loader below the css-loader + // When using cache-loader, the total count of loaders is up to 4 including cache-loader below the css-loader + // When not using cache-loader, the total count of loaders is 3 not including cache-loader below the css-loader importLoaders: shouldUseCacheLoader ? 4 : 3, sourceMap: isEnvProduction ? shouldUseSourceMap diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index c503a0eee..ca12d52e1 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -188,6 +188,12 @@ module.exports = function (webpackEnv) { if (preProcessor) { loaders.push( ...[ + // shouldUseCacheLoader && { + // loader: require.resolve('cache-loader'), + // options: { + // cacheDirectory: paths.cacheLoaderDir, + // }, + // }, { loader: require.resolve('resolve-url-loader'), options: { @@ -195,14 +201,6 @@ module.exports = function (webpackEnv) { root: paths.appSrc, }, }, - // Because sass-loader is the most expensive, so put cache-loader here to only cache sass-loader - // Note that there is an overhead for saving the reading and saving the cache file, so only use this loader to cache expensive loaders. - // shouldUseCacheLoader && { - // loader: require.resolve('cache-loader'), - // options: { - // cacheDirectory: paths.cacheLoaderDir, - // }, - // }, { loader: require.resolve(preProcessor), options: { @@ -734,8 +732,8 @@ module.exports = function (webpackEnv) { exclude: sassModuleRegex, use: getStyleLoaders( { - // When using sass-loader, the total count of loaders is up to 4 including cache-loader below the css-loader - // When not using sass-loader, the total count of loaders is 3 not including cache-loader below the css-loader + // When using cache-loader, the total count of loaders is up to 4 including cache-loader below the css-loader + // When not using cache-loader, the total count of loaders is 3 not including cache-loader below the css-loader // importLoaders: shouldUseCacheLoader ? 4 : 3, importLoaders: 3, sourceMap: isEnvProduction @@ -771,8 +769,8 @@ module.exports = function (webpackEnv) { ], use: getStyleLoaders( { - // When using sass-loader, the total count of loaders is up to 4 including cache-loader below the css-loader - // When not using sass-loader, the total count of loaders is 3 not including cache-loader below the css-loader + // When using cache-loader, the total count of loaders is up to 4 including cache-loader below the css-loader + // When not using cache-loader, the total count of loaders is 3 not including cache-loader below the css-loader // importLoaders: shouldUseCacheLoader ? 4 : 3, importLoaders: 3, sourceMap: isEnvProduction diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index b2371e0fc..c7b6948e0 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@skyscanner/backpack-react-scripts", - "version": "9.3.0", + "version": "9.3.1", "description": "Backpack configuration and scripts for Create React App.", "repository": { "type": "git", -- GitLab From 71e2574e14e84cce8f3e39e89fe9ccdea7c80439 Mon Sep 17 00:00:00 2001 From: Darrel Fox <fox.darrel@googlemail.com> Date: Thu, 23 Sep 2021 16:34:05 +0100 Subject: [PATCH 10/29] [NO JIRA] Ident creation using Project Name (#103) * Add hashes that also factor in project name * added comment * commit runaway formatting Co-authored-by: Darrel Fox <darrel.fox@skyscanner.net> --- packages/react-scripts/CHANGELOG.md | 9 +++++++- .../react-scripts/config/webpack.config.js | 5 ++++- .../config/webpack.config.ssr.js | 5 ++++- packages/react-scripts/package.json | 2 +- .../getCSSModuleLocalIdentWithProjectName.js | 22 +++++++++++++++++++ 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 packages/react-scripts/utils/getCSSModuleLocalIdentWithProjectName.js diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 719aa6124..0193a776c 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,11 +1,18 @@ # `backpack-react-scripts` Change Log +## 9.3.2 + +### Fixed + +- Resolved an issue where generated CSS hashes on class names clashed when using multiple of the same CSS on the page and overriding styles on components. [#103](https://github.com/Skyscanner/backpack-react-scripts/pull/103) + - It solves this by overriding the `getCSSModuleLocalIdent` from `react-dev-utils/getCSSModuleLocalIdent` to provide the project name as part of the hash that is generated at build. [Issue raised](https://github.com/facebook/create-react-app/issues/10190) with upstream CRA for a integrated fix. + ## 9.3.1 - Move `cache-loader` above `resolve-url-loader` to get the best performance - Note that there is an overhead for saving the reading and saving the cache file, so only use this loader to cache expensive loaders. It is said that `cache-loader` shouldn't deal with all the loaders and only the expensive parts. - Moving `cache-loader` above resolve-url-loader is because cache files it generates after this operation are small and it is faster to read the cache files, and it saves more time than `cache-loader` below resolve-url-loader, we can still speed up the process of compiling sass to css since sass-loader is the most expensive - + ## 9.3.0 - Apply `cache-loader` on CI diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index bae2d8c85..f5f742357 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -26,7 +26,6 @@ const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); -const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent'); // const ESLintPlugin = require('eslint-webpack-plugin'); const paths = require('./paths'); const modules = require('./modules'); @@ -55,6 +54,10 @@ const jsWorkerPool = { const appPackageJson = require(paths.appPackageJson); +const getCSSModuleLocalIdent = require('../utils/getCSSModuleLocalIdentWithProjectName')( + appPackageJson.name +); + const sassFunctions = require('bpk-mixins/sass-functions'); const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index ca12d52e1..de87ce32d 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -26,7 +26,6 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); -const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent'); // const ESLintPlugin = require('eslint-webpack-plugin'); const paths = require('./paths'); const modules = require('./modules'); @@ -55,6 +54,10 @@ const postcssNormalize = require('postcss-normalize'); const appPackageJson = require(paths.appPackageJson); +const getCSSModuleLocalIdent = require('../utils/getCSSModuleLocalIdentWithProjectName')( + appPackageJson.name +); + const sassFunctions = require('bpk-mixins/sass-functions'); // const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index c7b6948e0..69eb6e48a 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@skyscanner/backpack-react-scripts", - "version": "9.3.1", + "version": "9.3.2", "description": "Backpack configuration and scripts for Create React App.", "repository": { "type": "git", diff --git a/packages/react-scripts/utils/getCSSModuleLocalIdentWithProjectName.js b/packages/react-scripts/utils/getCSSModuleLocalIdentWithProjectName.js new file mode 100644 index 000000000..d3faef486 --- /dev/null +++ b/packages/react-scripts/utils/getCSSModuleLocalIdentWithProjectName.js @@ -0,0 +1,22 @@ +'use strict'; + +const crypto = require('crypto'); + +const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent'); + +const createHash = buffer => + new Buffer(crypto.createHash('md5').update(buffer).digest('hex')) + .toString('base64') + .substr(0, 5); + +module.exports = projectName => (...args) => { + const localIdent = getCSSModuleLocalIdent(...args); + + // Create an ident based on the file location, class name and Project Name. + // Will be unique across projects + // Format [ file/folder ]_[ localName ]__[ 5 character hash of CRA ident and project name ] + return ( + localIdent.substring(0, localIdent.length - 5) + + createHash(localIdent + projectName) + ); +}; -- GitLab From d1f438f30ba919fca86210604e0b7ab57ed33b50 Mon Sep 17 00:00:00 2001 From: dominicfraser <mrdjfraser@gmail.com> Date: Thu, 21 Oct 2021 12:55:10 +0100 Subject: [PATCH 11/29] Uninstall typescript linting dependencies from react-scripts (#104) * uninstall typescript linting dependencies as we did with eslint and eslint-config-react-app as these come from eslint-config-skyscanner * add changelog entry for typescript eslint removal --- packages/react-scripts/CHANGELOG.md | 5 +++++ packages/react-scripts/package.json | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 0193a776c..62c5f4701 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,5 +1,10 @@ # `backpack-react-scripts` Change Log + +## 9.4.0 + +- Uninstall `@typescript-eslint/eslint-plugin` and `@typescript-eslint/parser`. These must now be provided either by directly installing them in your project or by an upcoming version of `eslint-config-skyscanner`. + ## 9.3.2 ### Fixed diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 69eb6e48a..5cd2e5b87 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@skyscanner/backpack-react-scripts", - "version": "9.3.2", + "version": "9.4.0", "description": "Backpack configuration and scripts for Create React App.", "repository": { "type": "git", @@ -28,8 +28,6 @@ "@babel/core": "7.12.3", "@pmmmwh/react-refresh-webpack-plugin": "0.4.3", "@svgr/webpack": "5.5.0", - "@typescript-eslint/eslint-plugin": "^4.5.0", - "@typescript-eslint/parser": "^4.5.0", "babel-eslint": "^10.1.0", "babel-jest": "^26.6.0", "babel-loader": "8.1.0", -- GitLab From 5848cfaa10fb1823f1cb31d1e1d478dd3ab68929 Mon Sep 17 00:00:00 2001 From: Ollie Curtis <8831547+olliecurtis@users.noreply.github.com> Date: Mon, 10 Jan 2022 11:31:07 +0000 Subject: [PATCH 12/29] Correcting strange @ symbol in docs --- packages/react-scripts/docs/migrating-from-v8-to-v9.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-scripts/docs/migrating-from-v8-to-v9.md b/packages/react-scripts/docs/migrating-from-v8-to-v9.md index 71befeaad..a7eb786d4 100644 --- a/packages/react-scripts/docs/migrating-from-v8-to-v9.md +++ b/packages/react-scripts/docs/migrating-from-v8-to-v9.md @@ -3,7 +3,7 @@ Inside any created `backpack-react-scripts` project that has not been ejected, run: ``` -npm install --save-dev @skyscanner/backpack-react-scripts@ +npm install --save-dev @skyscanner/backpack-react-scripts ``` ## Breaking Changes -- GitLab From 0fce00694af1ac332eb01ca8d831c17e7facccc2 Mon Sep 17 00:00:00 2001 From: SophiaChen <52264893+SophiaChen2021@users.noreply.github.com> Date: Thu, 27 Jan 2022 18:40:03 +0800 Subject: [PATCH 13/29] [NO JIRA]: Set node version to v14.x in workflow (#117) * set node version to v14.x in workflows --- .github/workflows/build-brs.yml | 8 ++-- .github/workflows/build.yml | 7 +++ .github/workflows/lint.yml | 7 +++ tasks/e2e-installs.sh | 75 ++++++++++++++++++--------------- 4 files changed, 59 insertions(+), 38 deletions(-) diff --git a/.github/workflows/build-brs.yml b/.github/workflows/build-brs.yml index b08074b6f..b309ffca1 100644 --- a/.github/workflows/build-brs.yml +++ b/.github/workflows/build-brs.yml @@ -16,17 +16,17 @@ jobs: steps: - uses: actions/checkout@v1 - - name: nvm install - run: nvm install lts/erbium + - name: Use Node.js + uses: actions/setup-node@v2 + with: + node-version: 14.x - name: Run simple run: | - nvm use lts/erbium tasks/e2e-simple.sh - name: Run Installs run: | - nvm use lts/erbium tasks/e2e-installs.sh ## For now we don't need to worry about Kitchensink as this is also failing upstream and the functions is executes are not relevant diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a7f66cab6..bf91682a7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 + + - name: Use Node.js + uses: actions/setup-node@v2 + with: + node-version: 14.x + - name: Install run: yarn --no-progress --non-interactive --no-lockfile + - name: Build run: yarn build diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 7dae7aa40..263e9bbab 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,7 +11,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 + + - name: Use Node.js + uses: actions/setup-node@v2 + with: + node-version: 14.x + - name: Install run: yarn --no-progress --non-interactive --no-lockfile + - name: Alex run: yarn alex diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index b3325087d..efc996a27 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -184,18 +184,21 @@ checkDependencies # yarn build # CI=true yarn test -# ****************************************************************************** -# Test --scripts-version with a tarball url -# ****************************************************************************** +# TODO: Remove this test +# 2022-01-27 Update: This test will always fail because packageName is always `backpack-react-scripts` but not `@skyscanner/backpack-react-scripts`, and this issue comes from `npm` not `backpack-react-scripts`, therefore ignore this test for now, also test https://registry.npmjs.org/@skyscanner/backpack-react-scripts/-/backpack-react-scripts-9.4.0.tgz, it is still broken. +# Detail Here: https://github.com/facebook/create-react-app/blob/main/packages/create-react-app/createReactApp.js#L887-L906 +# # ****************************************************************************** +# # Test --scripts-version with a tarball url +# # ****************************************************************************** -cd "$temp_app_path" -npx create-react-app test-app-tarball-url --scripts-version=https://registry.npmjs.org/@skyscanner/backpack-react-scripts/-/backpack-react-scripts-8.0.1.tgz --template @skyscanner/backpack -cd test-app-tarball-url +# cd "$temp_app_path" +# npx create-react-app test-app-tarball-url --scripts-version=https://registry.npmjs.org/@skyscanner/backpack-react-scripts/-/backpack-react-scripts-8.0.1.tgz --template @skyscanner/backpack +# cd test-app-tarball-url -# Check corresponding scripts version is installed. -exists node_modules/@skyscanner/backpack-react-scripts -grep '"version": "8.0.1"' node_modules/@skyscanner/backpack-react-scripts/package.json -checkDependencies +# # Check corresponding scripts version is installed. +# exists node_modules/@skyscanner/backpack-react-scripts +# grep '"version": "8.0.1"' node_modules/@skyscanner/backpack-react-scripts/package.json +# checkDependencies # ****************************************************************************** # Test --scripts-version with a custom fork of react-scripts @@ -208,32 +211,36 @@ cd test-app-fork # Check corresponding scripts version is installed. exists node_modules/react-scripts-fork -# ****************************************************************************** -# Test project folder is deleted on failing package installation -# ****************************************************************************** +# TODO: Remove this test +# Detail Here: https://github.com/facebook/create-react-app/blob/main/packages/create-react-app/createReactApp.js#L887-L906 +# # ****************************************************************************** +# # Test project folder is deleted on failing package installation +# # ****************************************************************************** -cd "$temp_app_path" -# we will install a non-existing package to simulate a failed installation. -npx create-react-app test-app-should-not-exist --scripts-version=`date +%s` || true -# confirm that the project files were deleted -test ! -e test-app-should-not-exist/package.json -test ! -d test-app-should-not-exist/node_modules - -# ****************************************************************************** -# Test project folder is not deleted when creating app over existing folder -# ****************************************************************************** +# cd "$temp_app_path" +# # we will install a non-existing package to simulate a failed installation. +# npx create-react-app test-app-should-not-exist --scripts-version=`date +%s` || true +# # confirm that the project files were deleted +# test ! -e test-app-should-not-exist/package.json +# test ! -d test-app-should-not-exist/node_modules + +# TODO: Remove this test +# Detail Here: https://github.com/facebook/create-react-app/blob/main/packages/create-react-app/createReactApp.js#L887-L906 +# # ****************************************************************************** +# # Test project folder is not deleted when creating app over existing folder +# # ****************************************************************************** -cd "$temp_app_path" -mkdir test-app-should-remain -echo '## Hello' > ./test-app-should-remain/README.md -# we will install a non-existing package to simulate a failed installation. -npx create-react-app test-app-should-remain --scripts-version=`date +%s` || true -# confirm the file exist -test -e test-app-should-remain/README.md -# confirm only README.md and error log are the only files in the directory -if [ "$(ls -1 ./test-app-should-remain | wc -l | tr -d '[:space:]')" != "2" ]; then - false -fi +# cd "$temp_app_path" +# mkdir test-app-should-remain +# echo '## Hello' > ./test-app-should-remain/README.md +# # we will install a non-existing package to simulate a failed installation. +# npx create-react-app test-app-should-remain --scripts-version=`date +%s` || true +# # confirm the file exist +# test -e test-app-should-remain/README.md +# # confirm only README.md and error log are the only files in the directory +# if [ "$(ls -1 ./test-app-should-remain | wc -l | tr -d '[:space:]')" != "2" ]; then +# false +# fi # ****************************************************************************** # Test --scripts-version with a scoped fork tgz of react-scripts -- GitLab From 47fd7170438ec553c41d37966181985813794a06 Mon Sep 17 00:00:00 2001 From: SophiaChen <52264893+SophiaChen2021@users.noreply.github.com> Date: Fri, 28 Jan 2022 09:53:55 +0800 Subject: [PATCH 14/29] [LEOP-280]Upgrade sass-loader to v10.x (#116) * upgrade sass-loader to v10.x * revert format Co-authored-by: sophia-chen <sophia.chen@skyscanner.net> --- packages/react-scripts/config/webpack.config.js | 8 ++++++-- packages/react-scripts/config/webpack.config.ssr.js | 8 ++++++-- packages/react-scripts/package.json | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index f5f742357..a109ace49 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -742,7 +742,9 @@ module.exports = function (webpackEnv) { }, 'sass-loader', { - functions: sassFunctions, + sassOptions: { + functions: sassFunctions, + }, } ), // Don't consider CSS imports dead code even if the @@ -781,7 +783,9 @@ module.exports = function (webpackEnv) { }, 'sass-loader', { - functions: sassFunctions, + sassOptions: { + functions: sassFunctions, + }, } ), }, diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index de87ce32d..c0662485b 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -745,7 +745,9 @@ module.exports = function (webpackEnv) { }, 'sass-loader', { - functions: sassFunctions, + sassOptions: { + functions: sassFunctions, + }, } ), // Don't consider CSS imports dead code even if the @@ -785,7 +787,9 @@ module.exports = function (webpackEnv) { }, 'sass-loader', { - functions: sassFunctions, + sassOptions: { + functions: sassFunctions, + }, } ), }, diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 5cd2e5b87..a6e838bdf 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -65,7 +65,7 @@ "react-refresh": "^0.8.3", "resolve": "1.18.1", "resolve-url-loader": "^3.1.2", - "sass-loader": "7.3.1", + "sass-loader": "^10.2.1", "semver": "7.3.2", "style-loader": "1.3.0", "terser-webpack-plugin": "4.2.3", -- GitLab From c07c5d7406f90847707ad84d495c6e7783b5b6b0 Mon Sep 17 00:00:00 2001 From: Oliver Curtis <8831547+olliecurtis@users.noreply.github.com> Date: Wed, 9 Feb 2022 09:27:36 +0000 Subject: [PATCH 15/29] Publish version 9.5.1 --- packages/react-scripts/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index a6e838bdf..d01d305c5 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@skyscanner/backpack-react-scripts", - "version": "9.4.0", + "version": "9.5.1", "description": "Backpack configuration and scripts for Create React App.", "repository": { "type": "git", -- GitLab From 991f584d3756bb8cc0116311b3dc3b893d72aa23 Mon Sep 17 00:00:00 2001 From: Ollie Curtis <8831547+olliecurtis@users.noreply.github.com> Date: Wed, 16 Feb 2022 15:28:38 +0000 Subject: [PATCH 16/29] [skip ci] Add missing changelog entries They were not added in the latest PR #116 so adding it now as its missing --- packages/react-scripts/CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 62c5f4701..00b1aaca1 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,6 +1,16 @@ # `backpack-react-scripts` Change Log +## 9.5.1 + +### Changed + +- Upgraded `sass-loader` to `v^10.2.1`. + +## 9.5.0 + +Deprecated version. Do not use. + ## 9.4.0 - Uninstall `@typescript-eslint/eslint-plugin` and `@typescript-eslint/parser`. These must now be provided either by directly installing them in your project or by an upcoming version of `eslint-config-skyscanner`. -- GitLab From 6c1b69dc3ea0947a0d56db77bc7bcf851dbc963b Mon Sep 17 00:00:00 2001 From: SophiaChen <52264893+SophiaChen2021@users.noreply.github.com> Date: Fri, 18 Feb 2022 13:48:03 +0800 Subject: [PATCH 17/29] [LEOP-247]Upgrade node to v16 (#120) BRS support node >=12 --- packages/react-scripts/CHANGELOG.md | 10 ++++++++++ packages/react-scripts/config/webpack.config.js | 2 +- packages/react-scripts/config/webpack.config.ssr.js | 2 +- packages/react-scripts/package.json | 5 ++--- packages/react-scripts/utils/sassFunction.js | 9 +++++++++ 5 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 packages/react-scripts/utils/sassFunction.js diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 00b1aaca1..b07cd88a2 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,5 +1,15 @@ # `backpack-react-scripts` Change Log +## 9.6.0 + +- Node.js support limits to >=12. +- Implement sassFunctions inside backpack-react-scripts. +- Remove the dependency of bpk-mixins. +- Upgrade node-sass to v6 ([node-sass Support Node.js 16](https://github.com/sass/node-sass/releases/tag/v6.0.0)), never rely on the peerDenpendecy of node-sass from bpk-mixins, BRS can upgrade node-sass to whatever version it wants. + +## 9.5.1 + +- Upgrade sass-loader to v10 to support to set threadpoolzise by configuring the UV_THREADPOOL_SIZE env var to improve the compiling performance ## 9.5.1 diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index a109ace49..69bd5617d 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -58,7 +58,7 @@ const getCSSModuleLocalIdent = require('../utils/getCSSModuleLocalIdentWithProje appPackageJson.name ); -const sassFunctions = require('bpk-mixins/sass-functions'); +const sassFunctions = require('../utils/sassFunction'); const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; const customModuleRegexes = bpkReactScriptsConfig.babelIncludePrefixes diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index c0662485b..eb586b8a2 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -58,7 +58,7 @@ const getCSSModuleLocalIdent = require('../utils/getCSSModuleLocalIdentWithProje appPackageJson.name ); -const sassFunctions = require('bpk-mixins/sass-functions'); +const sassFunctions = require('../utils/sassFunction'); // const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; const customModuleRegexes = bpkReactScriptsConfig.babelIncludePrefixes diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index d01d305c5..09a6ce701 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -9,7 +9,7 @@ }, "license": "MIT", "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12.0.0" }, "files": [ "bin", @@ -34,7 +34,6 @@ "babel-plugin-named-asset-import": "^0.3.7", "babel-preset-react-app": "^10.0.0", "bfj": "^7.0.2", - "bpk-mixins": "^21.0.0", "cache-loader": "^4.1.0", "camelcase": "^6.1.0", "case-sensitive-paths-webpack-plugin": "2.3.0", @@ -51,7 +50,7 @@ "jest-watch-typeahead": "0.6.1", "lodash": "^4.17.20", "mini-css-extract-plugin": "0.11.3", - "node-sass": "^4.12.0", + "node-sass": "^6.0.1", "optimize-css-assets-webpack-plugin": "5.0.4", "pnp-webpack-plugin": "1.6.4", "postcss-flexbugs-fixes": "4.2.1", diff --git a/packages/react-scripts/utils/sassFunction.js b/packages/react-scripts/utils/sassFunction.js new file mode 100644 index 000000000..d518638b8 --- /dev/null +++ b/packages/react-scripts/utils/sassFunction.js @@ -0,0 +1,9 @@ +const nodeSass = require('node-sass'); + +module.exports = { + 'encodebase64($string)': str => { + const buffer = Buffer.from(str.getValue()); + + return nodeSass.types.String(buffer.toString('base64')); + }, +}; -- GitLab From bfdd54e7f7007328350ea65d544f954f51fd4299 Mon Sep 17 00:00:00 2001 From: SophiaChen <52264893+SophiaChen2021@users.noreply.github.com> Date: Fri, 18 Feb 2022 14:31:47 +0800 Subject: [PATCH 18/29] Merge change log (#121) Merge and update change log of 9.5.1 --- packages/react-scripts/CHANGELOG.md | 6 +----- packages/react-scripts/package.json | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index b07cd88a2..984d92799 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -9,13 +9,9 @@ ## 9.5.1 -- Upgrade sass-loader to v10 to support to set threadpoolzise by configuring the UV_THREADPOOL_SIZE env var to improve the compiling performance - -## 9.5.1 - ### Changed -- Upgraded `sass-loader` to `v^10.2.1`. +- Upgraded `sass-loader` to `v^10.2.1`, to support developers can set UV_THREADPOOL_SIZE environment variable to improve the performance of compiling Sass to CSS ## 9.5.0 diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 09a6ce701..278a94160 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@skyscanner/backpack-react-scripts", - "version": "9.5.1", + "version": "9.6.0", "description": "Backpack configuration and scripts for Create React App.", "repository": { "type": "git", -- GitLab From 35d776d1c0df20dcb5d95244096c0a5c7e60dd9d Mon Sep 17 00:00:00 2001 From: Tao Fang <85286316+taofang2021@users.noreply.github.com> Date: Fri, 25 Feb 2022 14:28:35 +0800 Subject: [PATCH 19/29] [LEOP-316]Extract babelIncludePrefixes feature (#122) * extract babelIncludePrefixes feature Co-authored-by: tao.fang <tao.fang@skyscanner.net> --- .../react-scripts/backpack-addons/README.md | 5 ++++ .../backpack-addons/babelIncludePrefixes.js | 25 +++++++++++++++++++ .../react-scripts/config/webpack.config.js | 21 ++-------------- .../config/webpack.config.ssr.js | 21 ++-------------- 4 files changed, 34 insertions(+), 38 deletions(-) create mode 100644 packages/react-scripts/backpack-addons/README.md create mode 100644 packages/react-scripts/backpack-addons/babelIncludePrefixes.js diff --git a/packages/react-scripts/backpack-addons/README.md b/packages/react-scripts/backpack-addons/README.md new file mode 100644 index 000000000..a38b4eb2a --- /dev/null +++ b/packages/react-scripts/backpack-addons/README.md @@ -0,0 +1,5 @@ +Our react scripts fork includes a number of custom configuration items in order to support building web products at Skyscanner. The table below will describe what each of the configs do + +| Feature | Description | Default Value | +|:---|:--|:---| +| **babelIncludePrefixes** | Array of module name prefixes to opt into babel compilation. <br> Default includes **@skyscanner/bpk-, bpk- and saddlebag-** packages by default to be compiled | **[@skyscanner/bpk-, bpk- and saddlebag-]** | diff --git a/packages/react-scripts/backpack-addons/babelIncludePrefixes.js b/packages/react-scripts/backpack-addons/babelIncludePrefixes.js new file mode 100644 index 000000000..708b39337 --- /dev/null +++ b/packages/react-scripts/backpack-addons/babelIncludePrefixes.js @@ -0,0 +1,25 @@ +"use strict"; + +const paths = require("../config/paths"); +const appPackageJson = require(paths.appPackageJson); +const bpkReactScriptsConfig = appPackageJson["backpack-react-scripts"] || {}; +const customModuleRegexes = bpkReactScriptsConfig.babelIncludePrefixes + ? bpkReactScriptsConfig.babelIncludePrefixes.map( + (prefix) => new RegExp(`node_modules[\\/]${prefix}`) + ) + : []; + +// Backpack / saddlebag node module regexes +const backpackModulesRegex = /node_modules[\\/]bpk-/; +const saddlebagModulesRegex = /node_modules[\\/]saddlebag-/; +const scopedBackpackModulesRegex = /node_modules[\\/]@skyscanner[\\/]bpk-/; + +module.exports = () => { + return [ + paths.appSrc, + backpackModulesRegex, + saddlebagModulesRegex, + scopedBackpackModulesRegex, + ...customModuleRegexes, + ]; +}; diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 69bd5617d..718c36827 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -61,11 +61,6 @@ const getCSSModuleLocalIdent = require('../utils/getCSSModuleLocalIdentWithProje const sassFunctions = require('../utils/sassFunction'); const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; -const customModuleRegexes = bpkReactScriptsConfig.babelIncludePrefixes - ? bpkReactScriptsConfig.babelIncludePrefixes.map( - prefix => new RegExp(`node_modules[\\/]${prefix}`) - ) - : []; const cssModulesEnabled = bpkReactScriptsConfig.cssModules !== false; const crossOriginLoading = bpkReactScriptsConfig.crossOriginLoading || false; const sriEnabled = bpkReactScriptsConfig.sriEnabled || false; @@ -489,13 +484,7 @@ module.exports = function (webpackEnv) { // The preset includes JSX, Flow, TypeScript, and some ESnext features. { test: /\.(js|mjs|jsx|ts|tsx)$/, - include: [ - paths.appSrc, - backpackModulesRegex, - saddlebagModulesRegex, - scopedBackpackModulesRegex, - ...customModuleRegexes, - ], + include: require('../backpack-addons/babelIncludePrefixes')(), // #backpack-addon babelIncludePrefixes loader: require.resolve('babel-loader'), options: { customize: require.resolve( @@ -559,13 +548,7 @@ module.exports = function (webpackEnv) { { test: /\.(js|mjs|jsx|ts|tsx)$/, exclude: /\.storybook/, - include: [ - paths.appSrc, - backpackModulesRegex, - saddlebagModulesRegex, - scopedBackpackModulesRegex, - ...customModuleRegexes, - ], + include: require('../backpack-addons/babelIncludePrefixes')(), // #backpack-addon babelIncludePrefixes use: [ { loader: require.resolve('thread-loader'), diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index eb586b8a2..45e69096a 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -61,11 +61,6 @@ const getCSSModuleLocalIdent = require('../utils/getCSSModuleLocalIdentWithProje const sassFunctions = require('../utils/sassFunction'); // const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; -const customModuleRegexes = bpkReactScriptsConfig.babelIncludePrefixes - ? bpkReactScriptsConfig.babelIncludePrefixes.map( - prefix => new RegExp(`node_modules[\\/]${prefix}`) - ) - : []; const cssModulesEnabled = bpkReactScriptsConfig.cssModules !== false; // const crossOriginLoading = bpkReactScriptsConfig.crossOriginLoading || false; // const sriEnabled = bpkReactScriptsConfig.sriEnabled || false; @@ -491,13 +486,7 @@ module.exports = function (webpackEnv) { // The preset includes JSX, Flow, TypeScript, and some ESnext features. { test: /\.(js|mjs|jsx|ts|tsx)$/, - include: [ - paths.appSrc, - backpackModulesRegex, - saddlebagModulesRegex, - scopedBackpackModulesRegex, - ...customModuleRegexes, - ], + include: require('../backpack-addons/babelIncludePrefixes')(), // #backpack-addon babelIncludePrefixes loader: require.resolve('babel-loader'), options: { customize: require.resolve( @@ -561,13 +550,7 @@ module.exports = function (webpackEnv) { { test: /\.(js|mjs|jsx|ts|tsx)$/, exclude: /\.storybook/, - include: [ - paths.appSrc, - backpackModulesRegex, - saddlebagModulesRegex, - scopedBackpackModulesRegex, - ...customModuleRegexes, - ], + include: require('../backpack-addons/babelIncludePrefixes')(), // #backpack-addon babelIncludePrefixes use: [ // { // loader: require.resolve('thread-loader'), -- GitLab From 49ad3038814181aa1940706cb3d248ac41ce4203 Mon Sep 17 00:00:00 2001 From: Tao Fang <85286316+taofang2021@users.noreply.github.com> Date: Fri, 25 Feb 2022 14:57:33 +0800 Subject: [PATCH 20/29] Extract crossOriginLoading and sriEnabled feature (#123) Co-authored-by: tao.fang <tao.fang@skyscanner.net> --- .../react-scripts/backpack-addons/README.md | 2 ++ .../backpack-addons/crossOriginLoading.js | 11 ++++++++++ .../backpack-addons/sriEnabled.js | 21 +++++++++++++++++++ .../react-scripts/config/webpack.config.js | 15 ++----------- 4 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 packages/react-scripts/backpack-addons/crossOriginLoading.js create mode 100644 packages/react-scripts/backpack-addons/sriEnabled.js diff --git a/packages/react-scripts/backpack-addons/README.md b/packages/react-scripts/backpack-addons/README.md index a38b4eb2a..8e3f68ea3 100644 --- a/packages/react-scripts/backpack-addons/README.md +++ b/packages/react-scripts/backpack-addons/README.md @@ -3,3 +3,5 @@ Our react scripts fork includes a number of custom configuration items in order | Feature | Description | Default Value | |:---|:--|:---| | **babelIncludePrefixes** | Array of module name prefixes to opt into babel compilation. <br> Default includes **@skyscanner/bpk-, bpk- and saddlebag-** packages by default to be compiled | **[@skyscanner/bpk-, bpk- and saddlebag-]** | +| **sriEnabled** | Determines if Subresource Intergrity is used during build to add an integrity hash for files. <br> The SRI is a security feature to enable browsers to verify the files they fetch are unmodified. <br> If enabled crossOriginLoading value is overriden with anonymous to allow output to have integrity value <br> See [webpack subresource integrity docs](https://github.com/waysact/webpack-subresource-integrity/blob/master/README.md) | **false** (this is currently the default in the future security may want to make it true by default but pending them still trying things about) | +| **crossOriginLoading** | Option to enable cross origin loading of chunks to modify the default webpack behaviour of being false. <br> Docs: https://webpack.js.org/configuration/output/#outputcrossoriginloading | **false** | diff --git a/packages/react-scripts/backpack-addons/crossOriginLoading.js b/packages/react-scripts/backpack-addons/crossOriginLoading.js new file mode 100644 index 000000000..fc20776cc --- /dev/null +++ b/packages/react-scripts/backpack-addons/crossOriginLoading.js @@ -0,0 +1,11 @@ +'use strict'; + +const paths = require("../config/paths"); +const appPackageJson = require(paths.appPackageJson); +const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; +const crossOriginLoading = bpkReactScriptsConfig.crossOriginLoading || false; +const sriEnabled = bpkReactScriptsConfig.sriEnabled || false; + +module.exports = { + crossOriginLoading: sriEnabled ? 'anonymous' : crossOriginLoading +} diff --git a/packages/react-scripts/backpack-addons/sriEnabled.js b/packages/react-scripts/backpack-addons/sriEnabled.js new file mode 100644 index 000000000..8223350e8 --- /dev/null +++ b/packages/react-scripts/backpack-addons/sriEnabled.js @@ -0,0 +1,21 @@ +"use strict"; + +const SubresourceIntegrityPlugin = require("webpack-subresource-integrity"); +const paths = require("../config/paths"); +const appPackageJson = require(paths.appPackageJson); +const bpkReactScriptsConfig = appPackageJson["backpack-react-scripts"] || {}; +const sriEnabled = bpkReactScriptsConfig.sriEnabled || false; + +module.exports = () => { + return ( + // Calculate and inject Subresource Integrity (SRI) hashes + // https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity + // This is a security feature that enables browsers to verify that resources + // they fetch (for example, from a CDN) are delivered without unexpected manipulation. + sriEnabled && + new SubresourceIntegrityPlugin({ + enabled: true, + hashFuncNames: ["sha384"], + }) + ); +}; diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 718c36827..7b17a6f53 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -21,7 +21,6 @@ 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'); -const SubresourceIntegrityPlugin = require('webpack-subresource-integrity'); const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); @@ -62,8 +61,6 @@ const sassFunctions = require('../utils/sassFunction'); const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; 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. @@ -255,7 +252,7 @@ module.exports = function (webpackEnv) { ] : paths.appIndexJs, output: { - crossOriginLoading: sriEnabled ? 'anonymous' : crossOriginLoading, + ...require('../backpack-addons/crossOriginLoading'), // #backpack-addon crossOriginLoading // The build folder. path: isEnvProduction ? paths.appBuild : undefined, // Add /* filename */ comments to generated require()s in the output. @@ -921,15 +918,7 @@ module.exports = function (webpackEnv) { }; }, }), - // Calculate and inject Subresource Integrity (SRI) hashes - // https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity - // This is a security feature that enables browsers to verify that resources - // they fetch (for example, from a CDN) are delivered without unexpected manipulation. - sriEnabled && - new SubresourceIntegrityPlugin({ - enabled: true, - hashFuncNames: ['sha384'], - }), + require('../backpack-addons/sriEnabled')(), // #backpack-addon sriEnabled // Moment.js is an extremely popular library that bundles large locale files // by default due to how webpack interprets its code. This is a practical // solution that requires the user to opt into importing specific locales. -- GitLab From b910bf5bd8cea49842efbf3034b0ba30238673e3 Mon Sep 17 00:00:00 2001 From: Tao Fang <85286316+taofang2021@users.noreply.github.com> Date: Fri, 25 Feb 2022 15:26:57 +0800 Subject: [PATCH 21/29] Extract ignoreCssWarnings feature (#124) Co-authored-by: tao.fang <tao.fang@skyscanner.net> --- packages/react-scripts/backpack-addons/README.md | 1 + .../react-scripts/backpack-addons/ignoreCssWarnings.js | 10 ++++++++++ packages/react-scripts/config/webpack.config.js | 3 +-- 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 packages/react-scripts/backpack-addons/ignoreCssWarnings.js diff --git a/packages/react-scripts/backpack-addons/README.md b/packages/react-scripts/backpack-addons/README.md index 8e3f68ea3..4a92b8d70 100644 --- a/packages/react-scripts/backpack-addons/README.md +++ b/packages/react-scripts/backpack-addons/README.md @@ -5,3 +5,4 @@ Our react scripts fork includes a number of custom configuration items in order | **babelIncludePrefixes** | Array of module name prefixes to opt into babel compilation. <br> Default includes **@skyscanner/bpk-, bpk- and saddlebag-** packages by default to be compiled | **[@skyscanner/bpk-, bpk- and saddlebag-]** | | **sriEnabled** | Determines if Subresource Intergrity is used during build to add an integrity hash for files. <br> The SRI is a security feature to enable browsers to verify the files they fetch are unmodified. <br> If enabled crossOriginLoading value is overriden with anonymous to allow output to have integrity value <br> See [webpack subresource integrity docs](https://github.com/waysact/webpack-subresource-integrity/blob/master/README.md) | **false** (this is currently the default in the future security may want to make it true by default but pending them still trying things about) | | **crossOriginLoading** | Option to enable cross origin loading of chunks to modify the default webpack behaviour of being false. <br> Docs: https://webpack.js.org/configuration/output/#outputcrossoriginloading | **false** | +| **ignoreCssWarnings** | Provides the ablity to supress CSS ordering warnings when its safe and ordering is not of a concern on the output <br> See [mini css extract plugin docs](https://github.com/webpack-contrib/mini-css-extract-plugin#remove-order-warnings) | **false** - by default we should care about order as it can sometimes have an output impact | diff --git a/packages/react-scripts/backpack-addons/ignoreCssWarnings.js b/packages/react-scripts/backpack-addons/ignoreCssWarnings.js new file mode 100644 index 000000000..9421bdce5 --- /dev/null +++ b/packages/react-scripts/backpack-addons/ignoreCssWarnings.js @@ -0,0 +1,10 @@ +'use strict'; + +const paths = require('../config/paths'); +const appPackageJson = require(paths.appPackageJson); +const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; +const ignoreCssWarnings = bpkReactScriptsConfig.ignoreCssWarnings || false; + +module.exports = { + ignoreOrder: ignoreCssWarnings +} diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 7b17a6f53..6f68bfe19 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -61,7 +61,6 @@ const sassFunctions = require('../utils/sassFunction'); const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; const cssModulesEnabled = bpkReactScriptsConfig.cssModules !== 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'; @@ -892,7 +891,7 @@ module.exports = function (webpackEnv) { // both options are optional filename: 'static/css/[name].[contenthash:8].css', chunkFilename: 'static/css/[name].[contenthash:8].chunk.css', - ignoreOrder: supressCssWarnings, + ...require('../backpack-addons/ignoreCssWarnings') // #backpack-addon ignoreCssWarnings }), // Generate an asset manifest file with the following content: // - "files" key: Mapping of all asset filenames to their corresponding -- GitLab From a87c78d9325c154d7f6d2eb220c708274e87cf51 Mon Sep 17 00:00:00 2001 From: Tao Fang <85286316+taofang2021@users.noreply.github.com> Date: Fri, 25 Feb 2022 16:07:30 +0800 Subject: [PATCH 22/29] [LEOP-316]Extract cssModules feature (#126) * Extract cssModules feature Co-authored-by: tao.fang <tao.fang@skyscanner.net> --- .../react-scripts/backpack-addons/README.md | 1 + .../backpack-addons/cssModules.js | 67 +++++++++++++++++++ .../react-scripts/config/webpack.config.js | 47 ++----------- .../config/webpack.config.ssr.js | 48 ++----------- 4 files changed, 81 insertions(+), 82 deletions(-) create mode 100644 packages/react-scripts/backpack-addons/cssModules.js diff --git a/packages/react-scripts/backpack-addons/README.md b/packages/react-scripts/backpack-addons/README.md index 4a92b8d70..668a31ac8 100644 --- a/packages/react-scripts/backpack-addons/README.md +++ b/packages/react-scripts/backpack-addons/README.md @@ -6,3 +6,4 @@ Our react scripts fork includes a number of custom configuration items in order | **sriEnabled** | Determines if Subresource Intergrity is used during build to add an integrity hash for files. <br> The SRI is a security feature to enable browsers to verify the files they fetch are unmodified. <br> If enabled crossOriginLoading value is overriden with anonymous to allow output to have integrity value <br> See [webpack subresource integrity docs](https://github.com/waysact/webpack-subresource-integrity/blob/master/README.md) | **false** (this is currently the default in the future security may want to make it true by default but pending them still trying things about) | | **crossOriginLoading** | Option to enable cross origin loading of chunks to modify the default webpack behaviour of being false. <br> Docs: https://webpack.js.org/configuration/output/#outputcrossoriginloading | **false** | | **ignoreCssWarnings** | Provides the ablity to supress CSS ordering warnings when its safe and ordering is not of a concern on the output <br> See [mini css extract plugin docs](https://github.com/webpack-contrib/mini-css-extract-plugin#remove-order-warnings) | **false** - by default we should care about order as it can sometimes have an output impact | +| **cssModules** | Determines if cssModules are being used. <br> If enabled supports css modules and configures css-loader for use <br> If not enabled supports sass modules in the project and configures sass-loader for use | **true** | diff --git a/packages/react-scripts/backpack-addons/cssModules.js b/packages/react-scripts/backpack-addons/cssModules.js new file mode 100644 index 000000000..2210efe2a --- /dev/null +++ b/packages/react-scripts/backpack-addons/cssModules.js @@ -0,0 +1,67 @@ +"use strict"; + +const postcssNormalize = require("postcss-normalize"); +const paths = require("../config/paths"); +const appPackageJson = require(paths.appPackageJson); +const bpkReactScriptsConfig = appPackageJson["backpack-react-scripts"] || {}; +const cssModulesEnabled = bpkReactScriptsConfig.cssModules !== false; + +// Backpack / saddlebag node module regexes +const backpackModulesRegex = /node_modules[\\/]bpk-/; +const scopedBackpackModulesRegex = /node_modules[\\/]@skyscanner[\\/]bpk-/; + +const getStyleTestRegexes = (regexType) => { + // style files regexes, the regex values should keep up to date with webpack.config.js + const cssRegex = /\.css$/; + const cssModuleRegex = /\.module\.css$/; + const sassRegex = /\.(scss|sass)$/; + const sassModuleRegex = /\.module\.(scss|sass)$/; + + switch (regexType) { + case "css": + return { + and: [cssRegex, () => !cssModulesEnabled], + exclude: [backpackModulesRegex, scopedBackpackModulesRegex], + }; + case "cssModule": + return [ + cssModuleRegex, + { + and: [cssRegex, () => cssModulesEnabled], + }, + { + and: [cssRegex, backpackModulesRegex, scopedBackpackModulesRegex], + }, + ]; + case "sass": + return { + and: [sassRegex, () => !cssModulesEnabled], + exclude: [backpackModulesRegex, scopedBackpackModulesRegex], + }; + case "sassModule": + return [ + sassModuleRegex, + { + and: [sassRegex, () => cssModulesEnabled], + }, + { + and: [sassRegex, backpackModulesRegex, scopedBackpackModulesRegex], + }, + ]; + default: + throw new Error("Not implemented."); + } +}; + +const getCSSModuleLocalIdent = () => { + return ( + require('../utils/getCSSModuleLocalIdentWithProjectName')( + appPackageJson.name + ) + ) +} + +module.exports = { + getStyleTestRegexes, + getCSSModuleLocalIdent +}; diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 6f68bfe19..901a25281 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -53,14 +53,9 @@ const jsWorkerPool = { const appPackageJson = require(paths.appPackageJson); -const getCSSModuleLocalIdent = require('../utils/getCSSModuleLocalIdentWithProjectName')( - appPackageJson.name -); - const sassFunctions = require('../utils/sassFunction'); const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; -const cssModulesEnabled = bpkReactScriptsConfig.cssModules !== false; // Source maps are resource heavy and can cause out of memory issue for large source files. const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; @@ -658,10 +653,7 @@ module.exports = function (webpackEnv) { // of CSS. // By default we support CSS Modules with the extension .module.css { - test: { - and: [cssRegex, () => !cssModulesEnabled], - exclude: [backpackModulesRegex, scopedBackpackModulesRegex], - }, + test: require('../backpack-addons/cssModules').getStyleTestRegexes('css'), // #backpack-addons cssModulesEnabled exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, @@ -678,26 +670,14 @@ module.exports = function (webpackEnv) { // Adds support for CSS Modules (https://github.com/css-modules/css-modules) // using the extension .module.css { - test: [ - cssModuleRegex, - { - and: [cssRegex, () => cssModulesEnabled], - }, - { - and: [ - cssRegex, - backpackModulesRegex, - scopedBackpackModulesRegex, - ], - }, - ], + test: require('../backpack-addons/cssModules').getStyleTestRegexes('cssModule'), // #backpack-addons cssModulesEnabled use: getStyleLoaders({ importLoaders: 1, sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, modules: { - getLocalIdent: getCSSModuleLocalIdent, + getLocalIdent: require('../backpack-addons/cssModules').getCSSModuleLocalIdent(), // #backpack-addons cssModulesEnabled }, }), }, @@ -705,10 +685,7 @@ module.exports = function (webpackEnv) { // By default we support SASS Modules with the // extensions .module.scss or .module.sass { - test: { - and: [sassRegex, () => !cssModulesEnabled], - exclude: [backpackModulesRegex, scopedBackpackModulesRegex], - }, + test: require('../backpack-addons/cssModules').getStyleTestRegexes('sass'), // #backpack-addons cssModulesEnabled exclude: sassModuleRegex, use: getStyleLoaders( { @@ -735,19 +712,7 @@ module.exports = function (webpackEnv) { // Adds support for CSS Modules, but using SASS // using the extension .module.scss or .module.sass { - test: [ - sassModuleRegex, - { - and: [sassRegex, () => cssModulesEnabled], - }, - { - and: [ - sassRegex, - backpackModulesRegex, - scopedBackpackModulesRegex, - ], - }, - ], + test: require('../backpack-addons/cssModules').getStyleTestRegexes('sassModule'), // #backpack-addons cssModulesEnabled use: getStyleLoaders( { // When using cache-loader, the total count of loaders is up to 4 including cache-loader below the css-loader @@ -757,7 +722,7 @@ module.exports = function (webpackEnv) { ? shouldUseSourceMap : isEnvDevelopment, modules: { - getLocalIdent: getCSSModuleLocalIdent, + getLocalIdent: require('../backpack-addons/cssModules').getCSSModuleLocalIdent(), // #backpack-addons cssModulesEnabled }, }, 'sass-loader', diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index 45e69096a..463c2c4d7 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -54,14 +54,10 @@ const postcssNormalize = require('postcss-normalize'); const appPackageJson = require(paths.appPackageJson); -const getCSSModuleLocalIdent = require('../utils/getCSSModuleLocalIdentWithProjectName')( - appPackageJson.name -); - const sassFunctions = require('../utils/sassFunction'); // const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; -const cssModulesEnabled = bpkReactScriptsConfig.cssModules !== false; + // const crossOriginLoading = bpkReactScriptsConfig.crossOriginLoading || false; // const sriEnabled = bpkReactScriptsConfig.sriEnabled || false; // const supressCssWarnings = bpkReactScriptsConfig.ignoreCssWarnings || false; @@ -664,10 +660,7 @@ module.exports = function (webpackEnv) { // of CSS. // By default we support CSS Modules with the extension .module.css { - test: { - and: [cssRegex, () => !cssModulesEnabled], - exclude: [backpackModulesRegex, scopedBackpackModulesRegex], - }, + test: require('../backpack-addons/cssModules').getStyleTestRegexes('css'), // #backpack-addons cssModulesEnabled exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, @@ -684,26 +677,14 @@ module.exports = function (webpackEnv) { // Adds support for CSS Modules (https://github.com/css-modules/css-modules) // using the extension .module.css { - test: [ - cssModuleRegex, - { - and: [cssRegex, () => cssModulesEnabled], - }, - { - and: [ - cssRegex, - backpackModulesRegex, - scopedBackpackModulesRegex, - ], - }, - ], + test: require('../backpack-addons/cssModules').getStyleTestRegexes('cssModule'), // #backpack-addons cssModulesEnabled use: getStyleLoaders({ importLoaders: 1, sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, modules: { - getLocalIdent: getCSSModuleLocalIdent, + getLocalIdent: require('../backpack-addons/cssModules').getCSSModuleLocalIdent(), // #backpack-addons cssModulesEnabled }, }), }, @@ -711,10 +692,7 @@ module.exports = function (webpackEnv) { // By default we support SASS Modules with the // extensions .module.scss or .module.sass { - test: { - and: [sassRegex, () => !cssModulesEnabled], - exclude: [backpackModulesRegex, scopedBackpackModulesRegex], - }, + test: require('../backpack-addons/cssModules').getStyleTestRegexes('sass'), // #backpack-addons cssModulesEnabled exclude: sassModuleRegex, use: getStyleLoaders( { @@ -742,19 +720,7 @@ module.exports = function (webpackEnv) { // Adds support for CSS Modules, but using SASS // using the extension .module.scss or .module.sass { - test: [ - sassModuleRegex, - { - and: [sassRegex, () => cssModulesEnabled], - }, - { - and: [ - sassRegex, - backpackModulesRegex, - scopedBackpackModulesRegex, - ], - }, - ], + test: require('../backpack-addons/cssModules').getStyleTestRegexes('sassModule'), // #backpack-addons cssModulesEnabled use: getStyleLoaders( { // When using cache-loader, the total count of loaders is up to 4 including cache-loader below the css-loader @@ -765,7 +731,7 @@ module.exports = function (webpackEnv) { ? shouldUseSourceMap : isEnvDevelopment, modules: { - getLocalIdent: getCSSModuleLocalIdent, + getLocalIdent: require('../backpack-addons/cssModules').getCSSModuleLocalIdent(), // #backpack-addons cssModulesEnabled }, }, 'sass-loader', -- GitLab From d7ffb765930f73ee1b6aa17ed335adba28e412dd Mon Sep 17 00:00:00 2001 From: salleyliu <86700834+salleyliu@users.noreply.github.com> Date: Tue, 1 Mar 2022 11:41:22 +0800 Subject: [PATCH 23/29] extract amdExludes (#130) --- .../react-scripts/backpack-addons/amdExcludes.js | 16 ++++++++++++++++ packages/react-scripts/config/webpack.config.js | 11 +---------- .../react-scripts/config/webpack.config.ssr.js | 11 +---------- 3 files changed, 18 insertions(+), 20 deletions(-) create mode 100644 packages/react-scripts/backpack-addons/amdExcludes.js diff --git a/packages/react-scripts/backpack-addons/amdExcludes.js b/packages/react-scripts/backpack-addons/amdExcludes.js new file mode 100644 index 000000000..28d1bdc30 --- /dev/null +++ b/packages/react-scripts/backpack-addons/amdExcludes.js @@ -0,0 +1,16 @@ +'use strict'; + +const paths = require('../config/paths'); +const appPackageJson = require(paths.appPackageJson); +const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; + +module.exports = { + test: new RegExp( + `(^|/)(${(bpkReactScriptsConfig.amdExcludes || []) + .concat('lodash') + .join('|')})(/|.|$)` + ), + parser: { + amd: false, + } +}; \ No newline at end of file diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 901a25281..56627ee62 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -450,16 +450,7 @@ module.exports = function (webpackEnv) { name: 'static/media/[name].[hash:8].[ext]', }, }, - { - test: new RegExp( - `(^|/)(${(bpkReactScriptsConfig.amdExcludes || []) - .concat('lodash') - .join('|')})(/|.|$)` - ), - parser: { - amd: false, - }, - }, + require('../backpack-addons/amdExcludes'), // #backpack-addons amdExcludes // "url" loader works like "file" loader except that it embeds assets // smaller than specified limit in bytes as data URLs to avoid requests. // A missing `test` is equivalent to a match. diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index 463c2c4d7..2a1259d3f 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -457,16 +457,7 @@ module.exports = function (webpackEnv) { name: 'static/media/[name].[hash:8].[ext]', }, }, - { - test: new RegExp( - `(^|/)(${(bpkReactScriptsConfig.amdExcludes || []) - .concat('lodash') - .join('|')})(/|.|$)` - ), - parser: { - amd: false, - }, - }, + require('../backpack-addons/amdExcludes'), // #backpack-addons amdExcludes // "url" loader works like "file" loader except that it embeds assets // smaller than specified limit in bytes as data URLs to avoid requests. // A missing `test` is equivalent to a match. -- GitLab From f5b619e21dc0bddc329cbc9083f0841a47c5624e Mon Sep 17 00:00:00 2001 From: salleyliu <86700834+salleyliu@users.noreply.github.com> Date: Tue, 1 Mar 2022 11:59:46 +0800 Subject: [PATCH 24/29] [LEOP-317]Extract splitChunks (#127) * extract splitChunks * update require path * add splitChunk annotation --- .../backpack-addons/splitChunks.js | 27 +++++++++++++++++++ .../react-scripts/config/webpack.config.js | 21 +-------------- 2 files changed, 28 insertions(+), 20 deletions(-) create mode 100644 packages/react-scripts/backpack-addons/splitChunks.js diff --git a/packages/react-scripts/backpack-addons/splitChunks.js b/packages/react-scripts/backpack-addons/splitChunks.js new file mode 100644 index 000000000..40c75f5b1 --- /dev/null +++ b/packages/react-scripts/backpack-addons/splitChunks.js @@ -0,0 +1,27 @@ +'use strict'; + +const paths = require('../config/paths'); +const appPackageJson = require(paths.appPackageJson); +const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; + +module.exports = (isEnvDevelopment) => { + // Automatically split vendor and commons + // https://twitter.com/wSokra/status/969633336732905474 + // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 + return { + splitChunks: bpkReactScriptsConfig.enableAutomaticChunking + ? { + chunks: 'all', + name: isEnvDevelopment, + cacheGroups: bpkReactScriptsConfig.vendorsChunkRegex + ? { + vendors: { + test: new RegExp(bpkReactScriptsConfig.vendorsChunkRegex), + name: 'vendor' + }, + } + : {}, + } + : {} + } +}; \ No newline at end of file diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 56627ee62..fa61ff60b 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -346,26 +346,7 @@ module.exports = function (webpackEnv) { }, }), ], - // Automatically split vendor and commons - // https://twitter.com/wSokra/status/969633336732905474 - // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 - // splitChunks: { - // chunks: 'all', - // name: false, - // }, - splitChunks: bpkReactScriptsConfig.enableAutomaticChunking - ? { - chunks: 'all', - name: isEnvDevelopment, - cacheGroups: bpkReactScriptsConfig.vendorsChunkRegex - ? { - vendors: { - test: new RegExp(bpkReactScriptsConfig.vendorsChunkRegex), - }, - } - : {}, - } - : {}, + ...require('../backpack-addons/splitChunks')(isEnvDevelopment), // #backpack-addons splitChunks // Keep the runtime chunk separated to enable long term caching // https://twitter.com/wSokra/status/969679223278505985 // https://github.com/facebook/create-react-app/issues/5358 -- GitLab From e4a30a740162f2c82a7150f21368d5723d5f9a52 Mon Sep 17 00:00:00 2001 From: salleyliu <86700834+salleyliu@users.noreply.github.com> Date: Tue, 1 Mar 2022 14:20:47 +0800 Subject: [PATCH 25/29] set ssrExternals (#129) --- .../backpack-addons/externals.js | 27 +++++++++++++++++++ .../react-scripts/config/webpack.config.js | 2 +- .../config/webpack.config.ssr.js | 2 +- 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 packages/react-scripts/backpack-addons/externals.js diff --git a/packages/react-scripts/backpack-addons/externals.js b/packages/react-scripts/backpack-addons/externals.js new file mode 100644 index 000000000..72304e0e3 --- /dev/null +++ b/packages/react-scripts/backpack-addons/externals.js @@ -0,0 +1,27 @@ +'use strict'; + +const paths = require('../config/paths'); +const appPackageJson = require(paths.appPackageJson); +const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; + +function externals(isEnvProduction) { + if (!isEnvProduction) { + return { + externals: {}, + } + } + return { + externals: bpkReactScriptsConfig.externals || {}, + } +} + +function ssrExternals() { + return { + externals: bpkReactScriptsConfig.ssrExternals || [], + } +} + +module.exports = { + externals, + ssrExternals +}; \ No newline at end of file diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index fa61ff60b..904c0820a 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -359,7 +359,7 @@ module.exports = function (webpackEnv) { } : false, }, - externals: isEnvProduction ? bpkReactScriptsConfig.externals || {} : {}, + ...require('../backpack-addons/externals').externals(isEnvProduction), // #backpack-addons externals resolve: { // This allows you to set a fallback for where webpack should look for modules. // We placed these paths second because we want `node_modules` to "win" diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index 2a1259d3f..644243ca2 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -385,7 +385,7 @@ module.exports = function (webpackEnv) { // : false, runtimeChunk: false, }, - externals: bpkReactScriptsConfig.ssrExternals || [], + ...require('../backpack-addons/externals').ssrExternals(), // #backpack-addons externals resolve: { // This allows you to set a fallback for where webpack should look for modules. // We placed these paths second because we want `node_modules` to "win" -- GitLab From 1f817c1d99adf7733162ed11f28fc59d1f5322e1 Mon Sep 17 00:00:00 2001 From: salleyliu <86700834+salleyliu@users.noreply.github.com> Date: Tue, 1 Mar 2022 14:26:59 +0800 Subject: [PATCH 26/29] [LEOP-317]Extract sassFunctions (#125) * sassFunctions addon * remove utils/sassFunctions.js * update ssr sassFunctions * update ssr sassFunctions --- .../react-scripts/backpack-addons/sassFunctions.js | 12 ++++++++++++ packages/react-scripts/config/webpack.config.js | 13 ++----------- packages/react-scripts/config/webpack.config.ssr.js | 13 ++----------- packages/react-scripts/utils/sassFunction.js | 9 --------- 4 files changed, 16 insertions(+), 31 deletions(-) create mode 100644 packages/react-scripts/backpack-addons/sassFunctions.js delete mode 100644 packages/react-scripts/utils/sassFunction.js diff --git a/packages/react-scripts/backpack-addons/sassFunctions.js b/packages/react-scripts/backpack-addons/sassFunctions.js new file mode 100644 index 000000000..06b4e7fdb --- /dev/null +++ b/packages/react-scripts/backpack-addons/sassFunctions.js @@ -0,0 +1,12 @@ +'use strict'; +const sass = require('node-sass'); + +module.exports = { + sassOptions: { + 'encodebase64($string)': str => { + const buffer = Buffer.from(str.getValue()); + + return sass.types.String(buffer.toString('base64')); + } + } +}; \ No newline at end of file diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 904c0820a..a20c20844 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -53,7 +53,6 @@ const jsWorkerPool = { const appPackageJson = require(paths.appPackageJson); -const sassFunctions = require('../utils/sassFunction'); const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; @@ -669,11 +668,7 @@ module.exports = function (webpackEnv) { : isEnvDevelopment, }, 'sass-loader', - { - sassOptions: { - functions: sassFunctions, - }, - } + require('../backpack-addons/sassFunctions') // #backpack-addons sassFunctions ), // Don't consider CSS imports dead code even if the // containing package claims to have no side effects. @@ -698,11 +693,7 @@ module.exports = function (webpackEnv) { }, }, 'sass-loader', - { - sassOptions: { - functions: sassFunctions, - }, - } + require('../backpack-addons/sassFunctions') // #backpack-addons sassFunctions ), }, // "file" loader makes sure those assets get served by WebpackDevServer. diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index 644243ca2..f631152d9 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -54,7 +54,6 @@ const postcssNormalize = require('postcss-normalize'); const appPackageJson = require(paths.appPackageJson); -const sassFunctions = require('../utils/sassFunction'); // const camelCase = require('lodash/camelCase'); const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; @@ -696,11 +695,7 @@ module.exports = function (webpackEnv) { : isEnvDevelopment, }, 'sass-loader', - { - sassOptions: { - functions: sassFunctions, - }, - } + require('../backpack-addons/sassFunctions') // #backpack-addons sassFunctions ), // Don't consider CSS imports dead code even if the // containing package claims to have no side effects. @@ -726,11 +721,7 @@ module.exports = function (webpackEnv) { }, }, 'sass-loader', - { - sassOptions: { - functions: sassFunctions, - }, - } + require('../backpack-addons/sassFunctions') // #backpack-addons sassFunctions ), }, // "file" loader makes sure those assets get served by WebpackDevServer. diff --git a/packages/react-scripts/utils/sassFunction.js b/packages/react-scripts/utils/sassFunction.js deleted file mode 100644 index d518638b8..000000000 --- a/packages/react-scripts/utils/sassFunction.js +++ /dev/null @@ -1,9 +0,0 @@ -const nodeSass = require('node-sass'); - -module.exports = { - 'encodebase64($string)': str => { - const buffer = Buffer.from(str.getValue()); - - return nodeSass.types.String(buffer.toString('base64')); - }, -}; -- GitLab From b9dfaf9575af3ac60c1c97c9e50b69ff16e0f0f4 Mon Sep 17 00:00:00 2001 From: salleyliu <86700834+salleyliu@users.noreply.github.com> Date: Tue, 1 Mar 2022 15:17:03 +0800 Subject: [PATCH 27/29] [LEOP-317]Prefect Backpack-addons README.md (#131) * prefect feature description * update file --- .../react-scripts/backpack-addons/README.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/packages/react-scripts/backpack-addons/README.md b/packages/react-scripts/backpack-addons/README.md index 668a31ac8..5ffda5a56 100644 --- a/packages/react-scripts/backpack-addons/README.md +++ b/packages/react-scripts/backpack-addons/README.md @@ -1,5 +1,7 @@ Our react scripts fork includes a number of custom configuration items in order to support building web products at Skyscanner. The table below will describe what each of the configs do +## Features Description + | Feature | Description | Default Value | |:---|:--|:---| | **babelIncludePrefixes** | Array of module name prefixes to opt into babel compilation. <br> Default includes **@skyscanner/bpk-, bpk- and saddlebag-** packages by default to be compiled | **[@skyscanner/bpk-, bpk- and saddlebag-]** | @@ -7,3 +9,26 @@ Our react scripts fork includes a number of custom configuration items in order | **crossOriginLoading** | Option to enable cross origin loading of chunks to modify the default webpack behaviour of being false. <br> Docs: https://webpack.js.org/configuration/output/#outputcrossoriginloading | **false** | | **ignoreCssWarnings** | Provides the ablity to supress CSS ordering warnings when its safe and ordering is not of a concern on the output <br> See [mini css extract plugin docs](https://github.com/webpack-contrib/mini-css-extract-plugin#remove-order-warnings) | **false** - by default we should care about order as it can sometimes have an output impact | | **cssModules** | Determines if cssModules are being used. <br> If enabled supports css modules and configures css-loader for use <br> If not enabled supports sass modules in the project and configures sass-loader for use | **true** | +| **amdExludes** | Array of module names to be excluded from AMD ([Asynchronous Module Definition](https://webpack.js.org/api/module-methods/#amd)) parsing.<br> lodash included by defeault. | **['lodash']** | +| **externals** | Provides a way of excluding dependencies from the bundles and instead relies on them being available at runtime on the clients environment E.g. React libraries.<br> See https://webpack.js.org/configuration/externals/ | **{}** | +| **ssrExternals** | The same as above `externals` except used for server side rendering only in **ssr.js** | **{}** | +| **enableAutomaticChunking** | Opts into automatic chunking of vender, common and app code.<br> When enabled the **splitChunks** plugin creates vender and common chunks which are split and when provided uses the `venderChunkRegex` to specify what is in each chunk.<br> When enabled **runtimeChunk** plugin creates a separate runtime chunk for projects to enable long term caching. | **false** | +| **vendorsChunkRegex** | Regex for picking what goes into the vendors chunk. Requires enableAutomaticChunking to be enabled.<br> See [cacheGroups](https://webpack.js.org/plugins/split-chunks-plugin/#splitchunkscachegroups) docs for further details. | | +| **sassFunctions** | This function encodes svg content into `base64` when there is a `bpk-icon` in the.scss file. | | + +## How to add new feature + +- Add the custom feature to backpack-addons. +- Require features in the file(for example, webpack.config.js) where they are needed. + - For each line of code that is changed, make sure to add a comment `// #backpack-addon {{featureName}}` + - Try to keep the lines of code changed outside of the backpack-addons folder to a minimum +`require(...../backpack-addons/...)` files instead of writing it inline as much as possible. +- Add a description of the new feature in the table above the current document. + +## How to upgrade from the upstream `facebook/create-react-app` repo + +- Replace all of `packages/react-scripts` with the upstream version. +- Restore `packages/react-scripts/backpack-addons` all features. +- Restore (will require manual work+checking) every line which has a `// #backpack-addon` comment. +- Compare [upgrade] document and restore the rest of the content (for example, added files, other modified files). +- Test for project. -- GitLab From 6aa03fa3e4922d0735b4027be0b88618853237d9 Mon Sep 17 00:00:00 2001 From: salleyliu <86700834+salleyliu@users.noreply.github.com> Date: Tue, 1 Mar 2022 16:06:05 +0800 Subject: [PATCH 28/29] [LEOP-317]Extract runtimeChunk (#128) * extract runtimeChunk * update runtimeChunk * reset runtimeChunk --- .../backpack-addons/runtimeChunk.js | 22 +++++++++++++++++++ .../react-scripts/config/webpack.config.js | 12 +--------- .../config/webpack.config.ssr.js | 2 +- 3 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 packages/react-scripts/backpack-addons/runtimeChunk.js diff --git a/packages/react-scripts/backpack-addons/runtimeChunk.js b/packages/react-scripts/backpack-addons/runtimeChunk.js new file mode 100644 index 000000000..7e18c36b3 --- /dev/null +++ b/packages/react-scripts/backpack-addons/runtimeChunk.js @@ -0,0 +1,22 @@ +'use strict'; + +const paths = require('../config/paths'); +const appPackageJson = require(paths.appPackageJson); +const bpkReactScriptsConfig = appPackageJson['backpack-react-scripts'] || {}; + +const runtimeChunk = { + runtimeChunk: bpkReactScriptsConfig.enableAutomaticChunking + ? { + name: entrypoint => `runtime-${entrypoint.name}`, + } + : false +} + +const ssrRuntimeChunk = { + runtimeChunk: false, +} + +module.exports = { + runtimeChunk, + ssrRuntimeChunk +}; \ No newline at end of file diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index a20c20844..52652d423 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -346,17 +346,7 @@ module.exports = function (webpackEnv) { }), ], ...require('../backpack-addons/splitChunks')(isEnvDevelopment), // #backpack-addons splitChunks - // Keep the runtime chunk separated to enable long term caching - // https://twitter.com/wSokra/status/969679223278505985 - // https://github.com/facebook/create-react-app/issues/5358 - // runtimeChunk: { - // name: entrypoint => `runtime-${entrypoint.name}`, - // }, - runtimeChunk: bpkReactScriptsConfig.enableAutomaticChunking - ? { - name: entrypoint => `runtime-${entrypoint.name}`, - } - : false, + ...require('../backpack-addons/runtimeChunk').runtimeChunk, // #backpack-addons runtimeChunk }, ...require('../backpack-addons/externals').externals(isEnvProduction), // #backpack-addons externals resolve: { diff --git a/packages/react-scripts/config/webpack.config.ssr.js b/packages/react-scripts/config/webpack.config.ssr.js index f631152d9..c1080f711 100644 --- a/packages/react-scripts/config/webpack.config.ssr.js +++ b/packages/react-scripts/config/webpack.config.ssr.js @@ -382,7 +382,7 @@ module.exports = function (webpackEnv) { // name: entrypoint => `runtime-${entrypoint.name}`, // } // : false, - runtimeChunk: false, + ...require('../backpack-addons/runtimeChunk').ssrRuntimeChunk, // #backpack-addons runtimeChunk }, ...require('../backpack-addons/externals').ssrExternals(), // #backpack-addons externals resolve: { -- GitLab From 079b9797c94b23d5f41292afa8ccaf4a7e27d817 Mon Sep 17 00:00:00 2001 From: Salley Liu <salley.liu@skyscanner.net> Date: Wed, 2 Mar 2022 11:11:45 +0800 Subject: [PATCH 29/29] fix not find encodebase64 function error --- .../react-scripts/backpack-addons/sassFunctions.js | 10 ++++++---- packages/react-scripts/config/webpack.config.js | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/react-scripts/backpack-addons/sassFunctions.js b/packages/react-scripts/backpack-addons/sassFunctions.js index 06b4e7fdb..366705f60 100644 --- a/packages/react-scripts/backpack-addons/sassFunctions.js +++ b/packages/react-scripts/backpack-addons/sassFunctions.js @@ -3,10 +3,12 @@ const sass = require('node-sass'); module.exports = { sassOptions: { - 'encodebase64($string)': str => { - const buffer = Buffer.from(str.getValue()); - - return sass.types.String(buffer.toString('base64')); + functions: { + 'encodebase64($string)': str => { + const buffer = Buffer.from(str.getValue()); + + return sass.types.String(buffer.toString('base64')); + } } } }; \ No newline at end of file diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 52652d423..962d76e42 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -196,7 +196,7 @@ module.exports = function (webpackEnv) { { loader: require.resolve(preProcessor), options: { - ...preProcessorOptions, + ...preProcessorOptions, // #backpack-addons sassFunctions ...{ sourceMap: true, }, -- GitLab