120 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| /* eslint-disable max-classes-per-file */
 | |
| 
 | |
| const path = require('path');
 | |
| const { History, HistoryWithTTL } = require('./history');
 | |
| const log = require('./log');
 | |
| 
 | |
| const onRequestEntryPoint = (callback) => {
 | |
|   return (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
 | |
|   createMiddleware() {
 | |
|     return null;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * 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);
 | |
|   }
 | |
| 
 | |
|   createMiddleware() {
 | |
|     return onRequestEntryPoint((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}`);
 | |
|   }
 | |
| 
 | |
|   createMiddleware(devServer) {
 | |
|     return onRequestEntryPoint((entryPoint) => {
 | |
|       const wasVisitedRecently = this.history.onRequestEntryPoint(entryPoint);
 | |
|       if (!wasVisitedRecently) {
 | |
|         log(`Have not visited ${entryPoint} recently. Adding to compilation.`);
 | |
| 
 | |
|         setTimeout(() => {
 | |
|           devServer.invalidate(() => {
 | |
|             if (devServer.sockets) {
 | |
|               devServer.sendMessage(devServer.webSocketServer.clients, 'static-changed');
 | |
|             }
 | |
|           });
 | |
|         }, TIMEOUT);
 | |
|       }
 | |
|     });
 | |
|   }
 | |
| }
 | |
| 
 | |
| module.exports = {
 | |
|   NoopCompiler,
 | |
|   HistoryOnlyCompiler,
 | |
|   IncrementalWebpackCompiler,
 | |
| };
 |