mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 18:27:56 +02:00
feat(core): upgrade to webpack-dev-server@4 (#5420)
Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
1ce6253cc1
commit
96da25e422
17 changed files with 437 additions and 1081 deletions
|
@ -86,7 +86,7 @@
|
|||
"@types/semver": "^7.1.0",
|
||||
"@types/shelljs": "^0.8.6",
|
||||
"@types/wait-on": "^5.2.0",
|
||||
"@types/webpack-dev-server": "^3.11.1",
|
||||
"@types/webpack-dev-server": "^4.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.18.0",
|
||||
"@typescript-eslint/parser": "^4.18.0",
|
||||
"concurrently": "^6.2.1",
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
"stringify-object": "^3.3.0",
|
||||
"unist-util-visit": "^2.0.2",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.40.0"
|
||||
"webpack": "^5.60.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/types": "2.0.0-beta.8",
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
"remark-admonitions": "^1.2.1",
|
||||
"tslib": "^2.3.1",
|
||||
"utility-types": "^3.10.0",
|
||||
"webpack": "^5.40.0"
|
||||
"webpack": "^5.60.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.4 || ^17.0.0",
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
"shelljs": "^0.8.4",
|
||||
"tslib": "^2.3.1",
|
||||
"utility-types": "^3.10.0",
|
||||
"webpack": "^5.40.0"
|
||||
"webpack": "^5.60.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.4 || ^17.0.0",
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"lodash": "^4.17.20",
|
||||
"remark-admonitions": "^1.2.1",
|
||||
"tslib": "^2.3.1",
|
||||
"webpack": "^5.40.0"
|
||||
"webpack": "^5.60.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.4 || ^17.0.0",
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
"react-waypoint": "^10.1.0",
|
||||
"sharp": "^0.29.1",
|
||||
"tslib": "^2.3.1",
|
||||
"webpack": "^5.40.0"
|
||||
"webpack": "^5.60.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.4 || ^17.0.0",
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"clsx": "^1.1.1",
|
||||
"core-js": "^2.6.5",
|
||||
"terser-webpack-plugin": "^5.2.4",
|
||||
"webpack": "^5.40.0",
|
||||
"webpack": "^5.60.0",
|
||||
"webpack-merge": "^5.7.3",
|
||||
"workbox-build": "^6.1.1",
|
||||
"workbox-precaching": "^6.1.1",
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
"joi": "^17.4.2",
|
||||
"querystring": "0.2.0",
|
||||
"utility-types": "^3.10.0",
|
||||
"webpack": "^5.40.0",
|
||||
"webpack": "^5.60.0",
|
||||
"webpack-merge": "^5.8.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,6 @@
|
|||
"detect-port": "^1.3.0",
|
||||
"escape-html": "^1.0.3",
|
||||
"eta": "^1.12.3",
|
||||
"express": "^4.17.1",
|
||||
"file-loader": "^6.2.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"github-slugger": "^1.4.0",
|
||||
|
@ -98,7 +97,7 @@
|
|||
"postcss": "^8.3.7",
|
||||
"postcss-loader": "^6.1.1",
|
||||
"prompts": "^2.4.1",
|
||||
"react-dev-utils": "^11.0.1",
|
||||
"react-dev-utils": "12.0.0-next.47",
|
||||
"react-error-overlay": "^6.0.9",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-loadable": "^5.5.0",
|
||||
|
@ -119,9 +118,9 @@
|
|||
"update-notifier": "^5.1.0",
|
||||
"url-loader": "^4.1.1",
|
||||
"wait-on": "^6.0.0",
|
||||
"webpack": "^5.40.0",
|
||||
"webpack": "^5.60.0",
|
||||
"webpack-bundle-analyzer": "^4.4.2",
|
||||
"webpack-dev-server": "^3.11.2",
|
||||
"webpack-dev-server": "^4.4.0",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"webpackbar": "^5.0.0-3"
|
||||
},
|
||||
|
|
|
@ -8,19 +8,16 @@
|
|||
import {normalizeUrl, posixPath} from '@docusaurus/utils';
|
||||
import chalk = require('chalk');
|
||||
import chokidar from 'chokidar';
|
||||
import express from 'express';
|
||||
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
import path from 'path';
|
||||
import {debounce} from 'lodash';
|
||||
import openBrowser from 'react-dev-utils/openBrowser';
|
||||
import {prepareUrls} from 'react-dev-utils/WebpackDevServerUtils';
|
||||
import errorOverlayMiddleware from 'react-dev-utils/errorOverlayMiddleware';
|
||||
// import evalSourceMapMiddleware from 'react-dev-utils/evalSourceMapMiddleware';
|
||||
import evalSourceMapMiddleware from '../webpack/react-dev-utils-webpack5/evalSourceMapMiddleware';
|
||||
import evalSourceMapMiddleware from 'react-dev-utils/evalSourceMapMiddleware';
|
||||
import webpack from 'webpack';
|
||||
import WebpackDevServer from 'webpack-dev-server';
|
||||
import merge from 'webpack-merge';
|
||||
import HotModuleReplacementPlugin from 'webpack/lib/HotModuleReplacementPlugin';
|
||||
import {load} from '../server';
|
||||
import {StartCLIOptions} from '@docusaurus/types';
|
||||
import {STATIC_DIR_NAME} from '../constants';
|
||||
|
@ -126,6 +123,10 @@ export default async function start(
|
|||
);
|
||||
|
||||
let config: webpack.Configuration = merge(createClientConfig(props), {
|
||||
infrastructureLogging: {
|
||||
// Reduce log verbosity, see https://github.com/facebook/docusaurus/pull/5420#issuecomment-906613105
|
||||
level: 'warn',
|
||||
},
|
||||
plugins: [
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
|
@ -141,8 +142,6 @@ export default async function start(
|
|||
preBodyTags,
|
||||
postBodyTags,
|
||||
}),
|
||||
// This is necessary to emit hot updates for webpack-dev-server.
|
||||
new HotModuleReplacementPlugin(),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -167,50 +166,52 @@ export default async function start(
|
|||
|
||||
// https://webpack.js.org/configuration/dev-server
|
||||
const devServerConfig: WebpackDevServer.Configuration = {
|
||||
...{
|
||||
compress: true,
|
||||
clientLogLevel: 'error',
|
||||
hot: true,
|
||||
hotOnly: cliOptions.hotOnly,
|
||||
// Use 'ws' instead of 'sockjs-node' on server since we're using native
|
||||
// websockets in `webpackHotDevClient`.
|
||||
transportMode: 'ws',
|
||||
// Prevent a WS client from getting injected as we're already including
|
||||
// `webpackHotDevClient`.
|
||||
injectClient: false,
|
||||
quiet: true,
|
||||
hot: cliOptions.hotOnly ? 'only' : true,
|
||||
client: {
|
||||
progress: true,
|
||||
overlay: {
|
||||
warnings: false,
|
||||
errors: true,
|
||||
},
|
||||
},
|
||||
https: getHttpsConfig(),
|
||||
headers: {
|
||||
'access-control-allow-origin': '*',
|
||||
},
|
||||
devMiddleware: {
|
||||
publicPath: baseUrl,
|
||||
watchOptions: {
|
||||
poll: cliOptions.poll,
|
||||
// Reduce log verbosity, see https://github.com/facebook/docusaurus/pull/5420#issuecomment-906613105
|
||||
stats: 'errors-warnings',
|
||||
},
|
||||
static: {
|
||||
directory: path.resolve(siteDir, STATIC_DIR_NAME),
|
||||
watch: {
|
||||
usePolling: !!cliOptions.poll,
|
||||
|
||||
// Useful options for our own monorepo using symlinks!
|
||||
// See https://github.com/webpack/webpack/issues/11612#issuecomment-879259806
|
||||
followSymlinks: true,
|
||||
ignored: /node_modules\/(?!@docusaurus)/,
|
||||
},
|
||||
},
|
||||
historyApiFallback: {
|
||||
rewrites: [{from: /\/*/, to: baseUrl}],
|
||||
},
|
||||
disableHostCheck: true,
|
||||
// Disable overlay on browser since we use CRA's overlay error reporting.
|
||||
overlay: false,
|
||||
allowedHosts: 'all',
|
||||
host,
|
||||
before: (app, server) => {
|
||||
app.use(
|
||||
baseUrl,
|
||||
express.static(path.resolve(siteDir, STATIC_DIR_NAME)),
|
||||
);
|
||||
port,
|
||||
onBeforeSetupMiddleware: (devServer) => {
|
||||
// This lets us fetch source contents from webpack for the error overlay.
|
||||
app.use(evalSourceMapMiddleware(server));
|
||||
// This lets us open files from the runtime error overlay.
|
||||
app.use(errorOverlayMiddleware());
|
||||
},
|
||||
devServer.app.use(
|
||||
evalSourceMapMiddleware(
|
||||
// @ts-expect-error: bad types
|
||||
devServer,
|
||||
),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const compiler = webpack(config);
|
||||
if (process.env.E2E_TEST) {
|
||||
compiler.hooks.done.tap('done', (stats) => {
|
||||
|
@ -223,15 +224,13 @@ export default async function start(
|
|||
});
|
||||
}
|
||||
|
||||
const devServer = new WebpackDevServer(compiler, devServerConfig);
|
||||
devServer.listen(port, host, (err) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
const devServer = new WebpackDevServer(devServerConfig, compiler);
|
||||
devServer.startCallback(() => {
|
||||
if (cliOptions.open) {
|
||||
openBrowser(openUrl);
|
||||
}
|
||||
});
|
||||
|
||||
['SIGINT', 'SIGTERM'].forEach((sig) => {
|
||||
process.on(sig as NodeJS.Signals, () => {
|
||||
devServer.close();
|
||||
|
|
|
@ -19,21 +19,12 @@ export default function createClientConfig(
|
|||
props: Props,
|
||||
minify: boolean = true,
|
||||
): Configuration {
|
||||
const isProd = process.env.NODE_ENV === 'production';
|
||||
const isBuilding = process.argv[2] === 'build';
|
||||
const config = createBaseConfig(props, false, minify);
|
||||
|
||||
const clientConfig = merge(config, {
|
||||
// target: 'browserslist', // useless, disabled on purpose (errors on existing sites with no browserslist cfg)
|
||||
entry: [
|
||||
// Instead of the default WebpackDevServer client, we use a custom one
|
||||
// like CRA to bring better experience.
|
||||
// note: the one in ./dev is modified to work with Docusaurus
|
||||
// !isProd && require.resolve('react-dev-utils/hotDevServer.js'),
|
||||
!isProd &&
|
||||
require.resolve('./react-dev-utils-webpack5/webpackHotDevClient.js'),
|
||||
path.resolve(__dirname, '../client/clientEntry.js'),
|
||||
].filter(Boolean) as string[],
|
||||
entry: path.resolve(__dirname, '../client/clientEntry.js'),
|
||||
optimization: {
|
||||
// Keep the runtime chunk separated to enable long term caching
|
||||
// https://twitter.com/wSokra/status/969679223278505985
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
*/
|
||||
import WebpackBar from 'webpackbar';
|
||||
import {Compiler} from 'webpack';
|
||||
// import formatWebpackMessages from 'react-dev-utils/formatWebpackMessages';
|
||||
import formatWebpackMessages from '../react-dev-utils-webpack5/formatWebpackMessages';
|
||||
import formatWebpackMessages from 'react-dev-utils/formatWebpackMessages';
|
||||
|
||||
function showError(arr: string[]) {
|
||||
console.log(`\n\n${arr.join('\n')}`);
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
This is a temporary copy of
|
||||
|
||||
CRA / react-dev-utils does not support Webpack 5 yet
|
||||
|
||||
https://github.com/facebook/create-react-app/issues/9994
|
||||
|
||||
This folder is a temporary copy of some react-dev-utils code to which we made some changes to support Webpack 5 without warnings
|
||||
|
||||
TODO remove this folder once Webpack 5 is supported (https://github.com/facebook/create-react-app/issues/9994)
|
||||
|
||||
The comment `// modified for Docusaurus` is added near the modified elements
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
/* eslint-disable */
|
||||
/*
|
||||
* THIS FILE IS MODIFIED FOR DOCUSAURUS
|
||||
* the above copyright header must be preserved for license compliance.
|
||||
*/
|
||||
|
||||
/*
|
||||
Implementation based on comment: https://github.com/facebook/create-react-app/issues/9994#issuecomment-811289191
|
||||
*/
|
||||
|
||||
function base64SourceMap(source) {
|
||||
const base64 = Buffer.from(JSON.stringify(source.map()), 'utf8').toString(
|
||||
'base64',
|
||||
);
|
||||
return `data:application/json;charset=utf-8;base64,${base64}`;
|
||||
}
|
||||
|
||||
// modified for Docusaurus => remove webpack 5 deprecation warnings
|
||||
// See https://github.com/facebook/create-react-app/issues/9994#issuecomment-811289191
|
||||
function getSourceById(server, id) {
|
||||
const module = Array.from(server._stats.compilation.modules).find(
|
||||
(m) => server._stats.compilation.chunkGraph.getModuleId(m) == id,
|
||||
);
|
||||
return module.originalSource();
|
||||
}
|
||||
|
||||
/*
|
||||
* Middleware responsible for retrieving a generated source
|
||||
* Receives a webpack internal url: "webpack-internal:///<module-id>"
|
||||
* Returns a generated source: "<source-text><sourceMappingURL><sourceURL>"
|
||||
*
|
||||
* Based on EvalSourceMapDevToolModuleTemplatePlugin.js
|
||||
*/
|
||||
module.exports = function createEvalSourceMapMiddleware(server) {
|
||||
return function handleWebpackInternalMiddleware(req, res, next) {
|
||||
if (req.url.startsWith('/__get-internal-source')) {
|
||||
const fileName = req.query.fileName;
|
||||
const id = fileName.match(/webpack-internal:\/\/\/(.+)/)[1];
|
||||
if (!id || !server._stats) {
|
||||
next();
|
||||
}
|
||||
|
||||
const source = getSourceById(server, id);
|
||||
const sourceMapURL = `//# sourceMappingURL=${base64SourceMap(source)}`;
|
||||
const sourceURL = `//# sourceURL=webpack-internal:///${module.id}`;
|
||||
res.end(`${source.source()}\n${sourceMapURL}\n${sourceURL}`);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1,138 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
/* eslint-disable */
|
||||
/*
|
||||
* THIS FILE IS MODIFIED FOR DOCUSAURUS
|
||||
* the above copyright header must be preserved for license compliance.
|
||||
*/
|
||||
|
||||
/*
|
||||
Implementation has been copied from https://github.com/facebook/create-react-app/pull/10656
|
||||
*/
|
||||
|
||||
const friendlySyntaxErrorLabel = 'Syntax error:';
|
||||
|
||||
function isLikelyASyntaxError(message) {
|
||||
return message.indexOf(friendlySyntaxErrorLabel) !== -1;
|
||||
}
|
||||
|
||||
// Cleans up webpack error messages.
|
||||
function formatMessage(message) {
|
||||
let lines = [];
|
||||
|
||||
// modified for Docusaurus => see https://github.com/facebook/create-react-app/pull/10656
|
||||
if (typeof message === 'string') {
|
||||
lines = message.split('\n');
|
||||
} else if ('message' in message) {
|
||||
lines = message['message'].split('\n');
|
||||
} else if (Array.isArray(message)) {
|
||||
message.forEach((message) => {
|
||||
if ('message' in message) {
|
||||
lines = message['message'].split('\n');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Strip webpack-added headers off errors/warnings
|
||||
// https://github.com/webpack/webpack/blob/main/lib/ModuleError.js
|
||||
lines = lines.filter((line) => !/Module [A-z ]+\(from/.test(line));
|
||||
|
||||
// Transform parsing error into syntax error
|
||||
// TODO: move this to our ESLint formatter?
|
||||
lines = lines.map((line) => {
|
||||
const parsingError = /Line (\d+):(?:(\d+):)?\s*Parsing error: (.+)$/.exec(
|
||||
line,
|
||||
);
|
||||
if (!parsingError) {
|
||||
return line;
|
||||
}
|
||||
const [, errorLine, errorColumn, errorMessage] = parsingError;
|
||||
return `${friendlySyntaxErrorLabel} ${errorMessage} (${errorLine}:${errorColumn})`;
|
||||
});
|
||||
|
||||
message = lines.join('\n');
|
||||
// Smoosh syntax errors (commonly found in CSS)
|
||||
message = message.replace(
|
||||
/SyntaxError\s+\((\d+):(\d+)\)\s*(.+?)\n/g,
|
||||
`${friendlySyntaxErrorLabel} $3 ($1:$2)\n`,
|
||||
);
|
||||
// Clean up export errors
|
||||
message = message.replace(
|
||||
/^.*export '(.+?)' was not found in '(.+?)'.*$/gm,
|
||||
`Attempted import error: '$1' is not exported from '$2'.`,
|
||||
);
|
||||
message = message.replace(
|
||||
/^.*export 'default' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm,
|
||||
`Attempted import error: '$2' does not contain a default export (imported as '$1').`,
|
||||
);
|
||||
message = message.replace(
|
||||
/^.*export '(.+?)' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm,
|
||||
`Attempted import error: '$1' is not exported from '$3' (imported as '$2').`,
|
||||
);
|
||||
lines = message.split('\n');
|
||||
|
||||
// Remove leading newline
|
||||
if (lines.length > 2 && lines[1].trim() === '') {
|
||||
lines.splice(1, 1);
|
||||
}
|
||||
// Clean up file name
|
||||
lines[0] = lines[0].replace(/^(.*) \d+:\d+-\d+$/, '$1');
|
||||
|
||||
// Cleans up verbose "module not found" messages for files and packages.
|
||||
if (lines[1] && lines[1].indexOf('Module not found: ') === 0) {
|
||||
lines = [
|
||||
lines[0],
|
||||
lines[1]
|
||||
.replace('Error: ', '')
|
||||
.replace('Module not found: Cannot find file:', 'Cannot find file:'),
|
||||
];
|
||||
}
|
||||
|
||||
// Add helpful message for users trying to use Sass for the first time
|
||||
if (lines[1] && lines[1].match(/Cannot find module.+node-sass/)) {
|
||||
lines[1] = 'To import Sass files, you first need to install node-sass.\n';
|
||||
lines[1] +=
|
||||
'Run `npm install node-sass` or `yarn add node-sass` inside your workspace.';
|
||||
}
|
||||
|
||||
message = lines.join('\n');
|
||||
// Internal stacks are generally useless so we strip them... with the
|
||||
// exception of stacks containing `webpack:` because they're normally
|
||||
// from user code generated by webpack. For more information see
|
||||
// https://github.com/facebook/create-react-app/pull/1050
|
||||
message = message.replace(
|
||||
/^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm,
|
||||
'',
|
||||
); // at ... ...:x:y
|
||||
message = message.replace(/^\s*at\s<anonymous>(\n|$)/gm, ''); // at <anonymous>
|
||||
lines = message.split('\n');
|
||||
|
||||
// Remove duplicated newlines
|
||||
lines = lines.filter(
|
||||
(line, index, arr) =>
|
||||
index === 0 ||
|
||||
line.trim() !== '' ||
|
||||
line.trim() !== arr[index - 1].trim(),
|
||||
);
|
||||
|
||||
// Reassemble the message
|
||||
message = lines.join('\n');
|
||||
return message.trim();
|
||||
}
|
||||
|
||||
function formatWebpackMessages(json) {
|
||||
const formattedErrors = json.errors.map(formatMessage);
|
||||
const formattedWarnings = json.warnings.map(formatMessage);
|
||||
const result = {errors: formattedErrors, warnings: formattedWarnings};
|
||||
if (result.errors.some(isLikelyASyntaxError)) {
|
||||
// If there are any syntax errors, show just them.
|
||||
result.errors = result.errors.filter(isLikelyASyntaxError);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = formatWebpackMessages;
|
|
@ -1,285 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
/* eslint-disable */
|
||||
/*
|
||||
* THIS FILE IS MODIFIED FOR DOCUSAURUS
|
||||
* the above copyright header must be preserved for license compliance.
|
||||
*/
|
||||
|
||||
// This alternative WebpackDevServer combines the functionality of:
|
||||
// https://github.com/webpack/webpack-dev-server/blob/webpack-1/client/index.js
|
||||
// https://github.com/webpack/webpack/blob/webpack-1/hot/dev-server.js
|
||||
|
||||
// It only supports their simplest configuration (hot updates on same server).
|
||||
// It makes some opinionated choices on top, like adding a syntax error overlay
|
||||
// that looks similar to our console output. The error overlay is inspired by:
|
||||
// https://github.com/glenjamin/webpack-hot-middleware
|
||||
|
||||
var stripAnsi = require('strip-ansi');
|
||||
var url = require('url');
|
||||
var launchEditorEndpoint = require('react-dev-utils/launchEditorEndpoint'); // modified for Docusaurus
|
||||
var formatWebpackMessages = require('./formatWebpackMessages');
|
||||
var ErrorOverlay = require('react-error-overlay');
|
||||
|
||||
ErrorOverlay.setEditorHandler(function editorHandler(errorLocation) {
|
||||
// Keep this sync with errorOverlayMiddleware.js
|
||||
fetch(
|
||||
launchEditorEndpoint +
|
||||
'?fileName=' +
|
||||
window.encodeURIComponent(errorLocation.fileName) +
|
||||
'&lineNumber=' +
|
||||
window.encodeURIComponent(errorLocation.lineNumber || 1) +
|
||||
'&colNumber=' +
|
||||
window.encodeURIComponent(errorLocation.colNumber || 1),
|
||||
);
|
||||
});
|
||||
|
||||
// We need to keep track of if there has been a runtime error.
|
||||
// Essentially, we cannot guarantee application state was not corrupted by the
|
||||
// runtime error. To prevent confusing behavior, we forcibly reload the entire
|
||||
// application. This is handled below when we are notified of a compile (code
|
||||
// change).
|
||||
// See https://github.com/facebook/create-react-app/issues/3096
|
||||
var hadRuntimeError = false;
|
||||
ErrorOverlay.startReportingRuntimeErrors({
|
||||
onError: function () {
|
||||
hadRuntimeError = true;
|
||||
},
|
||||
filename: '/static/js/bundle.js',
|
||||
});
|
||||
|
||||
if (module.hot && typeof module.hot.dispose === 'function') {
|
||||
module.hot.dispose(function () {
|
||||
// TODO: why do we need this?
|
||||
ErrorOverlay.stopReportingRuntimeErrors();
|
||||
});
|
||||
}
|
||||
|
||||
// Connect to WebpackDevServer via a socket.
|
||||
var connection = new WebSocket(
|
||||
url.format({
|
||||
protocol: window.location.protocol === 'https:' ? 'wss' : 'ws',
|
||||
// modified for Docusaurus => avoid "ReferenceError: process is not defined"
|
||||
hostname: window.location.hostname,
|
||||
port: window.location.port,
|
||||
// Hardcoded in WebpackDevServer
|
||||
pathname: '/sockjs-node',
|
||||
slashes: true,
|
||||
}),
|
||||
);
|
||||
|
||||
// Unlike WebpackDevServer client, we won't try to reconnect
|
||||
// to avoid spamming the console. Disconnect usually happens
|
||||
// when developer stops the server.
|
||||
connection.onclose = function () {
|
||||
if (typeof console !== 'undefined' && typeof console.info === 'function') {
|
||||
console.info(
|
||||
'The development server has disconnected.\nRefresh the page if necessary.',
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Remember some state related to hot module replacement.
|
||||
var isFirstCompilation = true;
|
||||
var mostRecentCompilationHash = null;
|
||||
var hasCompileErrors = false;
|
||||
|
||||
function clearOutdatedErrors() {
|
||||
// Clean up outdated compile errors, if any.
|
||||
if (typeof console !== 'undefined' && typeof console.clear === 'function') {
|
||||
if (hasCompileErrors) {
|
||||
console.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Successful compilation.
|
||||
function handleSuccess() {
|
||||
clearOutdatedErrors();
|
||||
|
||||
var isHotUpdate = !isFirstCompilation;
|
||||
isFirstCompilation = false;
|
||||
hasCompileErrors = false;
|
||||
|
||||
// Attempt to apply hot updates or reload.
|
||||
if (isHotUpdate) {
|
||||
tryApplyUpdates(function onHotUpdateSuccess() {
|
||||
// Only dismiss it when we're sure it's a hot update.
|
||||
// Otherwise it would flicker right before the reload.
|
||||
tryDismissErrorOverlay();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Compilation with warnings (e.g. ESLint).
|
||||
function handleWarnings(warnings) {
|
||||
clearOutdatedErrors();
|
||||
|
||||
var isHotUpdate = !isFirstCompilation;
|
||||
isFirstCompilation = false;
|
||||
hasCompileErrors = false;
|
||||
|
||||
function printWarnings() {
|
||||
// Print warnings to the console.
|
||||
var formatted = formatWebpackMessages({
|
||||
warnings: warnings,
|
||||
errors: [],
|
||||
});
|
||||
|
||||
if (typeof console !== 'undefined' && typeof console.warn === 'function') {
|
||||
for (var i = 0; i < formatted.warnings.length; i++) {
|
||||
if (i === 5) {
|
||||
console.warn(
|
||||
'There were more warnings in other files.\n' +
|
||||
'You can find a complete log in the terminal.',
|
||||
);
|
||||
break;
|
||||
}
|
||||
console.warn(stripAnsi(formatted.warnings[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printWarnings();
|
||||
|
||||
// Attempt to apply hot updates or reload.
|
||||
if (isHotUpdate) {
|
||||
tryApplyUpdates(function onSuccessfulHotUpdate() {
|
||||
// Only dismiss it when we're sure it's a hot update.
|
||||
// Otherwise it would flicker right before the reload.
|
||||
tryDismissErrorOverlay();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Compilation with errors (e.g. syntax error or missing modules).
|
||||
function handleErrors(errors) {
|
||||
clearOutdatedErrors();
|
||||
|
||||
isFirstCompilation = false;
|
||||
hasCompileErrors = true;
|
||||
|
||||
// "Massage" webpack messages.
|
||||
var formatted = formatWebpackMessages({
|
||||
errors: errors,
|
||||
warnings: [],
|
||||
});
|
||||
|
||||
// Only show the first error.
|
||||
ErrorOverlay.reportBuildError(formatted.errors[0]);
|
||||
|
||||
// Also log them to the console.
|
||||
if (typeof console !== 'undefined' && typeof console.error === 'function') {
|
||||
for (var i = 0; i < formatted.errors.length; i++) {
|
||||
console.error(stripAnsi(formatted.errors[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// Do not attempt to reload now.
|
||||
// We will reload on next success instead.
|
||||
}
|
||||
|
||||
function tryDismissErrorOverlay() {
|
||||
if (!hasCompileErrors) {
|
||||
ErrorOverlay.dismissBuildError();
|
||||
}
|
||||
}
|
||||
|
||||
// There is a newer version of the code available.
|
||||
function handleAvailableHash(hash) {
|
||||
// Update last known compilation hash.
|
||||
mostRecentCompilationHash = hash;
|
||||
}
|
||||
|
||||
// Handle messages from the server.
|
||||
connection.onmessage = function (e) {
|
||||
var message = JSON.parse(e.data);
|
||||
switch (message.type) {
|
||||
case 'hash':
|
||||
handleAvailableHash(message.data);
|
||||
break;
|
||||
case 'still-ok':
|
||||
case 'ok':
|
||||
handleSuccess();
|
||||
break;
|
||||
case 'content-changed':
|
||||
// Triggered when a file from `contentBase` changed.
|
||||
window.location.reload();
|
||||
break;
|
||||
case 'warnings':
|
||||
handleWarnings(message.data);
|
||||
break;
|
||||
case 'errors':
|
||||
handleErrors(message.data);
|
||||
break;
|
||||
default:
|
||||
// Do nothing.
|
||||
}
|
||||
};
|
||||
|
||||
// Is there a newer version of this code available?
|
||||
function isUpdateAvailable() {
|
||||
/* globals __webpack_hash__ */
|
||||
// __webpack_hash__ is the hash of the current compilation.
|
||||
// It's a global variable injected by webpack.
|
||||
return mostRecentCompilationHash !== __webpack_hash__;
|
||||
}
|
||||
|
||||
// webpack disallows updates in other states.
|
||||
function canApplyUpdates() {
|
||||
return module.hot.status() === 'idle';
|
||||
}
|
||||
|
||||
// Attempt to update code on the fly, fall back to a hard reload.
|
||||
function tryApplyUpdates(onHotUpdateSuccess) {
|
||||
if (!module.hot) {
|
||||
// HotModuleReplacementPlugin is not in webpack configuration.
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isUpdateAvailable() || !canApplyUpdates()) {
|
||||
return;
|
||||
}
|
||||
|
||||
function handleApplyUpdates(err, updatedModules) {
|
||||
// NOTE: This var is injected by Webpack's DefinePlugin, and is a boolean instead of string.
|
||||
// const hasReactRefresh = process.env.FAST_REFRESH;
|
||||
const hasReactRefresh = true; // modified for Docusaurus => avoid "ReferenceError: process is not defined"
|
||||
const wantsForcedReload = err || !updatedModules || hadRuntimeError;
|
||||
// React refresh can handle hot-reloading over errors.
|
||||
if (!hasReactRefresh && wantsForcedReload) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof onHotUpdateSuccess === 'function') {
|
||||
// Maybe we want to do something.
|
||||
onHotUpdateSuccess();
|
||||
}
|
||||
|
||||
if (isUpdateAvailable()) {
|
||||
// While we were updating, there was a new update! Do it again.
|
||||
tryApplyUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
// https://webpack.github.io/docs/hot-module-replacement.html#check
|
||||
var result = module.hot.check(/* autoApply */ true, handleApplyUpdates);
|
||||
|
||||
// // webpack 2 returns a Promise instead of invoking a callback
|
||||
if (result && result.then) {
|
||||
result.then(
|
||||
function (updatedModules) {
|
||||
handleApplyUpdates(null, updatedModules);
|
||||
},
|
||||
function (err) {
|
||||
handleApplyUpdates(err, null);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue