Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP]feat: circular plugin #648

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
725d20a
feat: circular plugin
easy1090 Dec 16, 2024
bf4c32f
feat: circular dependency plugin
easy1090 Dec 25, 2024
e6405a0
feat: circular dependency plugin
easy1090 Dec 25, 2024
608ff27
chore: update pnpm-lock
easy1090 Jan 16, 2025
aa37b33
feat: logo as home link (#711)
chenjiahan Jan 19, 2025
da2e846
chore: prevent vitest segfault on github CI runner (#715)
LingyuCoder Jan 21, 2025
b9e80e7
chore(deps): update all patch dependencies (#712)
renovate[bot] Jan 21, 2025
b731bd8
refactor: support compressJson option and refactor the reportDir & re…
easy1090 Jan 22, 2025
351e98a
chore: upgrade check syntax plugin version to support rspack or webpa…
nyqykk Jan 23, 2025
f19e361
chore: update Rslib description in README.md (#719)
Timeless0911 Jan 24, 2025
a42beed
release: 1.0.0-alpha.1 (#720)
easy1090 Jan 24, 2025
04aa7ba
chore(deps): update dependency memfs to v4.17.0 (#713)
renovate[bot] Jan 24, 2025
ac39fb9
fix: banner plugin switch condition (#721)
easy1090 Jan 24, 2025
b64ab2f
release: 1.0.0-alpha.2 (#722)
easy1090 Jan 25, 2025
7d54628
chore(deps): update dependency check-dependency-version-consistency t…
renovate[bot] Jan 25, 2025
a303b7d
chore(deps): update dependency @rspack/core to ^1.2.2 (#723)
renovate[bot] Jan 25, 2025
31618ee
chore(deps): update rsbuild v1.2 (#724)
renovate[bot] Jan 25, 2025
2fb9c75
chore: fix deprecated dependencies warning (#725)
chenjiahan Jan 25, 2025
8c74c6a
fix: failed to call `module.getExportsType` method (#726)
chenjiahan Jan 26, 2025
09fbd69
fix(UI): invalid font family for loader analysis text (#727)
chenjiahan Jan 26, 2025
d9028c2
release: 1.0.0-alpha.3 (#728)
chenjiahan Jan 26, 2025
779a830
feat: circular dependency plugin
easy1090 Feb 7, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/test-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:

- name: Install Dependencies
if: ${{steps.skip-ci.outputs.RESULT != 'true'}}
run: pnpm install
run: pnpm install && cd ./e2e && npx playwright install chromium

- name: Unit Test
if: ${{steps.skip-ci.outputs.RESULT != 'true'}}
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Come and chat with us on [Discord](https://discord.gg/wrBPBT6rkM)! The Rsdoctor

- [Rspack](https://github.com/web-infra-dev/rspack): A fast Rust-based web bundler.
- [Rsbuild](https://github.com/web-infra-dev/rsbuild): An Rspack-based build tool for the web, rebranded from Modern.js Builder.
- [Rslib](https://github.com/web-infra-dev/rslib): A library build tool powered by Rsbuild.
- [Rslib](https://github.com/web-infra-dev/rslib): A library development tool powered by Rsbuild.
- [Rspress](https://github.com/web-infra-dev/rspress): A fast Rspack-based static site generator.
- [Modern.js](https://github.com/web-infra-dev/modern.js): A progressive React framework based on Rsbuild.

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ https://github.com/user-attachments/assets/3400e0a2-a1dc-4a14-9466-6283af9dd9ed

- [Rspack](https://github.com/web-infra-dev/rspack): 基于 rust 的 web 构建器。
- [Rsbuild](https://github.com/web-infra-dev/rsbuild): 基于 Rspack 的 web 构建工具。
- [Rslib](https://github.com/web-infra-dev/rslib): 基于 Rsbuild 的 library 构建工具
- [Rslib](https://github.com/web-infra-dev/rslib): 基于 Rsbuild 的 library 开发工具
- [Rspress](https://github.com/web-infra-dev/rspress): 基于 Rsbuild 的静态站点生成器。
- [Modern.js](https://github.com/web-infra-dev/modern.js): 基于 Rsbuild 的渐进式 React 框架。

Expand Down
3 changes: 3 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ This folder contains the e2e test cases of Rsdoctor.
## Commands

```bash
# Install playwright browser
npx playwright install chromium

# Run all test cases, including Rspack and webpack
pnpm run test
```
Expand Down
6 changes: 3 additions & 3 deletions e2e/cases/doctor-rspack/banner-plugin.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { expect, test } from '@playwright/test';
import { Utils } from '@rsdoctor/core/build-utils';
import { getSDK, setSDK } from '@rsdoctor/core/plugins';
import { compileByRspack } from '@scripts/test-helper';
import { BannerPlugin, Compiler } from '@rspack/core';
import { compileByRspack } from '@scripts/test-helper';
import path from 'path';
import { createRsdoctorPlugin } from './test-utils';
import { parseBundle } from '../../node_modules/@rsdoctor/core/dist/build-utils/build/utils/parseBundle';

let reportLoaderStartOrEndTimes = 0;

Expand Down Expand Up @@ -118,7 +118,7 @@ test('rspack banner plugin', async () => {
const sdk = getSDK();

// @ts-ignore
const bundle = parseBundle(
const bundle = Utils.parseBundle(
path.join(__dirname, './fixtures/rspack-banner-plugin.js'),
// @ts-ignore
sdk.getStoreData().moduleGraph.modules,
Expand Down
8 changes: 4 additions & 4 deletions e2e/cases/doctor-rspack/brief.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect, test, webkit } from '@playwright/test';
import { expect, test, chromium } from '@playwright/test';
import { getSDK, setSDK } from '@rsdoctor/core/plugins';
import { compileByRspack } from '@scripts/test-helper';
import { Compiler } from '@rspack/core';
Expand All @@ -25,7 +25,7 @@ async function rspackCompile(
extensions: ['.ts', '.js'],
},
output: {
path: path.join(__dirname, '../doctor-rspack/dist'),
path: path.join(__dirname, '../doctor-rspack/dist/brief'),
},
module: {
rules: [
Expand Down Expand Up @@ -106,12 +106,12 @@ test('rspack brief mode', async () => {

const reportPath = path.join(
__dirname,
'./dist/.rsdoctor/rsdoctor-report.html',
'./dist/brief/.rsdoctor/rsdoctor-report.html',
);

fileExists(reportPath);

const browser = await webkit.launch();
const browser = await chromium.launch();

// Create a new browser context
const context = await browser.newContext();
Expand Down
1 change: 1 addition & 0 deletions e2e/cases/doctor-rspack/fixtures/c.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const c = 1;
153 changes: 153 additions & 0 deletions e2e/cases/doctor-rspack/linter-rule-render.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { expect, test, chromium } from '@playwright/test';
import { getSDK, setSDK } from '@rsdoctor/core/plugins';
import { compileByRspack } from '@scripts/test-helper';
import { Compiler } from '@rspack/core';
import path from 'path';
import fs from 'fs';
import { createRsdoctorPlugin } from './test-utils';

let reportLoaderStartOrEndTimes = 0;
const ecmaVersion = 3;

async function rspackCompile(
_tapName: string,
compile: typeof compileByRspack,
) {
const file = path.resolve(__dirname, './fixtures/c.js');

const res = await compile(file, {
resolve: {
extensions: ['.ts', '.js'],
},
output: {
path: path.join(__dirname, '../doctor-rspack/dist/linter-rule-render'),
},
module: {
rules: [
{
test: /\.[jt]s$/,
use: {
loader: 'builtin:swc-loader',
options: {
sourceMap: true,
jsc: {
parser: {
syntax: 'typescript',
},
externalHelpers: true,
preserveAllComments: false,
},
},
},
type: 'javascript/auto',
},
],
},
plugins: [
// @ts-ignore
createRsdoctorPlugin({
mode: 'brief',
linter: {
rules: {
'ecma-version-check': [
'Warn',
{
ecmaVersion,
},
],
},
},
}),
{
name: 'Foo',
apply(compiler: Compiler) {
compiler.hooks.beforeRun.tapPromise(
{ name: 'Foo', stage: 99999 },
async () => {
const sdk = getSDK();
setSDK(
new Proxy(sdk, {
get(target, key, receiver) {
switch (key) {
case 'reportLoader':
return null;
case 'reportLoaderStartOrEnd':
return (_data: any) => {
reportLoaderStartOrEndTimes += 1;
};
default:
return Reflect.get(target, key, receiver);
}
},
set(target, key, value, receiver) {
return Reflect.set(target, key, value, receiver);
},
defineProperty(target, p, attrs) {
return Reflect.defineProperty(target, p, attrs);
},
}),
);
},
);
},
},
],
});

return res;
}

test('linter rule render check', async () => {
const tapName = 'Foo';
await rspackCompile(tapName, compileByRspack);

const reportPath = path.join(
__dirname,
'./dist/linter-rule-render/.rsdoctor/rsdoctor-report.html',
);

fileExists(reportPath);

const browser = await chromium.launch();

// Create a new browser context
const context = await browser.newContext();

// Open a new page
const page = await context.newPage();

// Navigate to a URL
await page.goto(`file:///${reportPath}`);

const ecmaVersionButton = await page.$('[data-node-key="E1004"]');
await ecmaVersionButton?.click();
// ignore output text check because there's no .map file for track the source code
const source = await page.$('.e2e-ecma-source');
const error = await page.$('.e2e-ecma-error');
const sourceText = await source?.textContent();
const errorText = await error?.textContent();
expect(sourceText).toBe(
'/cases/doctor-rspack/dist/linter-rule-render/main.js:1:2',
);
expect(errorText).toBe(
`Find some syntax that does not match "ecmaVersion <= ${ecmaVersion}"`,
);

// Close the page
await page.close();

// Close the browser context
await context.close();

// Close the browser
await browser.close();
});

async function fileExists(filePath: string) {
try {
await fs.existsSync(filePath);
return true;
} catch {
return false;
}
}
123 changes: 123 additions & 0 deletions e2e/cases/doctor-rspack/tag-plugin-without-banner.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { expect, test } from '@playwright/test';
import { getSDK, setSDK } from '@rsdoctor/core/plugins';
import { compileByRspack } from '@scripts/test-helper';
import { Utils } from '@rsdoctor/core/build-utils';
import { Compiler } from '@rspack/core';
import path from 'path';
import { createRsdoctorPlugin } from './test-utils';

let reportLoaderStartOrEndTimes = 0;

async function rspackCompile(
_tapName: string,
compile: typeof compileByRspack,
) {
const file = path.resolve(__dirname, './fixtures/a.js');
const loader = path.resolve(__dirname, './fixtures/loaders/comment.js');

const esmLoader = path.resolve(
__dirname,
'./fixtures/loaders/esm-serialize-query-to-comment.mjs',
);

const res = await compile(file, {
resolve: {
extensions: ['.ts', '.js'],
},
output: {
path: path.join(__dirname, '../doctor-rspack/dist'),
},
module: {
rules: [
{
test: /\.js/,
use: loader,
},
{
test: /\.js/,
use: esmLoader,
},
{
test: /\.[jt]s$/,
use: {
loader: 'builtin:swc-loader',
options: {
sourceMap: true,
jsc: {
parser: {
syntax: 'typescript',
},
externalHelpers: true,
preserveAllComments: false,
},
},
},
type: 'javascript/auto',
},
],
},
plugins: [
// @ts-ignore
createRsdoctorPlugin({
supports: {
banner: true,
},
}),
{
name: 'Foo',
apply(compiler: Compiler) {
compiler.hooks.beforeRun.tapPromise(
{ name: 'Foo', stage: 99999 },
async () => {
const sdk = getSDK();
setSDK(
new Proxy(sdk, {
get(target, key, receiver) {
switch (key) {
case 'reportLoader':
return null;
case 'reportLoaderStartOrEnd':
return (_data: any) => {
reportLoaderStartOrEndTimes += 1;
};
default:
return Reflect.get(target, key, receiver);
}
},
set(target, key, value, receiver) {
return Reflect.set(target, key, value, receiver);
},
defineProperty(target, p, attrs) {
return Reflect.defineProperty(target, p, attrs);
},
}),
);
},
);
},
},
],
});

return res;
}

test('rspack banner plugin', async () => {
const tapName = 'Foo';
await rspackCompile(tapName, compileByRspack);
const sdk = getSDK();

// @ts-ignore
const bundle = Utils.parseBundle(
path.join(__dirname, './fixtures/rspack-banner-plugin.js'),
// @ts-ignore
sdk.getStoreData().moduleGraph.modules,
);

expect(JSON.stringify(bundle.modules)).toBe(
'{"":{"size":313,"sizeConvert":"313 B","content":"function (\\n __unused_webpack_module,\\n __webpack_exports__,\\n __webpack_require__,\\n ) {\\n \'use strict\';\\n __webpack_require__.r(__webpack_exports__);\\n __webpack_require__.d(__webpack_exports__, {\\n a: function () {\\n return a;\\n },\\n });\\n var a = 1;\\n }"}}',
);
const res = sdk.getStoreData().chunkGraph;
expect(res.assets[0].content).toContain('RSDOCTOR_START');
expect(res.assets[0].content).toContain('RSDOCTOR_END');
});
Loading