mirror of https://github.com/webpack/webpack.git
273 lines
7.4 KiB
JavaScript
273 lines
7.4 KiB
JavaScript
"use strict";
|
|
|
|
require("./helpers/warmup-webpack");
|
|
|
|
const path = require("path");
|
|
const fs = require("graceful-fs");
|
|
const rimraf = require("rimraf");
|
|
|
|
let fixtureCount = 0;
|
|
|
|
describe("Compiler (filesystem caching)", () => {
|
|
jest.setTimeout(5000);
|
|
|
|
const tempFixturePath = path.join(
|
|
__dirname,
|
|
"fixtures",
|
|
"temp-filesystem-cache-fixture"
|
|
);
|
|
|
|
function compile(entry, onSuccess, onError) {
|
|
const webpack = require("..");
|
|
|
|
const options = webpack.config.getNormalizedWebpackOptions({});
|
|
options.cache = {
|
|
type: "filesystem",
|
|
cacheDirectory: path.join(tempFixturePath, "cache")
|
|
};
|
|
options.entry = entry;
|
|
options.context = path.join(__dirname, "fixtures");
|
|
options.output.path = path.join(tempFixturePath, "dist");
|
|
options.output.filename = "bundle.js";
|
|
options.output.pathinfo = true;
|
|
options.module = {
|
|
rules: [
|
|
{
|
|
test: /\.svg$/,
|
|
type: "asset/resource",
|
|
use: {
|
|
loader: require.resolve("./fixtures/empty-svg-loader")
|
|
}
|
|
}
|
|
]
|
|
};
|
|
|
|
const isBigIntSupported = typeof BigInt !== "undefined";
|
|
const isErrorCaseSupported =
|
|
typeof new Error("test", { cause: new Error("cause") }).cause !==
|
|
"undefined";
|
|
const isAggregateErrorSupported = typeof AggregateError !== "undefined";
|
|
|
|
options.plugins = [
|
|
{
|
|
apply(compiler) {
|
|
const name = "TestCachePlugin";
|
|
|
|
compiler.hooks.thisCompilation.tap(name, (compilation) => {
|
|
compilation.hooks.processAssets.tapPromise(
|
|
{
|
|
name,
|
|
stage:
|
|
compiler.webpack.Compilation
|
|
.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE
|
|
},
|
|
async () => {
|
|
const cache = compilation.getCache(name);
|
|
const ident = "test.ext";
|
|
const cacheItem = cache.getItemCache(ident, null);
|
|
|
|
const result = await cacheItem.getPromise(ident);
|
|
|
|
if (result) {
|
|
expect(result.number).toBe(42);
|
|
expect(result.number1).toBe(3.14);
|
|
expect(result.number2).toBe(6.2);
|
|
expect(result.string).toBe("string");
|
|
|
|
if (isErrorCaseSupported) {
|
|
expect(result.error.cause.message).toBe("cause");
|
|
expect(result.error1.cause.string).toBe("string");
|
|
expect(result.error1.cause.number).toBe(42);
|
|
}
|
|
|
|
if (isAggregateErrorSupported) {
|
|
expect(result.aggregateError.errors).toEqual([
|
|
new Error("first", { cause: "nested cause" }),
|
|
"second"
|
|
]);
|
|
expect(result.aggregateError.message).toBe(
|
|
"aggregate error"
|
|
);
|
|
expect(result.aggregateError.cause.message).toBe("cause");
|
|
}
|
|
|
|
if (isBigIntSupported) {
|
|
expect(result.bigint).toBe(5n);
|
|
expect(result.bigint1).toBe(124n);
|
|
expect(result.bigint2).toBe(125n);
|
|
expect(result.bigint3).toBe(12345678901234567890n);
|
|
expect(result.bigint4).toBe(5n);
|
|
expect(result.bigint5).toBe(1000000n);
|
|
expect(result.bigint6).toBe(128n);
|
|
expect(result.bigint7).toBe(2147483647n);
|
|
expect(result.obj.foo).toBe(BigInt(-10));
|
|
expect([...result.set]).toEqual([BigInt(1), BigInt(2)]);
|
|
expect(result.arr).toEqual([256n, 257n, 258n]);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
const storeValue = {};
|
|
|
|
storeValue.number = 42;
|
|
storeValue.number1 = 3.14;
|
|
storeValue.number2 = 6.2;
|
|
storeValue.string = "string";
|
|
|
|
if (isErrorCaseSupported) {
|
|
storeValue.error = new Error("error", {
|
|
cause: new Error("cause")
|
|
});
|
|
storeValue.error1 = new Error("error", {
|
|
cause: { string: "string", number: 42 }
|
|
});
|
|
}
|
|
|
|
if (isAggregateErrorSupported) {
|
|
storeValue.aggregateError = new AggregateError(
|
|
[new Error("first", { cause: "nested cause" }), "second"],
|
|
"aggregate error",
|
|
{ cause: new Error("cause") }
|
|
);
|
|
}
|
|
|
|
if (isBigIntSupported) {
|
|
storeValue.bigint = BigInt(5);
|
|
storeValue.bigint1 = BigInt(124);
|
|
storeValue.bigint2 = BigInt(125);
|
|
storeValue.bigint3 = 12345678901234567890n;
|
|
storeValue.bigint4 = 5n;
|
|
storeValue.bigint5 = 1000000n;
|
|
storeValue.bigint6 = 128n;
|
|
storeValue.bigint7 = 2147483647n;
|
|
storeValue.obj = { foo: BigInt(-10) };
|
|
storeValue.set = new Set([BigInt(1), BigInt(2)]);
|
|
storeValue.arr = [256n, 257n, 258n];
|
|
}
|
|
|
|
await cacheItem.storePromise(storeValue);
|
|
}
|
|
);
|
|
});
|
|
}
|
|
}
|
|
];
|
|
|
|
function runCompiler(onSuccess, onError) {
|
|
const c = webpack(options);
|
|
c.hooks.compilation.tap(
|
|
"CompilerCachingTest",
|
|
(compilation) => (compilation.bail = true)
|
|
);
|
|
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 (stats.errors.length > 0) {
|
|
onError(new Error(JSON.stringify(stats.errors, null, 4)));
|
|
}
|
|
c.close(() => {
|
|
onSuccess(stats);
|
|
});
|
|
});
|
|
}
|
|
|
|
runCompiler(onSuccess, onError);
|
|
|
|
return {
|
|
runAgain: runCompiler
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @returns {void}
|
|
*/
|
|
function cleanup() {
|
|
rimraf.sync(`${tempFixturePath}*`);
|
|
}
|
|
|
|
beforeAll(cleanup);
|
|
|
|
afterAll(cleanup);
|
|
|
|
/**
|
|
* @returns {{ rootPath: string, usesAssetFilepath: string, svgFilepath: string }} temp fixture paths
|
|
*/
|
|
function createTempFixture() {
|
|
const fixturePath = `${tempFixturePath}-${fixtureCount}`;
|
|
const usesAssetFilepath = path.join(fixturePath, "uses-asset.js");
|
|
const svgFilepath = path.join(fixturePath, "file.svg");
|
|
|
|
// Remove previous copy if present
|
|
rimraf.sync(fixturePath);
|
|
|
|
// Copy over file since we"ll be modifying some of them
|
|
fs.mkdirSync(fixturePath);
|
|
fs.copyFileSync(
|
|
path.join(__dirname, "fixtures", "uses-asset.js"),
|
|
usesAssetFilepath
|
|
);
|
|
fs.copyFileSync(path.join(__dirname, "fixtures", "file.svg"), svgFilepath);
|
|
|
|
fixtureCount++;
|
|
return {
|
|
rootPath: fixturePath,
|
|
usesAssetFilepath,
|
|
svgFilepath
|
|
};
|
|
}
|
|
|
|
it("should compile again when cached asset has changed but loader output remains the same", (done) => {
|
|
const tempFixture = createTempFixture();
|
|
|
|
const onError = (error) => done(error);
|
|
|
|
const helper = compile(
|
|
tempFixture.usesAssetFilepath,
|
|
(stats) => {
|
|
// Not cached the first time
|
|
expect(stats.assets[0].name).toBe("bundle.js");
|
|
expect(stats.assets[0].emitted).toBe(true);
|
|
|
|
expect(stats.assets[1].name).toMatch(/\w+\.svg$/);
|
|
expect(stats.assets[0].emitted).toBe(true);
|
|
|
|
helper.runAgain((stats) => {
|
|
// Cached the second run
|
|
expect(stats.assets[0].name).toBe("bundle.js");
|
|
expect(stats.assets[0].emitted).toBe(false);
|
|
|
|
expect(stats.assets[1].name).toMatch(/\w+\.svg$/);
|
|
expect(stats.assets[0].emitted).toBe(false);
|
|
|
|
const svgContent = fs
|
|
.readFileSync(tempFixture.svgFilepath)
|
|
.toString()
|
|
.replace("icon-square-small", "icon-square-smaller");
|
|
|
|
fs.writeFileSync(tempFixture.svgFilepath, svgContent);
|
|
|
|
helper.runAgain((stats) => {
|
|
// Still cached after file modification because loader always returns empty
|
|
expect(stats.assets[0].name).toBe("bundle.js");
|
|
expect(stats.assets[0].emitted).toBe(false);
|
|
|
|
expect(stats.assets[1].name).toMatch(/\w+\.svg$/);
|
|
expect(stats.assets[0].emitted).toBe(false);
|
|
|
|
done();
|
|
}, onError);
|
|
}, onError);
|
|
},
|
|
onError
|
|
);
|
|
});
|
|
});
|