Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'config/helpers/incremental_webpack_compiler/compiler.js')
-rw-r--r--config/helpers/incremental_webpack_compiler/compiler.js117
1 files changed, 117 insertions, 0 deletions
diff --git a/config/helpers/incremental_webpack_compiler/compiler.js b/config/helpers/incremental_webpack_compiler/compiler.js
new file mode 100644
index 00000000000..480d7fa3263
--- /dev/null
+++ b/config/helpers/incremental_webpack_compiler/compiler.js
@@ -0,0 +1,117 @@
+/* eslint-disable max-classes-per-file */
+
+const path = require('path');
+const { History, HistoryWithTTL } = require('./history');
+const log = require('./log');
+
+const onRequestEntryPoint = (app, callback) => {
+ app.use((req, res, next) => {
+ const fileName = path.basename(req.url);
+
+ /**
+ * We are only interested in files that have a name like `pages.foo.bar.chunk.js`
+ * because those are the ones corresponding to our entry points.
+ *
+ * This filters out hot update files that are for example named "pages.foo.bar.[hash].hot-update.js"
+ */
+ if (fileName.startsWith('pages.') && fileName.endsWith('.chunk.js')) {
+ const entryPoint = fileName.replace(/\.chunk\.js$/, '');
+ callback(entryPoint);
+ }
+
+ next();
+ });
+};
+
+/**
+ * The NoopCompiler does nothing, following the null object pattern.
+ */
+class NoopCompiler {
+ constructor() {
+ this.enabled = false;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ filterEntryPoints(entryPoints) {
+ return entryPoints;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ logStatus() {}
+
+ // eslint-disable-next-line class-methods-use-this
+ setupMiddleware() {}
+}
+
+/**
+ * The HistoryOnlyCompiler only records which entry points have been requested.
+ * This is so that if the user disables incremental compilation, history is
+ * still recorded. If they later enable incremental compilation, that history
+ * can be used.
+ */
+class HistoryOnlyCompiler extends NoopCompiler {
+ constructor(historyFilePath) {
+ super();
+ this.history = new History(historyFilePath);
+ }
+
+ setupMiddleware(app) {
+ onRequestEntryPoint(app, (entryPoint) => {
+ this.history.onRequestEntryPoint(entryPoint);
+ });
+ }
+}
+
+// If we force a recompile immediately, the page reload doesn't seem to work.
+// Five seconds seem to work fine and the user can read the message
+const TIMEOUT = 5000;
+
+/**
+ * The IncrementalWebpackCompiler tracks which entry points have been
+ * requested, and only compiles entry points visited within the last `ttl`
+ * days.
+ */
+class IncrementalWebpackCompiler {
+ constructor(historyFilePath, ttl) {
+ this.enabled = true;
+ this.history = new HistoryWithTTL(historyFilePath, ttl);
+ }
+
+ filterEntryPoints(entrypoints) {
+ return Object.fromEntries(
+ Object.entries(entrypoints).map(([entryPoint, paths]) => {
+ if (this.history.isRecentlyVisited(entryPoint)) {
+ return [entryPoint, paths];
+ }
+ return [entryPoint, ['./webpack_non_compiled_placeholder.js']];
+ }),
+ );
+ }
+
+ logStatus(totalCount) {
+ log(`Currently compiling route entrypoints: ${this.history.size} of ${totalCount}`);
+ }
+
+ setupMiddleware(app, server) {
+ onRequestEntryPoint(app, (entryPoint) => {
+ const wasVisitedRecently = this.history.onRequestEntryPoint(entryPoint);
+ if (!wasVisitedRecently) {
+ log(`Have not visited ${entryPoint} recently. Adding to compilation.`);
+
+ setTimeout(() => {
+ server.middleware.invalidate(() => {
+ if (server.sockets) {
+ server.sockWrite(server.sockets, 'content-changed');
+ }
+ });
+ }, TIMEOUT);
+ }
+ });
+ }
+}
+
+module.exports = {
+ NoopCompiler,
+ HistoryOnlyCompiler,
+ IncrementalWebpackCompiler,
+};