mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			283 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			283 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
/* globals describe, it */
 | 
						|
"use strict";
 | 
						|
 | 
						|
const path = require("path");
 | 
						|
const fs = require("fs");
 | 
						|
const rimraf = require("rimraf");
 | 
						|
 | 
						|
const webpack = require("../");
 | 
						|
const WebpackOptionsDefaulter = require("../lib/WebpackOptionsDefaulter");
 | 
						|
let fixtureCount = 0;
 | 
						|
 | 
						|
describe("Compiler (caching)", () => {
 | 
						|
	jest.setTimeout(15000);
 | 
						|
 | 
						|
	function compile(entry, options, callback) {
 | 
						|
		options.mode = "none";
 | 
						|
		options = new WebpackOptionsDefaulter().process(options);
 | 
						|
		options.cache = true;
 | 
						|
		options.entry = entry;
 | 
						|
		options.optimization.minimize = false;
 | 
						|
		options.context = path.join(__dirname, "fixtures");
 | 
						|
		options.output.path = "/";
 | 
						|
		options.output.filename = "bundle.js";
 | 
						|
		options.output.pathinfo = true;
 | 
						|
		const logs = {
 | 
						|
			mkdirp: [],
 | 
						|
			writeFile: []
 | 
						|
		};
 | 
						|
 | 
						|
		const c = webpack(options);
 | 
						|
		const files = {};
 | 
						|
		c.outputFileSystem = {
 | 
						|
			join() {
 | 
						|
				return [].join.call(arguments, "/").replace(/\/+/g, "/");
 | 
						|
			},
 | 
						|
			mkdirp(path, callback) {
 | 
						|
				logs.mkdirp.push(path);
 | 
						|
				callback();
 | 
						|
			},
 | 
						|
			writeFile(name, content, callback) {
 | 
						|
				logs.writeFile.push(name, content);
 | 
						|
				files[name] = content.toString("utf-8");
 | 
						|
				callback();
 | 
						|
			}
 | 
						|
		};
 | 
						|
		c.hooks.compilation.tap(
 | 
						|
			"CompilerCachingTest",
 | 
						|
			compilation => (compilation.bail = true)
 | 
						|
		);
 | 
						|
 | 
						|
		let compilerIteration = 1;
 | 
						|
 | 
						|
		function runCompiler(options, callback) {
 | 
						|
			if (typeof options === "function") {
 | 
						|
				callback = options;
 | 
						|
				options = {};
 | 
						|
			}
 | 
						|
			c.run((err, stats) => {
 | 
						|
				if (err) throw err;
 | 
						|
				expect(typeof stats).toBe("object");
 | 
						|
				stats = stats.toJson({
 | 
						|
					modules: true,
 | 
						|
					reasons: true
 | 
						|
				});
 | 
						|
				expect(typeof stats).toBe("object");
 | 
						|
				expect(stats).toHaveProperty("errors");
 | 
						|
				expect(Array.isArray(stats.errors)).toBe(true);
 | 
						|
				if (options.expectErrors) {
 | 
						|
					expect(stats.errors).toHaveLength(options.expectErrors);
 | 
						|
				} else {
 | 
						|
					if (stats.errors.length > 0) {
 | 
						|
						expect(typeof stats.errors[0]).toBe("string");
 | 
						|
						throw new Error(stats.errors[0]);
 | 
						|
					}
 | 
						|
				}
 | 
						|
				stats.logs = logs;
 | 
						|
				callback(stats, files, compilerIteration++);
 | 
						|
			});
 | 
						|
		}
 | 
						|
 | 
						|
		runCompiler(callback);
 | 
						|
 | 
						|
		return {
 | 
						|
			compilerInstance: c,
 | 
						|
			runAgain: runCompiler
 | 
						|
		};
 | 
						|
	}
 | 
						|
 | 
						|
	const tempFixturePath = path.join(
 | 
						|
		__dirname,
 | 
						|
		"fixtures",
 | 
						|
		"temp-cache-fixture"
 | 
						|
	);
 | 
						|
 | 
						|
	function cleanup() {
 | 
						|
		rimraf.sync(`${tempFixturePath}-*`);
 | 
						|
	}
 | 
						|
 | 
						|
	beforeAll(cleanup);
 | 
						|
	afterAll(cleanup);
 | 
						|
 | 
						|
	function createTempFixture() {
 | 
						|
		const fixturePath = `${tempFixturePath}-${fixtureCount}`;
 | 
						|
		const aFilepath = path.join(fixturePath, "a.js");
 | 
						|
		const cFilepath = path.join(fixturePath, "c.js");
 | 
						|
 | 
						|
		// Remove previous copy if present
 | 
						|
		rimraf.sync(fixturePath);
 | 
						|
 | 
						|
		// Copy over file since we"ll be modifying some of them
 | 
						|
		fs.mkdirSync(fixturePath);
 | 
						|
		fs.createReadStream(path.join(__dirname, "fixtures", "a.js")).pipe(
 | 
						|
			fs.createWriteStream(aFilepath)
 | 
						|
		);
 | 
						|
		fs.createReadStream(path.join(__dirname, "fixtures", "c.js")).pipe(
 | 
						|
			fs.createWriteStream(cFilepath)
 | 
						|
		);
 | 
						|
 | 
						|
		fixtureCount++;
 | 
						|
		return {
 | 
						|
			rootPath: fixturePath,
 | 
						|
			aFilepath: aFilepath,
 | 
						|
			cFilepath: cFilepath
 | 
						|
		};
 | 
						|
	}
 | 
						|
 | 
						|
	it("should cache single file (with manual 1s wait) ", done => {
 | 
						|
		const options = {};
 | 
						|
		const tempFixture = createTempFixture();
 | 
						|
 | 
						|
		const helper = compile(tempFixture.cFilepath, options, (stats, files) => {
 | 
						|
			// Not cached the first time
 | 
						|
			expect(stats.assets[0].name).toBe("bundle.js");
 | 
						|
			expect(stats.assets[0].emitted).toBe(true);
 | 
						|
 | 
						|
			helper.runAgain((stats, files, iteration) => {
 | 
						|
				// Cached the second run
 | 
						|
				expect(stats.assets[0].name).toBe("bundle.js");
 | 
						|
				expect(stats.assets[0].emitted).toBe(false);
 | 
						|
 | 
						|
				const aContent = fs
 | 
						|
					.readFileSync(tempFixture.aFilepath)
 | 
						|
					.toString()
 | 
						|
					.replace("This is a", "This is a MODIFIED");
 | 
						|
 | 
						|
				setTimeout(() => {
 | 
						|
					fs.writeFileSync(tempFixture.aFilepath, aContent);
 | 
						|
 | 
						|
					helper.runAgain((stats, files, iteration) => {
 | 
						|
						// Cached the third run
 | 
						|
						expect(stats.assets[0].name).toBe("bundle.js");
 | 
						|
						expect(stats.assets[0].emitted).toBe(true);
 | 
						|
 | 
						|
						done();
 | 
						|
					});
 | 
						|
				}, 1100);
 | 
						|
			});
 | 
						|
		});
 | 
						|
	});
 | 
						|
 | 
						|
	it("should cache single file (even with no timeout) ", done => {
 | 
						|
		const options = {};
 | 
						|
		const tempFixture = createTempFixture();
 | 
						|
 | 
						|
		const helper = compile(tempFixture.cFilepath, options, (stats, files) => {
 | 
						|
			// Not cached the first time
 | 
						|
			expect(stats.assets[0].name).toBe("bundle.js");
 | 
						|
			expect(stats.assets[0].emitted).toBe(true);
 | 
						|
 | 
						|
			helper.runAgain((stats, files, iteration) => {
 | 
						|
				// Cached the second run
 | 
						|
				expect(stats.assets[0].name).toBe("bundle.js");
 | 
						|
				expect(stats.assets[0].emitted).toBe(false);
 | 
						|
 | 
						|
				expect(files["/bundle.js"]).toMatch("This is a");
 | 
						|
 | 
						|
				const aContent = fs
 | 
						|
					.readFileSync(tempFixture.aFilepath)
 | 
						|
					.toString()
 | 
						|
					.replace("This is a", "This is a MODIFIED");
 | 
						|
 | 
						|
				fs.writeFileSync(tempFixture.aFilepath, aContent);
 | 
						|
 | 
						|
				helper.runAgain((stats, files, iteration) => {
 | 
						|
					// Cached the third run
 | 
						|
					expect(stats.assets[0].name).toBe("bundle.js");
 | 
						|
					expect(stats.assets[0].emitted).toBe(true);
 | 
						|
 | 
						|
					expect(files["/bundle.js"]).toMatch("This is a MODIFIED");
 | 
						|
 | 
						|
					done();
 | 
						|
				});
 | 
						|
			});
 | 
						|
		});
 | 
						|
	});
 | 
						|
 | 
						|
	it("should only build when modified (with manual 2s wait)", done => {
 | 
						|
		const options = {};
 | 
						|
		const tempFixture = createTempFixture();
 | 
						|
 | 
						|
		const helper = compile(tempFixture.cFilepath, options, (stats, files) => {
 | 
						|
			// Built the first time
 | 
						|
			expect(stats.modules[0].name).toMatch("c.js");
 | 
						|
			expect(stats.modules[0].built).toBe(true);
 | 
						|
 | 
						|
			expect(stats.modules[1].name).toMatch("a.js");
 | 
						|
			expect(stats.modules[1].built).toBe(true);
 | 
						|
 | 
						|
			setTimeout(() => {
 | 
						|
				helper.runAgain((stats, files, iteration) => {
 | 
						|
					// Not built when cached the second run
 | 
						|
					expect(stats.modules[0].name).toMatch("c.js");
 | 
						|
					// expect(stats.modules[0].built).toBe(false);
 | 
						|
 | 
						|
					expect(stats.modules[1].name).toMatch("a.js");
 | 
						|
					// expect(stats.modules[1].built).toBe(false);
 | 
						|
 | 
						|
					const aContent = fs
 | 
						|
						.readFileSync(tempFixture.aFilepath)
 | 
						|
						.toString()
 | 
						|
						.replace("This is a", "This is a MODIFIED");
 | 
						|
 | 
						|
					setTimeout(() => {
 | 
						|
						fs.writeFileSync(tempFixture.aFilepath, aContent);
 | 
						|
 | 
						|
						helper.runAgain((stats, files, iteration) => {
 | 
						|
							// And only a.js built after it was modified
 | 
						|
							expect(stats.modules[0].name).toMatch("c.js");
 | 
						|
							expect(stats.modules[0].built).toBe(false);
 | 
						|
 | 
						|
							expect(stats.modules[1].name).toMatch("a.js");
 | 
						|
							expect(stats.modules[1].built).toBe(true);
 | 
						|
 | 
						|
							done();
 | 
						|
						});
 | 
						|
					}, 2100);
 | 
						|
				});
 | 
						|
			}, 4100);
 | 
						|
		});
 | 
						|
	});
 | 
						|
 | 
						|
	it("should build when modified (even with no timeout)", done => {
 | 
						|
		const options = {};
 | 
						|
		const tempFixture = createTempFixture();
 | 
						|
 | 
						|
		const helper = compile(tempFixture.cFilepath, options, (stats, files) => {
 | 
						|
			// Built the first time
 | 
						|
			expect(stats.modules[0].name).toMatch("c.js");
 | 
						|
			expect(stats.modules[0].built).toBe(true);
 | 
						|
 | 
						|
			expect(stats.modules[1].name).toMatch("a.js");
 | 
						|
			expect(stats.modules[1].built).toBe(true);
 | 
						|
 | 
						|
			helper.runAgain((stats, files, iteration) => {
 | 
						|
				// Not built when cached the second run
 | 
						|
				expect(stats.modules[0].name).toMatch("c.js");
 | 
						|
				// expect(stats.modules[0].built).toBe(false);
 | 
						|
 | 
						|
				expect(stats.modules[1].name).toMatch("a.js");
 | 
						|
				// expect(stats.modules[1].built).toBe(false);
 | 
						|
 | 
						|
				const aContent = fs
 | 
						|
					.readFileSync(tempFixture.aFilepath)
 | 
						|
					.toString()
 | 
						|
					.replace("This is a", "This is a MODIFIED");
 | 
						|
 | 
						|
				fs.writeFileSync(tempFixture.aFilepath, aContent);
 | 
						|
 | 
						|
				helper.runAgain((stats, files, iteration) => {
 | 
						|
					// And only a.js built after it was modified
 | 
						|
					expect(stats.modules[0].name).toMatch("c.js");
 | 
						|
					// expect(stats.modules[0].built).toBe(false);
 | 
						|
 | 
						|
					expect(stats.modules[1].name).toMatch("a.js");
 | 
						|
					expect(stats.modules[1].built).toBe(true);
 | 
						|
 | 
						|
					done();
 | 
						|
				});
 | 
						|
			});
 | 
						|
		});
 | 
						|
	});
 | 
						|
});
 |