diff --git a/.circleci/config.yml b/.circleci/config.yml
index 6cc1a86c8e5f6..5dbe61c0b83d0 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -325,14 +325,6 @@ jobs:
e2e_tests_development_runtime:
<<: *e2e_tests_development_runtime_alias
- e2e_tests_development_runtime_fast_refresh:
- <<: *e2e_tests_development_runtime_alias
- environment:
- GATSBY_HOT_LOADER: fast-refresh
- CYPRESS_HOT_LOADER: fast-refresh
- CYPRESS_PROJECT_ID: 917bea
- CYPRESS_RECORD_KEY: 4750fb36-4576-4638-a617-d243a381acef
-
e2e_tests_development_runtime_with_experimental_react:
<<: *e2e_tests_development_runtime_alias
@@ -616,8 +608,6 @@ workflows:
<<: *e2e-test-workflow
- e2e_tests_development_runtime:
<<: *e2e-test-workflow
- - e2e_tests_development_runtime_fast_refresh:
- <<: *e2e-test-workflow
- e2e_tests_production_runtime:
<<: *e2e-test-workflow
- themes_e2e_tests_production_runtime:
diff --git a/docs/docs/conceptual/gatsby-lifecycle-apis.md b/docs/docs/conceptual/gatsby-lifecycle-apis.md
index 3e0709d58ad4d..ce9580365e1ad 100644
--- a/docs/docs/conceptual/gatsby-lifecycle-apis.md
+++ b/docs/docs/conceptual/gatsby-lifecycle-apis.md
@@ -44,7 +44,7 @@ During the main bootstrap sequence, Gatsby (in this order):
- writes page redirects (if any) to `.cache/redirects.json`
- the [onPostBootstrap](/docs/reference/config-files/gatsby-node/#onPostBootstrap) lifecycle is executed
-In development this is a running process powered by [webpack](https://github.com/gatsbyjs/gatsby/blob/dd91b8dceb3b8a20820b15acae36529799217ae4/packages/gatsby/package.json#L128) and [`react-hot-loader`](https://github.com/gatsbyjs/gatsby/blob/dd91b8dceb3b8a20820b15acae36529799217ae4/packages/gatsby/package.json#L104), so changes to any files get re-run through the sequence again, with [smart cache invalidation](https://github.com/gatsbyjs/gatsby/blob/ffd8b2d691c995c760fe380769852bcdb26a2278/packages/gatsby/src/bootstrap/index.js#L141). For example, `gatsby-source-filesystem` watches files for changes, and each change triggers re-running queries. Other plugins may also perform this service. Queries are also watched, so if you modify a query, your development app is hot reloaded.
+In development this is a running process powered by [webpack](https://github.com/gatsbyjs/gatsby/blob/dd91b8dceb3b8a20820b15acae36529799217ae4/packages/gatsby/package.json#L128) and [`react-refresh`](https://github.com/gatsbyjs/gatsby/blob/4dff7550a29f4635bf47a068a05f634470eb9ef1/packages/gatsby/package.json#L134)), so changes to any files get re-run through the sequence again, with [smart cache invalidation](https://github.com/gatsbyjs/gatsby/blob/ffd8b2d691c995c760fe380769852bcdb26a2278/packages/gatsby/src/bootstrap/index.js#L141). For example, `gatsby-source-filesystem` watches files for changes, and each change triggers re-running queries. Other plugins may also perform this service. Queries are also watched, so if you modify a query, your development app is hot reloaded.
The core of the bootstrap process is the "api-runner", which helps to execute APIs in sequence, with state managed in Redux. Gatsby exposes a number of lifecycle APIs which can either be implemented by you (or any of your configured plugins) in `gatsby-node.js`, `gatsby-browser.js` or `gatsby-ssr.js`.
diff --git a/e2e-tests/development-runtime/cypress/integration/eslint-rules/limited-exports-page-templates.js b/e2e-tests/development-runtime/cypress/integration/eslint-rules/limited-exports-page-templates.js
index 5c32d2bd47cb6..2cc1ad530ee1d 100644
--- a/e2e-tests/development-runtime/cypress/integration/eslint-rules/limited-exports-page-templates.js
+++ b/e2e-tests/development-runtime/cypress/integration/eslint-rules/limited-exports-page-templates.js
@@ -1,21 +1,19 @@
-if (Cypress.env("HOT_LOADER") === `fast-refresh`) {
- describe(`limited-exports-page-templates`, () => {
- // Skipped because HMR not show warnings because of https://github.com/webpack-contrib/webpack-hot-middleware/pull/397
- it.skip(`should log warning to console for invalid export`, () => {
- cy.visit(`/eslint-rules/limited-exports-page-templates`, {
- onBeforeLoad(win) {
- cy.stub(win.console, "log").as(`consoleLog`)
- },
- }).waitForRouteChange()
+describe(`limited-exports-page-templates`, () => {
+ // Skipped because HMR not show warnings because of https://github.com/webpack-contrib/webpack-hot-middleware/pull/397
+ it.skip(`should log warning to console for invalid export`, () => {
+ cy.visit(`/eslint-rules/limited-exports-page-templates`, {
+ onBeforeLoad(win) {
+ cy.stub(win.console, "log").as(`consoleLog`)
+ },
+ }).waitForRouteChange()
- cy.get(`@consoleLog`).should(
- `be.calledWithMatch`,
- /15:1 warning In page templates only a default export of a valid React component and the named export of a page query is allowed./i
- )
- cy.get(`@consoleLog`).should(
- `not.be.calledWithMatch`,
- /17:1 warning In page templates only a default export of a valid React component and the named export of a page query is allowed./i
- )
- })
+ cy.get(`@consoleLog`).should(
+ `be.calledWithMatch`,
+ /15:1 warning In page templates only a default export of a valid React component and the named export of a page query is allowed./i
+ )
+ cy.get(`@consoleLog`).should(
+ `not.be.calledWithMatch`,
+ /17:1 warning In page templates only a default export of a valid React component and the named export of a page query is allowed./i
+ )
})
-}
+})
diff --git a/e2e-tests/development-runtime/cypress/integration/eslint-rules/no-anonymous-exports-page-templates.js b/e2e-tests/development-runtime/cypress/integration/eslint-rules/no-anonymous-exports-page-templates.js
index 04d7a521b5d87..2b09f3b455d30 100644
--- a/e2e-tests/development-runtime/cypress/integration/eslint-rules/no-anonymous-exports-page-templates.js
+++ b/e2e-tests/development-runtime/cypress/integration/eslint-rules/no-anonymous-exports-page-templates.js
@@ -1,29 +1,27 @@
-if (Cypress.env("HOT_LOADER") === `fast-refresh`) {
- describe(`no-anonymous-exports-page-templates`, () => {
- // Skipped because HMR not show warnings because of https://github.com/webpack-contrib/webpack-hot-middleware/pull/397
- it.skip(`should log warning to console for arrow functions`, () => {
- cy.visit(`/eslint-rules/no-anonymous-exports-page-templates`, {
- onBeforeLoad(win) {
- cy.stub(win.console, "log").as(`consoleLog`)
- },
- }).waitForRouteChange()
+describe(`no-anonymous-exports-page-templates`, () => {
+ // Skipped because HMR not show warnings because of https://github.com/webpack-contrib/webpack-hot-middleware/pull/397
+ it.skip(`should log warning to console for arrow functions`, () => {
+ cy.visit(`/eslint-rules/no-anonymous-exports-page-templates`, {
+ onBeforeLoad(win) {
+ cy.stub(win.console, "log").as(`consoleLog`)
+ },
+ }).waitForRouteChange()
- cy.get(`@consoleLog`).should(
- `be.calledWithMatch`,
- /Anonymous arrow functions cause Fast Refresh to not preserve local component state./i
- )
- })
- it.skip(`should log warning to console for function declarations`, () => {
- cy.visit(`/eslint-rules/no-anonymous-exports-page-templates-function`, {
- onBeforeLoad(win) {
- cy.stub(win.console, "log").as(`consoleLog`)
- },
- }).waitForRouteChange()
+ cy.get(`@consoleLog`).should(
+ `be.calledWithMatch`,
+ /Anonymous arrow functions cause Fast Refresh to not preserve local component state./i
+ )
+ })
+ it.skip(`should log warning to console for function declarations`, () => {
+ cy.visit(`/eslint-rules/no-anonymous-exports-page-templates-function`, {
+ onBeforeLoad(win) {
+ cy.stub(win.console, "log").as(`consoleLog`)
+ },
+ }).waitForRouteChange()
- cy.get(`@consoleLog`).should(
- `be.calledWithMatch`,
- /Anonymous function declarations cause Fast Refresh to not preserve local component state./i
- )
- })
+ cy.get(`@consoleLog`).should(
+ `be.calledWithMatch`,
+ /Anonymous function declarations cause Fast Refresh to not preserve local component state./i
+ )
})
-}
+})
diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/arrow-functions.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/arrow-functions.js
index 2bb158180585c..4b97fe3e7b9af 100644
--- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/arrow-functions.js
+++ b/e2e-tests/development-runtime/cypress/integration/hot-reloading/arrow-functions.js
@@ -19,6 +19,8 @@ describe(`hot-reloading anonymous arrow functions`, () => {
`npm run update -- --file src/components/title.tsx --replacements "TITLE:${text}"`
)
+ cy.waitForHmr()
+
cy.getTestElement(IDS.title).should(`have.text`, text)
})
})
diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/class-component.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/class-component.js
index ef7b10fa6203b..411479dd1f0bc 100644
--- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/class-component.js
+++ b/e2e-tests/development-runtime/cypress/integration/hot-reloading/class-component.js
@@ -23,6 +23,8 @@ describe(`reloading class component`, () => {
`npm run update -- --file src/components/class-component.js --replacements "CUSTOM_STATE:${value}"`
)
+ cy.waitForHmr()
+
cy.getTestElement(`stateful-${TEST_ID}`).should(
`have.text`,
`Custom Message`
diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/hooks.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/hooks.js
index 00f34f5d69df4..a398819c6c4d2 100644
--- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/hooks.js
+++ b/e2e-tests/development-runtime/cypress/integration/hot-reloading/hooks.js
@@ -1,16 +1,23 @@
const COUNT_ID = `count`
+const amount = 100
describe(`hot-reloading hooks`, () => {
beforeEach(() => {
+ cy.exec(
+ `npm run update -- --file src/pages/hooks.js --replacements "count + ${amount}:count + 1" --exact`
+ )
+ cy.wait(1000)
+
cy.visit(`/hooks`).waitForRouteChange()
})
- it.skip(`can update component`, () => {
- const amount = 100
+ it(`can update component`, () => {
cy.exec(
`npm run update -- --file src/pages/hooks.js --replacements "count + 1:count + ${amount}" --exact`
)
+ cy.waitForHmr()
+
cy.getTestElement(`increment`).click()
cy.getTestElement(COUNT_ID).invoke(`text`).should(`eq`, `${amount}`)
diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/new-file.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/new-file.js
index a38d15f58616a..c98ba303436cd 100644
--- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/new-file.js
+++ b/e2e-tests/development-runtime/cypress/integration/hot-reloading/new-file.js
@@ -18,12 +18,14 @@ describe(`hot reloading new page component`, () => {
})
it(`can hot reload a new page file`, () => {
+ cy.visit(`/sample`).waitForRouteChange()
+
const text = `World`
cy.exec(
`npm run update -- --file src/pages/sample.js --replacements "REPLACEMENT:${text}"`
)
- cy.visit(`/sample`).waitForRouteChange()
+ cy.waitForHmr()
cy.getTestElement(`message`).invoke(`text`).should(`eq`, `Hello ${text}`)
})
diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/non-js-file.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/non-js-file.js
index 287886a3ac714..61b1961150c5c 100644
--- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/non-js-file.js
+++ b/e2e-tests/development-runtime/cypress/integration/hot-reloading/non-js-file.js
@@ -1,21 +1,33 @@
const TEMPLATE = `SUB_TITLE`
const TEST_ID = `sub-title`
+const message = `This is a sub-title`
describe(`hot reloading non-js file`, () => {
beforeEach(() => {
+ cy.exec(
+ `npm run update -- --file content/2018-12-14-hello-world.md --replacements "${message}:%${TEMPLATE}%" --exact`
+ )
+ cy.wait(1000)
+
cy.visit(`/2018-12-14-hello-world/`).waitForRouteChange()
+
+ cy.wait(1000)
})
it(`displays placeholder content on launch`, () => {
cy.getTestElement(TEST_ID).invoke(`text`).should(`contain`, TEMPLATE)
})
- it.skip(`hot reloads with new content`, () => {
- const message = `This is a sub-title`
+ it(`hot reloads with new content`, () => {
+ cy.getTestElement(TEST_ID).invoke(`text`).should(`contain`, TEMPLATE)
+
cy.exec(
`npm run update -- --file content/2018-12-14-hello-world.md --replacements "${TEMPLATE}:${message}"`
)
+ // wati for socket.io to update
+ cy.wait(5000)
+
cy.getTestElement(TEST_ID).invoke(`text`).should(`eq`, message)
})
})
diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/page-component.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/page-component.js
index 63d82c8c1baae..c554457e31647 100644
--- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/page-component.js
+++ b/e2e-tests/development-runtime/cypress/integration/hot-reloading/page-component.js
@@ -14,6 +14,8 @@ describe(`hot reloading page component`, () => {
`npm run update -- --file src/pages/index.js --replacements "GATSBY_SITE:${text}"`
)
+ cy.waitForHmr()
+
cy.getTestElement(TEST_ID).should(`contain.text`, text)
})
})
diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/page-queries.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/page-queries.js
index 9c1b5bae104a8..7e20536d40d3c 100644
--- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/page-queries.js
+++ b/e2e-tests/development-runtime/cypress/integration/hot-reloading/page-queries.js
@@ -18,6 +18,8 @@ describe(`hot-reloading page queries`, () => {
`npm run update -- --file src/pages/page-query.js --replacements "# %AUTHOR%:author" --exact`
)
+ cy.waitForHmr()
+
cy.getTestElement(`hot`).invoke(`text`).should(`contain`, author)
})
})
diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/static-queries.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/static-queries.js
index 926f2a623e58a..bf4e806ec6fc9 100644
--- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/static-queries.js
+++ b/e2e-tests/development-runtime/cypress/integration/hot-reloading/static-queries.js
@@ -29,6 +29,8 @@ describe(`hot-reloading static queries`, () => {
`npm run update -- --file src/components/static-query/use-static-query/hot.js --replacements "# %AUTHOR%:author" --exact`
)
+ cy.waitForHmr()
+
cy.getTestElement(`use-static-query-hot`)
.invoke(`text`)
.should(`contain`, author)
diff --git a/e2e-tests/development-runtime/cypress/integration/hot-reloading/template-component.js b/e2e-tests/development-runtime/cypress/integration/hot-reloading/template-component.js
index 3abf79121c17d..a06d39ca1fca6 100644
--- a/e2e-tests/development-runtime/cypress/integration/hot-reloading/template-component.js
+++ b/e2e-tests/development-runtime/cypress/integration/hot-reloading/template-component.js
@@ -15,6 +15,8 @@ describe(`hot reloading template component`, () => {
`npm run update -- --file src/templates/blog-post.js --replacements "${TEMPLATE}:${message}"`
)
+ cy.waitForHmr()
+
cy.getTestElement(TEST_ID).should(`have.text`, `Hello ${message}`)
})
})
diff --git a/e2e-tests/development-runtime/cypress/integration/navigation/linking.js b/e2e-tests/development-runtime/cypress/integration/navigation/linking.js
index 450d61d9fa8ae..46e7d7763505b 100644
--- a/e2e-tests/development-runtime/cypress/integration/navigation/linking.js
+++ b/e2e-tests/development-runtime/cypress/integration/navigation/linking.js
@@ -143,76 +143,36 @@ describe(`navigation`, () => {
})
})
- if (Cypress.env("HOT_LOADER") !== `fast-refresh`) {
- describe(`All location changes should trigger an effect (react-hot-loader)`, () => {
- beforeEach(() => {
- cy.visit(`/navigation-effects`).waitForRouteChange()
- })
-
- it(`should trigger an effect after a search param has changed`, () => {
- cy.findByTestId(`effect-message`).should(
- `have.text`,
- `Waiting for effect`
- )
- cy.findByTestId(`send-search-message`).click().waitForRouteChange()
- cy.findByTestId(`effect-message`).should(
- `have.text`,
- `?message=searchParam`
- )
- })
-
- it(`should trigger an effect after the hash has changed`, () => {
- cy.findByTestId(`effect-message`).should(
- `have.text`,
- `Waiting for effect`
- )
- cy.findByTestId(`send-hash-message`).click().waitForRouteChange()
- cy.findByTestId(`effect-message`).should(`have.text`, `#message-hash`)
- })
-
- it(`should trigger an effect after the state has changed`, () => {
- cy.findByTestId(`effect-message`).should(`have.text`, ``)
- cy.findByTestId(`send-state-message`).click().waitForRouteChange()
- cy.findByTestId(`effect-message`).should(
- `have.text`,
- `this is a message using the state`
- )
- })
- })
- }
-
// TODO: Check if this is the correct behavior
- if (Cypress.env("HOT_LOADER") === `fast-refresh`) {
- describe(`All location changes should trigger an effect (fast-refresh)`, () => {
- beforeEach(() => {
- cy.visit(`/navigation-effects`).waitForRouteChange()
- })
-
- it(`should trigger an effect after a search param has changed`, () => {
- cy.findByTestId(`effect-message`).should(`have.text`, ``)
- cy.findByTestId(`send-search-message`).click().waitForRouteChange()
- cy.findByTestId(`effect-message`).should(
- `have.text`,
- `?message=searchParam`
- )
- })
-
- it(`should trigger an effect after the hash has changed`, () => {
- cy.findByTestId(`effect-message`).should(`have.text`, ``)
- cy.findByTestId(`send-hash-message`).click().waitForRouteChange()
- cy.findByTestId(`effect-message`).should(`have.text`, `#message-hash`)
- })
-
- it(`should trigger an effect after the state has changed`, () => {
- cy.findByTestId(`effect-message`).should(`have.text`, ``)
- cy.findByTestId(`send-state-message`).click().waitForRouteChange()
- cy.findByTestId(`effect-message`).should(
- `have.text`,
- `this is a message using the state`
- )
- })
- })
- }
+ describe(`All location changes should trigger an effect (fast-refresh)`, () => {
+ beforeEach(() => {
+ cy.visit(`/navigation-effects`).waitForRouteChange()
+ })
+
+ it(`should trigger an effect after a search param has changed`, () => {
+ cy.findByTestId(`effect-message`).should(`have.text`, ``)
+ cy.findByTestId(`send-search-message`).click().waitForRouteChange()
+ cy.findByTestId(`effect-message`).should(
+ `have.text`,
+ `?message=searchParam`
+ )
+ })
+
+ it(`should trigger an effect after the hash has changed`, () => {
+ cy.findByTestId(`effect-message`).should(`have.text`, ``)
+ cy.findByTestId(`send-hash-message`).click().waitForRouteChange()
+ cy.findByTestId(`effect-message`).should(`have.text`, `#message-hash`)
+ })
+
+ it(`should trigger an effect after the state has changed`, () => {
+ cy.findByTestId(`effect-message`).should(`have.text`, ``)
+ cy.findByTestId(`send-state-message`).click().waitForRouteChange()
+ cy.findByTestId(`effect-message`).should(
+ `have.text`,
+ `this is a message using the state`
+ )
+ })
+ })
describe(`Route lifecycle update order`, () => {
it(`calls onPreRouteUpdate, render and onRouteUpdate the correct amount of times on route change`, () => {
diff --git a/e2e-tests/development-runtime/cypress/support/commands.js b/e2e-tests/development-runtime/cypress/support/commands.js
index c30ad592e9874..b109d1e1eb937 100644
--- a/e2e-tests/development-runtime/cypress/support/commands.js
+++ b/e2e-tests/development-runtime/cypress/support/commands.js
@@ -24,7 +24,7 @@ Cypress.Commands.add(`lifecycleCallOrder`, expectedActionCallOrder =>
if (expectedActionCallOrderLength > actionsLength) {
return false
}
-
+
let prevActionIndex = -1
for (let i = 0; i < actionsLength; i += 1) {
const nextActionIndex = prevActionIndex + 1
@@ -81,6 +81,27 @@ Cypress.Commands.add(
}
)
-Cypress.Commands.add(`assertRoute`, (route) => {
+Cypress.Commands.add(`assertRoute`, route => {
cy.url().should(`equal`, `${window.location.origin}${route}`)
})
+
+// overwriting visit and creating a waitForHmr function to help us deal with HMR
+Cypress.Commands.overwrite("visit", (orig, url, options = {}) => {
+ const newOptions = {
+ ...options,
+ onBeforeLoad: win => {
+ if (options.onBeforeLoad) {
+ optiosn.onBeforeLoad(win)
+ }
+
+ cy.spy(win.console, "log").as(`hmrConsoleLog`)
+ },
+ }
+
+ return orig(url, newOptions)
+})
+
+Cypress.Commands.add(`waitForHmr`, (message = `App is up to date`) => {
+ cy.get(`@hmrConsoleLog`).should(`be.calledWithMatch`, message)
+ cy.wait(1000)
+})
diff --git a/e2e-tests/development-runtime/package.json b/e2e-tests/development-runtime/package.json
index 8728b24aa482a..f1a1f077235d5 100644
--- a/e2e-tests/development-runtime/package.json
+++ b/e2e-tests/development-runtime/package.json
@@ -30,7 +30,6 @@
"scripts": {
"build": "gatsby build",
"develop": "cross-env CYPRESS_SUPPORT=y ENABLE_GATSBY_REFRESH_ENDPOINT=true gatsby develop",
- "develop:fast-refresh": "cross-env CYPRESS_SUPPORT=y ENABLE_GATSBY_REFRESH_ENDPOINT=true GATSBY_HOT_LOADER=fast-refresh gatsby develop",
"serve": "gatsby serve",
"start": "npm run develop",
"format": "prettier --write \"src/**/*.js\"",
@@ -65,4 +64,4 @@
"resolutions": {
"cypress": "6.1.0"
}
-}
\ No newline at end of file
+}
diff --git a/packages/gatsby-plugin-preact/src/gatsby-node.js b/packages/gatsby-plugin-preact/src/gatsby-node.js
index 5e25c8e97c70d..f6805ee2f11d0 100644
--- a/packages/gatsby-plugin-preact/src/gatsby-node.js
+++ b/packages/gatsby-plugin-preact/src/gatsby-node.js
@@ -1,10 +1,5 @@
const PreactRefreshPlugin = require(`@prefresh/webpack`)
-exports.onPreInit = () => {
- // force fast-refresh in gatsby
- process.env.GATSBY_HOT_LOADER = `fast-refresh`
-}
-
exports.onCreateBabelConfig = ({ actions, stage }) => {
if (stage === `develop`) {
// enable react-refresh babel plugin to enable hooks
diff --git a/packages/gatsby/cache-dir/__tests__/error-overlay-handler.js b/packages/gatsby/cache-dir/__tests__/error-overlay-handler.js
deleted file mode 100644
index 34a195ef61f87..0000000000000
--- a/packages/gatsby/cache-dir/__tests__/error-overlay-handler.js
+++ /dev/null
@@ -1,58 +0,0 @@
-const {
- reportError,
- clearError,
- errorMap,
-} = require(`../error-overlay-handler`)
-
-import * as ErrorOverlay from "react-error-overlay"
-
-jest.mock(`react-error-overlay`, () => {
- return {
- reportBuildError: jest.fn(),
- dismissBuildError: jest.fn(),
- startReportingRuntimeErrors: jest.fn(),
- setEditorHandler: jest.fn(),
- }
-})
-
-beforeEach(() => {
- ErrorOverlay.reportBuildError.mockClear()
- ErrorOverlay.dismissBuildError.mockClear()
-})
-
-describe(`errorOverlayHandler`, () => {
- describe(`clearError()`, () => {
- beforeEach(() => {
- reportError(`foo`, `error`)
- reportError(`bar`, `error`)
- })
- afterAll(() => {
- clearError(`foo`)
- clearError(`bar`)
- })
- it(`should clear specific error type`, () => {
- expect(Object.keys(errorMap)).toHaveLength(2)
- clearError(`foo`)
- expect(Object.keys(errorMap)).toHaveLength(1)
- expect(ErrorOverlay.dismissBuildError).not.toHaveBeenCalled()
- })
-
- it(`should call ErrorOverlay to dismiss build errors`, () => {
- clearError(`foo`)
- clearError(`bar`)
- expect(ErrorOverlay.dismissBuildError).toHaveBeenCalled()
- })
- })
- describe(`reportErrorOverlay()`, () => {
- it(`should not add error if it's empty and not call ErrorOverlay`, () => {
- reportError(`foo`, null)
- expect(Object.keys(errorMap)).toHaveLength(0)
- expect(ErrorOverlay.reportBuildError).not.toHaveBeenCalled()
- })
- it(`should add error if it has a truthy value and call ErrorOverlay`, () => {
- reportError(`foo`, `bar`)
- expect(Object.keys(errorMap)).toHaveLength(1)
- expect(ErrorOverlay.reportBuildError).toHaveBeenCalled()
- })
- })
-})
diff --git a/packages/gatsby/cache-dir/app.js b/packages/gatsby/cache-dir/app.js
index 0927b5999202f..32fc4f87aca9f 100644
--- a/packages/gatsby/cache-dir/app.js
+++ b/packages/gatsby/cache-dir/app.js
@@ -13,11 +13,10 @@ import syncRequires from "$virtual/sync-requires"
// Generated during bootstrap
import matchPaths from "$virtual/match-paths.json"
-if (process.env.GATSBY_HOT_LOADER === `fast-refresh` && module.hot) {
- module.hot.accept(`$virtual/sync-requires`, () => {
- // Manually reload
- })
-}
+// Enable fast-refresh for virtual sync-requires
+module.hot.accept(`$virtual/sync-requires`, () => {
+ // Manually reload
+})
window.___emitter = emitter
diff --git a/packages/gatsby/cache-dir/error-overlay-handler.js b/packages/gatsby/cache-dir/error-overlay-handler.js
index c4dea30377c63..cf9361d02e6e2 100644
--- a/packages/gatsby/cache-dir/error-overlay-handler.js
+++ b/packages/gatsby/cache-dir/error-overlay-handler.js
@@ -1,33 +1,8 @@
-const overlayPackage =
- process.env.GATSBY_HOT_LOADER !== `fast-refresh`
- ? require(`react-error-overlay`)
- : require(`@pmmmwh/react-refresh-webpack-plugin/overlay`)
+const overlayPackage = require(`@pmmmwh/react-refresh-webpack-plugin/overlay`)
const ErrorOverlay = {
- showCompileError:
- process.env.GATSBY_HOT_LOADER !== `fast-refresh`
- ? overlayPackage.reportBuildError
- : overlayPackage.showCompileError,
- clearCompileError:
- process.env.GATSBY_HOT_LOADER !== `fast-refresh`
- ? overlayPackage.dismissBuildError
- : overlayPackage.clearCompileError,
-}
-
-if (process.env.GATSBY_HOT_LOADER !== `fast-refresh`) {
- // Report runtime errors
- overlayPackage.startReportingRuntimeErrors({
- onError: () => {},
- filename: `/commons.js`,
- })
- overlayPackage.setEditorHandler(errorLocation =>
- window.fetch(
- `/__open-stack-frame-in-editor?fileName=` +
- window.encodeURIComponent(errorLocation.fileName) +
- `&lineNumber=` +
- window.encodeURIComponent(errorLocation.lineNumber || 1)
- )
- )
+ showCompileError: overlayPackage.showCompileError,
+ clearCompileError: overlayPackage.clearCompileError,
}
const errorMap = {}
diff --git a/packages/gatsby/cache-dir/root.js b/packages/gatsby/cache-dir/root.js
index 1a62430b4ce08..1e3fb8c2674fe 100644
--- a/packages/gatsby/cache-dir/root.js
+++ b/packages/gatsby/cache-dir/root.js
@@ -12,32 +12,8 @@ import loader from "./loader"
import { PageQueryStore, StaticQueryStore } from "./query-result-store"
import EnsureResources from "./ensure-resources"
import FastRefreshOverlay from "./fast-refresh-overlay"
-
-import { reportError, clearError } from "./error-overlay-handler"
import { LoadingIndicatorEventHandler } from "./loading-indicator"
-// TODO: Remove entire block when we make fast-refresh the default
-// In fast-refresh, this logic is all moved into the `error-overlay-handler`
-if (
- window.__webpack_hot_middleware_reporter__ !== undefined &&
- process.env.GATSBY_HOT_LOADER !== `fast-refresh`
-) {
- const overlayErrorID = `webpack`
- // Report build errors
- window.__webpack_hot_middleware_reporter__.useCustomOverlay({
- showProblems(type, obj) {
- if (type !== `errors`) {
- clearError(overlayErrorID)
- return
- }
- reportError(overlayErrorID, obj[0])
- },
- clear() {
- clearError(overlayErrorID)
- },
- })
-}
-
navigationInit()
// In gatsby v2 if Router is used in page using matchPaths
@@ -137,20 +113,12 @@ const WrappedRoot = apiRunner(
}
).pop()
-const ConditionalFastRefreshOverlay = ({ children }) => {
- if (process.env.GATSBY_HOT_LOADER === `fast-refresh`) {
- return {children}
- }
-
- return {children}
-}
-
export default () => (
-
+
{WrappedRoot}
{process.env.GATSBY_EXPERIMENTAL_QUERY_ON_DEMAND &&
process.env.GATSBY_QUERY_ON_DEMAND_LOADING_INDICATOR === `true` && (
)}
-
+
)
diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json
index fc708739a45d5..17c51fd15ccb8 100644
--- a/packages/gatsby/package.json
+++ b/packages/gatsby/package.json
@@ -260,4 +260,4 @@
"yargs": {
"boolean-negation": false
}
-}
+}
\ No newline at end of file
diff --git a/packages/gatsby/src/bootstrap/requires-writer.ts b/packages/gatsby/src/bootstrap/requires-writer.ts
index 93268a065e698..e384fd311b27d 100644
--- a/packages/gatsby/src/bootstrap/requires-writer.ts
+++ b/packages/gatsby/src/bootstrap/requires-writer.ts
@@ -208,26 +208,18 @@ export const writeAll = async (state: IGatsbyState): Promise => {
lastHash = newHash
- // TODO: Remove all "hot" references in this `syncRequires` variable when fast-refresh is the default
- const hotImport =
- process.env.GATSBY_HOT_LOADER !== `fast-refresh`
- ? `const { hot } = require("react-hot-loader/root")`
- : ``
- const hotMethod =
- process.env.GATSBY_HOT_LOADER !== `fast-refresh` ? `hot` : ``
-
if (process.env.GATSBY_EXPERIMENTAL_DEV_SSR) {
// Create file with sync requires of visited page components files.
- let lazySyncRequires = `${hotImport}
+ let lazySyncRequires = `
// prefer default export if available
const preferDefault = m => (m && m.default) || m
\n\n`
lazySyncRequires += `exports.ssrComponents = {\n${cleanedSSRVisitedPageComponents
.map(
(c: IGatsbyPageComponent): string =>
- ` "${
- c.componentChunkName
- }": ${hotMethod}(preferDefault(require("${joinPath(c.component)}")))`
+ ` "${c.componentChunkName}": preferDefault(require("${joinPath(
+ c.component
+ )}"))`
)
.join(`,\n`)}
}\n\n`
@@ -236,17 +228,16 @@ export const writeAll = async (state: IGatsbyState): Promise => {
}
// Create file with sync requires of components/json files.
- let syncRequires = `${hotImport}
-
+ let syncRequires = `
// prefer default export if available
const preferDefault = m => (m && m.default) || m
\n\n`
syncRequires += `exports.components = {\n${components
.map(
(c: IGatsbyPageComponent): string =>
- ` "${
- c.componentChunkName
- }": ${hotMethod}(preferDefault(require("${joinPath(c.component)}")))`
+ ` "${c.componentChunkName}": preferDefault(require("${joinPath(
+ c.component
+ )}"))`
)
.join(`,\n`)}
}\n\n`
diff --git a/packages/gatsby/src/services/initialize.ts b/packages/gatsby/src/services/initialize.ts
index 03c5f1f07b3f2..a8e9f404aea35 100644
--- a/packages/gatsby/src/services/initialize.ts
+++ b/packages/gatsby/src/services/initialize.ts
@@ -19,7 +19,6 @@ import { loadPlugins } from "../bootstrap/load-plugins"
import { store, emitter } from "../redux"
import loadThemes from "../bootstrap/load-themes"
import reporter from "gatsby-cli/lib/reporter"
-import { getReactHotLoaderStrategy } from "../utils/get-react-hot-loader-strategy"
import { getConfigFile } from "../bootstrap/get-config-file"
import { removeStaleJobs } from "../bootstrap/remove-stale-jobs"
import { IPluginInfoOptions } from "../bootstrap/load-plugins/types"
@@ -165,24 +164,6 @@ export async function initialize({
// Setup flags
if (config) {
- // TODO: this should be handled in FAST_REFRESH configuration and not be one-off here.
- if (
- config.flags?.FAST_REFRESH &&
- process.env.GATSBY_HOT_LOADER &&
- process.env.GATSBY_HOT_LOADER !== `fast-refresh`
- ) {
- delete config.flags.FAST_REFRESH
- reporter.warn(
- reporter.stripIndent(`
- Both FAST_REFRESH gatsby-config flag and GATSBY_HOT_LOADER environment variable is used with conflicting setting ("${process.env.GATSBY_HOT_LOADER}").
-
- Will use react-hot-loader.
-
- To use Fast Refresh either do not use GATSBY_HOT_LOADER environment variable or set it to "fast-refresh".
- `)
- )
- }
-
// Get flags
const { enabledConfigFlags, unknownFlagMessage, message } = handleFlags(
availableFlags,
@@ -216,8 +197,6 @@ export async function initialize({
}
}
- process.env.GATSBY_HOT_LOADER = getReactHotLoaderStrategy()
-
// TODO: figure out proper way of disabling loading indicator
// for now GATSBY_QUERY_ON_DEMAND_LOADING_INDICATOR=false gatsby develop
// will work, but we don't want to force users into using env vars
diff --git a/packages/gatsby/src/utils/babel-loader-helpers.js b/packages/gatsby/src/utils/babel-loader-helpers.js
index 081f5058f0829..db580da2c186c 100644
--- a/packages/gatsby/src/utils/babel-loader-helpers.js
+++ b/packages/gatsby/src/utils/babel-loader-helpers.js
@@ -50,21 +50,11 @@ const prepareOptions = (babel, options = {}, resolve = require.resolve) => {
}
if (stage === `develop`) {
- if (process.env.GATSBY_HOT_LOADER === `fast-refresh`) {
- requiredPlugins.push(
- babel.createConfigItem([resolve(`react-refresh/babel`)], {
- type: `plugin`,
- })
- )
- }
- // TODO: Remove entire block when we make fast-refresh the default
- else {
- requiredPlugins.push(
- babel.createConfigItem([resolve(`react-hot-loader/babel`)], {
- type: `plugin`,
- })
- )
- }
+ requiredPlugins.push(
+ babel.createConfigItem([resolve(`react-refresh/babel`)], {
+ type: `plugin`,
+ })
+ )
}
// Fallback preset
diff --git a/packages/gatsby/src/utils/eslint/required.js b/packages/gatsby/src/utils/eslint/required.js
index 7ac22d57db856..ab05990ed383a 100644
--- a/packages/gatsby/src/utils/eslint/required.js
+++ b/packages/gatsby/src/utils/eslint/required.js
@@ -1,9 +1,7 @@
module.exports = {
rules: {
// Custom ESLint rules from Gatsby
- "no-anonymous-exports-page-templates":
- process.env.GATSBY_HOT_LOADER === `fast-refresh` ? `warn` : `off`,
- "limited-exports-page-templates":
- process.env.GATSBY_HOT_LOADER === `fast-refresh` ? `warn` : `off`,
+ "no-anonymous-exports-page-templates": `warn`,
+ "limited-exports-page-templates": `warn`,
},
}
diff --git a/packages/gatsby/src/utils/flags.ts b/packages/gatsby/src/utils/flags.ts
index d3b44affea052..c295a5a824207 100644
--- a/packages/gatsby/src/utils/flags.ts
+++ b/packages/gatsby/src/utils/flags.ts
@@ -156,16 +156,6 @@ const activeFlags: Array = [
umbrellaIssue: `https://gatsby.dev/cache-clearing-feedback`,
testFitness: (): fitnessEnum => true,
},
- {
- name: `FAST_REFRESH`,
- env: `GATSBY_FAST_REFRESH`,
- command: `develop`,
- telemetryId: `FastRefresh`,
- experimental: false,
- description: `Use React Fast Refresh instead of the legacy react-hot-loader for instantaneous feedback in your development server. Recommended for versions of React >= 17.0.`,
- umbrellaIssue: `https://gatsby.dev/fast-refresh-feedback`,
- testFitness: (): fitnessEnum => true,
- },
{
name: `PARALLEL_SOURCING`,
env: `GATSBY_EXPERIMENTAL_PARALLEL_SOURCING`,
diff --git a/packages/gatsby/src/utils/get-react-hot-loader-strategy.ts b/packages/gatsby/src/utils/get-react-hot-loader-strategy.ts
deleted file mode 100644
index 3b817d05b6978..0000000000000
--- a/packages/gatsby/src/utils/get-react-hot-loader-strategy.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import semver from "semver"
-
-// Fast refresh is supported as of React 16.9.
-// This package will do some sniffing to see if the current version of
-// React installed is greater than 17.0.
-export function getReactHotLoaderStrategy(): string {
- // If the user has defined this, we don't want to do any package sniffing
- if (process.env.GATSBY_HOT_LOADER) return process.env.GATSBY_HOT_LOADER
-
- // If the config flag is true, return fast-refresh
- if (process.env.GATSBY_FAST_REFRESH) return `fast-refresh`
-
- // Do some package sniffing to see if we can use fast-refresh if the user didn't
- // specify a specific hot loader with the environment variable.
-
- try {
- const reactVersion = require(`react/package.json`).version
-
- if (semver.satisfies(reactVersion, `>=17.0.0`)) {
- return `fast-refresh`
- }
- } catch (e) {
- return `react-hot-loader`
- }
-
- return `react-hot-loader`
-}
diff --git a/packages/gatsby/src/utils/webpack-hmr-hooks-patch.js b/packages/gatsby/src/utils/webpack-hmr-hooks-patch.js
deleted file mode 100644
index 7aca2012242c2..0000000000000
--- a/packages/gatsby/src/utils/webpack-hmr-hooks-patch.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * This file should remain as JS because the migration to TypeScript break the patch.
- * For more details, https://github.com/gatsbyjs/gatsby/pull/22280
- */
-const originalFetch = global.fetch
-delete global.fetch
-
-module.exports = require(`react-hot-loader/webpack`)
-
-global.fetch = originalFetch
diff --git a/packages/gatsby/src/utils/webpack.config.js b/packages/gatsby/src/utils/webpack.config.js
index eb56d9ada0f25..9f847ede24eb2 100644
--- a/packages/gatsby/src/utils/webpack.config.js
+++ b/packages/gatsby/src/utils/webpack.config.js
@@ -172,13 +172,7 @@ module.exports = async (
case `develop`:
return {
polyfill: directoryPath(`.cache/polyfill-entry`),
- commons: [
- process.env.GATSBY_HOT_LOADER !== `fast-refresh` &&
- `${require.resolve(
- `webpack-hot-middleware/client`
- )}?path=${getHmrPath()}`,
- directoryPath(`.cache/app`),
- ].filter(Boolean),
+ commons: [directoryPath(`.cache/app`)],
}
case `develop-html`:
return {
@@ -222,8 +216,7 @@ module.exports = async (
case `develop`:
configPlugins = configPlugins
.concat([
- process.env.GATSBY_HOT_LOADER === `fast-refresh` &&
- plugins.fastRefresh(),
+ plugins.fastRefresh(),
plugins.hotModuleReplacement(),
plugins.noEmitOnErrors(),
plugins.eslintGraphqlSchemaReload(),
@@ -265,9 +258,7 @@ module.exports = async (
function getDevtool() {
switch (stage) {
case `develop`:
- return process.env.GATSBY_HOT_LOADER !== `fast-refresh`
- ? `cheap-module-source-map`
- : `eval-cheap-module-source-map`
+ return `eval-cheap-module-source-map`
// use a normal `source-map` for the html phases since
// it gives better line and column numbers
case `develop-html`:
@@ -350,10 +341,7 @@ module.exports = async (
}
// Enforce fast-refresh rules even with local eslint config
- if (
- isCustomEslint &&
- process.env.GATSBY_HOT_LOADER === `fast-refresh`
- ) {
+ if (isCustomEslint) {
configRules = configRules.concat([rules.eslintRequired()])
}
@@ -363,19 +351,6 @@ module.exports = async (
},
])
- // RHL will patch React, replace React-DOM by React-🔥-DOM and work with fiber directly
- // It's necessary to remove the warning in console (https://github.com/gatsbyjs/gatsby/issues/11934)
- // TODO: Remove entire block when we make fast-refresh the default
- if (process.env.GATSBY_HOT_LOADER !== `fast-refresh`) {
- configRules.push({
- include: /node_modules\/react-dom/,
- test: /\.jsx?$/,
- use: {
- loader: require.resolve(`./webpack-hmr-hooks-patch`),
- },
- })
- }
-
break
}
case `build-html`:
@@ -433,12 +408,6 @@ module.exports = async (
// relative path imports are used sometimes
// See https://stackoverflow.com/a/49455609/6420957 for more details
"@babel/runtime": getPackageRoot(`@babel/runtime`),
- // TODO: Remove entire block when we make fast-refresh the default
- ...(process.env.GATSBY_HOT_LOADER !== `fast-refresh`
- ? {
- "react-hot-loader": getPackageRoot(`react-hot-loader`),
- }
- : {}),
"react-lifecycles-compat": directoryPath(
`.cache/react-lifecycles-compat.js`
),