Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 54 additions & 65 deletions e2e/cases/cache/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,108 +1,97 @@
import fs from 'node:fs';
import path from 'node:path';
import { build, webpackOnlyTest } from '@e2e/helper';
import { expect } from '@playwright/test';
import { build } from '@e2e/helper';
import { expect, test } from '@playwright/test';
import type { RsbuildConfig } from '@rsbuild/core';
import fse from 'fs-extra';

webpackOnlyTest(
'should save the buildDependencies to cache directory and hit cache',
async () => {
const cacheDirectory = path.resolve(
__dirname,
'./node_modules/.cache/webpack',
);

process.env.TEST_ENV = undefined;

const buildConfig = {
cwd: __dirname,
rsbuildConfig: {
tools: {
bundlerChain: (chain: any) => {
if (process.env.TEST_ENV === 'a') {
chain.resolve.extensions.prepend('.a.js');
}
},
test('should save the buildDependencies to cache directory and hit cache', async () => {
const cacheDirectory = path.resolve(
__dirname,
'./node_modules/.cache/test-build-dependencies',
);

process.env.TEST_ENV = undefined;

const buildConfig = {
cwd: __dirname,
rsbuildConfig: {
tools: {
bundlerChain: (chain) => {
if (process.env.TEST_ENV === 'a') {
chain.resolve.extensions.prepend('.test.js');
}
},
performance: {
buildCache: {
cacheDirectory,
},
},
performance: {
buildCache: {
cacheDirectory,
},
},
};
} as RsbuildConfig,
};

const configFile = path.resolve(cacheDirectory, 'buildDependencies.json');
const configFile = path.resolve(cacheDirectory, 'buildDependencies.json');

fs.rmSync(cacheDirectory, { recursive: true, force: true });
fs.rmSync(cacheDirectory, { recursive: true, force: true });

// first build no cache
let rsbuild = await build(buildConfig);
// first build without cache
let rsbuild = await build(buildConfig);

expect(
(await rsbuild.getIndexFile()).content.includes('222222'),
).toBeTruthy();
expect(
(await rsbuild.getIndexFile()).content.includes('222222'),
).toBeTruthy();

const buildDependencies = await fse.readJSON(configFile);
expect(Object.keys(buildDependencies)).toEqual(['tsconfig']);
const buildDependencies = await fse.readJSON(configFile);
expect(Object.keys(buildDependencies)).toEqual(['tsconfig']);

process.env.TEST_ENV = 'a';
process.env.TEST_ENV = 'a';

// hit cache => unfortunately, extension '.a.js' not work
rsbuild = await build(buildConfig);
// hit cache, so the extension '.test.js' will not work
rsbuild = await build(buildConfig);

expect(
(await rsbuild.getIndexFile()).content.includes('222222'),
).toBeTruthy();
},
);
expect(
(await rsbuild.getIndexFile()).content.includes('222222'),
).toBeTruthy();
});

webpackOnlyTest('cacheDigest should work', async () => {
test('cacheDigest should work', async () => {
const cacheDirectory = path.resolve(
__dirname,
'./node_modules/.cache/webpack-1',
'./node_modules/.cache/test-cache-digest',
);

process.env.TEST_ENV = undefined;
fs.rmSync(cacheDirectory, { recursive: true, force: true });

const getBuildConfig = () => ({
const getBuildConfig = (input: string) => ({
cwd: __dirname,
rsbuildConfig: {
tools: {
bundlerChain: (chain: any) => {
if (process.env.TEST_ENV === 'a') {
chain.resolve.extensions.prepend('.a.js');
bundlerChain: (chain) => {
if (input === 'foo') {
chain.resolve.extensions.prepend('.test.js');
}
},
},
performance: {
buildCache: {
cacheDirectory,
cacheDigest: [process.env.TEST_ENV],
cacheDigest: [input],
},
},
},
} as RsbuildConfig,
});

const configFile = path.resolve(cacheDirectory, 'buildDependencies.json');

fs.rmSync(cacheDirectory, { recursive: true, force: true });

// first build no cache
let rsbuild = await build(getBuildConfig());
// first build without cache
let rsbuild = await build(getBuildConfig(''));

expect(
(await rsbuild.getIndexFile()).content.includes('222222'),
).toBeTruthy();

const buildDependencies = await fse.readJSON(configFile);
expect(Object.keys(buildDependencies)).toEqual(['tsconfig']);

process.env.TEST_ENV = 'a';

rsbuild = await build(getBuildConfig());
rsbuild = await build(getBuildConfig('foo'));

// extension '.a.js' should work
// extension '.test.js' should work
expect(
(await rsbuild.getIndexFile()).content.includes('111111'),
).toBeTruthy();
Expand Down
File renamed without changes.
1 change: 0 additions & 1 deletion packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ const getDefaultToolsConfig = (): NormalizedToolsConfig => ({

const getDefaultPerformanceConfig = (): NormalizedPerformanceConfig => ({
profile: false,
buildCache: true,
printFileSize: true,
removeConsole: false,
removeMomentLocale: false,
Expand Down
49 changes: 31 additions & 18 deletions packages/core/src/plugins/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function getCacheDirectory(
}

/**
* webpack can't detect the changes of framework config, tsconfig, tailwind config and browserslist config.
* Rspack can't detect the changes of framework config, tsconfig, tailwind config and browserslist config.
* but they will affect the compilation result, so they need to be added to buildDependencies.
*/
async function getBuildDependencies(
Expand Down Expand Up @@ -104,17 +104,16 @@ export const pluginCache = (): RsbuildPlugin => ({
name: 'rsbuild:cache',

setup(api) {
// Rspack does not support persistent cache yet
if (api.context.bundlerType === 'rspack') {
return;
}

api.modifyBundlerChain(async (chain, { environment, env }) => {
const { config } = environment;
const { buildCache } = config.performance;
const { bundlerType } = api.context;

// Enable webpack persistent cache by default
// Rspack's persistent cache is still experimental and should be manually enabled
const buildCache =
config.performance.buildCache ?? bundlerType === 'webpack';

if (buildCache === false) {
chain.cache(false);
return;
}

Expand All @@ -133,16 +132,30 @@ export const pluginCache = (): RsbuildPlugin => ({
Array.isArray(cacheConfig.cacheDigest) &&
cacheConfig.cacheDigest.length;

chain.cache({
// The default cache name of webpack is '${name}-${env}', and the `name` is `default` by default.
// We set cache name to avoid cache conflicts of different targets.
name: useDigest
? `${environment.name}-${env}-${getDigestHash(cacheConfig.cacheDigest!)}`
: `${environment.name}-${env}`,
type: 'filesystem',
cacheDirectory,
buildDependencies,
});
// set cache name to avoid cache conflicts between different environments
const cacheVersion = useDigest
? `${environment.name}-${env}-${getDigestHash(cacheConfig.cacheDigest!)}`
: `${environment.name}-${env}`;

if (bundlerType === 'rspack') {
chain.cache(true);
chain.experiments({
...chain.get('experiments'),
cache: {
type: 'persistent',
version: cacheVersion,
directory: cacheDirectory,
buildDependencies: Object.values(buildDependencies).flat(),
},
});
} else {
chain.cache({
name: cacheVersion,
type: 'filesystem',
cacheDirectory,
buildDependencies,
});
}
});
},
});
1 change: 0 additions & 1 deletion packages/core/src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,6 @@ export interface PerformanceConfig {

export interface NormalizedPerformanceConfig extends PerformanceConfig {
printFileSize: PrintFileSizeOptions | boolean;
buildCache: BuildCacheOptions | boolean;
chunkSplit: RsbuildChunkSplit;
}

Expand Down
116 changes: 116 additions & 0 deletions packages/core/tests/__snapshots__/cache.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`plugin-cache > 'should add cache config correctly' 1`] = `
{
"cache": true,
"experiments": {
"cache": {
"buildDependencies": [
"<ROOT>/packages/core/tests/tsconfig.json",
],
"directory": "<ROOT>/packages/core/tests/node_modules/.cache/rspack",
"type": "persistent",
"version": "web-test",
},
},
"plugins": [
{
"name": "RsbuildCorePlugin",
},
],
}
`;

exports[`plugin-cache > 'should apply cacheDigest' 1`] = `
{
"cache": true,
"experiments": {
"cache": {
"buildDependencies": [
"<ROOT>/packages/core/tests/tsconfig.json",
],
"directory": "<ROOT>/packages/core/tests/node_modules/.cache/rspack",
"type": "persistent",
"version": "web-test-c29a5747",
},
},
"plugins": [
{
"name": "RsbuildCorePlugin",
},
],
}
`;

exports[`plugin-cache > 'should custom cache directory by user' 1`] = `
{
"cache": true,
"experiments": {
"cache": {
"buildDependencies": [
"<ROOT>/packages/core/tests/tsconfig.json",
],
"directory": "<ROOT>/packages/core/tests/node_modules/.cache/tmp",
"type": "persistent",
"version": "web-test",
},
},
"plugins": [
{
"name": "RsbuildCorePlugin",
},
],
}
`;

exports[`plugin-cache > 'should disable cache' 1`] = `
{
"plugins": [
{
"name": "RsbuildCorePlugin",
},
],
}
`;

exports[`plugin-cache > 'should not apply cacheDigest' 1`] = `
{
"cache": true,
"experiments": {
"cache": {
"buildDependencies": [
"<ROOT>/packages/core/tests/tsconfig.json",
],
"directory": "<ROOT>/packages/core/tests/node_modules/.cache/rspack",
"type": "persistent",
"version": "web-test",
},
},
"plugins": [
{
"name": "RsbuildCorePlugin",
},
],
}
`;

exports[`plugin-cache > 'should watch tsconfig change' 1`] = `
{
"cache": true,
"experiments": {
"cache": {
"buildDependencies": [
"<ROOT>/packages/core/tests/tsconfig.json",
],
"directory": "<ROOT>/packages/core/tests/node_modules/.cache/rspack",
"type": "persistent",
"version": "web-test",
},
},
"plugins": [
{
"name": "RsbuildCorePlugin",
},
],
}
`;
Loading