From f257a46ffec60e10d0755bbfdb56e9c38fb13d6c Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Mon, 20 May 2024 11:41:42 +0800 Subject: [PATCH 01/48] test: fix dependencies of test tools (#6575) --- packages/rspack-test-tools/package.json | 11 +++-- pnpm-lock.yaml | 64 ++++++++----------------- 2 files changed, 29 insertions(+), 46 deletions(-) diff --git a/packages/rspack-test-tools/package.json b/packages/rspack-test-tools/package.json index 6b83f2e02cf..66032920fb8 100644 --- a/packages/rspack-test-tools/package.json +++ b/packages/rspack-test-tools/package.json @@ -49,11 +49,18 @@ "@rspack/core": "workspace:*", "csv-to-markdown-table": "^1.3.0", "deepmerge": "^4.3.1", + "filenamify": "4.3.0", "fs-extra": "^11.1.1", "glob": "^10.3.10", "jest-diff": "^29.7.0", "jest-serializer-path": "^0.1.15", + "jest-snapshot": "29.7.0", + "jsdom": "24.0.0", "memfs": "4.7.7", + "mkdirp": "0.5.6", + "pretty-format": "29.7.0", + "rimraf": "3.0.2", + "strip-ansi": "6.0.1", "webpack": "^5.90.1", "webpack-merge": "5.9.0", "webpack-sources": "3.2.3", @@ -71,8 +78,6 @@ "@types/webpack": "5.28.5", "@types/webpack-sources": "3.2.3", "core-js": "3.36.1", - "filenamify": "4.3.0", - "mkdirp": "0.5.6", "monaco-editor": "0.47.0", "monaco-editor-webpack-plugin": "7.1.0", "normalize.css": "^8.0.0", @@ -81,4 +86,4 @@ "react-dom": "18.0.0", "react-refresh": "0.14.0" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8b9c55a4ac6..eb74eb88955 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -763,6 +763,9 @@ importers: deepmerge: specifier: ^4.3.1 version: 4.3.1 + filenamify: + specifier: 4.3.0 + version: 4.3.0 fs-extra: specifier: ^11.1.1 version: 11.2.0 @@ -775,9 +778,27 @@ importers: jest-serializer-path: specifier: ^0.1.15 version: 0.1.15 + jest-snapshot: + specifier: 29.7.0 + version: 29.7.0 + jsdom: + specifier: 24.0.0 + version: 24.0.0 memfs: specifier: 4.7.7 version: 4.7.7 + mkdirp: + specifier: 0.5.6 + version: 0.5.6 + pretty-format: + specifier: 29.7.0 + version: 29.7.0 + rimraf: + specifier: 3.0.2 + version: 3.0.2 + strip-ansi: + specifier: 6.0.1 + version: 6.0.1 webpack: specifier: ^5.90.1 version: 5.90.1(@swc/core@1.4.0)(webpack-cli@4.10.0) @@ -824,12 +845,6 @@ importers: core-js: specifier: 3.36.1 version: 3.36.1 - filenamify: - specifier: 4.3.0 - version: 4.3.0 - mkdirp: - specifier: 0.5.6 - version: 0.5.6 monaco-editor: specifier: 0.47.0 version: 0.47.0 @@ -6774,7 +6789,6 @@ packages: debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true /aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} @@ -7065,7 +7079,6 @@ packages: /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true /available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} @@ -8042,7 +8055,6 @@ packages: engines: {node: '>= 0.8'} dependencies: delayed-stream: 1.0.0 - dev: true /commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} @@ -8593,7 +8605,6 @@ packages: engines: {node: '>=18'} dependencies: rrweb-cssom: 0.6.0 - dev: true /csstype@2.6.21: resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==} @@ -8781,7 +8792,6 @@ packages: dependencies: whatwg-mimetype: 4.0.0 whatwg-url: 14.0.0 - dev: true /data-view-buffer@1.0.1: resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} @@ -8837,7 +8847,6 @@ packages: /decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} - dev: true /decode-uri-component@0.2.2: resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} @@ -8940,7 +8949,6 @@ packages: /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - dev: true /density-clustering@1.3.0: resolution: {integrity: sha512-icpmBubVTwLnsaor9qH/4tG5+7+f61VcqMN3V3pm9sxxSCt2Jcs0zWOgwZW9ARJYaKD3FumIgHiMOcIMRRAzFQ==} @@ -9905,7 +9913,6 @@ packages: /filename-reserved-regex@2.0.0: resolution: {integrity: sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==} engines: {node: '>=4'} - dev: true /filenamify@4.3.0: resolution: {integrity: sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==} @@ -9914,7 +9921,6 @@ packages: filename-reserved-regex: 2.0.0 strip-outer: 1.0.1 trim-repeated: 1.0.0 - dev: true /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} @@ -10060,7 +10066,6 @@ packages: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 - dev: true /formdata-polyfill@4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} @@ -10539,7 +10544,6 @@ packages: engines: {node: '>=18'} dependencies: whatwg-encoding: 3.1.1 - dev: true /html-entities@2.5.2: resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} @@ -10669,7 +10673,6 @@ packages: debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true /http-proxy-middleware@2.0.6(@types/express@4.17.21): resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} @@ -10721,7 +10724,6 @@ packages: debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} @@ -10749,7 +10751,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 - dev: true /icss-utils@5.1.0(postcss@8.4.38): resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} @@ -11174,7 +11175,6 @@ packages: /is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - dev: true /is-promise@2.2.2: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} @@ -11882,7 +11882,6 @@ packages: - bufferutil - supports-color - utf-8-validate - dev: true /jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} @@ -12612,7 +12611,6 @@ packages: hasBin: true dependencies: minimist: 1.2.8 - dev: true /mock-property@1.0.3: resolution: {integrity: sha512-2emPTb1reeLLYwHxyVx993iYyCHEiRRO+y8NFXFPL5kl5q14sgTK76cXyEKkeKCHeRw35SfdkUJ10Q1KfHuiIQ==} @@ -12921,7 +12919,6 @@ packages: /nwsapi@2.2.7: resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} - dev: true /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -13248,7 +13245,6 @@ packages: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} dependencies: entities: 4.5.0 - dev: true /parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} @@ -13796,7 +13792,6 @@ packages: /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} - dev: true /public-encrypt@4.0.3: resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} @@ -13990,7 +13985,6 @@ packages: /querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - dev: true /queue-lit@1.5.2: resolution: {integrity: sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==} @@ -14768,7 +14762,6 @@ packages: /rrweb-cssom@0.6.0: resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} - dev: true /run-async@3.0.0: resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} @@ -14912,7 +14905,6 @@ packages: engines: {node: '>=v12.22.7'} dependencies: xmlchars: 2.2.0 - dev: true /scheduler@0.19.1: resolution: {integrity: sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==} @@ -15681,7 +15673,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: escape-string-regexp: 1.0.5 - dev: true /style-loader@3.3.4(webpack@5.90.1): resolution: {integrity: sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==} @@ -15799,7 +15790,6 @@ packages: /symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - dev: true /syntax-error@1.4.0: resolution: {integrity: sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==} @@ -16079,7 +16069,6 @@ packages: punycode: 2.3.1 universalify: 0.2.0 url-parse: 1.5.10 - dev: true /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -16097,14 +16086,12 @@ packages: engines: {node: '>=18'} dependencies: punycode: 2.3.1 - dev: true /trim-repeated@1.0.0: resolution: {integrity: sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==} engines: {node: '>=0.10.0'} dependencies: escape-string-regexp: 1.0.5 - dev: true /ts-api-utils@1.3.0(typescript@5.0.2): resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} @@ -16475,7 +16462,6 @@ packages: /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} - dev: true /universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} @@ -16539,7 +16525,6 @@ packages: dependencies: querystringify: 2.2.0 requires-port: 1.0.0 - dev: true /url@0.11.3: resolution: {integrity: sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==} @@ -16787,7 +16772,6 @@ packages: engines: {node: '>=18'} dependencies: xml-name-validator: 5.0.0 - dev: true /wabt@1.0.0-nightly.20180421: resolution: {integrity: sha512-bsu9zk672KACjoabONcAS94IS20prRm05IbiIUGfa8eBpRLjWZv8ugocdinV/ONh0mFMfXrVWkvF1/BNtwIfUw==} @@ -16848,7 +16832,6 @@ packages: /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} - dev: true /webpack-bundle-analyzer@4.6.1: resolution: {integrity: sha512-oKz9Oz9j3rUciLNfpGFjOb49/jEpXNmWdVH8Ls//zNcnLlQdTGXQQMsBbb/gR7Zl8WNLxVCq+0Hqbx3zv6twBw==} @@ -17112,7 +17095,6 @@ packages: engines: {node: '>=18'} dependencies: iconv-lite: 0.6.3 - dev: true /whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} @@ -17122,7 +17104,6 @@ packages: /whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} - dev: true /whatwg-url@11.0.0: resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} @@ -17138,7 +17119,6 @@ packages: dependencies: tr46: 5.0.0 webidl-conversions: 7.0.0 - dev: true /whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -17362,11 +17342,9 @@ packages: /xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} - dev: true /xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - dev: true /xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} From 8b7a2a41cfdcea584b1b5790a763b8a41fdae873 Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Mon, 20 May 2024 12:16:34 +0800 Subject: [PATCH 02/48] test: fix dependencies of test tools (#6577) --- packages/rspack-test-tools/package.json | 5 ++++- pnpm-lock.yaml | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/rspack-test-tools/package.json b/packages/rspack-test-tools/package.json index 66032920fb8..2075996427e 100644 --- a/packages/rspack-test-tools/package.json +++ b/packages/rspack-test-tools/package.json @@ -46,7 +46,6 @@ "@babel/template": "7.22.15", "@babel/traverse": "7.23.2", "@babel/types": "7.23.0", - "@rspack/core": "workspace:*", "csv-to-markdown-table": "^1.3.0", "deepmerge": "^4.3.1", "filenamify": "4.3.0", @@ -71,6 +70,7 @@ "@monaco-editor/react": "^4.6.0", "@rspack/cli": "workspace:*", "@rspack/plugin-minify": "workspace:*", + "@rspack/core": "workspace:*", "@swc/jest": "^0.2.29", "@types/prettier": "^2.7.2", "@types/react": "^18.2.48", @@ -85,5 +85,8 @@ "react": "18.0.0", "react-dom": "18.0.0", "react-refresh": "0.14.0" + }, + "peerDependencies": { + "@rspack/core": ">=0.7.0" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb74eb88955..e8c92c844af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -754,9 +754,6 @@ importers: '@babel/types': specifier: 7.23.0 version: 7.23.0 - '@rspack/core': - specifier: workspace:* - version: link:../rspack csv-to-markdown-table: specifier: ^1.3.0 version: 1.4.1 @@ -821,6 +818,9 @@ importers: '@rspack/cli': specifier: workspace:* version: link:../rspack-cli + '@rspack/core': + specifier: workspace:* + version: link:../rspack '@rspack/plugin-minify': specifier: workspace:* version: link:../rspack-plugin-minify From 6d831b6982a7165829a5b7365cade1985ccdc93f Mon Sep 17 00:00:00 2001 From: gaoyuan <9aoyuao@gmail.com> Date: Mon, 20 May 2024 14:24:26 +0800 Subject: [PATCH 03/48] docs: list more webpack-contrib plugins compatible (#6578) --- website/components/CommunityCompatibleTable.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/website/components/CommunityCompatibleTable.tsx b/website/components/CommunityCompatibleTable.tsx index fa5dbfe3c0c..14ec71fb1b5 100644 --- a/website/components/CommunityCompatibleTable.tsx +++ b/website/components/CommunityCompatibleTable.tsx @@ -107,6 +107,21 @@ export const CommunityPluginCompatibleTable: React.FC = () => { status: CompatibleStatus.Alternative, description: i18n[lang]['terser-webpack-plugin-desc'], }, + { + name: 'html-minimizer-webpack-plugin', + url: 'https://github.com/webpack-contrib/html-minimizer-webpack-plugin', + status: CompatibleStatus.Compatible, + }, + { + name: 'json-minimizer-webpack-plugin', + url: 'https://github.com/webpack-contrib/json-minimizer-webpack-plugin', + status: CompatibleStatus.Compatible, + }, + { + name: 'stylelint-webpack-plugin', + url: 'https://github.com/webpack-contrib/stylelint-webpack-plugin', + status: CompatibleStatus.Compatible, + }, { name: 'tsconfig-paths-webpack-plugin', url: 'https://www.npmjs.com/package/tsconfig-paths-webpack-plugin', From 4917589e1e6d77e954e1cf758c453930527a299b Mon Sep 17 00:00:00 2001 From: Fy <1114550440@qq.com> Date: Mon, 20 May 2024 16:31:54 +0800 Subject: [PATCH 04/48] feat: lazy compilation (#5915) --- Cargo.lock | 18 + crates/node_binding/binding.d.ts | 24 +- crates/node_binding/scripts/banner.d.ts | 2 + crates/rspack_binding_options/Cargo.toml | 1 + .../src/options/raw_builtins/mod.rs | 18 +- .../raw_builtins/raw_lazy_compilation.rs | 135 +++ .../src/dependency/dependency_type.rs | 2 + crates/rspack_core/src/module_factory.rs | 2 +- crates/rspack_core/src/utils/queue.rs | 8 + crates/rspack_database/src/database.rs | 8 + crates/rspack_macros/src/plugin.rs | 40 +- crates/rspack_plugin_javascript/Cargo.toml | 1 + .../rspack_plugin_lazy_compilation/Cargo.toml | 19 + .../rspack_plugin_lazy_compilation/expand.rs | 957 ++++++++++++++++++ .../src/backend.rs | 14 + .../src/dependency.rs | 54 + .../src/factory.rs | 50 + .../rspack_plugin_lazy_compilation/src/lib.rs | 6 + .../src/module.rs | 323 ++++++ .../src/plugin.rs | 199 ++++ crates/rspack_plugin_runtime/src/lib.rs | 2 - packages/rspack-dev-server/src/server.ts | 32 - packages/rspack/etc/api.md | 87 +- packages/rspack/src/Watching.ts | 4 + packages/rspack/src/builtin-plugin/base.ts | 2 +- packages/rspack/src/builtin-plugin/index.ts | 1 + .../lazy-compilation/backend.ts | 230 +++++ .../lazy-compilation/lazyCompilation.ts | 19 + .../builtin-plugin/lazy-compilation/plugin.ts | 68 ++ packages/rspack/src/config/normalization.ts | 9 +- packages/rspack/src/config/zod.ts | 16 +- packages/rspack/src/rspackOptionsApply.ts | 29 + .../lazy-compilation/context/test.filter.js | 3 - .../context/webpack.config.js | 1 + .../lazy-compilation/https/test.filter.js | 3 +- .../lazy-compilation/https/webpack.config.js | 1 + .../module-test/test.filter.js | 3 - .../module-test/webpack.config.js | 3 +- .../only-entries/test.filter.js | 3 - .../lazy-compilation/simple/test.filter.js | 3 +- .../lazy-compilation/simple/webpack.config.js | 3 +- .../lazy-compilation/unrelated/test.filter.js | 3 - website/docs/en/config/experiments.mdx | 26 + website/docs/zh/config/experiments.mdx | 26 + 44 files changed, 2371 insertions(+), 87 deletions(-) create mode 100644 crates/rspack_binding_options/src/options/raw_builtins/raw_lazy_compilation.rs create mode 100644 crates/rspack_plugin_lazy_compilation/Cargo.toml create mode 100644 crates/rspack_plugin_lazy_compilation/expand.rs create mode 100644 crates/rspack_plugin_lazy_compilation/src/backend.rs create mode 100644 crates/rspack_plugin_lazy_compilation/src/dependency.rs create mode 100644 crates/rspack_plugin_lazy_compilation/src/factory.rs create mode 100644 crates/rspack_plugin_lazy_compilation/src/lib.rs create mode 100644 crates/rspack_plugin_lazy_compilation/src/module.rs create mode 100644 crates/rspack_plugin_lazy_compilation/src/plugin.rs create mode 100644 packages/rspack/src/builtin-plugin/lazy-compilation/backend.ts create mode 100644 packages/rspack/src/builtin-plugin/lazy-compilation/lazyCompilation.ts create mode 100644 packages/rspack/src/builtin-plugin/lazy-compilation/plugin.ts delete mode 100644 webpack-test/hotCases/lazy-compilation/context/test.filter.js delete mode 100644 webpack-test/hotCases/lazy-compilation/module-test/test.filter.js delete mode 100644 webpack-test/hotCases/lazy-compilation/only-entries/test.filter.js delete mode 100644 webpack-test/hotCases/lazy-compilation/unrelated/test.filter.js diff --git a/Cargo.lock b/Cargo.lock index d1c2850a940..202b57293f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2831,6 +2831,7 @@ dependencies = [ "rspack_plugin_ignore", "rspack_plugin_javascript", "rspack_plugin_json", + "rspack_plugin_lazy_compilation", "rspack_plugin_library", "rspack_plugin_limit_chunk_count", "rspack_plugin_merge_duplicate_chunks", @@ -3404,6 +3405,23 @@ dependencies = [ "rspack_error", ] +[[package]] +name = "rspack_plugin_lazy_compilation" +version = "0.1.0" +dependencies = [ + "async-trait", + "once_cell", + "rspack_core", + "rspack_error", + "rspack_hook", + "rspack_identifier", + "rspack_plugin_javascript", + "rspack_regex", + "rspack_util", + "rustc-hash", + "tokio", +] + [[package]] name = "rspack_plugin_library" version = "0.1.0" diff --git a/crates/node_binding/binding.d.ts b/crates/node_binding/binding.d.ts index 6112f732e4f..a70b0db259e 100644 --- a/crates/node_binding/binding.d.ts +++ b/crates/node_binding/binding.d.ts @@ -7,6 +7,8 @@ export type JsFilename = | ((pathData: JsPathData, assetInfo?: JsAssetInfo) => string); export type LocalJsFilename = JsFilename; + +export type RawLazyCompilationTest = RegExp | ((m: JsModule) => boolean); /* -- banner.d.ts end -- */ /* -- napi-rs generated below -- */ @@ -171,7 +173,8 @@ export enum BuiltinPluginName { SwcCssMinimizerRspackPlugin = 'SwcCssMinimizerRspackPlugin', BundlerInfoRspackPlugin = 'BundlerInfoRspackPlugin', CssExtractRspackPlugin = 'CssExtractRspackPlugin', - JsLoaderRspackPlugin = 'JsLoaderRspackPlugin' + JsLoaderRspackPlugin = 'JsLoaderRspackPlugin', + LazyCompilationPlugin = 'LazyCompilationPlugin' } export function cleanupGlobalTrace(): void @@ -969,6 +972,14 @@ export interface RawJavascriptParserOptions { wrappedContextCritical: boolean } +export interface RawLazyCompilationOption { + module: (err: Error | null, arg: RawModuleArg) => any + test?: RawLazyCompilationTest + entries: boolean + imports: boolean + cacheable: boolean +} + export interface RawLibraryAuxiliaryComment { root?: string commonjs?: string @@ -1004,6 +1015,11 @@ export interface RawLimitChunkCountPluginOptions { maxChunks: number } +export interface RawModuleArg { + module: string + path: string +} + export interface RawModuleFilenameTemplateFnCtx { identifier: string shortIdentifier: string @@ -1018,6 +1034,12 @@ export interface RawModuleFilenameTemplateFnCtx { namespace: string } +export interface RawModuleInfo { + active: boolean + client: string + data: string +} + export interface RawModuleOptions { rules: Array parser?: Record diff --git a/crates/node_binding/scripts/banner.d.ts b/crates/node_binding/scripts/banner.d.ts index 052dc4f4f10..b77c3ec55cb 100644 --- a/crates/node_binding/scripts/banner.d.ts +++ b/crates/node_binding/scripts/banner.d.ts @@ -7,6 +7,8 @@ export type JsFilename = | ((pathData: JsPathData, assetInfo?: JsAssetInfo) => string); export type LocalJsFilename = JsFilename; + +export type RawLazyCompilationTest = RegExp | ((m: JsModule) => boolean); /* -- banner.d.ts end -- */ /* -- napi-rs generated below -- */ diff --git a/crates/rspack_binding_options/Cargo.toml b/crates/rspack_binding_options/Cargo.toml index c4f2ec697cb..fec0d2226e1 100644 --- a/crates/rspack_binding_options/Cargo.toml +++ b/crates/rspack_binding_options/Cargo.toml @@ -40,6 +40,7 @@ rspack_plugin_html = { path = "../rspack_plugin_html" } rspack_plugin_ignore = { path = "../rspack_plugin_ignore" } rspack_plugin_javascript = { path = "../rspack_plugin_javascript" } rspack_plugin_json = { path = "../rspack_plugin_json" } +rspack_plugin_lazy_compilation = { path = "../rspack_plugin_lazy_compilation" } rspack_plugin_library = { path = "../rspack_plugin_library" } rspack_plugin_limit_chunk_count = { path = "../rspack_plugin_limit_chunk_count" } rspack_plugin_merge_duplicate_chunks = { path = "../rspack_plugin_merge_duplicate_chunks" } diff --git a/crates/rspack_binding_options/src/options/raw_builtins/mod.rs b/crates/rspack_binding_options/src/options/raw_builtins/mod.rs index 68284bc97f8..4e02139ed3e 100644 --- a/crates/rspack_binding_options/src/options/raw_builtins/mod.rs +++ b/crates/rspack_binding_options/src/options/raw_builtins/mod.rs @@ -4,6 +4,7 @@ mod raw_copy; mod raw_css_extract; mod raw_html; mod raw_ignore; +mod raw_lazy_compilation; mod raw_limit_chunk_count; mod raw_mf; mod raw_progress; @@ -14,7 +15,7 @@ mod raw_to_be_deprecated; use napi::{bindgen_prelude::FromNapiValue, Env, JsUnknown}; use napi_derive::napi; -use rspack_core::{BoxPlugin, Define, DefinePlugin, PluginExt, Provide, ProvidePlugin}; +use rspack_core::{BoxPlugin, Define, DefinePlugin, Plugin, PluginExt, Provide, ProvidePlugin}; use rspack_error::Result; use rspack_ids::{ DeterministicChunkIdsPlugin, DeterministicModuleIdsPlugin, NamedChunkIdsPlugin, @@ -79,6 +80,7 @@ pub use self::{ use self::{ raw_bundle_info::{RawBundlerInfoModeWrapper, RawBundlerInfoPluginOptions}, raw_css_extract::RawCssExtractPluginOption, + raw_lazy_compilation::{JsBackend, RawLazyCompilationOption}, raw_mf::{RawConsumeSharedPluginOptions, RawContainerReferencePluginOptions, RawProvideOptions}, raw_runtime_chunk::RawRuntimeChunkOptions, raw_size_limits::RawSizeLimitsPluginOptions, @@ -165,6 +167,7 @@ pub enum BuiltinPluginName { // rspack js adapter plugins // naming format follow XxxRspackPlugin JsLoaderRspackPlugin, + LazyCompilationPlugin, } #[napi(object)] @@ -468,6 +471,19 @@ impl BuiltinPlugin { JsLoaderResolverPlugin::new(downcast_into::(self.options)?).boxed(), ); } + BuiltinPluginName::LazyCompilationPlugin => { + let options = downcast_into::(self.options)?; + let js_backend = JsBackend::from(&options); + plugins.push(Box::new( + rspack_plugin_lazy_compilation::plugin::LazyCompilationPlugin::new( + options.cacheable, + js_backend, + options.test.map(|test| test.into()), + options.entries, + options.imports, + ), + ) as Box) + } } Ok(()) } diff --git a/crates/rspack_binding_options/src/options/raw_builtins/raw_lazy_compilation.rs b/crates/rspack_binding_options/src/options/raw_builtins/raw_lazy_compilation.rs new file mode 100644 index 00000000000..5a74ea15191 --- /dev/null +++ b/crates/rspack_binding_options/src/options/raw_builtins/raw_lazy_compilation.rs @@ -0,0 +1,135 @@ +use napi::{ + bindgen_prelude::{FromNapiValue, ToNapiValue, ValidateNapiValue}, + Either, +}; +use napi_derive::napi; +use rspack_binding_values::{JsModule, ToJsModule}; +use rspack_core::ModuleIdentifier; +use rspack_napi::threadsafe_function::ThreadsafeFunction; +use rspack_plugin_lazy_compilation::{ + backend::{Backend, ModuleInfo}, + plugin::{LazyCompilationTest, LazyCompilationTestCheck}, +}; +use rspack_regex::RspackRegex; + +use crate::RawRegexMatcher; + +#[derive(Debug)] +pub struct RawLazyCompilationTest>>( + pub Either, +); + +impl FromNapiValue for RawLazyCompilationTest { + unsafe fn from_napi_value( + env: napi::sys::napi_env, + napi_val: napi::sys::napi_value, + ) -> napi::Result { + Ok(Self(Either::from_napi_value(env, napi_val)?)) + } +} + +impl ToNapiValue for RawLazyCompilationTest { + unsafe fn to_napi_value( + env: napi::sys::napi_env, + val: Self, + ) -> napi::Result { + Either::to_napi_value(env, val.0) + } +} + +#[derive(Debug)] +pub struct LazyCompilationTestFn { + tsfn: ThreadsafeFunction>, +} + +impl LazyCompilationTestCheck for LazyCompilationTestFn { + fn test(&self, m: &dyn rspack_core::Module) -> bool { + let res = self + .tsfn + .blocking_call_with_sync( + m.to_js_module() + .expect("failed to convert module to js module"), + ) + .expect("failed to invoke lazyCompilation.test"); + + res.unwrap_or(false) + } +} + +impl From for LazyCompilationTest { + fn from(value: RawLazyCompilationTest) -> Self { + match value.0 { + Either::A(regex) => Self::Regex( + RspackRegex::with_flags(®ex.source, ®ex.flags).unwrap_or_else(|_| { + let msg = format!("[lazyCompilation]incorrect regex {:?}", regex); + panic!("{msg}"); + }), + ), + Either::B(tsfn) => Self::Fn(LazyCompilationTestFn { tsfn }), + } + } +} + +#[napi(object)] +pub struct RawModuleInfo { + pub active: bool, + pub client: String, + pub data: String, +} + +#[napi(object, object_to_js = false)] +pub struct RawLazyCompilationOption { + pub module: ThreadsafeFunction, + pub test: Option, + pub entries: bool, + pub imports: bool, + pub cacheable: bool, +} + +#[napi(object)] +pub struct RawModuleArg { + pub module: String, + pub path: String, +} + +pub(crate) struct JsBackend { + module: ThreadsafeFunction, +} + +impl std::fmt::Debug for JsBackend { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("JsBackend").finish() + } +} + +impl From<&RawLazyCompilationOption> for JsBackend { + fn from(value: &RawLazyCompilationOption) -> Self { + Self { + module: value.module.clone(), + } + } +} + +#[async_trait::async_trait] +impl Backend for JsBackend { + async fn module( + &mut self, + identifier: ModuleIdentifier, + path: String, + ) -> rspack_error::Result { + let module_info = self + .module + .call(RawModuleArg { + module: identifier.to_string(), + path, + }) + .await + .expect("channel should have result"); + + Ok(ModuleInfo { + active: module_info.active, + client: module_info.client, + data: module_info.data, + }) + } +} diff --git a/crates/rspack_core/src/dependency/dependency_type.rs b/crates/rspack_core/src/dependency/dependency_type.rs index 757dd6920fd..79838cc5f92 100644 --- a/crates/rspack_core/src/dependency/dependency_type.rs +++ b/crates/rspack_core/src/dependency/dependency_type.rs @@ -93,6 +93,7 @@ pub enum DependencyType { /// Webpack is included WebpackIsIncluded, LoaderImport, + LazyImport, Custom(Box), // TODO it will increase large layout size } @@ -149,6 +150,7 @@ impl DependencyType { DependencyType::ProvideModuleForShared => Cow::Borrowed("provide module for shared"), DependencyType::ConsumeSharedFallback => Cow::Borrowed("consume shared fallback"), DependencyType::WebpackIsIncluded => Cow::Borrowed("__webpack_is_included__"), + DependencyType::LazyImport => Cow::Borrowed("lazy import()"), } } } diff --git a/crates/rspack_core/src/module_factory.rs b/crates/rspack_core/src/module_factory.rs index 321f4db1064..3ad57230608 100644 --- a/crates/rspack_core/src/module_factory.rs +++ b/crates/rspack_core/src/module_factory.rs @@ -6,7 +6,7 @@ use sugar_path::SugarPath; use crate::{BoxDependency, BoxModule, Context, ModuleIdentifier, Resolve}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ModuleFactoryCreateData { pub resolve_options: Option>, pub context: Context, diff --git a/crates/rspack_core/src/utils/queue.rs b/crates/rspack_core/src/utils/queue.rs index f337e5789e2..70d1c135479 100644 --- a/crates/rspack_core/src/utils/queue.rs +++ b/crates/rspack_core/src/utils/queue.rs @@ -32,6 +32,14 @@ impl WorkerQueue { } } + pub fn len(&self) -> usize { + self.inner.len() + } + + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + pub fn add_task(&mut self, task: T) -> usize { self.inner.push_back(task); self.inner.len() diff --git a/crates/rspack_database/src/database.rs b/crates/rspack_database/src/database.rs index afd6283f65b..9bf7f6d4d01 100644 --- a/crates/rspack_database/src/database.rs +++ b/crates/rspack_database/src/database.rs @@ -31,6 +31,14 @@ impl Database { } } + pub fn len(&self) -> usize { + self.inner.len() + } + + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + pub fn contains(&self, id: &Ukey) -> bool { self.inner.contains_key(id) } diff --git a/crates/rspack_macros/src/plugin.rs b/crates/rspack_macros/src/plugin.rs index 39c68551242..38d4e86490c 100644 --- a/crates/rspack_macros/src/plugin.rs +++ b/crates/rspack_macros/src/plugin.rs @@ -7,7 +7,7 @@ use syn::{ pub fn expand_struct(mut input: syn::ItemStruct) -> proc_macro::TokenStream { let ident = &input.ident; let inner_ident = plugin_inner_ident(ident); - + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let inner_fields = input.fields.clone(); let is_named_struct = matches!(&inner_fields, syn::Fields::Named(_)); let is_unit_struct = matches!(&inner_fields, syn::Fields::Unit); @@ -19,7 +19,7 @@ pub fn expand_struct(mut input: syn::ItemStruct) -> proc_macro::TokenStream { input.fields = syn::Fields::Named( syn::FieldsNamed::parse - .parse2(quote! { { inner: ::std::sync::Arc<#inner_ident> } }) + .parse2(quote! { { inner: ::std::sync::Arc<#inner_ident #ty_generics> } }) .expect("Failed to parse"), ); @@ -51,33 +51,33 @@ pub fn expand_struct(mut input: syn::ItemStruct) -> proc_macro::TokenStream { let inner_struct = if is_named_struct { quote! { - pub struct #inner_ident #inner_fields + pub struct #inner_ident #impl_generics #where_clause #inner_fields } } else { quote! { - pub struct #inner_ident; + pub struct #inner_ident #impl_generics #where_clause; } }; let expanded = quote! { #input - impl #ident { + impl #impl_generics #ident #ty_generics #where_clause { #new_inner_fn - fn from_inner(inner: &::std::sync::Arc<#inner_ident>) -> Self { + fn from_inner(inner: &::std::sync::Arc<#inner_ident #ty_generics>) -> Self { Self { inner: ::std::sync::Arc::clone(inner), } } - fn inner(&self) -> &::std::sync::Arc<#inner_ident> { + fn inner(&self) -> &::std::sync::Arc<#inner_ident #ty_generics> { &self.inner } } - impl ::std::ops::Deref for #ident { - type Target = #inner_ident; + impl #impl_generics ::std::ops::Deref for #ident #ty_generics #where_clause { + type Target = #inner_ident #ty_generics; fn deref(&self) -> &Self::Target { &self.inner } @@ -99,6 +99,7 @@ pub struct HookArgs { trait_: syn::Path, name: syn::Ident, stage: Option, + generics: syn::Generics, } impl Parse for HookArgs { @@ -118,10 +119,13 @@ impl Parse for HookArgs { _ => return Err(input.error("expected \"stage\" or end of attribute")), } } + + let generics = input.parse::()?; Ok(Self { trait_, name, stage, + generics, }) } } @@ -131,7 +135,9 @@ pub fn expand_fn(args: HookArgs, input: syn::ItemFn) -> proc_macro::TokenStream name, trait_, stage, + generics, } = args; + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let syn::ItemFn { mut sig, block, .. } = input; let real_sig = sig.clone(); let mut rest_args = Vec::new(); @@ -172,32 +178,32 @@ pub fn expand_fn(args: HookArgs, input: syn::ItemFn) -> proc_macro::TokenStream let expanded = quote! { #[allow(non_camel_case_types)] - struct #fn_ident { - inner: ::std::sync::Arc<#inner_ident>, + struct #fn_ident #impl_generics #where_clause { + inner: ::std::sync::Arc<#inner_ident #ty_generics>, } - impl #fn_ident { - pub(crate) fn new(plugin: &#name) -> Self { + impl #impl_generics #fn_ident #ty_generics #where_clause { + pub(crate) fn new(plugin: &#name #ty_generics) -> Self { #fn_ident { inner: ::std::sync::Arc::clone(plugin.inner()), } } } - impl #name { + impl #impl_generics #name #ty_generics #where_clause { #[allow(clippy::ptr_arg)] #real_sig #block } - impl ::std::ops::Deref for #fn_ident { - type Target = #inner_ident; + impl #impl_generics ::std::ops::Deref for #fn_ident #ty_generics #where_clause { + type Target = #inner_ident #ty_generics; fn deref(&self) -> &Self::Target { &self.inner } } #attr - impl #trait_ for #fn_ident { + impl #impl_generics #trait_ for #fn_ident #ty_generics #where_clause { #sig { #call_real_fn } diff --git a/crates/rspack_plugin_javascript/Cargo.toml b/crates/rspack_plugin_javascript/Cargo.toml index 32410fa9c7e..1e5c639895e 100644 --- a/crates/rspack_plugin_javascript/Cargo.toml +++ b/crates/rspack_plugin_javascript/Cargo.toml @@ -44,6 +44,7 @@ swc_core = { workspace = true, features = [ "ecma_transforms_typescript", "base", "ecma_quote", + "base", ] } swc_node_comments = { workspace = true } url = { workspace = true } diff --git a/crates/rspack_plugin_lazy_compilation/Cargo.toml b/crates/rspack_plugin_lazy_compilation/Cargo.toml new file mode 100644 index 00000000000..9a61fd5cd60 --- /dev/null +++ b/crates/rspack_plugin_lazy_compilation/Cargo.toml @@ -0,0 +1,19 @@ +[package] +edition = "2021" +license = "MIT" +name = "rspack_plugin_lazy_compilation" +version = "0.1.0" + +[dependencies] +async-trait = { workspace = true } +once_cell = { workspace = true } +rustc-hash = { workspace = true } +tokio = { workspace = true } + +rspack_core = { path = "../rspack_core" } +rspack_error = { path = "../rspack_error" } +rspack_hook = { path = "../rspack_hook" } +rspack_identifier = { path = "../rspack_identifier" } +rspack_plugin_javascript = { path = "../rspack_plugin_javascript" } +rspack_regex = { path = "../rspack_regex" } +rspack_util = { path = "../rspack_util" } diff --git a/crates/rspack_plugin_lazy_compilation/expand.rs b/crates/rspack_plugin_lazy_compilation/expand.rs new file mode 100644 index 00000000000..03b6edfbaae --- /dev/null +++ b/crates/rspack_plugin_lazy_compilation/expand.rs @@ -0,0 +1,957 @@ +#![feature(prelude_import)] +#![feature(let_chains)] +#[prelude_import] +use std::prelude::rust_2021::*; +#[macro_use] +extern crate std; +pub mod backend { + use rspack_core::ModuleIdentifier; + use rspack_error::Result; + pub struct ModuleInfo { + pub active: bool, + pub data: String, + pub client: String, + } + pub trait Backend: std::fmt::Debug + Send + Sync { + #[must_use] + #[allow(clippy::type_complexity, clippy::type_repetition_in_bounds)] + fn module<'life0, 'async_trait>( + &'life0 mut self, + original_module: ModuleIdentifier, + path: String, + ) -> ::core::pin::Pin< + Box< + dyn ::core::future::Future> + + ::core::marker::Send + + 'async_trait, + >, + > + where + 'life0: 'async_trait, + Self: 'async_trait; + } +} +mod dependency { + use std::path::PathBuf; + + use rspack_core::{ + AsContextDependency, AsDependencyTemplate, Context, Dependency, DependencyCategory, + DependencyId, DependencyType, ModuleDependency, NormalModuleCreateData, Resolve, ResourceData, + }; + use rspack_error::Diagnostic; + use rspack_identifier::Identifier; + use rustc_hash::FxHashSet as HashSet; + pub(crate) struct ProxyCreateData { + pub resolve_options: Option>, + pub resource_resolve_data: ResourceData, + pub context: Context, + pub issuer: Option>, + pub issuer_identifier: Option, + pub file_dependencies: HashSet, + pub context_dependencies: HashSet, + pub missing_dependencies: HashSet, + pub diagnostics: Vec, + } + #[automatically_derived] + impl ::core::fmt::Debug for ProxyCreateData { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + let names: &'static _ = &[ + "resolve_options", + "resource_resolve_data", + "context", + "issuer", + "issuer_identifier", + "file_dependencies", + "context_dependencies", + "missing_dependencies", + "diagnostics", + ]; + let values: &[&dyn ::core::fmt::Debug] = &[ + &self.resolve_options, + &self.resource_resolve_data, + &self.context, + &self.issuer, + &self.issuer_identifier, + &self.file_dependencies, + &self.context_dependencies, + &self.missing_dependencies, + &&self.diagnostics, + ]; + ::core::fmt::Formatter::debug_struct_fields_finish(f, "ProxyCreateData", names, values) + } + } + #[automatically_derived] + impl ::core::clone::Clone for ProxyCreateData { + #[inline] + fn clone(&self) -> ProxyCreateData { + ProxyCreateData { + resolve_options: ::core::clone::Clone::clone(&self.resolve_options), + resource_resolve_data: ::core::clone::Clone::clone(&self.resource_resolve_data), + context: ::core::clone::Clone::clone(&self.context), + issuer: ::core::clone::Clone::clone(&self.issuer), + issuer_identifier: ::core::clone::Clone::clone(&self.issuer_identifier), + file_dependencies: ::core::clone::Clone::clone(&self.file_dependencies), + context_dependencies: ::core::clone::Clone::clone(&self.context_dependencies), + missing_dependencies: ::core::clone::Clone::clone(&self.missing_dependencies), + diagnostics: ::core::clone::Clone::clone(&self.diagnostics), + } + } + } + impl ProxyCreateData { + pub(crate) fn new(module_create_data: &NormalModuleCreateData) -> Self { + Self { + resolve_options: module_create_data.create_data.resolve_options.clone(), + resource_resolve_data: module_create_data.resource_resolve_data.clone(), + context: module_create_data.context.clone(), + issuer: module_create_data.create_data.issuer.clone(), + issuer_identifier: module_create_data.create_data.issuer_identifier, + file_dependencies: module_create_data.create_data.file_dependencies.clone(), + context_dependencies: module_create_data.create_data.context_dependencies.clone(), + missing_dependencies: module_create_data.create_data.missing_dependencies.clone(), + diagnostics: module_create_data.diagnostics.clone(), + } + } + } + pub(crate) struct LazyCompilationDependency { + id: DependencyId, + pub original_module_create_data: ProxyCreateData, + request: String, + } + #[automatically_derived] + impl ::core::fmt::Debug for LazyCompilationDependency { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_struct_field3_finish( + f, + "LazyCompilationDependency", + "id", + &self.id, + "original_module_create_data", + &self.original_module_create_data, + "request", + &&self.request, + ) + } + } + #[automatically_derived] + impl ::core::clone::Clone for LazyCompilationDependency { + #[inline] + fn clone(&self) -> LazyCompilationDependency { + LazyCompilationDependency { + id: ::core::clone::Clone::clone(&self.id), + original_module_create_data: ::core::clone::Clone::clone(&self.original_module_create_data), + request: ::core::clone::Clone::clone(&self.request), + } + } + } + impl LazyCompilationDependency { + pub fn new(original_module_create_data: ProxyCreateData) -> Self { + let request = { + let res = ::alloc::fmt::format(format_args!( + "{0}?lazy-compilation-proxy-dep", + &original_module_create_data.resource_resolve_data.resource + )); + res + }; + Self { + id: DependencyId::new(), + original_module_create_data, + request, + } + } + } + impl ModuleDependency for LazyCompilationDependency { + fn request(&self) -> &str { + &self.request + } + } + impl AsDependencyTemplate for LazyCompilationDependency {} + impl AsContextDependency for LazyCompilationDependency {} + impl Dependency for LazyCompilationDependency { + fn dependency_debug_name(&self) -> &'static str { + "lazy compilation dependency" + } + fn id(&self) -> &rspack_core::DependencyId { + &self.id + } + fn category(&self) -> &DependencyCategory { + &DependencyCategory::Esm + } + fn dependency_type(&self) -> &DependencyType { + &DependencyType::LazyImport + } + } +} +mod factory { + use std::sync::Arc; + + use rspack_core::{ + ModuleFactory, ModuleFactoryCreateData, ModuleFactoryResult, NormalModuleFactory, + }; + use rspack_error::Result; + + use crate::dependency::LazyCompilationDependency; + pub(crate) struct LazyCompilationDependencyFactory { + normal_module_factory: Arc, + } + #[automatically_derived] + impl ::core::fmt::Debug for LazyCompilationDependencyFactory { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_struct_field1_finish( + f, + "LazyCompilationDependencyFactory", + "normal_module_factory", + &&self.normal_module_factory, + ) + } + } + impl LazyCompilationDependencyFactory { + pub fn new(normal_module_factory: Arc) -> Self { + Self { + normal_module_factory, + } + } + } + impl ModuleFactory for LazyCompilationDependencyFactory { + #[allow( + clippy::async_yields_async, + clippy::diverging_sub_expression, + clippy::let_unit_value, + clippy::no_effect_underscore_binding, + clippy::shadow_same, + clippy::type_complexity, + clippy::type_repetition_in_bounds, + clippy::used_underscore_binding + )] + fn create<'life0, 'life1, 'async_trait>( + &'life0 self, + data: &'life1 mut ModuleFactoryCreateData, + ) -> ::core::pin::Pin< + Box< + dyn ::core::future::Future> + + ::core::marker::Send + + 'async_trait, + >, + > + where + 'life0: 'async_trait, + 'life1: 'async_trait, + Self: 'async_trait, + { + Box::pin(async move { + if let ::core::option::Option::Some(__ret) = + ::core::option::Option::None::> + { + return __ret; + } + let __self = self; + let __ret: Result = { + let dep: &LazyCompilationDependency = data + .dependency + .as_any() + .downcast_ref() + .expect("should be lazy compile dependency"); + let proxy_data = &dep.original_module_create_data; + let dep = dep.clone(); + let mut create_data = ModuleFactoryCreateData { + resolve_options: proxy_data.resolve_options.clone(), + context: proxy_data.context.clone(), + dependency: Box::new(dep), + issuer: proxy_data.issuer.clone(), + issuer_identifier: proxy_data.issuer_identifier, + file_dependencies: proxy_data.file_dependencies.clone(), + context_dependencies: proxy_data.context_dependencies.clone(), + missing_dependencies: proxy_data.missing_dependencies.clone(), + diagnostics: proxy_data.diagnostics.clone(), + }; + __self.normal_module_factory.create(&mut create_data).await + }; + #[allow(unreachable_code)] + __ret + }) + } + } +} +mod module { + use std::{hash::Hash, path::PathBuf, sync::Arc}; + + use rspack_core::{ + impl_build_info_meta, module_namespace_promise, + rspack_sources::{RawSource, Source}, + AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, BoxDependency, BuildContext, + BuildInfo, BuildMeta, BuildResult, CodeGenerationResult, Compilation, ConcatenationScope, + Context, DependenciesBlock, DependencyId, Module, ModuleIdentifier, ModuleType, RuntimeGlobals, + RuntimeSpec, SourceType, TemplateContext, + }; + use rspack_error::{Diagnosable, Diagnostic, Result}; + use rspack_identifier::Identifiable; + use rspack_plugin_javascript::dependency::CommonJsRequireDependency; + use rspack_util::source_map::{ModuleSourceMapConfig, SourceMapKind}; + use rustc_hash::FxHashSet; + + use crate::dependency::{LazyCompilationDependency, ProxyCreateData}; + static MODULE_TYPE: ModuleType = ModuleType::Js; + static SOURCE_TYPE: [SourceType; 1] = [SourceType::JavaScript]; + pub(crate) struct LazyCompilationProxyModule { + build_info: Option, + build_meta: Option, + original_module: ModuleIdentifier, + cacheable: bool, + readable_identifier: String, + identifier: ModuleIdentifier, + blocks: Vec, + dependencies: Vec, + source_map_kind: SourceMapKind, + create_data: ProxyCreateData, + pub request: String, + pub active: bool, + pub data: String, + pub client: String, + } + #[automatically_derived] + impl ::core::fmt::Debug for LazyCompilationProxyModule { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + let names: &'static _ = &[ + "build_info", + "build_meta", + "original_module", + "cacheable", + "readable_identifier", + "identifier", + "blocks", + "dependencies", + "source_map_kind", + "create_data", + "request", + "active", + "data", + "client", + ]; + let values: &[&dyn ::core::fmt::Debug] = &[ + &self.build_info, + &self.build_meta, + &self.original_module, + &self.cacheable, + &self.readable_identifier, + &self.identifier, + &self.blocks, + &self.dependencies, + &self.source_map_kind, + &self.create_data, + &self.request, + &self.active, + &self.data, + &&self.client, + ]; + ::core::fmt::Formatter::debug_struct_fields_finish( + f, + "LazyCompilationProxyModule", + names, + values, + ) + } + } + impl Hash for LazyCompilationProxyModule { + fn hash(&self, state: &mut H) { + self.build_meta.hash(state); + self.original_module.hash(state); + self.readable_identifier.hash(state); + self.identifier.hash(state); + self.blocks.hash(state); + self.dependencies.hash(state); + } + } + impl PartialEq for LazyCompilationProxyModule { + fn eq(&self, other: &Self) -> bool { + self.original_module == other.original_module + && self.readable_identifier == other.readable_identifier + && self.identifier == other.identifier + } + } + impl Eq for LazyCompilationProxyModule {} + impl ModuleSourceMapConfig for LazyCompilationProxyModule { + fn get_source_map_kind(&self) -> &SourceMapKind { + &self.source_map_kind + } + fn set_source_map_kind(&mut self, source_map: SourceMapKind) { + self.source_map_kind = source_map; + } + } + impl LazyCompilationProxyModule { + pub(crate) fn new( + original_module: ModuleIdentifier, + create_data: ProxyCreateData, + request: String, + cacheable: bool, + active: bool, + data: String, + client: String, + ) -> Self { + let readable_identifier = { + let res = ::alloc::fmt::format(format_args!( + "lazy-compilation-proxy|{0}", + create_data.context.shorten(&original_module) + )); + res + }; + let identifier = { + let res = ::alloc::fmt::format(format_args!("lazy-compilation-proxy|{0}", original_module)); + res + } + .into(); + Self { + build_info: None, + build_meta: None, + cacheable, + original_module, + create_data, + readable_identifier, + identifier, + source_map_kind: SourceMapKind::None, + blocks: ::alloc::vec::Vec::new(), + dependencies: ::alloc::vec::Vec::new(), + active, + request, + client, + data, + } + } + } + impl Diagnosable for LazyCompilationProxyModule { + fn add_diagnostic(&self, _diagnostic: Diagnostic) { + ::core::panicking::panic("not implemented") + } + fn add_diagnostics(&self, _diagnostics: Vec) { + ::core::panicking::panic("not implemented") + } + } + impl Module for LazyCompilationProxyModule { + fn build_info(&self) -> Option<&::rspack_core::BuildInfo> { + self.build_info.as_ref() + } + fn build_meta(&self) -> Option<&::rspack_core::BuildMeta> { + self.build_meta.as_ref() + } + fn set_module_build_info_and_meta( + &mut self, + build_info: ::rspack_core::BuildInfo, + build_meta: ::rspack_core::BuildMeta, + ) { + self.build_info = Some(build_info); + self.build_meta = Some(build_meta); + } + fn source_types(&self) -> &[SourceType] { + &SOURCE_TYPE + } + fn module_type(&self) -> &ModuleType { + &MODULE_TYPE + } + fn size(&self, _source_type: &SourceType) -> f64 { + 200f64 + } + fn original_source(&self) -> Option<&dyn Source> { + None + } + fn readable_identifier(&self, _context: &Context) -> std::borrow::Cow { + std::borrow::Cow::Borrowed(&self.readable_identifier) + } + fn get_diagnostics(&self) -> Vec { + ::alloc::vec::Vec::new() + } + #[allow( + clippy::async_yields_async, + clippy::diverging_sub_expression, + clippy::let_unit_value, + clippy::no_effect_underscore_binding, + clippy::shadow_same, + clippy::type_complexity, + clippy::type_repetition_in_bounds, + clippy::used_underscore_binding + )] + fn build<'life0, 'life1, 'life2, 'async_trait>( + &'life0 mut self, + _build_context: BuildContext<'life1>, + _compilation: Option<&'life2 Compilation>, + ) -> ::core::pin::Pin< + Box< + dyn ::core::future::Future> + + ::core::marker::Send + + 'async_trait, + >, + > + where + 'life0: 'async_trait, + 'life1: 'async_trait, + 'life2: 'async_trait, + Self: 'async_trait, + { + Box::pin(async move { + if let ::core::option::Option::Some(__ret) = + ::core::option::Option::None::> + { + return __ret; + } + let mut __self = self; + let _build_context = _build_context; + let _compilation = _compilation; + let __ret: Result = { + let client_dep = CommonJsRequireDependency::new(__self.client.clone(), None, 0, 0, false); + let mut dependencies = ::alloc::vec::Vec::new(); + let mut blocks = ::alloc::vec::Vec::new(); + dependencies.push(Box::new(client_dep) as BoxDependency); + if __self.active { + let dep = LazyCompilationDependency::new(__self.create_data.clone()); + blocks.push(AsyncDependenciesBlock::new( + __self.identifier, + None, + None, + <[_]>::into_vec( + #[rustc_box] + ::alloc::boxed::Box::new([Box::new(dep)]), + ), + )); + } + let mut files = FxHashSet::default(); + files.extend(__self.create_data.file_dependencies.clone()); + files.insert(PathBuf::from( + &__self.create_data.resource_resolve_data.resource, + )); + Ok(BuildResult { + build_info: BuildInfo { + cacheable: __self.cacheable, + file_dependencies: files, + ..Default::default() + }, + build_meta: BuildMeta::default(), + analyze_result: Default::default(), + dependencies, + blocks, + optimization_bailouts: ::alloc::vec::Vec::new(), + }) + }; + #[allow(unreachable_code)] + __ret + }) + } + fn code_generation( + &self, + compilation: &Compilation, + _runtime: Option<&RuntimeSpec>, + mut concatenation_scope: Option, + ) -> Result { + let mut runtime_requirements = RuntimeGlobals::empty(); + runtime_requirements.insert(RuntimeGlobals::MODULE); + runtime_requirements.insert(RuntimeGlobals::REQUIRE); + let client_dep_id = self.dependencies[0]; + let module_graph = &compilation.get_module_graph(); + let chunk_graph = &compilation.chunk_graph; + let client_module = module_graph + .module_identifier_by_dependency_id(&client_dep_id) + .expect("should have module"); + let block = self.blocks.first(); + let client = { + let res = ::alloc::fmt::format(format_args!( + "var client = __webpack_require__(\"{0}\");\nvar data = \"{1}\"", + chunk_graph + .get_module_id(*client_module) + .as_ref() + .expect("should have module id"), + self.data + )); + res + }; + let keep_active = { + let res = ::alloc::fmt::format( + format_args!( + "var dispose = client.keepAlive({{ data: data, active: {0}, module: module, onError: onError }})", + block.is_some() + ), + ); + res + }; + let source = if let Some(block_id) = block { + let block = module_graph + .block_by_id(block_id) + .expect("should have block"); + let dep_id = block.get_dependencies()[0]; + let module = module_graph + .module_identifier_by_dependency_id(&dep_id) + .expect("should have module"); + let mut template_ctx = TemplateContext { + compilation, + module: module_graph + .module_by_identifier(module) + .expect("should have module") + .as_ref(), + runtime_requirements: &mut runtime_requirements, + init_fragments: &mut ::alloc::vec::Vec::new(), + runtime: None, + concatenation_scope: concatenation_scope.as_mut(), + }; + RawSource::from({ + let res = ::alloc::fmt::format( + format_args!( + "{3}\n module.exports = {0};\n if (module.hot) {{\n module.hot.accept();\n module.hot.accept(\"{1}\", function() {{ module.hot.invalidate(); }});\n module.hot.dispose(function(data) {{ delete data.resolveSelf; dispose(data); }});\n if (module.hot.data && module.hot.data.resolveSelf)\n module.hot.data.resolveSelf(module.exports);\n }}\n function onError() {{ /* ignore */ }}\n {2}\n ", + module_namespace_promise(& mut template_ctx, & dep_id, + Some(block_id), & self.request, "import()", false), + chunk_graph.get_module_id(* module).as_ref() + .expect("should have module id"), keep_active, client + ), + ); + res + }) + } else { + RawSource::from({ + let res = ::alloc::fmt::format( + format_args!( + "{0}\n var resolveSelf, onError;\n module.exports = new Promise(function(resolve, reject) {{ resolveSelf = resolve; onError = reject; }});\n if (module.hot) {{\n module.hot.accept();\n if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);\n module.hot.dispose(function(data) {{ data.resolveSelf = resolveSelf; dispose(data); }});\n }}\n {1}\n ", + client, keep_active + ), + ); + res + }) + }; + let mut codegen_result = CodeGenerationResult::default().with_javascript(Arc::new(source)); + codegen_result.runtime_requirements = runtime_requirements; + codegen_result.set_hash( + &compilation.options.output.hash_function, + &compilation.options.output.hash_digest, + &compilation.options.output.hash_salt, + ); + Ok(codegen_result) + } + } + impl Identifiable for LazyCompilationProxyModule { + fn identifier(&self) -> rspack_identifier::Identifier { + self.identifier + } + } + impl DependenciesBlock for LazyCompilationProxyModule { + fn add_block_id(&mut self, block: rspack_core::AsyncDependenciesBlockIdentifier) { + self.blocks.push(block); + } + fn get_blocks(&self) -> &[rspack_core::AsyncDependenciesBlockIdentifier] { + &self.blocks + } + fn add_dependency_id(&mut self, dependency: rspack_core::DependencyId) { + self.dependencies.push(dependency); + } + fn get_dependencies(&self) -> &[rspack_core::DependencyId] { + &self.dependencies + } + } +} +pub mod plugin { + use std::sync::Arc; + + use once_cell::sync::Lazy; + use rspack_core::{ + BoxModule, Compilation, CompilationParams, DependencyType, ModuleFactory, + NormalModuleCreateData, Plugin, PluginContext, PluginNormalModuleFactoryModuleHookOutput, + }; + use rspack_hook::{plugin, plugin_hook, AsyncSeries2}; + use rspack_regex::RspackRegex; + use tokio::sync::Mutex; + + use crate::{ + backend::Backend, dependency::ProxyCreateData, factory::LazyCompilationDependencyFactory, + module::LazyCompilationProxyModule, + }; + static WEBPACK_DEV_SERVER_CLIENT_RE: Lazy = Lazy::new(|| { + RspackRegex::new( + r#"(webpack|rspack)[/\\]hot[/\\]|(webpack|rspack)-dev-server[/\\]client|(webpack|rspack)-hot-middleware[/\\]client"#, + ) + .expect("should compile regex") + }); + pub struct LazyCompilationPlugin { + inner: ::std::sync::Arc>, + } + #[automatically_derived] + impl ::core::fmt::Debug for LazyCompilationPlugin { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_struct_field1_finish( + f, + "LazyCompilationPlugin", + "inner", + &&self.inner, + ) + } + } + impl LazyCompilationPlugin { + #[allow(clippy::too_many_arguments)] + fn new_inner( + backend: Mutex, + entries: bool, + imports: bool, + test: Option, + cacheable: bool, + ) -> Self { + Self { + inner: ::std::sync::Arc::new(LazyCompilationPluginInner { + backend, + entries, + imports, + test, + cacheable, + }), + } + } + fn from_inner(inner: &::std::sync::Arc>) -> Self { + Self { + inner: ::std::sync::Arc::clone(inner), + } + } + fn inner(&self) -> &::std::sync::Arc> { + &self.inner + } + } + impl ::std::ops::Deref for LazyCompilationPlugin { + type Target = LazyCompilationPluginInner; + fn deref(&self) -> &Self::Target { + &self.inner + } + } + #[doc(hidden)] + pub struct LazyCompilationPluginInner { + backend: Mutex, + entries: bool, + imports: bool, + test: Option, + cacheable: bool, + } + #[automatically_derived] + impl ::core::fmt::Debug for LazyCompilationPluginInner { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_struct_field5_finish( + f, + "LazyCompilationPluginInner", + "backend", + &self.backend, + "entries", + &self.entries, + "imports", + &self.imports, + "test", + &self.test, + "cacheable", + &&self.cacheable, + ) + } + } + impl LazyCompilationPlugin { + pub fn new( + cacheable: bool, + backend: T, + test: Option, + entries: bool, + imports: bool, + ) -> Self { + Self::new_inner(Mutex::new(backend), entries, imports, test, cacheable) + } + fn check_test(&self, module: &BoxModule) -> bool { + if let Some(test) = &self.test { + test.test(&module.name_for_condition().unwrap_or("".into())) + } else { + true + } + } + } + #[allow(non_camel_case_types)] + struct compilation { + inner: ::std::sync::Arc>, + } + impl compilation { + pub(crate) fn new(plugin: &LazyCompilationPlugin) -> Box { + Box::new(compilation { + inner: ::std::sync::Arc::clone(plugin.inner()), + }) + } + } + impl LazyCompilationPlugin { + #[allow(clippy::ptr_arg)] + async fn compilation( + &self, + compilation: &mut Compilation, + params: &mut CompilationParams, + ) -> Result<()> { + Ok(()) + } + } + impl ::std::ops::Deref for compilation { + type Target = LazyCompilationPluginInner; + fn deref(&self) -> &Self::Target { + &self.inner + } + } + impl AsyncSeries2 for compilation { + #[allow( + clippy::async_yields_async, + clippy::diverging_sub_expression, + clippy::let_unit_value, + clippy::no_effect_underscore_binding, + clippy::shadow_same, + clippy::type_complexity, + clippy::type_repetition_in_bounds, + clippy::used_underscore_binding + )] + fn run<'life0, 'life1, 'life2, 'async_trait>( + &'life0 self, + compilation: &'life1 mut Compilation, + params: &'life2 mut CompilationParams, + ) -> ::core::pin::Pin< + Box> + ::core::marker::Send + 'async_trait>, + > + where + 'life0: 'async_trait, + 'life1: 'async_trait, + 'life2: 'async_trait, + Self: 'async_trait, + { + Box::pin(async move { + if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::> { + return __ret; + } + let __self = self; + let __ret: Result<()> = { + LazyCompilationPlugin::compilation( + &LazyCompilationPlugin::from_inner(&__self.inner), + compilation, + params, + ) + .await + }; + #[allow(unreachable_code)] + __ret + }) + } + } + impl Plugin for LazyCompilationPlugin { + #[allow( + clippy::async_yields_async, + clippy::diverging_sub_expression, + clippy::let_unit_value, + clippy::no_effect_underscore_binding, + clippy::shadow_same, + clippy::type_complexity, + clippy::type_repetition_in_bounds, + clippy::used_underscore_binding + )] + fn normal_module_factory_module<'life0, 'life1, 'life2, 'async_trait>( + &'life0 self, + _ctx: PluginContext, + module: BoxModule, + args: &'life1 mut NormalModuleCreateData<'life2>, + ) -> ::core::pin::Pin< + Box< + dyn ::core::future::Future + + ::core::marker::Send + + 'async_trait, + >, + > + where + 'life0: 'async_trait, + 'life1: 'async_trait, + 'life2: 'async_trait, + Self: 'async_trait, + { + Box::pin(async move { + if let ::core::option::Option::Some(__ret) = + ::core::option::Option::None:: + { + return __ret; + } + let __self = self; + let _ctx = _ctx; + let module = module; + let __ret: PluginNormalModuleFactoryModuleHookOutput = { + if let Some(query) = &args.resource_resolve_data.resource_query + && query.contains("lazy-compilation-proxy-dep") + { + let remaining_query = query.clone().replace("lazy-compilation-proxy-dep", ""); + args.resource_resolve_data.resource_query = + if remaining_query.is_empty() || remaining_query == "?" { + None + } else { + Some(remaining_query) + }; + return Ok(module); + } + let create_data = args.create_data; + let dep_type = create_data.dependency.dependency_type(); + let is_imports = match dep_type { + DependencyType::DynamicImport + | DependencyType::DynamicImportEager + | DependencyType::ContextElement => true, + _ => false, + }; + let is_entries = match dep_type { + DependencyType::Entry => true, + _ => false, + }; + #[allow(clippy::if_same_then_else)] + if match dep_type { + DependencyType::ModuleHotAccept + | DependencyType::ModuleHotDecline + | DependencyType::ImportMetaHotAccept + | DependencyType::ImportMetaHotDecline => true, + _ => false, + } { + return Ok(module); + } else if !is_entries && !is_imports { + return Ok(module); + } + if !__self.entries && is_entries { + return Ok(module); + } + if !__self.imports && is_imports { + return Ok(module); + } + if WEBPACK_DEV_SERVER_CLIENT_RE.test(args.resolve_data_request) + || !__self.check_test(&module) + { + return Ok(module); + } + let mut backend = __self.backend.lock().await; + let module_identifier = module.identifier(); + let info = backend + .module( + module_identifier, + args.resource_resolve_data.resource.clone(), + ) + .await?; + match module_identifier { + tmp => { + { + ::std::io::_eprint(format_args!( + "[{0}:{1}:{2}] {3} = {4:#?}\n", + "crates/rspack_plugin_lazy_compilation/src/plugin.rs", + 151u32, + 5u32, + "module_identifier", + &tmp + )); + }; + tmp + } + }; + Ok(Box::new(LazyCompilationProxyModule::new( + module_identifier, + ProxyCreateData::new(args), + args.resolve_data_request.to_string(), + __self.cacheable, + info.active, + info.data, + info.client, + )) as BoxModule) + }; + #[allow(unreachable_code)] + __ret + }) + } + } +} diff --git a/crates/rspack_plugin_lazy_compilation/src/backend.rs b/crates/rspack_plugin_lazy_compilation/src/backend.rs new file mode 100644 index 00000000000..87f2e8d07f6 --- /dev/null +++ b/crates/rspack_plugin_lazy_compilation/src/backend.rs @@ -0,0 +1,14 @@ +use rspack_core::ModuleIdentifier; +use rspack_error::Result; + +pub struct ModuleInfo { + pub active: bool, + pub data: String, + pub client: String, +} + +#[async_trait::async_trait] +pub trait Backend: std::fmt::Debug + Send + Sync { + async fn module(&mut self, original_module: ModuleIdentifier, path: String) + -> Result; +} diff --git a/crates/rspack_plugin_lazy_compilation/src/dependency.rs b/crates/rspack_plugin_lazy_compilation/src/dependency.rs new file mode 100644 index 00000000000..b7562843bd4 --- /dev/null +++ b/crates/rspack_plugin_lazy_compilation/src/dependency.rs @@ -0,0 +1,54 @@ +use rspack_core::{ + AsContextDependency, AsDependencyTemplate, Dependency, DependencyCategory, DependencyId, + DependencyType, ModuleDependency, ModuleFactoryCreateData, +}; + +#[derive(Debug, Clone)] +pub(crate) struct LazyCompilationDependency { + id: DependencyId, + pub original_module_create_data: ModuleFactoryCreateData, + request: String, +} + +impl LazyCompilationDependency { + pub fn new(original_module_create_data: ModuleFactoryCreateData) -> Self { + let dep = original_module_create_data + .dependency + .as_module_dependency() + .expect("LazyCompilation: should convert to module dependency"); + let request = format!("{}?lazy-compilation-proxy-dep", dep.request()); + + Self { + id: DependencyId::new(), + original_module_create_data, + request, + } + } +} + +impl ModuleDependency for LazyCompilationDependency { + fn request(&self) -> &str { + &self.request + } +} + +impl AsDependencyTemplate for LazyCompilationDependency {} +impl AsContextDependency for LazyCompilationDependency {} + +impl Dependency for LazyCompilationDependency { + fn dependency_debug_name(&self) -> &'static str { + "lazy compilation dependency" + } + + fn id(&self) -> &rspack_core::DependencyId { + &self.id + } + + fn category(&self) -> &DependencyCategory { + &DependencyCategory::Esm + } + + fn dependency_type(&self) -> &DependencyType { + &DependencyType::LazyImport + } +} diff --git a/crates/rspack_plugin_lazy_compilation/src/factory.rs b/crates/rspack_plugin_lazy_compilation/src/factory.rs new file mode 100644 index 00000000000..c5dde4621f1 --- /dev/null +++ b/crates/rspack_plugin_lazy_compilation/src/factory.rs @@ -0,0 +1,50 @@ +use std::sync::Arc; + +use rspack_core::{ + ModuleFactory, ModuleFactoryCreateData, ModuleFactoryResult, NormalModuleFactory, +}; +use rspack_error::Result; + +use crate::dependency::LazyCompilationDependency; + +#[derive(Debug)] +pub(crate) struct LazyCompilationDependencyFactory { + normal_module_factory: Arc, +} + +impl LazyCompilationDependencyFactory { + pub fn new(normal_module_factory: Arc) -> Self { + Self { + normal_module_factory, + } + } +} + +#[async_trait::async_trait] +impl ModuleFactory for LazyCompilationDependencyFactory { + async fn create(&self, data: &mut ModuleFactoryCreateData) -> Result { + let dep: &LazyCompilationDependency = data + .dependency + .as_any() + .downcast_ref() + .expect("should be lazy compile dependency"); + + let proxy_data = &dep.original_module_create_data; + + let dep = dep.clone(); + + let mut create_data = ModuleFactoryCreateData { + resolve_options: proxy_data.resolve_options.clone(), + context: proxy_data.context.clone(), + dependency: Box::new(dep), + issuer: proxy_data.issuer.clone(), + issuer_identifier: proxy_data.issuer_identifier, + file_dependencies: proxy_data.file_dependencies.clone(), + context_dependencies: proxy_data.context_dependencies.clone(), + missing_dependencies: proxy_data.missing_dependencies.clone(), + diagnostics: proxy_data.diagnostics.clone(), + }; + + self.normal_module_factory.create(&mut create_data).await + } +} diff --git a/crates/rspack_plugin_lazy_compilation/src/lib.rs b/crates/rspack_plugin_lazy_compilation/src/lib.rs new file mode 100644 index 00000000000..c30623e5320 --- /dev/null +++ b/crates/rspack_plugin_lazy_compilation/src/lib.rs @@ -0,0 +1,6 @@ +#![feature(let_chains)] +pub mod backend; +mod dependency; +mod factory; +mod module; +pub mod plugin; diff --git a/crates/rspack_plugin_lazy_compilation/src/module.rs b/crates/rspack_plugin_lazy_compilation/src/module.rs new file mode 100644 index 00000000000..aa4c6157e89 --- /dev/null +++ b/crates/rspack_plugin_lazy_compilation/src/module.rs @@ -0,0 +1,323 @@ +use std::{hash::Hash, path::PathBuf, sync::Arc}; + +use rspack_core::{ + impl_module_meta_info, module_namespace_promise, + rspack_sources::{RawSource, Source}, + AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, BoxDependency, BuildContext, BuildInfo, + BuildMeta, BuildResult, CodeGenerationResult, Compilation, ConcatenationScope, Context, + DependenciesBlock, DependencyId, FactoryMeta, Module, ModuleFactoryCreateData, ModuleIdentifier, + ModuleType, RuntimeGlobals, RuntimeSpec, SourceType, TemplateContext, +}; +use rspack_error::{Diagnosable, Diagnostic, Result}; +use rspack_identifier::Identifiable; +use rspack_plugin_javascript::dependency::CommonJsRequireDependency; +use rspack_util::source_map::{ModuleSourceMapConfig, SourceMapKind}; +use rustc_hash::FxHashSet; + +use crate::dependency::LazyCompilationDependency; + +static MODULE_TYPE: ModuleType = ModuleType::Js; +static SOURCE_TYPE: [SourceType; 1] = [SourceType::JavaScript]; + +#[derive(Debug)] +pub(crate) struct LazyCompilationProxyModule { + build_info: Option, + build_meta: Option, + factory_meta: Option, + original_module: ModuleIdentifier, + cacheable: bool, + + readable_identifier: String, + identifier: ModuleIdentifier, + + blocks: Vec, + dependencies: Vec, + + source_map_kind: SourceMapKind, + create_data: ModuleFactoryCreateData, + pub resource: String, + + pub active: bool, + pub data: String, + pub client: String, +} + +impl Hash for LazyCompilationProxyModule { + fn hash(&self, state: &mut H) { + self.build_meta.hash(state); + self.original_module.hash(state); + self.readable_identifier.hash(state); + self.identifier.hash(state); + self.blocks.hash(state); + self.dependencies.hash(state); + } +} + +impl PartialEq for LazyCompilationProxyModule { + fn eq(&self, other: &Self) -> bool { + self.original_module == other.original_module + && self.readable_identifier == other.readable_identifier + && self.identifier == other.identifier + } +} + +impl Eq for LazyCompilationProxyModule {} + +impl ModuleSourceMapConfig for LazyCompilationProxyModule { + fn get_source_map_kind(&self) -> &SourceMapKind { + &self.source_map_kind + } + + fn set_source_map_kind(&mut self, source_map: SourceMapKind) { + self.source_map_kind = source_map; + } +} + +impl LazyCompilationProxyModule { + pub(crate) fn new( + original_module: ModuleIdentifier, + create_data: ModuleFactoryCreateData, + resource: String, + cacheable: bool, + active: bool, + data: String, + client: String, + ) -> Self { + let readable_identifier = format!( + "lazy-compilation-proxy|{}", + create_data.context.shorten(&original_module) + ); + let identifier = format!("lazy-compilation-proxy|{original_module}").into(); + + Self { + build_info: None, + build_meta: None, + cacheable, + original_module, + create_data, + readable_identifier, + resource, + identifier, + source_map_kind: SourceMapKind::empty(), + factory_meta: None, + blocks: vec![], + dependencies: vec![], + active, + client, + data, + } + } +} + +impl Diagnosable for LazyCompilationProxyModule { + fn add_diagnostic(&self, _diagnostic: Diagnostic) { + unimplemented!() + } + fn add_diagnostics(&self, _diagnostics: Vec) { + unimplemented!() + } +} + +#[async_trait::async_trait] +impl Module for LazyCompilationProxyModule { + impl_module_meta_info!(); + + fn source_types(&self) -> &[SourceType] { + &SOURCE_TYPE + } + + fn module_type(&self) -> &ModuleType { + &MODULE_TYPE + } + + fn size(&self, _source_type: &SourceType) -> f64 { + 200f64 + } + + fn original_source(&self) -> Option<&dyn Source> { + None + } + + fn readable_identifier(&self, _context: &Context) -> std::borrow::Cow { + std::borrow::Cow::Borrowed(&self.readable_identifier) + } + + fn get_diagnostics(&self) -> Vec { + vec![] + } + + async fn build( + &mut self, + _build_context: BuildContext<'_>, + _compilation: Option<&Compilation>, + ) -> Result { + let client_dep = CommonJsRequireDependency::new(self.client.clone(), None, 0, 0, false); + let mut dependencies = vec![]; + let mut blocks = vec![]; + + dependencies.push(Box::new(client_dep) as BoxDependency); + + if self.active { + let dep = LazyCompilationDependency::new(self.create_data.clone()); + + blocks.push(AsyncDependenciesBlock::new( + self.identifier, + None, + None, + vec![Box::new(dep)], + )); + } + + let mut files = FxHashSet::default(); + files.extend(self.create_data.file_dependencies.clone()); + files.insert(PathBuf::from(&self.resource)); + + Ok(BuildResult { + build_info: BuildInfo { + cacheable: self.cacheable, + file_dependencies: files, + ..Default::default() + }, + build_meta: BuildMeta::default(), + analyze_result: Default::default(), + dependencies, + blocks, + optimization_bailouts: vec![], + }) + } + + fn code_generation( + &self, + compilation: &Compilation, + _runtime: Option<&RuntimeSpec>, + mut concatenation_scope: Option, + ) -> Result { + let mut runtime_requirements = RuntimeGlobals::empty(); + runtime_requirements.insert(RuntimeGlobals::MODULE); + runtime_requirements.insert(RuntimeGlobals::REQUIRE); + + let client_dep_id = self.dependencies[0]; + let module_graph = &compilation.get_module_graph(); + let chunk_graph = &compilation.chunk_graph; + + let client_module = module_graph + .module_identifier_by_dependency_id(&client_dep_id) + .expect("should have module"); + + let block = self.blocks.first(); + + let client = format!( + "var client = __webpack_require__(\"{}\");\nvar data = \"{}\"", + chunk_graph + .get_module_id(*client_module) + .as_ref() + .expect("should have module id"), + self.data + ); + + let keep_active = format!( + "var dispose = client.keepAlive({{ data: data, active: {}, module: module, onError: onError }})", + block.is_some() + ); + + let source = if let Some(block_id) = block { + let block = module_graph + .block_by_id(block_id) + .expect("should have block"); + + let dep_id = block.get_dependencies()[0]; + let module = module_graph + .module_identifier_by_dependency_id(&dep_id) + .expect("should have module"); + + let mut template_ctx = TemplateContext { + compilation, + module: module_graph + .module_by_identifier(module) + .expect("should have module") + .as_ref(), + runtime_requirements: &mut runtime_requirements, + init_fragments: &mut vec![], + runtime: None, + concatenation_scope: concatenation_scope.as_mut(), + }; + + RawSource::from(format!( + "{client} + module.exports = {}; + if (module.hot) {{ + module.hot.accept(); + module.hot.accept(\"{}\", function() {{ module.hot.invalidate(); }}); + module.hot.dispose(function(data) {{ delete data.resolveSelf; dispose(data); }}); + if (module.hot.data && module.hot.data.resolveSelf) + module.hot.data.resolveSelf(module.exports); + }} + function onError() {{ /* ignore */ }} + {} + ", + module_namespace_promise( + &mut template_ctx, + &dep_id, + Some(block_id), + &self.resource, + "import()", + false + ), + chunk_graph + .get_module_id(*module) + .as_ref() + .expect("should have module id"), + keep_active, + )) + } else { + RawSource::from(format!( + "{} + var resolveSelf, onError; + module.exports = new Promise(function(resolve, reject) {{ resolveSelf = resolve; onError = reject; }}); + if (module.hot) {{ + module.hot.accept(); + if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports); + module.hot.dispose(function(data) {{ data.resolveSelf = resolveSelf; dispose(data); }}); + }} + {} + ", + client, + keep_active + )) + }; + + let mut codegen_result = CodeGenerationResult::default().with_javascript(Arc::new(source)); + codegen_result.runtime_requirements = runtime_requirements; + codegen_result.set_hash( + &compilation.options.output.hash_function, + &compilation.options.output.hash_digest, + &compilation.options.output.hash_salt, + ); + + Ok(codegen_result) + } +} + +impl Identifiable for LazyCompilationProxyModule { + fn identifier(&self) -> rspack_identifier::Identifier { + self.identifier + } +} + +impl DependenciesBlock for LazyCompilationProxyModule { + fn add_block_id(&mut self, block: rspack_core::AsyncDependenciesBlockIdentifier) { + self.blocks.push(block); + } + + fn get_blocks(&self) -> &[rspack_core::AsyncDependenciesBlockIdentifier] { + &self.blocks + } + + fn add_dependency_id(&mut self, dependency: rspack_core::DependencyId) { + self.dependencies.push(dependency); + } + + fn get_dependencies(&self) -> &[rspack_core::DependencyId] { + &self.dependencies + } +} diff --git a/crates/rspack_plugin_lazy_compilation/src/plugin.rs b/crates/rspack_plugin_lazy_compilation/src/plugin.rs new file mode 100644 index 00000000000..9c6e36adb4c --- /dev/null +++ b/crates/rspack_plugin_lazy_compilation/src/plugin.rs @@ -0,0 +1,199 @@ +use std::{fmt::Debug, sync::Arc}; + +use once_cell::sync::Lazy; +use rspack_core::{ + ApplyContext, BoxModule, Compilation, CompilationParams, CompilerCompilation, CompilerOptions, + DependencyType, Module, ModuleFactory, ModuleFactoryCreateData, NormalModuleCreateData, + NormalModuleFactoryModule, Plugin, PluginContext, +}; +use rspack_error::Result; +use rspack_hook::{plugin, plugin_hook}; +use rspack_regex::RspackRegex; +use tokio::sync::Mutex; + +use crate::{ + backend::Backend, factory::LazyCompilationDependencyFactory, module::LazyCompilationProxyModule, +}; + +static WEBPACK_DEV_SERVER_CLIENT_RE: Lazy = Lazy::new(|| { + RspackRegex::new( + r#"(webpack|rspack)[/\\]hot[/\\]|(webpack|rspack)-dev-server[/\\]client|(webpack|rspack)-hot-middleware[/\\]client"#, + ) + .expect("should compile regex") +}); + +#[derive(Debug, Hash, Clone)] +pub enum LazyCompilationTest { + Regex(RspackRegex), + Fn(F), +} + +pub trait LazyCompilationTestCheck: Send + Sync + Debug { + fn test(&self, module: &dyn Module) -> bool; +} + +impl LazyCompilationTest { + fn test(&self, module: &dyn Module) -> bool { + match self { + LazyCompilationTest::Regex(regex) => { + regex.test(&module.name_for_condition().unwrap_or("".into())) + } + LazyCompilationTest::Fn(f) => f.test(module), + } + } +} + +#[derive(Debug)] +#[plugin] +pub struct LazyCompilationPlugin { + backend: Mutex, + entries: bool, // enable for entries + imports: bool, // enable for imports + test: Option>, + cacheable: bool, +} + +impl LazyCompilationPlugin { + pub fn new( + cacheable: bool, + backend: T, + test: Option>, + entries: bool, + imports: bool, + ) -> Self { + Self::new_inner(Mutex::new(backend), entries, imports, test, cacheable) + } + + fn check_test(&self, module: &BoxModule) -> bool { + if let Some(test) = &self.inner.test { + test.test(module.as_ref()) + } else { + true + } + } +} + +#[plugin_hook(CompilerCompilation for LazyCompilationPlugin)] +async fn compilation( + &self, + compilation: &mut Compilation, + params: &mut CompilationParams, +) -> Result<()> { + compilation.set_dependency_factory( + DependencyType::LazyImport, + Arc::new(LazyCompilationDependencyFactory::new( + params.normal_module_factory.clone(), + )) as Arc, + ); + + Ok(()) +} + +#[plugin_hook(NormalModuleFactoryModule for LazyCompilationPlugin)] +async fn normal_module_factory_module( + &self, + module_factory_create_data: &mut ModuleFactoryCreateData, + create_data: &mut NormalModuleCreateData, + module: &mut BoxModule, +) -> Result<()> { + if let Some(query) = &create_data.resource_resolve_data.resource_query + && query.contains("lazy-compilation-proxy-dep") + { + let remaining_query = query.clone().replace("lazy-compilation-proxy-dep", ""); + + create_data.resource_resolve_data.resource_query = + if remaining_query.is_empty() || remaining_query == "?" { + None + } else { + Some(remaining_query) + }; + + return Ok(()); + } + + let dep_type = module_factory_create_data.dependency.dependency_type(); + + let is_imports = matches!( + dep_type, + DependencyType::DynamicImport + | DependencyType::DynamicImportEager + | DependencyType::ContextElement + ); + let is_entries = matches!(dep_type, DependencyType::Entry); + + #[allow(clippy::if_same_then_else)] + if matches!( + dep_type, + DependencyType::ModuleHotAccept + | DependencyType::ModuleHotDecline + | DependencyType::ImportMetaHotAccept + | DependencyType::ImportMetaHotDecline + ) { + // TODO: we cannot access module graph at this stage + // if hmr point to a module that is already been dyn imported + // eg: import('./foo'); module.hot.accept('./foo') + // however we cannot access module graph at this time, so we cannot + // detect this case easily + return Ok(()); + } else if !is_entries && !is_imports { + return Ok(()); + } + + if !self.entries && is_entries { + return Ok(()); + } + if !self.imports && is_imports { + return Ok(()); + } + + if WEBPACK_DEV_SERVER_CLIENT_RE.test(&create_data.resource_resolve_data.resource) + || !self.check_test(module) + { + return Ok(()); + } + + let mut backend = self.backend.lock().await; + let module_identifier = module.identifier(); + let info = backend + .module( + module_identifier, + create_data.resource_resolve_data.resource.clone(), + ) + .await?; + + *module = Box::new(LazyCompilationProxyModule::new( + module_identifier, + module_factory_create_data.clone(), + create_data.resource_resolve_data.resource.clone(), + self.cacheable, + info.active, + info.data, + info.client, + )); + + Ok(()) +} + +#[async_trait::async_trait] +impl Plugin + for LazyCompilationPlugin +{ + fn apply( + &self, + ctx: PluginContext<&mut ApplyContext>, + _options: &mut CompilerOptions, + ) -> Result<()> { + ctx + .context + .compiler_hooks + .compilation + .tap(compilation::new(self)); + + ctx + .context + .normal_module_factory_hooks + .module + .tap(normal_module_factory_module::new(self)); + Ok(()) + } +} diff --git a/crates/rspack_plugin_runtime/src/lib.rs b/crates/rspack_plugin_runtime/src/lib.rs index 59f113b3202..195b39e0132 100644 --- a/crates/rspack_plugin_runtime/src/lib.rs +++ b/crates/rspack_plugin_runtime/src/lib.rs @@ -1,8 +1,6 @@ #![feature(get_mut_unchecked)] mod helpers; pub use helpers::*; -mod lazy_compilation; -pub use lazy_compilation::LazyCompilationPlugin; mod common_js_chunk_format; pub use common_js_chunk_format::CommonJsChunkFormatPlugin; mod runtime_plugin; diff --git a/packages/rspack-dev-server/src/server.ts b/packages/rspack-dev-server/src/server.ts index e222fa9e357..276661bf5c0 100644 --- a/packages/rspack-dev-server/src/server.ts +++ b/packages/rspack-dev-server/src/server.ts @@ -219,38 +219,6 @@ export class RspackDevServer extends WebpackDevServer { private override setupMiddlewares() { const middlewares: WebpackDevServer.Middleware[] = []; - const compilers = - this.compiler instanceof MultiCompiler - ? this.compiler.compilers - : [this.compiler]; - - compilers.forEach(compiler => { - if (compiler.options.experiments.lazyCompilation) { - middlewares.push({ - // @ts-expect-error - middleware: (req, res) => { - if (req.url.indexOf("/lazy-compilation-web/") > -1) { - const path = req.url.replace("/lazy-compilation-web/", ""); - if (fs.existsSync(path)) { - compiler.__internal__rebuild( - new Set([path]), - new Set(), - error => { - if (error) { - throw error; - } - res.write(""); - res.end(); - console.log("lazy compiler success"); - } - ); - } - } - } - }); - } - }); - middlewares.forEach(middleware => { if (typeof middleware === "function") { // @ts-expect-error diff --git a/packages/rspack/etc/api.md b/packages/rspack/etc/api.md index 67447dd711d..7e4d7600f0d 100644 --- a/packages/rspack/etc/api.md +++ b/packages/rspack/etc/api.md @@ -2826,7 +2826,19 @@ export type Experiments = z.infer; // @public (undocumented) const experiments: z.ZodObject<{ - lazyCompilation: z.ZodOptional; + lazyCompilation: z.ZodUnion<[z.ZodOptional, z.ZodObject<{ + imports: z.ZodOptional; + entries: z.ZodOptional; + test: z.ZodOptional, z.ZodFunction], z.ZodUnknown>, z.ZodBoolean>]>>; + }, "strip", z.ZodTypeAny, { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; + }, { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; + }>]>; asyncWebAssembly: z.ZodOptional; outputModule: z.ZodOptional; topLevelAwait: z.ZodOptional; @@ -2858,7 +2870,11 @@ const experiments: z.ZodObject<{ } | undefined; }>>; }, "strict", z.ZodTypeAny, { - lazyCompilation?: boolean | undefined; + lazyCompilation?: boolean | { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; + } | undefined; asyncWebAssembly?: boolean | undefined; outputModule?: boolean | undefined; topLevelAwait?: boolean | undefined; @@ -2872,7 +2888,11 @@ const experiments: z.ZodObject<{ } | undefined; } | undefined; }, { - lazyCompilation?: boolean | undefined; + lazyCompilation?: boolean | { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; + } | undefined; asyncWebAssembly?: boolean | undefined; outputModule?: boolean | undefined; topLevelAwait?: boolean | undefined; @@ -2896,7 +2916,7 @@ export interface ExperimentsNormalized { // (undocumented) futureDefaults?: boolean; // (undocumented) - lazyCompilation?: boolean; + lazyCompilation?: false | LazyCompilationOptions; // (undocumented) outputModule?: boolean; // (undocumented) @@ -4256,6 +4276,24 @@ type KnownStatsProfile = { building: number; }; +// @public (undocumented) +export type LazyCompilationOptions = z.infer; + +// @public (undocumented) +const lazyCompilationOptions: z.ZodObject<{ + imports: z.ZodOptional; + entries: z.ZodOptional; + test: z.ZodOptional, z.ZodFunction], z.ZodUnknown>, z.ZodBoolean>]>>; +}, "strip", z.ZodTypeAny, { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; +}, { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; +}>; + // @public (undocumented) export type Library = z.infer; @@ -7995,6 +8033,7 @@ declare namespace rspackExports { OptimizationSplitChunksOptions, Optimization, RspackFutureOptions, + LazyCompilationOptions, Experiments, Watch, WatchOptions, @@ -8692,7 +8731,19 @@ export const rspackOptions: z.ZodObject<{ target: z.ZodOptional, z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodEnum<["web", "webworker", "es3", "es5", "es2015", "es2016", "es2017", "es2018", "es2019", "es2020", "es2021", "es2022", "browserslist"]>, z.ZodLiteral<"node">]>, z.ZodLiteral<"async-node">]>, z.ZodType<`node${number}`, z.ZodTypeDef, `node${number}`>]>, z.ZodType<`async-node${number}`, z.ZodTypeDef, `async-node${number}`>]>, z.ZodType<`node${number}.${number}`, z.ZodTypeDef, `node${number}.${number}`>]>, z.ZodType<`async-node${number}.${number}`, z.ZodTypeDef, `async-node${number}.${number}`>]>, z.ZodLiteral<"electron-main">]>, z.ZodType<`electron${number}-main`, z.ZodTypeDef, `electron${number}-main`>]>, z.ZodType<`electron${number}.${number}-main`, z.ZodTypeDef, `electron${number}.${number}-main`>]>, z.ZodLiteral<"electron-renderer">]>, z.ZodType<`electron${number}-renderer`, z.ZodTypeDef, `electron${number}-renderer`>]>, z.ZodType<`electron${number}.${number}-renderer`, z.ZodTypeDef, `electron${number}.${number}-renderer`>]>, z.ZodLiteral<"electron-preload">]>, z.ZodType<`electron${number}-preload`, z.ZodTypeDef, `electron${number}-preload`>]>, z.ZodType<`electron${number}.${number}-preload`, z.ZodTypeDef, `electron${number}.${number}-preload`>]>]>, z.ZodArray, z.ZodLiteral<"node">]>, z.ZodLiteral<"async-node">]>, z.ZodType<`node${number}`, z.ZodTypeDef, `node${number}`>]>, z.ZodType<`async-node${number}`, z.ZodTypeDef, `async-node${number}`>]>, z.ZodType<`node${number}.${number}`, z.ZodTypeDef, `node${number}.${number}`>]>, z.ZodType<`async-node${number}.${number}`, z.ZodTypeDef, `async-node${number}.${number}`>]>, z.ZodLiteral<"electron-main">]>, z.ZodType<`electron${number}-main`, z.ZodTypeDef, `electron${number}-main`>]>, z.ZodType<`electron${number}.${number}-main`, z.ZodTypeDef, `electron${number}.${number}-main`>]>, z.ZodLiteral<"electron-renderer">]>, z.ZodType<`electron${number}-renderer`, z.ZodTypeDef, `electron${number}-renderer`>]>, z.ZodType<`electron${number}.${number}-renderer`, z.ZodTypeDef, `electron${number}.${number}-renderer`>]>, z.ZodLiteral<"electron-preload">]>, z.ZodType<`electron${number}-preload`, z.ZodTypeDef, `electron${number}-preload`>]>, z.ZodType<`electron${number}.${number}-preload`, z.ZodTypeDef, `electron${number}.${number}-preload`>]>, "many">]>>; mode: z.ZodOptional>; experiments: z.ZodOptional; + lazyCompilation: z.ZodUnion<[z.ZodOptional, z.ZodObject<{ + imports: z.ZodOptional; + entries: z.ZodOptional; + test: z.ZodOptional, z.ZodFunction], z.ZodUnknown>, z.ZodBoolean>]>>; + }, "strip", z.ZodTypeAny, { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; + }, { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; + }>]>; asyncWebAssembly: z.ZodOptional; outputModule: z.ZodOptional; topLevelAwait: z.ZodOptional; @@ -8724,7 +8775,11 @@ export const rspackOptions: z.ZodObject<{ } | undefined; }>>; }, "strict", z.ZodTypeAny, { - lazyCompilation?: boolean | undefined; + lazyCompilation?: boolean | { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; + } | undefined; asyncWebAssembly?: boolean | undefined; outputModule?: boolean | undefined; topLevelAwait?: boolean | undefined; @@ -8738,7 +8793,11 @@ export const rspackOptions: z.ZodObject<{ } | undefined; } | undefined; }, { - lazyCompilation?: boolean | undefined; + lazyCompilation?: boolean | { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; + } | undefined; asyncWebAssembly?: boolean | undefined; outputModule?: boolean | undefined; topLevelAwait?: boolean | undefined; @@ -10179,7 +10238,11 @@ export const rspackOptions: z.ZodObject<{ target?: false | "es3" | "es5" | "es2015" | "es2016" | "es2017" | "es2018" | "es2019" | "es2020" | "es2021" | "es2022" | "node" | "async-node" | "web" | "webworker" | "browserslist" | `node${number}` | `async-node${number}` | `node${number}.${number}` | `async-node${number}.${number}` | "electron-main" | `electron${number}-main` | `electron${number}.${number}-main` | "electron-renderer" | `electron${number}-renderer` | `electron${number}.${number}-renderer` | "electron-preload" | `electron${number}-preload` | `electron${number}.${number}-preload` | ("es3" | "es5" | "es2015" | "es2016" | "es2017" | "es2018" | "es2019" | "es2020" | "es2021" | "es2022" | "node" | "async-node" | "web" | "webworker" | "browserslist" | `node${number}` | `async-node${number}` | `node${number}.${number}` | `async-node${number}.${number}` | "electron-main" | `electron${number}-main` | `electron${number}.${number}-main` | "electron-renderer" | `electron${number}-renderer` | `electron${number}.${number}-renderer` | "electron-preload" | `electron${number}-preload` | `electron${number}.${number}-preload`)[] | undefined; mode?: "none" | "development" | "production" | undefined; experiments?: { - lazyCompilation?: boolean | undefined; + lazyCompilation?: boolean | { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; + } | undefined; asyncWebAssembly?: boolean | undefined; outputModule?: boolean | undefined; topLevelAwait?: boolean | undefined; @@ -10618,7 +10681,11 @@ export const rspackOptions: z.ZodObject<{ target?: false | "es3" | "es5" | "es2015" | "es2016" | "es2017" | "es2018" | "es2019" | "es2020" | "es2021" | "es2022" | "node" | "async-node" | "web" | "webworker" | "browserslist" | `node${number}` | `async-node${number}` | `node${number}.${number}` | `async-node${number}.${number}` | "electron-main" | `electron${number}-main` | `electron${number}.${number}-main` | "electron-renderer" | `electron${number}-renderer` | `electron${number}.${number}-renderer` | "electron-preload" | `electron${number}-preload` | `electron${number}.${number}-preload` | ("es3" | "es5" | "es2015" | "es2016" | "es2017" | "es2018" | "es2019" | "es2020" | "es2021" | "es2022" | "node" | "async-node" | "web" | "webworker" | "browserslist" | `node${number}` | `async-node${number}` | `node${number}.${number}` | `async-node${number}.${number}` | "electron-main" | `electron${number}-main` | `electron${number}.${number}-main` | "electron-renderer" | `electron${number}-renderer` | `electron${number}.${number}-renderer` | "electron-preload" | `electron${number}-preload` | `electron${number}.${number}-preload`)[] | undefined; mode?: "none" | "development" | "production" | undefined; experiments?: { - lazyCompilation?: boolean | undefined; + lazyCompilation?: boolean | { + imports?: boolean | undefined; + entries?: boolean | undefined; + test?: RegExp | ((args_0: Module, ...args_1: unknown[]) => boolean) | undefined; + } | undefined; asyncWebAssembly?: boolean | undefined; outputModule?: boolean | undefined; topLevelAwait?: boolean | undefined; @@ -12262,6 +12329,8 @@ export class Watching { // (undocumented) lastWatcherStartTime: number; // (undocumented) + lazyCompilationInvalidate(files: Set): void; + // (undocumented) onChange?: () => void; // (undocumented) onInvalid?: () => void; diff --git a/packages/rspack/src/Watching.ts b/packages/rspack/src/Watching.ts index 0dc67476d3b..3575883e8e6 100644 --- a/packages/rspack/src/Watching.ts +++ b/packages/rspack/src/Watching.ts @@ -197,6 +197,10 @@ export class Watching { this.#invalidate(); } + lazyCompilationInvalidate(files: Set) { + this.#invalidate(new Map(), new Map(), files, new Set()); + } + #invalidate( fileTimeInfoEntries?: Map, contextTimeInfoEntries?: Map, diff --git a/packages/rspack/src/builtin-plugin/base.ts b/packages/rspack/src/builtin-plugin/base.ts index e756cf7da6d..2a02ddadc43 100644 --- a/packages/rspack/src/builtin-plugin/base.ts +++ b/packages/rspack/src/builtin-plugin/base.ts @@ -50,7 +50,7 @@ export function createBuiltinPlugin( export function create( name: binding.BuiltinPluginName, resolve: (...args: T) => R, - // `affectedHooks` is used to inform `createChildCompile` about which builtin plugin can be reversed. + // `affectedHooks` is used to inform `createChildCompile` about which builtin plugin can be reserved. // However, this has a drawback as it doesn't represent the actual condition but merely serves as an indicator. affectedHooks?: AffectedHooks ) { diff --git a/packages/rspack/src/builtin-plugin/index.ts b/packages/rspack/src/builtin-plugin/index.ts index 4e8c7222b31..b2178c63ace 100644 --- a/packages/rspack/src/builtin-plugin/index.ts +++ b/packages/rspack/src/builtin-plugin/index.ts @@ -35,6 +35,7 @@ export * from "./InferAsyncModulesPlugin"; export * from "./JavascriptModulesPlugin"; export * from "./JsLoaderRspackPlugin"; export * from "./JsonModulesPlugin"; +export * from "./lazy-compilation/plugin"; export * from "./LimitChunkCountPlugin"; export * from "./MangleExportsPlugin"; export * from "./MergeDuplicateChunksPlugin"; diff --git a/packages/rspack/src/builtin-plugin/lazy-compilation/backend.ts b/packages/rspack/src/builtin-plugin/lazy-compilation/backend.ts new file mode 100644 index 00000000000..b7cfb1eae54 --- /dev/null +++ b/packages/rspack/src/builtin-plugin/lazy-compilation/backend.ts @@ -0,0 +1,230 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +import type { + IncomingMessage, + ServerOptions as ServerOptionsImport, + ServerResponse +} from "http"; +import type { AddressInfo, ListenOptions, Server, Socket } from "net"; +import type { SecureContextOptions, TlsOptions } from "tls"; + +import type { Compiler } from "../.."; + +export interface LazyCompilationDefaultBackendOptions { + /** + * A custom client. + */ + client?: string; + + /** + * Specifies where to listen to from the server. + */ + listen?: number | ListenOptions | ((server: Server) => void); + + /** + * Specifies the protocol the client should use to connect to the server. + */ + protocol?: "http" | "https"; + + /** + * Specifies how to create the server handling the EventSource requests. + */ + server?: + | ServerOptionsImport + | ServerOptionsHttps + | (() => Server); +} + +export type ServerOptionsHttps< + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends typeof ServerResponse = typeof ServerResponse +> = SecureContextOptions & TlsOptions & ServerOptionsImport; + +const getBackend = + ( + options: Omit & { + client: NonNullable; + } + ) => + ( + compiler: Compiler, + callback: ( + err: any, + obj?: { + dispose: (callback: (err: any) => void) => void; + module: (args: { module: string; path: string }) => { + data: string; + client: string; + active: boolean; + }; + } + ) => void + ) => { + const logger = compiler.getInfrastructureLogger("LazyCompilationBackend"); + const activeModules = new Map(); + const filesByKey: Map = new Map(); + const prefix = "/lazy-compilation-using-"; + const isHttps = + options.protocol === "https" || + (typeof options.server === "object" && + ("key" in options.server || "pfx" in options.server)); + + const createServer = + typeof options.server === "function" + ? options.server + : (() => { + const http = isHttps ? require("https") : require("http"); + return http.createServer.bind(http, options.server); + })(); + const listen = + typeof options.listen === "function" + ? options.listen + : (server: Server) => { + let listen = options.listen; + if (typeof listen === "object" && !("port" in listen)) + listen = { ...listen, port: undefined }; + server.listen(listen); + }; + + const protocol = options.protocol || (isHttps ? "https" : "http"); + + const requestListener = (req: any, res: ServerResponse) => { + const keys = req.url.slice(prefix.length).split("@"); + req.socket.on("close", () => { + setTimeout(() => { + for (const key of keys) { + const oldValue = activeModules.get(key) || 0; + activeModules.set(key, oldValue - 1); + if (oldValue === 1) { + logger.log( + `${key} is no longer in use. Next compilation will skip this module.` + ); + } + } + }, 120000); + }); + req.socket.setNoDelay(true); + res.writeHead(200, { + "content-type": "text/event-stream", + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "*", + "Access-Control-Allow-Headers": "*" + }); + res.write("\n"); + const moduleActivated = []; + for (const key of keys) { + const oldValue = activeModules.get(key) || 0; + activeModules.set(key, oldValue + 1); + if (oldValue === 0) { + logger.log(`${key} is now in use and will be compiled.`); + moduleActivated.push(key); + } + } + + if (moduleActivated.length && compiler.watching) { + compiler.watching.lazyCompilationInvalidate( + new Set(moduleActivated.map(key => filesByKey.get(key)!)) + ); + } + }; + + const server = createServer() as Server; + server.on("request", requestListener); + + let isClosing = false; + const sockets: Set = new Set(); + server.on("connection", socket => { + sockets.add(socket); + socket.on("close", () => { + sockets.delete(socket); + }); + if (isClosing) socket.destroy(); + }); + server.on("clientError", e => { + if (e.message !== "Server is disposing") logger.warn(e); + }); + server.on("listening", (err: any) => { + if (err) return callback(err); + const addr = server.address() as AddressInfo; + if (typeof addr === "string") + throw new Error("addr must not be a string"); + const urlBase = + addr.address === "::" || addr.address === "0.0.0.0" + ? `${protocol}://localhost:${addr.port}` + : addr.family === "IPv6" + ? `${protocol}://[${addr.address}]:${addr.port}` + : `${protocol}://${addr.address}:${addr.port}`; + logger.log( + `Server-Sent-Events server for lazy compilation open at ${urlBase}.` + ); + + const result = { + dispose(callback: any) { + isClosing = true; + // Removing the listener is a workaround for a memory leak in node.js + server.off("request", requestListener); + server.close(err => { + callback(err); + }); + for (const socket of sockets) { + socket.destroy(new Error("Server is disposing")); + } + }, + module({ + module: originalModule, + path + }: { + module: string; + path: string; + }) { + const key = `${encodeURIComponent( + originalModule.replace(/\\/g, "/").replace(/@/g, "_") + ).replace(/%(2F|3A|24|26|2B|2C|3B|3D|3A)/g, decodeURIComponent)}`; + filesByKey.set(key, path); + const active = activeModules.get(key) > 0; + return { + client: `${options.client}?${encodeURIComponent(urlBase + prefix)}`, + data: key, + active + }; + } + }; + state.module = result.module; + state.dispose = result.dispose; + callback(null, result); + }); + listen(server); + }; + +export default getBackend; + +function unimplemented() { + throw new Error("access before initialization"); +} + +const state: { + module: typeof moduleImpl; + dispose: typeof dispose; +} = { + module: unimplemented as any, + dispose: unimplemented +}; + +export function dispose(callback: any) { + state.dispose(callback); + state.dispose = unimplemented; + state.module = unimplemented as any; +} + +export function moduleImpl(args: { module: string; path: string }): { + active: boolean; + data: string; + client: string; +} { + return state.module(args); +} diff --git a/packages/rspack/src/builtin-plugin/lazy-compilation/lazyCompilation.ts b/packages/rspack/src/builtin-plugin/lazy-compilation/lazyCompilation.ts new file mode 100644 index 00000000000..538d4d1b4e7 --- /dev/null +++ b/packages/rspack/src/builtin-plugin/lazy-compilation/lazyCompilation.ts @@ -0,0 +1,19 @@ +import { BuiltinPluginName, JsModule, RawRegexMatcher } from "@rspack/binding"; + +import { create } from "../base"; + +export const BuiltinLazyCompilationPlugin = create( + BuiltinPluginName.LazyCompilationPlugin, + ( + module: (args: { module: string; path: string }) => { + active: boolean; + data: string; + client: string; + }, + cacheable: boolean, + entries: boolean, + imports: boolean, + test?: RawRegexMatcher | ((m: JsModule) => boolean) + ) => ({ module, cacheable, imports, entries, test }), + "thisCompilation" +); diff --git a/packages/rspack/src/builtin-plugin/lazy-compilation/plugin.ts b/packages/rspack/src/builtin-plugin/lazy-compilation/plugin.ts new file mode 100644 index 00000000000..fd908a731b0 --- /dev/null +++ b/packages/rspack/src/builtin-plugin/lazy-compilation/plugin.ts @@ -0,0 +1,68 @@ +import { JsModule, RawRegexMatcher } from "@rspack/binding"; + +import type { Compiler } from "../.."; +import getBackend, { + dispose, + LazyCompilationDefaultBackendOptions, + moduleImpl +} from "./backend"; +import { BuiltinLazyCompilationPlugin } from "./lazyCompilation"; + +export default class LazyCompilationPlugin { + cacheable: boolean; + entries: boolean; + imports: boolean; + test?: RawRegexMatcher | ((m: JsModule) => boolean); + backend?: LazyCompilationDefaultBackendOptions; + + constructor( + cacheable: boolean, + entries: boolean, + imports: boolean, + test?: RawRegexMatcher | ((m: JsModule) => boolean), + backend?: LazyCompilationDefaultBackendOptions + ) { + this.cacheable = cacheable; + this.entries = entries; + this.imports = imports; + this.test = test; + this.backend = backend; + } + + apply(compiler: Compiler) { + const backend = getBackend({ + ...this.backend, + client: require.resolve( + `../../../hot/lazy-compilation-${ + compiler.options.externalsPresets.node ? "node" : "web" + }.js` + ) + }); + + new BuiltinLazyCompilationPlugin( + moduleImpl, + this.cacheable, + this.entries, + this.imports, + this.test + ).apply(compiler); + + let initialized = false; + compiler.hooks.beforeCompile.tapAsync( + "LazyCompilationPlugin", + (_params, callback) => { + if (initialized) return callback(); + backend(compiler, (err, result) => { + if (err) return callback(err); + initialized = true; + callback(); + }); + } + ); + compiler.hooks.shutdown.tapAsync("LazyCompilationPlugin", callback => { + dispose(callback); + }); + } +} + +export { LazyCompilationPlugin }; diff --git a/packages/rspack/src/config/normalization.ts b/packages/rspack/src/config/normalization.ts index 95d6ee11eb8..1861ca7f2ac 100644 --- a/packages/rspack/src/config/normalization.ts +++ b/packages/rspack/src/config/normalization.ts @@ -52,6 +52,7 @@ import type { Iife, ImportFunctionName, InfrastructureLogging, + LazyCompilationOptions, LibraryOptions, Mode, Name, @@ -300,7 +301,11 @@ export const getNormalizedRspackOptions = ( performance: config.performance, plugins: nestedArray(config.plugins, p => [...p]), experiments: nestedConfig(config.experiments, experiments => ({ - ...experiments + ...experiments, + lazyCompilation: optionalNestedConfig( + experiments.lazyCompilation, + options => (options === true ? {} : options) + ) })), watch: config.watch, watchOptions: cloneObject(config.watchOptions), @@ -502,7 +507,7 @@ export interface ModuleOptionsNormalized { } export interface ExperimentsNormalized { - lazyCompilation?: boolean; + lazyCompilation?: false | LazyCompilationOptions; asyncWebAssembly?: boolean; outputModule?: boolean; topLevelAwait?: boolean; diff --git a/packages/rspack/src/config/zod.ts b/packages/rspack/src/config/zod.ts index 756665aaaef..0d4ef82cf28 100644 --- a/packages/rspack/src/config/zod.ts +++ b/packages/rspack/src/config/zod.ts @@ -1,4 +1,4 @@ -import { JsAssetInfo, RawFuncUseCtx } from "@rspack/binding"; +import { JsAssetInfo, JsModule, RawFuncUseCtx } from "@rspack/binding"; import type * as webpackDevServer from "webpack-dev-server"; import { z } from "zod"; @@ -7,7 +7,6 @@ import type { Builtins as BuiltinsType } from "../builtin-plugin"; import { Chunk } from "../Chunk"; import { PathData } from "../Compilation"; import { Module } from "../Module"; -import { deprecatedWarn } from "../util"; //#region Name const name = z.string(); @@ -1211,8 +1210,19 @@ const rspackFutureOptions = z.strictObject({ }); export type RspackFutureOptions = z.infer; +const lazyCompilationOptions = z.object({ + imports: z.boolean().optional(), + entries: z.boolean().optional(), + test: z + .instanceof(RegExp) + .or(z.function().args(z.custom()).returns(z.boolean())) + .optional() +}); + +export type LazyCompilationOptions = z.infer; + const experiments = z.strictObject({ - lazyCompilation: z.boolean().optional(), + lazyCompilation: z.boolean().optional().or(lazyCompilationOptions), asyncWebAssembly: z.boolean().optional(), outputModule: z.boolean().optional(), topLevelAwait: z.boolean().optional(), diff --git a/packages/rspack/src/rspackOptionsApply.ts b/packages/rspack/src/rspackOptionsApply.ts index 0ed88eef180..54f94d3162d 100644 --- a/packages/rspack/src/rspackOptionsApply.ts +++ b/packages/rspack/src/rspackOptionsApply.ts @@ -45,6 +45,7 @@ import { JavascriptModulesPlugin, JsLoaderRspackPlugin, JsonModulesPlugin, + LazyCompilationPlugin, MangleExportsPlugin, MergeDuplicateChunksPlugin, ModuleChunkFormatPlugin, @@ -65,6 +66,7 @@ import { } from "./builtin-plugin"; import EntryOptionPlugin from "./lib/EntryOptionPlugin"; import IgnoreWarningsPlugin from "./lib/ignoreWarningsPlugin"; +import { Module } from "./Module"; import { DefaultStatsFactoryPlugin } from "./stats/DefaultStatsFactoryPlugin"; import { DefaultStatsPrinterPlugin } from "./stats/DefaultStatsPrinterPlugin"; import { assertNotNill } from "./util/assertNotNil"; @@ -256,6 +258,33 @@ export class RspackOptionsApply { } } + if (options.experiments.lazyCompilation) { + const lazyOptions = options.experiments.lazyCompilation; + + new LazyCompilationPlugin( + // this is only for test + // @ts-expect-error cacheable is hide + lazyOptions.cacheable ?? true, + lazyOptions.entries ?? true, + lazyOptions.imports ?? true, + typeof lazyOptions.test === "function" + ? function (jsModule) { + return (lazyOptions.test as (jsModule: Module) => boolean)!.call( + lazyOptions, + new Module(jsModule) + ); + } + : lazyOptions.test + ? { + source: lazyOptions.test.source, + flags: lazyOptions.test.flags + } + : undefined, + // @ts-expect-error backend is hide + lazyOptions.backend + ).apply(compiler); + } + if ( options.output.enabledLibraryTypes && options.output.enabledLibraryTypes.length > 0 diff --git a/webpack-test/hotCases/lazy-compilation/context/test.filter.js b/webpack-test/hotCases/lazy-compilation/context/test.filter.js deleted file mode 100644 index 5c32e24f1f8..00000000000 --- a/webpack-test/hotCases/lazy-compilation/context/test.filter.js +++ /dev/null @@ -1,3 +0,0 @@ - -module.exports = () => {return false} - \ No newline at end of file diff --git a/webpack-test/hotCases/lazy-compilation/context/webpack.config.js b/webpack-test/hotCases/lazy-compilation/context/webpack.config.js index 95c9eda7187..bca70843c7f 100644 --- a/webpack-test/hotCases/lazy-compilation/context/webpack.config.js +++ b/webpack-test/hotCases/lazy-compilation/context/webpack.config.js @@ -4,6 +4,7 @@ module.exports = { experiments: { lazyCompilation: { + cacheable: false, entries: false, imports: true, backend: { diff --git a/webpack-test/hotCases/lazy-compilation/https/test.filter.js b/webpack-test/hotCases/lazy-compilation/https/test.filter.js index 5c32e24f1f8..90e5eab00bc 100644 --- a/webpack-test/hotCases/lazy-compilation/https/test.filter.js +++ b/webpack-test/hotCases/lazy-compilation/https/test.filter.js @@ -1,3 +1,2 @@ -module.exports = () => {return false} - \ No newline at end of file +module.exports = () => { return false } diff --git a/webpack-test/hotCases/lazy-compilation/https/webpack.config.js b/webpack-test/hotCases/lazy-compilation/https/webpack.config.js index 11b07858d4d..ca3f7afdf0f 100644 --- a/webpack-test/hotCases/lazy-compilation/https/webpack.config.js +++ b/webpack-test/hotCases/lazy-compilation/https/webpack.config.js @@ -7,6 +7,7 @@ const path = require("path"); module.exports = { experiments: { lazyCompilation: { + cacheable: false, entries: false, backend: { server: { diff --git a/webpack-test/hotCases/lazy-compilation/module-test/test.filter.js b/webpack-test/hotCases/lazy-compilation/module-test/test.filter.js deleted file mode 100644 index 5c32e24f1f8..00000000000 --- a/webpack-test/hotCases/lazy-compilation/module-test/test.filter.js +++ /dev/null @@ -1,3 +0,0 @@ - -module.exports = () => {return false} - \ No newline at end of file diff --git a/webpack-test/hotCases/lazy-compilation/module-test/webpack.config.js b/webpack-test/hotCases/lazy-compilation/module-test/webpack.config.js index ede992e2343..559f2fcbd22 100644 --- a/webpack-test/hotCases/lazy-compilation/module-test/webpack.config.js +++ b/webpack-test/hotCases/lazy-compilation/module-test/webpack.config.js @@ -5,7 +5,8 @@ module.exports = { experiments: { lazyCompilation: { entries: false, - test: module => !/moduleB/.test(module.nameForCondition()) + cacheable: false, + test: /moduleA/ } } }; diff --git a/webpack-test/hotCases/lazy-compilation/only-entries/test.filter.js b/webpack-test/hotCases/lazy-compilation/only-entries/test.filter.js deleted file mode 100644 index 5c32e24f1f8..00000000000 --- a/webpack-test/hotCases/lazy-compilation/only-entries/test.filter.js +++ /dev/null @@ -1,3 +0,0 @@ - -module.exports = () => {return false} - \ No newline at end of file diff --git a/webpack-test/hotCases/lazy-compilation/simple/test.filter.js b/webpack-test/hotCases/lazy-compilation/simple/test.filter.js index 5c32e24f1f8..90e5eab00bc 100644 --- a/webpack-test/hotCases/lazy-compilation/simple/test.filter.js +++ b/webpack-test/hotCases/lazy-compilation/simple/test.filter.js @@ -1,3 +1,2 @@ -module.exports = () => {return false} - \ No newline at end of file +module.exports = () => { return false } diff --git a/webpack-test/hotCases/lazy-compilation/simple/webpack.config.js b/webpack-test/hotCases/lazy-compilation/simple/webpack.config.js index 148a5e40010..16ad9ede08e 100644 --- a/webpack-test/hotCases/lazy-compilation/simple/webpack.config.js +++ b/webpack-test/hotCases/lazy-compilation/simple/webpack.config.js @@ -4,7 +4,8 @@ module.exports = { experiments: { lazyCompilation: { - entries: false + entries: false, + cacheable: false } } }; diff --git a/webpack-test/hotCases/lazy-compilation/unrelated/test.filter.js b/webpack-test/hotCases/lazy-compilation/unrelated/test.filter.js deleted file mode 100644 index 5c32e24f1f8..00000000000 --- a/webpack-test/hotCases/lazy-compilation/unrelated/test.filter.js +++ /dev/null @@ -1,3 +0,0 @@ - -module.exports = () => {return false} - \ No newline at end of file diff --git a/website/docs/en/config/experiments.mdx b/website/docs/en/config/experiments.mdx index a0aeba64a50..638dddcac95 100644 --- a/website/docs/en/config/experiments.mdx +++ b/website/docs/en/config/experiments.mdx @@ -62,6 +62,32 @@ Enable support for [top level await](https://github.com/tc39/proposal-top-level- Enabled by default and can be turned off with this configuration. +## experiments.lazyCompilation + + + +- **Type:** + +```ts +type LazyCompilationOptions = + | boolean + | { + entries?: boolean; + + imports?: boolean; + + test?: RegExp | ((m: Module) => boolean); + }; +``` + +- **Default:** `false` + +Enable lazy compilation, which can greatly improve the build performance of multi-entry projects or large projects. For example, if you have twenty entry points, only the accessed entry points will be built. Or if there are many `import()` statements in the project, each module pointed to by `import()` will only be built when it is actually accessed. + +If set to true, lazy compilation will be applied by default to both entry modules and modules pointed to by `import()`. You can decide whether it applies only to entries or only to `import()` through a configuration object. The `entries` option determines whether it applies to entries, while the `import()` option determines whether it applies to `import()`. + +In addition, you can also configure a `test` parameter for more fine-grained control over which modules are lazily compiled. The `test` parameter can be a regular expression that matches only those modules that should be lazily compiled. It can also be a function where the input is of type 'Module' and returns a boolean value indicating whether it meets the criteria for lazy compilation logic. + ## experiments.rspackFuture diff --git a/website/docs/zh/config/experiments.mdx b/website/docs/zh/config/experiments.mdx index 4b99175660b..18fbebdceab 100644 --- a/website/docs/zh/config/experiments.mdx +++ b/website/docs/zh/config/experiments.mdx @@ -59,6 +59,32 @@ module.exports = { 默认开启,可通过该配置关闭。 +## experiments.lazyCompilation + + + +- **类型:** + +```ts +type LazyCompilationOptions = + | boolean + | { + entries?: boolean; + + imports?: boolean; + + test?: RegExp | ((m: Module) => boolean); + }; +``` + +- **默认值:** `false` + +开启懒编译,这对提高多入口项目或大型项目的构建性能会非常有帮助。例如你有二十个入口,只有访问到的入口才会进行构建,或者如果项目中存在非常多的 `import()`,每一个 `import()` 所指向的模块都只有在被真正访问到时,才进行构建。 + +如果设置为 true,则默认会对入口模块以及 `import()` 指向的模块进行懒编译。你可以通过配置对象形式,来决定是否只对入口或只对 `import()` 生效。`entries` 决定是否对入口生效,`import()` 决定是否对 `import()` 生效。 + +除此以外你还可以配置 `test` 来更细粒度控制对哪些模块进行懒编译。`test` 可以是一个正则表达式,只对该正则匹配到的模块进行懒编译,`test` 也可以是一个函数,函数的输入是 `Module` 类型,返回 `boolean` 类型,表示是否命中懒编译逻辑。 + ## experiments.rspackFuture From 093a237f6daafd454d478b93baa9e1b2a3f70a45 Mon Sep 17 00:00:00 2001 From: Fy <1114550440@qq.com> Date: Mon, 20 May 2024 16:46:19 +0800 Subject: [PATCH 05/48] fix: css-extract-plugin should keep file dependencies (#6576) --- crates/rspack_core/src/normal_module.rs | 13 ++-- .../src/css_dependency.rs | 33 ++++++---- .../src/css_module.rs | 19 ++++-- .../src/parser_and_generator.rs | 7 +- .../rspack_plugin_extract_css/src/plugin.rs | 49 ++++++++------ .../index.test.ts | 30 +++++++++ .../rspack.config.js | 66 +++++++++++++++++++ .../tailwindcss-with-css-extract/src/App.css | 10 +++ .../tailwindcss-with-css-extract/src/App.jsx | 12 ++++ .../src/index.html | 12 ++++ .../tailwindcss-with-css-extract/src/main.jsx | 5 ++ .../tailwind.config.js | 9 +++ 12 files changed, 220 insertions(+), 45 deletions(-) create mode 100644 packages/playground/cases/react/tailwindcss-with-css-extract/index.test.ts create mode 100644 packages/playground/cases/react/tailwindcss-with-css-extract/rspack.config.js create mode 100644 packages/playground/cases/react/tailwindcss-with-css-extract/src/App.css create mode 100644 packages/playground/cases/react/tailwindcss-with-css-extract/src/App.jsx create mode 100644 packages/playground/cases/react/tailwindcss-with-css-extract/src/index.html create mode 100644 packages/playground/cases/react/tailwindcss-with-css-extract/src/main.jsx create mode 100644 packages/playground/cases/react/tailwindcss-with-css-extract/tailwind.config.js diff --git a/crates/rspack_core/src/normal_module.rs b/crates/rspack_core/src/normal_module.rs index dc094c89e3e..d84678bc000 100644 --- a/crates/rspack_core/src/normal_module.rs +++ b/crates/rspack_core/src/normal_module.rs @@ -489,6 +489,13 @@ impl Module for NormalModule { let mut code_generation_dependencies: Vec> = Vec::new(); + build_info.cacheable = loader_result.cacheable; + build_info.file_dependencies = loader_result.file_dependencies; + build_info.context_dependencies = loader_result.context_dependencies; + build_info.missing_dependencies = loader_result.missing_dependencies; + build_info.build_dependencies = loader_result.build_dependencies; + build_info.asset_filenames = loader_result.asset_filenames; + let ( ParseResult { source, @@ -540,12 +547,6 @@ impl Module for NormalModule { build_meta.hash(&mut hasher); build_info.hash = Some(hasher.digest(&build_context.compiler_options.output.hash_digest)); - build_info.cacheable = loader_result.cacheable; - build_info.file_dependencies = loader_result.file_dependencies; - build_info.context_dependencies = loader_result.context_dependencies; - build_info.missing_dependencies = loader_result.missing_dependencies; - build_info.build_dependencies = loader_result.build_dependencies; - build_info.asset_filenames = loader_result.asset_filenames; Ok(BuildResult { build_info, diff --git a/crates/rspack_plugin_extract_css/src/css_dependency.rs b/crates/rspack_plugin_extract_css/src/css_dependency.rs index e68bbe69d43..289b6ac0aed 100644 --- a/crates/rspack_plugin_extract_css/src/css_dependency.rs +++ b/crates/rspack_plugin_extract_css/src/css_dependency.rs @@ -10,23 +10,26 @@ use crate::css_module::DEPENDENCY_TYPE; #[derive(Debug, Clone)] pub struct CssDependency { - pub id: DependencyId, - pub identifier: String, - pub content: String, - pub context: String, - pub media: String, - pub supports: String, - pub source_map: String, + pub(crate) id: DependencyId, + pub(crate) identifier: String, + pub(crate) content: String, + pub(crate) context: String, + pub(crate) media: String, + pub(crate) supports: String, + pub(crate) source_map: String, // One module can be split apart by using `@import` in the middle of one module - pub identifier_index: u32, + pub(crate) identifier_index: u32, // determine module's postOrderIndex - pub order_index: u32, + pub(crate) order_index: u32, resource_identifier: String, - pub filepath: PathBuf, + pub(crate) file_dependencies: FxHashSet, + pub(crate) context_dependencies: FxHashSet, + pub(crate) missing_dependencies: FxHashSet, + pub(crate) build_dependencies: FxHashSet, } impl CssDependency { @@ -40,7 +43,10 @@ impl CssDependency { source_map: String, identifier_index: u32, order_index: u32, - filepath: PathBuf, + file_dependencies: FxHashSet, + context_dependencies: FxHashSet, + missing_dependencies: FxHashSet, + build_dependencies: FxHashSet, ) -> Self { let resource_identifier = format!("css-module-{}-{}", &identifier, identifier_index); Self { @@ -54,7 +60,10 @@ impl CssDependency { identifier_index, order_index, resource_identifier, - filepath, + file_dependencies, + context_dependencies, + missing_dependencies, + build_dependencies, } } } diff --git a/crates/rspack_plugin_extract_css/src/css_module.rs b/crates/rspack_plugin_extract_css/src/css_module.rs index fbd4e364f7e..47e21891680 100644 --- a/crates/rspack_plugin_extract_css/src/css_module.rs +++ b/crates/rspack_plugin_extract_css/src/css_module.rs @@ -40,7 +40,11 @@ pub(crate) struct CssModule { dependencies: Vec, identifier__: Identifier, - filepath: PathBuf, + + file_dependencies: FxHashSet, + context_dependencies: FxHashSet, + missing_dependencies: FxHashSet, + build_dependencies: FxHashSet, } impl Hash for CssModule { @@ -80,7 +84,10 @@ impl CssModule { build_meta: None, source_map_kind: rspack_util::source_map::SourceMapKind::empty(), identifier__, - filepath: dep.filepath, + file_dependencies: dep.file_dependencies, + context_dependencies: dep.context_dependencies, + missing_dependencies: dep.missing_dependencies, + build_dependencies: dep.build_dependencies, } } @@ -150,13 +157,13 @@ impl Module for CssModule { build_context: BuildContext<'_>, _compilation: Option<&Compilation>, ) -> Result { - let mut file_deps = FxHashSet::default(); - file_deps.insert(self.filepath.clone()); - Ok(BuildResult { build_info: BuildInfo { hash: Some(self.compute_hash(build_context.compiler_options)), - file_dependencies: file_deps, + file_dependencies: self.file_dependencies.clone(), + context_dependencies: self.context_dependencies.clone(), + missing_dependencies: self.missing_dependencies.clone(), + build_dependencies: self.build_dependencies.clone(), ..Default::default() }, ..Default::default() diff --git a/crates/rspack_plugin_extract_css/src/parser_and_generator.rs b/crates/rspack_plugin_extract_css/src/parser_and_generator.rs index bfa0086a476..13f311cb57e 100644 --- a/crates/rspack_plugin_extract_css/src/parser_and_generator.rs +++ b/crates/rspack_plugin_extract_css/src/parser_and_generator.rs @@ -76,7 +76,7 @@ impl ParserAndGenerator for CssExtractParserAndGenerator { supports, source_map, identifier_index, - filepath, + .. }| { let dep = Box::new(CssDependency::new( identifier.into(), @@ -87,7 +87,10 @@ impl ParserAndGenerator for CssExtractParserAndGenerator { source_map.clone(), *identifier_index, idx, - filepath.clone(), + parse_context.build_info.file_dependencies.clone(), + parse_context.build_info.context_dependencies.clone(), + parse_context.build_info.missing_dependencies.clone(), + parse_context.build_info.build_dependencies.clone(), )); idx += 1; dep diff --git a/crates/rspack_plugin_extract_css/src/plugin.rs b/crates/rspack_plugin_extract_css/src/plugin.rs index fc88400fb58..672af5d753a 100644 --- a/crates/rspack_plugin_extract_css/src/plugin.rs +++ b/crates/rspack_plugin_extract_css/src/plugin.rs @@ -1,4 +1,9 @@ -use std::{borrow::Cow, cmp::max, hash::Hash, sync::Arc}; +use std::{ + borrow::Cow, + cmp::max, + hash::Hash, + sync::{atomic::AtomicBool, Arc}, +}; use once_cell::sync::Lazy; use regex::Regex; @@ -58,7 +63,8 @@ struct CssOrderConflicts { #[plugin] #[derive(Debug)] pub struct PluginCssExtract { - pub options: Arc, + pub(crate) options: Arc, + registered: AtomicBool, } impl Eq for PluginCssExtractInner {} @@ -113,7 +119,7 @@ pub enum InsertType { impl PluginCssExtract { pub fn new(options: CssExtractOptions) -> Self { - Self::new_inner(Arc::new(options)) + Self::new_inner(Arc::new(options), false.into()) } // port from https://github.com/webpack-contrib/mini-css-extract-plugin/blob/d5e540baf8280442e523530ebbbe31c57a4c4336/src/index.js#L1127 @@ -430,22 +436,27 @@ async fn compilation( ) -> Result<()> { compilation.set_dependency_factory(DEPENDENCY_TYPE.clone(), Arc::new(CssModuleFactory)); - let (_, parser_and_generator) = compilation - .plugin_driver - .registered_parser_and_generator_builder - .remove(&ModuleType::Js) - .expect("No JavaScript parser registered"); - - compilation - .plugin_driver - .registered_parser_and_generator_builder - .insert( - ModuleType::Js, - Box::new(move |parser_opt, generator_opt| { - let parser = parser_and_generator(parser_opt, generator_opt); - Box::new(CssExtractParserAndGenerator::new(parser)) - }), - ); + if !self + .registered + .swap(true, std::sync::atomic::Ordering::Relaxed) + { + let (_, parser_and_generator) = compilation + .plugin_driver + .registered_parser_and_generator_builder + .remove(&ModuleType::Js) + .expect("No JavaScript parser registered"); + + compilation + .plugin_driver + .registered_parser_and_generator_builder + .insert( + ModuleType::Js, + Box::new(move |parser_opt, generator_opt| { + let parser = parser_and_generator(parser_opt, generator_opt); + Box::new(CssExtractParserAndGenerator::new(parser)) + }), + ); + } Ok(()) } diff --git a/packages/playground/cases/react/tailwindcss-with-css-extract/index.test.ts b/packages/playground/cases/react/tailwindcss-with-css-extract/index.test.ts new file mode 100644 index 00000000000..dcb7226cd37 --- /dev/null +++ b/packages/playground/cases/react/tailwindcss-with-css-extract/index.test.ts @@ -0,0 +1,30 @@ +import { test, expect } from "@/fixtures"; + +test("tailwindcss should work when modify js file", async ({ + page, + fileAction, + rspack +}) => { + function getAppFontSize() { + return page.evaluate(() => { + const app = document.querySelector("#app"); + if (!app) { + return ""; + } + return window.getComputedStyle(app).fontSize; + }); + } + + let appFontSize = await getAppFontSize(); + expect(appFontSize).toBe("24px"); + + // update + fileAction.updateFile("src/App.jsx", content => { + return content.replace("text-2xl", "text-3xl"); + }); + + await expect(page.locator("#app")).toHaveClass(/text-3xl/); + + appFontSize = await getAppFontSize(); + expect(appFontSize).toBe("30px"); +}); diff --git a/packages/playground/cases/react/tailwindcss-with-css-extract/rspack.config.js b/packages/playground/cases/react/tailwindcss-with-css-extract/rspack.config.js new file mode 100644 index 00000000000..a4e3bc7e5f1 --- /dev/null +++ b/packages/playground/cases/react/tailwindcss-with-css-extract/rspack.config.js @@ -0,0 +1,66 @@ +const path = require("path"); +const rspack = require("@rspack/core"); +const ReactRefreshPlugin = require("@rspack/plugin-react-refresh"); + +module.exports = { + context: __dirname, + mode: "development", + entry: { + main: "./src/main.jsx" + }, + plugins: [ + new rspack.HtmlRspackPlugin({ template: "./src/index.html" }), + new ReactRefreshPlugin(), + new rspack.CssExtractRspackPlugin() + ], + resolve: { + extensions: ["...", ".ts", ".tsx", ".jsx"] + }, + experiments: { + css: false + }, + module: { + rules: [ + { + test: /\.jsx$/, + use: { + loader: "builtin:swc-loader", + options: { + jsc: { + parser: { + syntax: "ecmascript", + jsx: true + }, + transform: { + react: { + runtime: "automatic", + development: true, + refresh: true + } + } + } + } + } + }, + { + test: /\.css$/, + use: [ + rspack.CssExtractRspackPlugin.loader, + "css-loader", + { + loader: "postcss-loader", + options: { + postcssOptions: { + plugins: { + tailwindcss: { + config: path.join(__dirname, "./tailwind.config.js") + } + } + } + } + } + ] + } + ] + } +}; diff --git a/packages/playground/cases/react/tailwindcss-with-css-extract/src/App.css b/packages/playground/cases/react/tailwindcss-with-css-extract/src/App.css new file mode 100644 index 00000000000..6300d8a49d6 --- /dev/null +++ b/packages/playground/cases/react/tailwindcss-with-css-extract/src/App.css @@ -0,0 +1,10 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} diff --git a/packages/playground/cases/react/tailwindcss-with-css-extract/src/App.jsx b/packages/playground/cases/react/tailwindcss-with-css-extract/src/App.jsx new file mode 100644 index 00000000000..51826c77656 --- /dev/null +++ b/packages/playground/cases/react/tailwindcss-with-css-extract/src/App.jsx @@ -0,0 +1,12 @@ +import React from "react"; +import "./App.css"; + +function App() { + return ( +

+ Hello world! +

+ ); +} + +export default App; diff --git a/packages/playground/cases/react/tailwindcss-with-css-extract/src/index.html b/packages/playground/cases/react/tailwindcss-with-css-extract/src/index.html new file mode 100644 index 00000000000..127a457455b --- /dev/null +++ b/packages/playground/cases/react/tailwindcss-with-css-extract/src/index.html @@ -0,0 +1,12 @@ + + + + + + + Document + + +
+ + diff --git a/packages/playground/cases/react/tailwindcss-with-css-extract/src/main.jsx b/packages/playground/cases/react/tailwindcss-with-css-extract/src/main.jsx new file mode 100644 index 00000000000..d0d585c0881 --- /dev/null +++ b/packages/playground/cases/react/tailwindcss-with-css-extract/src/main.jsx @@ -0,0 +1,5 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; + +ReactDOM.createRoot(document.getElementById("root")).render(); diff --git a/packages/playground/cases/react/tailwindcss-with-css-extract/tailwind.config.js b/packages/playground/cases/react/tailwindcss-with-css-extract/tailwind.config.js new file mode 100644 index 00000000000..dffcc47fcd0 --- /dev/null +++ b/packages/playground/cases/react/tailwindcss-with-css-extract/tailwind.config.js @@ -0,0 +1,9 @@ +const path = require("path"); +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [path.join(__dirname, "./src/**/*.{html,js,jsx}")], + theme: { + extend: {} + }, + plugins: [] +}; From 5fbabcfdd73bd8baa279573972ea965a2c7cdf7e Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Mon, 20 May 2024 17:22:30 +0800 Subject: [PATCH 06/48] test: pass expect in test env (#6579) * test: pass expect in test env * test: pass expect in test env * test: pass expect in test env --- packages/rspack-test-tools/etc/api.md | 14 +++++++------- packages/rspack-test-tools/src/case/defaults.ts | 2 +- packages/rspack-test-tools/src/case/error.ts | 2 +- packages/rspack-test-tools/src/case/stats-api.ts | 2 +- .../src/helper/legacy/createFakeWorker.js | 8 ++++---- .../src/helper/legacy/createLazyTestEnv.js | 1 + .../rspack-test-tools/src/processor/defaults.ts | 10 +++++----- .../rspack-test-tools/src/processor/diagnostic.ts | 2 +- packages/rspack-test-tools/src/processor/error.ts | 14 +++++++------- packages/rspack-test-tools/src/processor/hash.ts | 6 +++--- packages/rspack-test-tools/src/processor/hook.ts | 13 ++++++------- .../rspack-test-tools/src/processor/hot-step.ts | 10 ++++++---- .../rspack-test-tools/src/processor/snapshot.ts | 2 +- .../rspack-test-tools/src/processor/stats-api.ts | 6 +++--- packages/rspack-test-tools/src/processor/stats.ts | 10 +++++----- .../rspack-test-tools/src/runner/runner/cjs.ts | 7 ++++--- .../src/runner/runner/web/fake.ts | 8 ++++---- .../src/runner/runner/web/jsdom.ts | 4 ++-- packages/rspack-test-tools/src/runner/type.ts | 1 - packages/rspack-test-tools/src/test/creator.ts | 4 +++- packages/rspack-test-tools/src/test/simple.ts | 3 ++- packages/rspack-test-tools/src/type.ts | 1 + packages/rspack-test-tools/tests/Defaults.test.js | 2 +- 23 files changed, 69 insertions(+), 63 deletions(-) diff --git a/packages/rspack-test-tools/etc/api.md b/packages/rspack-test-tools/etc/api.md index 362cb398e5a..b3972dfce08 100644 --- a/packages/rspack-test-tools/etc/api.md +++ b/packages/rspack-test-tools/etc/api.md @@ -126,7 +126,7 @@ export function createWatchCase(name: string, src: string, dist: string, temp: s export class DefaultsConfigTaskProcessor extends SimpleTaskProcessor { constructor(_defaultsConfigOptions: IDefaultsConfigProcessorOptions); // (undocumented) - static addSnapshotSerializer(): void; + static addSnapshotSerializer(expectImpl: jest.Expect): void; // (undocumented) after(context: ITestContext): Promise; // (undocumented) @@ -249,7 +249,7 @@ export enum EEsmMode { export class ErrorTaskProcessor extends SimpleTaskProcessor { constructor(_errorOptions: IErrorTaskProcessorOptions); // (undocumented) - static addSnapshotSerializer(): void; + static addSnapshotSerializer(expectImpl: jest.Expect): void; // (undocumented) check(env: ITestEnv, context: ITestContext): Promise; // (undocumented) @@ -281,7 +281,7 @@ export class HookCasesContext extends TestContext { // @internal (undocumented) _addSnapshot(content: unknown, name: string, group: string | number): void; // @internal (undocumented) - collectSnapshots(options?: { + collectSnapshots(env: ITestEnv, options?: { diff: {}; }): Promise; // (undocumented) @@ -335,8 +335,6 @@ export interface IBasicGlobalContext { // (undocumented) console: Console; // (undocumented) - expect: jest.Expect; - // (undocumented) setTimeout: typeof setTimeout; } @@ -716,6 +714,8 @@ export interface ITestEnv { // (undocumented) beforeEach: (...args: any[]) => void; // (undocumented) + expect: jest.Expect; + // (undocumented) it: (...args: any[]) => void; } @@ -932,7 +932,7 @@ export class RspackHotStepProcessor extends RspackHotProcessor { // (undocumented) protected _hotOptions: IRspackHotProcessorOptions; // (undocumented) - protected matchStepSnapshot(context: ITestContext, step: number, stats: StatsCompilation, runtime?: THotStepRuntimeData): void; + protected matchStepSnapshot(env: ITestEnv, context: ITestContext, step: number, stats: StatsCompilation, runtime?: THotStepRuntimeData): void; // (undocumented) run(env: ITestEnv, context: ITestContext): Promise; } @@ -1026,7 +1026,7 @@ export class SnapshotProcessor extends BasicTaskProcess export class StatsAPITaskProcessor extends SimpleTaskProcessor { constructor(_statsAPIOptions: IStatsAPITaskProcessorOptions); // (undocumented) - static addSnapshotSerializer(): void; + static addSnapshotSerializer(expectImpl: jest.Expect): void; // (undocumented) check(env: ITestEnv, context: ITestContext): Promise; // (undocumented) diff --git a/packages/rspack-test-tools/src/case/defaults.ts b/packages/rspack-test-tools/src/case/defaults.ts index 6920e40eaf6..32bbfc8d964 100644 --- a/packages/rspack-test-tools/src/case/defaults.ts +++ b/packages/rspack-test-tools/src/case/defaults.ts @@ -29,7 +29,7 @@ async function run(name: string, processor: ITestProcessor) { } catch (e: unknown) { context.emitError(name, e as Error); } finally { - await processor.check?.(null as unknown as ITestEnv, context); + await processor.check?.({ expect, it, beforeEach, afterEach }, context); await processor.after?.(context); } } diff --git a/packages/rspack-test-tools/src/case/error.ts b/packages/rspack-test-tools/src/case/error.ts index f4f11bb3742..2ba08493ed4 100644 --- a/packages/rspack-test-tools/src/case/error.ts +++ b/packages/rspack-test-tools/src/case/error.ts @@ -18,7 +18,7 @@ export function createErrorCase( testConfig: string ) { if (!addedSerializer) { - ErrorTaskProcessor.addSnapshotSerializer(); + ErrorTaskProcessor.addSnapshotSerializer(expect); addedSerializer = true; } const caseConfig = require(testConfig); diff --git a/packages/rspack-test-tools/src/case/stats-api.ts b/packages/rspack-test-tools/src/case/stats-api.ts index 83ef28f4aec..81dc40a799d 100644 --- a/packages/rspack-test-tools/src/case/stats-api.ts +++ b/packages/rspack-test-tools/src/case/stats-api.ts @@ -21,7 +21,7 @@ export function createStatsAPICase( testConfig: string ) { if (!addedSerializer) { - StatsAPITaskProcessor.addSnapshotSerializer(); + StatsAPITaskProcessor.addSnapshotSerializer(expect); addedSerializer = true; } const caseConfig: TStatsAPICaseConfig = require(testConfig); diff --git a/packages/rspack-test-tools/src/helper/legacy/createFakeWorker.js b/packages/rspack-test-tools/src/helper/legacy/createFakeWorker.js index 17c4507d7d9..43e640dbb54 100644 --- a/packages/rspack-test-tools/src/helper/legacy/createFakeWorker.js +++ b/packages/rspack-test-tools/src/helper/legacy/createFakeWorker.js @@ -2,12 +2,12 @@ const path = require("path"); -module.exports = ({ outputDirectory }) => +module.exports = (env, { outputDirectory }) => class Worker { constructor(url, options = {}) { - expect(url).toBeInstanceOf(URL); - expect(url.origin).toBe("https://test.cases"); - expect(url.pathname.startsWith("/path/")).toBe(true); + env.expect(url).toBeInstanceOf(URL); + env.expect(url.origin).toBe("https://test.cases"); + env.expect(url.pathname.startsWith("/path/")).toBe(true); this.url = url; const file = url.pathname.slice(6); const workerBootstrap = ` diff --git a/packages/rspack-test-tools/src/helper/legacy/createLazyTestEnv.js b/packages/rspack-test-tools/src/helper/legacy/createLazyTestEnv.js index 0f2c9099681..1068631ff63 100644 --- a/packages/rspack-test-tools/src/helper/legacy/createLazyTestEnv.js +++ b/packages/rspack-test-tools/src/helper/legacy/createLazyTestEnv.js @@ -85,6 +85,7 @@ module.exports = (globalTimeout = 2000, nameSuffix = "") => { getNumberOfTests() { return numberOfTests; }, + expect, it(...args) { numberOfTests++; if (runTests >= numberOfTests) throw new Error("it called too late"); diff --git a/packages/rspack-test-tools/src/processor/defaults.ts b/packages/rspack-test-tools/src/processor/defaults.ts index 85d2d39916e..3c83d580f88 100644 --- a/packages/rspack-test-tools/src/processor/defaults.ts +++ b/packages/rspack-test-tools/src/processor/defaults.ts @@ -93,8 +93,8 @@ export class DefaultsConfigTaskProcessor extends SimpleTaskProcessor 0); + env.expect((statsJson.errors || []).length > 0); } else { - expect((statsJson.errors || []).length === 0); + env.expect((statsJson.errors || []).length === 0); } if (typeof testConfig.validate === "function") { diff --git a/packages/rspack-test-tools/src/processor/hook.ts b/packages/rspack-test-tools/src/processor/hook.ts index 1870c2c307a..d6bce35dadb 100644 --- a/packages/rspack-test-tools/src/processor/hook.ts +++ b/packages/rspack-test-tools/src/processor/hook.ts @@ -147,6 +147,7 @@ export class HookCasesContext extends TestContext { * @internal */ async collectSnapshots( + env: ITestEnv, options = { diff: {} } @@ -167,12 +168,10 @@ export class HookCasesContext extends TestContext { group = `# ${group}\n\n`; return (acc += group + block); }, ""); - - // @ts-ignore - expect(snapshots).toMatchFileSnapshot( - path.join(this.src, "hooks.snap.txt"), - options - ); + env + .expect(snapshots) + // @ts-ignore + .toMatchFileSnapshot(path.join(this.src, "hooks.snap.txt"), options); } } @@ -230,7 +229,7 @@ export class HookTaskProcessor extends SnapshotProcessor { } async check(env: ITestEnv, context: HookCasesContext) { - await (context as any).collectSnapshots(); + await (context as any).collectSnapshots(env); await super.check(env, context); if (typeof this._hookOptions.check === "function") { await this._hookOptions.check(context); diff --git a/packages/rspack-test-tools/src/processor/hot-step.ts b/packages/rspack-test-tools/src/processor/hot-step.ts index 7b5e481779c..7d76f814737 100644 --- a/packages/rspack-test-tools/src/processor/hot-step.ts +++ b/packages/rspack-test-tools/src/processor/hot-step.ts @@ -88,6 +88,7 @@ export class RspackHotStepProcessor extends RspackHotProcessor { } } this.matchStepSnapshot( + env, context, hotUpdateContext.updateIndex, statsJson, @@ -114,7 +115,7 @@ export class RspackHotStepProcessor extends RspackHotProcessor { const compiler = this.getCompiler(context); const stats = compiler.getStats(); if (!stats || !stats.hash) { - expect(false); + env.expect(false); return; } const statsJson = stats.toJson({ assets: true, chunks: true }); @@ -125,7 +126,7 @@ export class RspackHotStepProcessor extends RspackHotProcessor { } let matchFailed: Error | null = null; try { - this.matchStepSnapshot(context, 0, statsJson); + this.matchStepSnapshot(env, context, 0, statsJson); } catch (e) { matchFailed = e as Error; } @@ -136,6 +137,7 @@ export class RspackHotStepProcessor extends RspackHotProcessor { } protected matchStepSnapshot( + env: ITestEnv, context: ITestContext, step: number, stats: StatsCompilation, @@ -145,7 +147,7 @@ export class RspackHotStepProcessor extends RspackHotProcessor { const compilerOptions = compiler.getOptions(); const getModuleHandler = GET_MODULE_HANDLER[compilerOptions.target as TSupportTarget]; - expect(typeof getModuleHandler).toBe("function"); + env.expect(typeof getModuleHandler).toBe("function"); const lastHash = this.hashes[this.hashes.length - 1]; const snapshotPath = context.getSource( @@ -359,6 +361,6 @@ ${runtime.javascript.disposedModules.map(i => `- ${i}`).join("\n")} return; } const snapshotContent = escapeEOL(fs.readFileSync(snapshotPath, "utf-8")); - expect(content).toBe(snapshotContent); + env.expect(content).toBe(snapshotContent); } } diff --git a/packages/rspack-test-tools/src/processor/snapshot.ts b/packages/rspack-test-tools/src/processor/snapshot.ts index a4702541669..65b672d44f6 100644 --- a/packages/rspack-test-tools/src/processor/snapshot.ts +++ b/packages/rspack-test-tools/src/processor/snapshot.ts @@ -80,6 +80,6 @@ export class SnapshotProcessor< return; } const snapshotContent = escapeEOL(fs.readFileSync(snapshotPath, "utf-8")); - expect(content).toBe(snapshotContent); + env.expect(content).toBe(snapshotContent); } } diff --git a/packages/rspack-test-tools/src/processor/stats-api.ts b/packages/rspack-test-tools/src/processor/stats-api.ts index eff1096b468..576f203f8b2 100644 --- a/packages/rspack-test-tools/src/processor/stats-api.ts +++ b/packages/rspack-test-tools/src/processor/stats-api.ts @@ -50,11 +50,11 @@ export class StatsAPITaskProcessor< async check(env: ITestEnv, context: ITestContext) { const compiler = this.getCompiler(context); const stats = compiler.getStats(); - expect(typeof stats).toBe("object"); + env.expect(typeof stats).toBe("object"); await this._statsAPIOptions.check?.(stats!, compiler.getCompiler()!); } - static addSnapshotSerializer() { - expect.addSnapshotSerializer(serializer); + static addSnapshotSerializer(expectImpl: jest.Expect) { + expectImpl.addSnapshotSerializer(serializer); } } diff --git a/packages/rspack-test-tools/src/processor/stats.ts b/packages/rspack-test-tools/src/processor/stats.ts index 6ea5e96c5c8..11e492ef810 100644 --- a/packages/rspack-test-tools/src/processor/stats.ts +++ b/packages/rspack-test-tools/src/processor/stats.ts @@ -98,7 +98,7 @@ export class RspackStatsProcessor extends MultiTaskProcessor void, ms: number | undefined, @@ -39,12 +38,12 @@ export class CommonJsRunner< protected createBaseModuleScope(): IBasicModuleScope { const baseModuleScope: IBasicModuleScope = { console: this.globalContext!.console, - expect: this.globalContext!.expect, setTimeout: this.globalContext!.setTimeout, clearTimeout: this.globalContext!.clearTimeout, it: this._options.env.it, beforeEach: this._options.env.beforeEach, afterEach: this._options.env.afterEach, + expect: this._options.env.expect, jest, nsObj: (m: Object) => { Object.defineProperty(m, Symbol.toStringTag, { @@ -71,7 +70,9 @@ export class CommonJsRunner< exports: m.exports, __dirname: path.dirname(file.path), __filename: file.path, - _globalAssign: { expect }, + _globalAssign: { + expect: this._options.env.expect + }, define }; } diff --git a/packages/rspack-test-tools/src/runner/runner/web/fake.ts b/packages/rspack-test-tools/src/runner/runner/web/fake.ts index 6b7f6011d1f..a30bb40a814 100644 --- a/packages/rspack-test-tools/src/runner/runner/web/fake.ts +++ b/packages/rspack-test-tools/src/runner/runner/web/fake.ts @@ -73,11 +73,11 @@ export class FakeDocumentWebRunner< } }; globalContext["importScripts"] = (url: string) => { - expect(url).toMatch(/^https:\/\/test\.cases\/path\//); + this._options.env.expect(url).toMatch(/^https:\/\/test\.cases\/path\//); this.requirers.get("entry")!(this._options.dist, urlToRelativePath(url)); }; globalContext["document"] = this.document; - globalContext["Worker"] = createFakeWorker({ + globalContext["Worker"] = createFakeWorker(this._options.env, { outputDirectory: this._options.dist }); globalContext["EventSource"] = EventSource; @@ -98,7 +98,7 @@ export class FakeDocumentWebRunner< ) { const subModuleScope = super.createModuleScope(requireFn, m, file); subModuleScope["importScripts"] = (url: string) => { - expect(url).toMatch(/^https:\/\/test\.cases\/path\//); + this._options.env.expect(url).toMatch(/^https:\/\/test\.cases\/path\//); this.getRequire()( this._options.dist, `.${url.slice("https://test.cases/path".length)}` @@ -118,7 +118,7 @@ export class FakeDocumentWebRunner< moduleScope["Worker"] = this.globalContext!["Worker"]; moduleScope["EventSource"] = this.globalContext!["EventSource"]; moduleScope["URL"] = URL; - moduleScope["Worker"] = createFakeWorker({ + moduleScope["Worker"] = createFakeWorker(this._options.env, { outputDirectory: this._options.dist }); moduleScope["__dirname"] = this._options.dist; diff --git a/packages/rspack-test-tools/src/runner/runner/web/jsdom.ts b/packages/rspack-test-tools/src/runner/runner/web/jsdom.ts index f26c45a7e54..fffdfaa17c0 100644 --- a/packages/rspack-test-tools/src/runner/runner/web/jsdom.ts +++ b/packages/rspack-test-tools/src/runner/runner/web/jsdom.ts @@ -103,7 +103,7 @@ export class JSDOMWebRunner< protected createBaseModuleScope() { const moduleScope = super.createBaseModuleScope(); moduleScope["EventSource"] = EventSource; - moduleScope["Worker"] = createFakeWorker({ + moduleScope["Worker"] = createFakeWorker(this._options.env, { outputDirectory: this._options.dist }); const urlToPath = (url: string) => { @@ -134,7 +134,7 @@ export class JSDOMWebRunner< }; moduleScope["URL"] = URL; moduleScope["importScripts"] = (url: string) => { - expect(url).toMatch(/^https:\/\/test\.cases\/path\//); + this._options.env.expect(url).toMatch(/^https:\/\/test\.cases\/path\//); this.requirers.get("entry")!(this._options.dist, urlToRelativePath(url)); }; moduleScope["STATS"] = moduleScope.__STATS__; diff --git a/packages/rspack-test-tools/src/runner/type.ts b/packages/rspack-test-tools/src/runner/type.ts index 1f464583dd9..61994bbe7e6 100644 --- a/packages/rspack-test-tools/src/runner/type.ts +++ b/packages/rspack-test-tools/src/runner/type.ts @@ -30,7 +30,6 @@ export interface IBasicModuleScope extends ITestEnv { export interface IBasicGlobalContext { console: Console; - expect: jest.Expect; setTimeout: typeof setTimeout; clearTimeout: typeof clearTimeout; [key: string]: any; diff --git a/packages/rspack-test-tools/src/test/creator.ts b/packages/rspack-test-tools/src/test/creator.ts index 3d2ed325319..e07434c1bfe 100644 --- a/packages/rspack-test-tools/src/test/creator.ts +++ b/packages/rspack-test-tools/src/test/creator.ts @@ -6,6 +6,7 @@ import createLazyTestEnv from "../helper/legacy/createLazyTestEnv"; import { ECompilerType, ITestContext, + ITestEnv, ITester, ITestProcessor, TRunnerFactory, @@ -88,11 +89,12 @@ export class BasicCaseCreator { }); } - protected createEnv(testConfig: TTestConfig) { + protected createEnv(testConfig: TTestConfig): ITestEnv { if (typeof this._options.runner === "function" && !testConfig.noTest) { return createLazyTestEnv(10000); } else { return { + expect, it, beforeEach, afterEach diff --git a/packages/rspack-test-tools/src/test/simple.ts b/packages/rspack-test-tools/src/test/simple.ts index b3e4c40590e..ae9f4a58a11 100644 --- a/packages/rspack-test-tools/src/test/simple.ts +++ b/packages/rspack-test-tools/src/test/simple.ts @@ -14,7 +14,8 @@ export function getSimpleProcessorRunner( context?: (src: string, dist: string) => ITestContext; } = {} ) { - const createEnv = options.env || (() => ({ it, beforeEach, afterEach })); + const createEnv = + options.env || (() => ({ expect, it, beforeEach, afterEach })); const createContext = options.context || ((src: string, dist: string) => new TestContext({ src, dist })); diff --git a/packages/rspack-test-tools/src/type.ts b/packages/rspack-test-tools/src/type.ts index 0938e9f17cc..096cf06e39f 100644 --- a/packages/rspack-test-tools/src/type.ts +++ b/packages/rspack-test-tools/src/type.ts @@ -168,6 +168,7 @@ export type TDiffStats = { }; export interface ITestEnv { + expect: jest.Expect; it: (...args: any[]) => void; beforeEach: (...args: any[]) => void; afterEach: (...args: any[]) => void; diff --git a/packages/rspack-test-tools/tests/Defaults.test.js b/packages/rspack-test-tools/tests/Defaults.test.js index 9cb95be9031..781179c5123 100644 --- a/packages/rspack-test-tools/tests/Defaults.test.js +++ b/packages/rspack-test-tools/tests/Defaults.test.js @@ -5,7 +5,7 @@ const { describeByWalk } = require(".."); -DefaultsConfigTaskProcessor.addSnapshotSerializer(); +DefaultsConfigTaskProcessor.addSnapshotSerializer(expect); describe("Base Defaults Snapshot", () => { const baseConfig = DefaultsConfigTaskProcessor.getDefaultConfig( From 63110e3ed4eaaa80407bc5e922581a26db38db73 Mon Sep 17 00:00:00 2001 From: neverland Date: Tue, 21 May 2024 11:27:59 +0800 Subject: [PATCH 07/48] perf(core): prebundle enhanced-resolve to reduce dependencies (#6585) * perf(core): prebundle enhanced-resolve to reduce dependencies * fix: api.md * fix: lock file --- packages/rspack/etc/api.md | 40 +++++++++++++++++++++++++++- packages/rspack/package.json | 2 +- packages/rspack/prebundle.config.mjs | 28 ++++++++++++++++++- packages/rspack/tsconfig.json | 4 +++ pnpm-lock.yaml | 7 +++-- 5 files changed, 74 insertions(+), 7 deletions(-) diff --git a/packages/rspack/etc/api.md b/packages/rspack/etc/api.md index 7e4d7600f0d..c4e2b40d338 100644 --- a/packages/rspack/etc/api.md +++ b/packages/rspack/etc/api.md @@ -61,7 +61,6 @@ import type { RawRelayConfig } from '@rspack/binding'; import { RawRuntimeChunkOptions } from '@rspack/binding'; import { RawSourceMapDevToolPluginOptions } from '@rspack/binding'; import { RawSwcJsMinimizerRspackPluginOptions } from '@rspack/binding'; -import { ResolveRequest } from 'enhanced-resolve'; import ResolverFactory = require('./ResolverFactory'); import { RspackOptionsNormalized as RspackOptionsNormalized_2 } from '.'; import { Source } from 'webpack-sources'; @@ -646,6 +645,24 @@ const baseResolveOptions: z.ZodObject<{ roots?: string[] | undefined; }>; +// @public (undocumented) +interface BaseResolveRequest { + // (undocumented) + descriptionFileData?: object; + // (undocumented) + descriptionFilePath?: string; + // (undocumented) + descriptionFileRoot?: string; + // (undocumented) + fullySpecified?: boolean; + // (undocumented) + ignoreSymlinks?: boolean; + // (undocumented) + path: string | false; + // (undocumented) + relativePath?: string; +} + // @public (undocumented) const baseRuleSetCondition: z.ZodUnion<[z.ZodUnion<[z.ZodType, z.ZodString]>, z.ZodFunction, z.ZodBoolean>]>; @@ -6974,6 +6991,24 @@ export interface OutputNormalized { workerWasmLoading?: WasmLoading; } +// @public (undocumented) +interface ParsedIdentifier { + // (undocumented) + directory: boolean; + // (undocumented) + file: boolean; + // (undocumented) + fragment: string; + // (undocumented) + internal: boolean; + // (undocumented) + module: boolean; + // (undocumented) + query: string; + // (undocumented) + request: string; +} + // @public (undocumented) export type ParserOptionsByModuleType = z.infer; @@ -7684,6 +7719,9 @@ export type ResolveOptions = z.infer & { byDependency?: Record; }; +// @public (undocumented) +type ResolveRequest = BaseResolveRequest & Partial; + // @public (undocumented) export type ResolveTsconfig = z.infer; diff --git a/packages/rspack/package.json b/packages/rspack/package.json index f588debfacd..e500e19648a 100644 --- a/packages/rspack/package.json +++ b/packages/rspack/package.json @@ -51,6 +51,7 @@ "copy-webpack-plugin": "5.1.2", "cross-env": "^7.0.3", "del": "^6.0.0", + "enhanced-resolve": "5.12.0", "file-loader": "^6.2.0", "glob": "^10.3.10", "graceful-fs": "4.2.10", @@ -86,7 +87,6 @@ "@module-federation/runtime-tools": "0.1.6", "@rspack/binding": "workspace:*", "caniuse-lite": "^1.0.30001616", - "enhanced-resolve": "5.12.0", "tapable": "2.2.1", "webpack-sources": "3.2.3" }, diff --git a/packages/rspack/prebundle.config.mjs b/packages/rspack/prebundle.config.mjs index 209d1471558..9fa79d2b4a3 100644 --- a/packages/rspack/prebundle.config.mjs +++ b/packages/rspack/prebundle.config.mjs @@ -1,4 +1,6 @@ // @ts-check +import { copyFileSync, readFileSync, writeFileSync } from "node:fs"; +import { join } from "node:path"; /** @type {import('prebundle').Config} */ export default { @@ -11,7 +13,7 @@ export default { { name: "watchpack", externals: { - "graceful-fs": "../graceful-fs" + "graceful-fs": "../graceful-fs/index.js" } }, { @@ -21,6 +23,30 @@ export default { "caniuse-lite": "caniuse-lite", "/^caniuse-lite(/.*)/": "caniuse-lite$1" } + }, + { + name: "enhanced-resolve", + externals: { + tapable: "tapable", + "graceful-fs": "../graceful-fs/index.js" + }, + afterBundle({ depPath, distPath }) { + copyFileSync( + join(depPath, "lib/CachedInputFileSystem.js"), + join(distPath, "CachedInputFileSystem.js") + ); + + // ResolveRequest type is used by Rspack but not exported + const dtsFile = join(distPath, "index.d.ts"); + const content = readFileSync(dtsFile, "utf-8"); + writeFileSync( + dtsFile, + content.replace( + "type ResolveRequest =", + "export type ResolveRequest =" + ) + ); + } } ] }; diff --git a/packages/rspack/tsconfig.json b/packages/rspack/tsconfig.json index e45a4a595fb..f20361dfd54 100644 --- a/packages/rspack/tsconfig.json +++ b/packages/rspack/tsconfig.json @@ -10,6 +10,10 @@ "watchpack": ["../compiled/watchpack"], "graceful-fs": ["../compiled/graceful-fs"], "browserslist": ["../compiled/browserslist"], + "enhanced-resolve": ["../compiled/enhanced-resolve"], + "enhanced-resolve/lib/CachedInputFileSystem": [ + "../compiled/enhanced-resolve/CachedInputFileSystem" + ], "zod-validation-error": ["../compiled/zod-validation-error"], "json-parse-even-better-errors": [ "../compiled/json-parse-even-better-errors" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e8c92c844af..19b68451138 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -466,9 +466,6 @@ importers: caniuse-lite: specifier: ^1.0.30001616 version: 1.0.30001616 - enhanced-resolve: - specifier: 5.12.0 - version: 5.12.0 tapable: specifier: 2.2.1 version: 2.2.1 @@ -515,6 +512,9 @@ importers: del: specifier: ^6.0.0 version: 6.1.1 + enhanced-resolve: + specifier: 5.12.0 + version: 5.12.0 file-loader: specifier: ^6.2.0 version: 6.2.0(webpack@5.90.1) @@ -9258,7 +9258,6 @@ packages: dependencies: graceful-fs: 4.2.10 tapable: 2.2.1 - dev: false /enhanced-resolve@5.16.0: resolution: {integrity: sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==} From f2afb4dc2e222476ce78842375322187a41ac10d Mon Sep 17 00:00:00 2001 From: Gengkun Date: Tue, 21 May 2024 11:36:23 +0800 Subject: [PATCH 08/48] fix: support `"..."` in importFields (#6363) --- .../src/options/raw_resolve.rs | 8 ++--- .../src/options/resolve/clever_merge.rs | 36 +++++++++---------- crates/rspack_core/src/options/resolve/mod.rs | 12 +++---- .../rspack_core/src/resolver/resolver_impl.rs | 5 +-- .../tests/__snapshots__/Defaults.test.js.snap | 3 ++ packages/rspack/src/config/defaults.ts | 1 + .../resolve-merging/imports-fields/index.js | 8 +++++ .../imports-fields/node_modules/lib/index.js | 2 ++ .../imports-fields/node_modules/lib/lib.mjs | 1 + .../node_modules/lib/package.json | 6 ++++ .../imports-fields/package.json | 6 ++++ .../resolve-merging/imports-fields/pkg.mjs | 1 + .../imports-fields/webpack.config.js | 6 ++++ 13 files changed, 65 insertions(+), 30 deletions(-) create mode 100644 webpack-test/configCases/resolve-merging/imports-fields/index.js create mode 100644 webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/index.js create mode 100644 webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/lib.mjs create mode 100644 webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/package.json create mode 100644 webpack-test/configCases/resolve-merging/imports-fields/package.json create mode 100644 webpack-test/configCases/resolve-merging/imports-fields/pkg.mjs create mode 100644 webpack-test/configCases/resolve-merging/imports-fields/webpack.config.js diff --git a/crates/rspack_binding_options/src/options/raw_resolve.rs b/crates/rspack_binding_options/src/options/raw_resolve.rs index 97c1c13e3e5..bdbb8dd6f25 100644 --- a/crates/rspack_binding_options/src/options/raw_resolve.rs +++ b/crates/rspack_binding_options/src/options/raw_resolve.rs @@ -110,7 +110,7 @@ impl TryFrom for Resolve { .collect::>() }) .transpose()?; - let exports_field = value + let exports_fields = value .exports_fields .map(|v| v.into_iter().map(|s| vec![s]).collect()); let extension_alias = value.extension_alias.map(|v| v.into_iter().collect()); @@ -121,7 +121,7 @@ impl TryFrom for Resolve { let roots = value.roots; let enforce_extension = value.enforce_extension; let description_files = value.description_files; - let imports_field = value + let imports_fields = value .imports_fields .map(|v| v.into_iter().map(|s| vec![s]).collect()); @@ -139,14 +139,14 @@ impl TryFrom for Resolve { fallback, by_dependency, fully_specified, - exports_field, + exports_fields, extension_alias, alias_fields, restrictions, roots, enforce_extension, description_files, - imports_field, + imports_fields, }) } } diff --git a/crates/rspack_core/src/options/resolve/clever_merge.rs b/crates/rspack_core/src/options/resolve/clever_merge.rs index 4fe172c385a..807e408d95e 100644 --- a/crates/rspack_core/src/options/resolve/clever_merge.rs +++ b/crates/rspack_core/src/options/resolve/clever_merge.rs @@ -2,8 +2,8 @@ use hashlink::LinkedHashMap; use super::value_type::{GetValueType, ValueType}; use super::{ - Alias, AliasFields, ConditionNames, DescriptionFiles, EnforceExtension, ExportsField, - ExtensionAlias, Extensions, Fallback, FullySpecified, ImportsField, MainFields, MainFiles, + Alias, AliasFields, ConditionNames, DescriptionFiles, EnforceExtension, ExportsFields, + ExtensionAlias, Extensions, Fallback, FullySpecified, ImportsFields, MainFields, MainFiles, Modules, PreferAbsolute, PreferRelative, Restrictions, Roots, Symlink, TsconfigOptions, }; use super::{ByDependency, DependencyCategoryStr, Resolve}; @@ -30,8 +30,8 @@ fn is_empty(resolve: &Resolve) -> bool { && is_none!(modules) && is_none!(fallback) && is_none!(fully_specified) - && is_none!(exports_field) - && is_none!(imports_field) + && is_none!(exports_fields) + && is_none!(imports_fields) && is_none!(description_files) && is_none!(enforce_extension) && is_none!(extension_alias) @@ -62,8 +62,8 @@ struct ResolveWithEntry { fallback: Entry, tsconfig: Entry, fully_specified: Entry, - exports_field: Entry, - imports_field: Entry, + exports_fields: Entry, + imports_fields: Entry, description_files: Entry, enforce_extension: Entry, extension_alias: Entry, @@ -94,8 +94,8 @@ fn parse_resolve(resolve: Resolve) -> ResolveWithEntry { fallback: entry!(fallback), tsconfig: entry!(tsconfig), fully_specified: entry!(fully_specified), - exports_field: entry!(exports_field), - imports_field: entry!(imports_field), + exports_fields: entry!(exports_fields), + imports_fields: entry!(imports_fields), description_files: entry!(description_files), enforce_extension: entry!(enforce_extension), extension_alias: entry!(extension_alias), @@ -141,8 +141,8 @@ fn parse_resolve(resolve: Resolve) -> ResolveWithEntry { update_by_value!(modules); update_by_value!(fallback); update_by_value!(fully_specified); - update_by_value!(exports_field); - update_by_value!(imports_field); + update_by_value!(exports_fields); + update_by_value!(imports_fields); update_by_value!(description_files); update_by_value!(enforce_extension); update_by_value!(extension_alias); @@ -317,8 +317,8 @@ fn _merge_resolve(first: Resolve, second: Resolve) -> Resolve { ), fallback: merge!(fallback, ValueType::Other, |_| false, extend_alias), alias: merge!(alias, ValueType::Other, |_| false, extend_alias), - exports_field: merge!(exports_field, ValueType::Other, |_| false, |_, b| b), - imports_field: merge!(imports_field, ValueType::Other, |_| false, |_, b| b), + exports_fields: merge!(exports_fields, ValueType::Other, |_| false, |_, b| b), + imports_fields: merge!(imports_fields, ValueType::Other, |_| false, |_, b| b), description_files: merge!( description_files, second.description_files.base.get_value_type(), @@ -366,8 +366,8 @@ fn _merge_resolve(first: Resolve, second: Resolve) -> Resolve { setup_by_values!(modules); setup_by_values!(fallback); setup_by_values!(fully_specified); - setup_by_values!(exports_field); - setup_by_values!(imports_field); + setup_by_values!(exports_fields); + setup_by_values!(imports_fields); setup_by_values!(description_files); setup_by_values!(enforce_extension); setup_by_values!(extension_alias); @@ -399,8 +399,8 @@ fn _merge_resolve(first: Resolve, second: Resolve) -> Resolve { to_resolve!(modules); to_resolve!(fallback); to_resolve!(fully_specified); - to_resolve!(exports_field); - to_resolve!(imports_field); + to_resolve!(exports_fields); + to_resolve!(imports_fields); to_resolve!(description_files); to_resolve!(enforce_extension); to_resolve!(extension_alias); @@ -428,8 +428,8 @@ fn _merge_resolve(first: Resolve, second: Resolve) -> Resolve { modules: result_entry.modules.base, fallback: result_entry.fallback.base, fully_specified: result_entry.fully_specified.base, - exports_field: result_entry.exports_field.base, - imports_field: result_entry.imports_field.base, + exports_fields: result_entry.exports_fields.base, + imports_fields: result_entry.imports_fields.base, description_files: result_entry.description_files.base, enforce_extension: result_entry.enforce_extension.base, extension_alias: result_entry.extension_alias.base, diff --git a/crates/rspack_core/src/options/resolve/mod.rs b/crates/rspack_core/src/options/resolve/mod.rs index a640fa2991d..66a09385f51 100644 --- a/crates/rspack_core/src/options/resolve/mod.rs +++ b/crates/rspack_core/src/options/resolve/mod.rs @@ -22,8 +22,8 @@ pub(super) type ConditionNames = Vec; pub(super) type Fallback = Alias; pub(super) type FullySpecified = bool; pub(super) type EnforceExtension = bool; -pub(super) type ExportsField = Vec>; -pub(super) type ImportsField = Vec>; +pub(super) type ExportsFields = Vec>; +pub(super) type ImportsFields = Vec>; pub(super) type ExtensionAlias = Vec<(String, Vec)>; pub(super) type Modules = Vec; pub(super) type Roots = Vec; @@ -67,7 +67,7 @@ pub struct Resolve { pub fully_specified: Option, /// A list of exports fields in descriptions files /// Default is `[["exports"]]`. - pub exports_field: Option, + pub exports_fields: Option, /// A list map ext to another. /// Default is `[]` pub extension_alias: Option, @@ -76,7 +76,9 @@ pub struct Resolve { /// A list of directories where requests of server-relative URLs (starting with '/') are resolved pub roots: Option, /// A list of resolve restrictions to restrict the paths that a request can be resolved on. - pub restrictions: Option, + pub restrictions: Option, + /// Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal). + pub imports_fields: Option, /// Configure resolve options by the type of module request. pub by_dependency: Option, /// The JSON files to use for descriptions @@ -84,8 +86,6 @@ pub struct Resolve { pub description_files: Option, /// If enforce_extension is set to EnforceExtension::Enabled, resolution will not allow extension-less files. This means require('./foo.js') will resolve, while require('./foo') will not. pub enforce_extension: Option, - /// Fields from package.json which are used to provide the internal requests of a package (requests starting with # are considered internal). - pub imports_field: Option, } /// Tsconfig Options diff --git a/crates/rspack_core/src/resolver/resolver_impl.rs b/crates/rspack_core/src/resolver/resolver_impl.rs index e0b8e40682f..1a70cd03137 100644 --- a/crates/rspack_core/src/resolver/resolver_impl.rs +++ b/crates/rspack_core/src/resolver/resolver_impl.rs @@ -202,7 +202,7 @@ fn to_oxc_resolver_options( .description_files .unwrap_or_else(|| vec!["package.json".to_string()]); let imports_fields = options - .imports_field + .imports_fields .unwrap_or_else(|| vec![vec!["imports".to_string()]]); let extensions = options.extensions.expect("should have extensions"); let alias = options @@ -252,7 +252,7 @@ fn to_oxc_resolver_options( .collect(); let fully_specified = options.fully_specified.unwrap_or_default(); let exports_fields = options - .exports_field + .exports_fields .unwrap_or_else(|| vec![vec!["exports".to_string()]]); let extension_alias = options.extension_alias.unwrap_or_default(); let alias_fields = options @@ -270,6 +270,7 @@ fn to_oxc_resolver_options( .into_iter() .map(PathBuf::from) .collect(); + oxc_resolver::ResolveOptions { fallback, modules, diff --git a/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap b/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap index 3f1bfb0aeca..fa7d4c5f9e0 100644 --- a/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap +++ b/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap @@ -487,6 +487,9 @@ Object { "exports", ], "extensions": Array [], + "importsFields": Array [ + "imports", + ], "mainFields": Array [ "main", ], diff --git a/packages/rspack/src/config/defaults.ts b/packages/rspack/src/config/defaults.ts index 34fcdf8e185..e2de2bbc547 100644 --- a/packages/rspack/src/config/defaults.ts +++ b/packages/rspack/src/config/defaults.ts @@ -1007,6 +1007,7 @@ const getResolveDefaults = ({ exportsFields: ["exports"], roots: [context], mainFields: ["main"], + importsFields: ["imports"], byDependency: { wasm: esmDeps(), esm: esmDeps(), diff --git a/webpack-test/configCases/resolve-merging/imports-fields/index.js b/webpack-test/configCases/resolve-merging/imports-fields/index.js new file mode 100644 index 00000000000..616dbc039b9 --- /dev/null +++ b/webpack-test/configCases/resolve-merging/imports-fields/index.js @@ -0,0 +1,8 @@ +import d1 from "./pkg.mjs"; +import d2 from "#internal"; +import { d3, d4 } from "lib"; + +it("imports field to resolve to the same", () => { + expect(d2).toBe(d1); + expect(d4).toBe(d3); +}); diff --git a/webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/index.js b/webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/index.js new file mode 100644 index 00000000000..1953c3537f5 --- /dev/null +++ b/webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/index.js @@ -0,0 +1,2 @@ +export { default as d3 } from "./lib.mjs"; +export { default as d4 } from "#internal"; diff --git a/webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/lib.mjs b/webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/lib.mjs new file mode 100644 index 00000000000..71c401bf2aa --- /dev/null +++ b/webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/lib.mjs @@ -0,0 +1 @@ +export default 'lib'; diff --git a/webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/package.json b/webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/package.json new file mode 100644 index 00000000000..a085977002b --- /dev/null +++ b/webpack-test/configCases/resolve-merging/imports-fields/node_modules/lib/package.json @@ -0,0 +1,6 @@ +{ + "name": "lib", + "hash-start": { + "#internal": "./lib.mjs" + } +} \ No newline at end of file diff --git a/webpack-test/configCases/resolve-merging/imports-fields/package.json b/webpack-test/configCases/resolve-merging/imports-fields/package.json new file mode 100644 index 00000000000..1843391bb5a --- /dev/null +++ b/webpack-test/configCases/resolve-merging/imports-fields/package.json @@ -0,0 +1,6 @@ +{ + "name": "pkg", + "imports": { + "#internal": "./pkg.mjs" + } +} \ No newline at end of file diff --git a/webpack-test/configCases/resolve-merging/imports-fields/pkg.mjs b/webpack-test/configCases/resolve-merging/imports-fields/pkg.mjs new file mode 100644 index 00000000000..3fa44fe7fa6 --- /dev/null +++ b/webpack-test/configCases/resolve-merging/imports-fields/pkg.mjs @@ -0,0 +1 @@ +export default 'pkg'; diff --git a/webpack-test/configCases/resolve-merging/imports-fields/webpack.config.js b/webpack-test/configCases/resolve-merging/imports-fields/webpack.config.js new file mode 100644 index 00000000000..a1150b90eed --- /dev/null +++ b/webpack-test/configCases/resolve-merging/imports-fields/webpack.config.js @@ -0,0 +1,6 @@ +module.exports = { + entry: "./index.js", + resolve: { + importsFields: ["hash-start", "..."] + } +}; From 2aa11cdf83837aedc986ab1c7382268ba113f985 Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Tue, 21 May 2024 13:14:17 +0800 Subject: [PATCH 09/48] test: compiler type extends (#6582) * test: compiler type extends * test: compiler type extends * test: compiler type extends * test: compiler type extends * test: compiler type extends --- packages/rspack-test-tools/etc/api.md | 468 +++++++++--------- .../rspack-test-tools/src/case/builtin.ts | 14 +- .../rspack-test-tools/src/case/compiler.ts | 2 +- packages/rspack-test-tools/src/case/config.ts | 10 +- .../rspack-test-tools/src/case/defaults.ts | 11 +- .../rspack-test-tools/src/case/diagnostic.ts | 10 +- packages/rspack-test-tools/src/case/error.ts | 8 +- packages/rspack-test-tools/src/case/hash.ts | 8 +- .../rspack-test-tools/src/case/hot-step.ts | 8 +- packages/rspack-test-tools/src/case/hot.ts | 8 +- packages/rspack-test-tools/src/case/normal.ts | 8 +- .../rspack-test-tools/src/case/stats-api.ts | 11 +- .../src/case/stats-output.ts | 9 +- .../rspack-test-tools/src/case/treeshaking.ts | 8 +- packages/rspack-test-tools/src/case/watch.ts | 18 +- .../rspack-test-tools/src/processor/basic.ts | 9 +- .../src/processor/builtin.ts | 311 ++++++------ .../rspack-test-tools/src/processor/config.ts | 49 +- .../src/processor/defaults.ts | 32 +- .../src/processor/diagnostic.ts | 31 +- .../rspack-test-tools/src/processor/diff.ts | 10 +- .../rspack-test-tools/src/processor/error.ts | 6 +- .../rspack-test-tools/src/processor/hash.ts | 38 +- .../rspack-test-tools/src/processor/hook.ts | 56 ++- .../src/processor/hot-step.ts | 40 +- .../rspack-test-tools/src/processor/hot.ts | 101 ++-- .../rspack-test-tools/src/processor/multi.ts | 13 +- .../rspack-test-tools/src/processor/normal.ts | 41 +- .../rspack-test-tools/src/processor/simple.ts | 6 +- .../src/processor/snapshot.ts | 4 +- .../src/processor/stats-api.ts | 6 +- .../rspack-test-tools/src/processor/stats.ts | 37 +- .../src/processor/treeshaking.ts | 39 +- .../rspack-test-tools/src/processor/watch.ts | 52 +- .../rspack-test-tools/tests/Defaults.test.js | 6 +- 35 files changed, 751 insertions(+), 737 deletions(-) diff --git a/packages/rspack-test-tools/etc/api.md b/packages/rspack-test-tools/etc/api.md index b3972dfce08..a9804919707 100644 --- a/packages/rspack-test-tools/etc/api.md +++ b/packages/rspack-test-tools/etc/api.md @@ -24,22 +24,7 @@ import { StatsWarnings } from '@rspack/core'; import { WebpackOptionsNormalized } from 'webpack'; // @public (undocumented) -export class BasicRunnerFactory implements TRunnerFactory { - constructor(name: string, context: ITestContext); - // (undocumented) - protected context: ITestContext; - // (undocumented) - create(file: string, compilerOptions: TCompilerOptions, env: ITestEnv): ITestRunner; - // (undocumented) - protected createRunner(file: string, stats: TCompilerStatsCompilation, compilerOptions: TCompilerOptions, env: ITestEnv): ITestRunner; - // (undocumented) - protected getRunnerKey(file: string): string; - // (undocumented) - protected name: string; -} - -// @public (undocumented) -export class BasicTaskProcessor implements ITestProcessor { +export class BasicProcessor implements ITestProcessor { constructor(_options: IBasicProcessorOptions); // (undocumented) after(context: ITestContext): Promise; @@ -65,6 +50,30 @@ export class BasicTaskProcessor run(env: ITestEnv, context: ITestContext): Promise; } +// @public (undocumented) +export class BasicRunnerFactory implements TRunnerFactory { + constructor(name: string, context: ITestContext); + // (undocumented) + protected context: ITestContext; + // (undocumented) + create(file: string, compilerOptions: TCompilerOptions, env: ITestEnv): ITestRunner; + // (undocumented) + protected createRunner(file: string, stats: TCompilerStatsCompilation, compilerOptions: TCompilerOptions, env: ITestEnv): ITestRunner; + // (undocumented) + protected getRunnerKey(file: string): string; + // (undocumented) + protected name: string; +} + +// @public (undocumented) +export class BuiltinProcessor extends SnapshotProcessor { + constructor(_builtinOptions: IBuiltinProcessorOptions); + // (undocumented) + protected _builtinOptions: IBuiltinProcessorOptions; + // (undocumented) + static defaultOptions(compilerType: T): (context: ITestContext) => TCompilerOptions; +} + // @public (undocumented) export function compareContent(sourceContent: string | false, distContent: string | false, compareOptions: ICompareOptions): TCompareResult; @@ -74,6 +83,19 @@ export function compareFile(sourceFile: string, distFile: string, compareOptions // @public (undocumented) export function compareModules(modules: string[], sourceModules: Map, distModules: Map, compareOptions: ICompareOptions): TModuleCompareResult[]; +// @public (undocumented) +export class ConfigProcessor extends MultiTaskProcessor { + constructor(_configOptions: IConfigProcessorOptions); + // (undocumented) + protected _configOptions: IConfigProcessorOptions; + // (undocumented) + static defaultOptions(index: number, context: ITestContext): TCompilerOptions; + // (undocumented) + static findBundle(index: number, context: ITestContext, options: TCompilerOptions): string | string[] | undefined; + // (undocumented) + static overrideOptions(index: number, context: ITestContext, options: TCompilerOptions): void; +} + // @public (undocumented) export function createBuiltinCase(name: string, src: string, dist: string): void; @@ -123,8 +145,8 @@ export function createTreeShakingCase(name: string, src: string, dist: string): export function createWatchCase(name: string, src: string, dist: string, temp: string): void; // @public (undocumented) -export class DefaultsConfigTaskProcessor extends SimpleTaskProcessor { - constructor(_defaultsConfigOptions: IDefaultsConfigProcessorOptions); +export class DefaultsConfigProcessor extends SimpleTaskProcessor { + constructor(_defaultsConfigOptions: IDefaultsConfigProcessorOptions); // (undocumented) static addSnapshotSerializer(expectImpl: jest.Expect): void; // (undocumented) @@ -142,11 +164,11 @@ export class DefaultsConfigTaskProcessor extends SimpleTaskProcessor; // (undocumented) - protected _defaultsConfigOptions: IDefaultsConfigProcessorOptions; + protected _defaultsConfigOptions: IDefaultsConfigProcessorOptions; // (undocumented) - protected getCompiler(context: ITestContext): ITestCompilerManager_2; + protected getCompiler(context: ITestContext): ITestCompilerManager_2; // (undocumented) - static getDefaultConfig(cwd: string, config: TCompilerOptions): TCompilerOptions; + static getDefaultConfig(cwd: string, config: TCompilerOptions): TCompilerOptions; // (undocumented) run(env: ITestEnv, context: ITestContext): Promise; } @@ -160,6 +182,17 @@ export function describeByWalk(testFile: string, createCase: (name: string, src: absoluteDist?: boolean; }): void; +// @public (undocumented) +export class DiagnosticProcessor extends BasicProcessor { + constructor(_diagnosticOptions: IDiagnosticProcessorOptions); + // (undocumented) + check(env: ITestEnv, context: ITestContext): Promise; + // (undocumented) + static defaultOptions(context: ITestContext): TCompilerOptions; + // (undocumented) + protected _diagnosticOptions: IDiagnosticProcessorOptions; +} + // @public (undocumented) class Diff { constructor(value: string); @@ -246,8 +279,8 @@ export enum EEsmMode { } // @public (undocumented) -export class ErrorTaskProcessor extends SimpleTaskProcessor { - constructor(_errorOptions: IErrorTaskProcessorOptions); +export class ErrorProcessor extends SimpleTaskProcessor { + constructor(_errorOptions: IErrorProcessorOptions); // (undocumented) static addSnapshotSerializer(expectImpl: jest.Expect): void; // (undocumented) @@ -255,7 +288,7 @@ export class ErrorTaskProcessor extends SimpleTaskProce // (undocumented) compiler(context: ITestContext): Promise; // (undocumented) - protected _errorOptions: IErrorTaskProcessorOptions; + protected _errorOptions: IErrorProcessorOptions; // (undocumented) run(env: ITestEnv, context: ITestContext): Promise; } @@ -275,6 +308,17 @@ export function getSimpleProcessorRunner(src: string, dist: string, options?: { context?: (src: string, dist: string) => ITestContext; }): (name: string, processor: ITestProcessor) => Promise; +// @public (undocumented) +export class HashProcessor extends MultiTaskProcessor { + constructor(_hashOptions: IHashProcessorOptions); + // (undocumented) + check(env: ITestEnv, context: ITestContext): Promise; + // (undocumented) + static defaultOptions(index: number, context: ITestContext): TCompilerOptions; + // (undocumented) + static overrideOptions(index: number, context: ITestContext, options: TCompilerOptions): void; +} + // @public (undocumented) export class HookCasesContext extends TestContext { constructor(src: string, testName: string, options: TTestContextOptions); @@ -302,8 +346,8 @@ export class HookCasesContext extends TestContext { } // @public (undocumented) -export class HookTaskProcessor extends SnapshotProcessor { - constructor(_hookOptions: IHookProcessorOptions); +export class HookTaskProcessor extends SnapshotProcessor { + constructor(_hookOptions: IHookProcessorOptions); // (undocumented) check(env: ITestEnv, context: HookCasesContext): Promise; // (undocumented) @@ -311,7 +355,28 @@ export class HookTaskProcessor extends SnapshotProcessor { // (undocumented) config(context: ITestContext): Promise; // (undocumented) - protected _hookOptions: IHookProcessorOptions; + static defaultOptions(context: ITestContext): TCompilerOptions; + // (undocumented) + protected _hookOptions: IHookProcessorOptions; +} + +// @public (undocumented) +export class HotProcessor extends BasicProcessor { + constructor(_hotOptions: IHotProcessorOptions); + // (undocumented) + static defaultOptions(hotOptions: IHotProcessorOptions, updateOptions: TUpdateOptions): IBasicProcessorOptions["defaultOptions"]; + // (undocumented) + static findBundle(hotOptions: IHotProcessorOptions): IBasicProcessorOptions["findBundle"]; + // (undocumented) + protected _hotOptions: IHotProcessorOptions; + // (undocumented) + static overrideOptions(hotOptions: IHotProcessorOptions, updateOptions: TUpdateOptions): IBasicProcessorOptions["overrideOptions"]; + // (undocumented) + run(env: ITestEnv, context: ITestContext): Promise; + // (undocumented) + protected runner: ITestRunner | null; + // (undocumented) + protected updateOptions: TUpdateOptions; } // @public (undocumented) @@ -320,6 +385,19 @@ export class HotRunnerFactory extends BasicRunnerFactor protected createRunner(file: string, stats: TCompilerStatsCompilation, compilerOptions: TCompilerOptions, env: ITestEnv): ITestRunner; } +// @public (undocumented) +export class HotSnapshotProcessor extends HotProcessor { + constructor(_hotOptions: IHotSnapshotProcessorOptions); + // (undocumented) + check(env: ITestEnv, context: ITestContext): Promise; + // (undocumented) + protected _hotOptions: IHotSnapshotProcessorOptions; + // (undocumented) + protected matchStepSnapshot(env: ITestEnv, context: ITestContext, step: number, stats: TCompilerStatsCompilation, runtime?: THotStepRuntimeData): void; + // (undocumented) + run(env: ITestEnv, context: ITestContext): Promise; +} + // @public (undocumented) export class HotStepRunnerFactory extends HotRunnerFactory { // (undocumented) @@ -351,7 +429,7 @@ export interface IBasicModuleScope extends ITestEnv { } // @public (undocumented) -export interface IBasicProcessorOptions { +export interface IBasicProcessorOptions { // (undocumented) compilerType: T; // (undocumented) @@ -368,6 +446,10 @@ export interface IBasicProcessorOptions extends Omit, "defaultOptions" | "runable"> { +} + // @public (undocumented) export interface ICompareOptions { // (undocumented) @@ -385,15 +467,27 @@ export interface ICompareOptions { } // @public (undocumented) -export interface IDefaultsConfigProcessorOptions { +export interface IConfigProcessorOptions extends Omit, "defaultOptions" | "overrideOptions" | "findBundle"> { +} + +// @public (undocumented) +export interface IDefaultsConfigProcessorOptions { + // (undocumented) + compilerType: T; // (undocumented) cwd?: string; // (undocumented) - diff: (diff: jest.JestMatchers, defaults: jest.JestMatchers>) => Promise; + diff: (diff: jest.JestMatchers, defaults: jest.JestMatchers>) => Promise; // (undocumented) name: string; // (undocumented) - options?: (context: ITestContext) => TCompilerOptions; + options?: (context: ITestContext) => TCompilerOptions; +} + +// @public (undocumented) +export interface IDiagnosticProcessorOptions extends Omit, "defaultOptions" | "runable"> { + // (undocumented) + snapshot: string; } // @public (undocumented) @@ -461,7 +555,7 @@ export interface IDiffStatsReporterOptions { } // @public (undocumented) -export interface IErrorTaskProcessorOptions { +export interface IErrorProcessorOptions { // (undocumented) build?: (context: ITestContext, compiler: TCompiler) => Promise; // (undocumented) @@ -497,107 +591,45 @@ export interface IFormatCodeOptions { } // @public (undocumented) -export interface IHookProcessorOptions extends ISnapshotProcessorOptions { - // (undocumented) - check?: (context: ITestContext) => Promise; - // (undocumented) - compiler?: (context: ITestContext, compiler: TCompiler) => Promise; - // (undocumented) - options?: (context: ITestContext) => TCompilerOptions; -} - -// @public (undocumented) -export interface IMultiTaskProcessorOptions { - // (undocumented) - compilerType: ECompilerType.Rspack; - // (undocumented) - configFiles?: string[]; - // (undocumented) - defaultOptions?: (index: number, context: ITestContext) => TCompilerOptions; - // (undocumented) - findBundle?: (index: number, context: ITestContext, options: TCompilerOptions) => string[] | string | void; - // (undocumented) - name: string; - // (undocumented) - overrideOptions?: (index: number, context: ITestContext, options: TCompilerOptions) => void; - // (undocumented) - runable: boolean; +export interface IHashProcessorOptions extends Omit, "defaultOptions" | "overrideOptions" | "runable"> { } // @public (undocumented) -export interface IRspackBuiltinProcessorOptions { - // (undocumented) - name: string; - // (undocumented) - snapshot: string; +export interface IHookProcessorOptions extends Omit, "defaultOptions"> { // (undocumented) - snapshotFileFilter?: ISnapshotProcessorOptions["snapshotFileFilter"]; -} - -// @public (undocumented) -export interface IRspackConfigProcessorOptions { + check?: (context: ITestContext) => Promise; // (undocumented) - name: string; + compiler?: (context: ITestContext, compiler: TCompiler) => Promise; // (undocumented) - runable: boolean; + options?: (context: ITestContext) => TCompilerOptions; } // @public (undocumented) -export interface IRspackDiagnosticProcessorOptions { +export interface IHotProcessorOptions extends Omit, "defaultOptions" | "overrideOptions" | "runable" | "findBundle"> { // (undocumented) - name: string; + target: TCompilerOptions["target"]; } // @public (undocumented) -export interface IRspackHashProcessorOptions { - // (undocumented) - name: string; +export interface IHotSnapshotProcessorOptions extends IHotProcessorOptions { } // @public (undocumented) -export interface IRspackHotProcessorOptions { +export interface IMultiTaskProcessorOptions { // (undocumented) - name: string; + compilerType: T; // (undocumented) - target: TCompilerOptions["target"]; -} - -// @public (undocumented) -export interface IRspackHotStepProcessorOptions extends IRspackHotProcessorOptions { -} - -// @public (undocumented) -export interface IRspackStatsProcessorOptions { + configFiles?: string[]; // (undocumented) - name: string; -} - -// @public (undocumented) -export interface IRspackWatchProcessorOptions { + defaultOptions?: (index: number, context: ITestContext) => TCompilerOptions; // (undocumented) - experiments?: TRspackExperiments; + findBundle?: (index: number, context: ITestContext, options: TCompilerOptions) => string[] | string | void; // (undocumented) name: string; // (undocumented) - optimization?: TRspackOptimization; - // (undocumented) - runable: boolean; - // (undocumented) - stepName: string; - // (undocumented) - tempDir: string; -} - -// @public (undocumented) -export interface IRspackWatchStepProcessorOptions { - // (undocumented) - name: string; + overrideOptions?: (index: number, context: ITestContext, options: TCompilerOptions) => void; // (undocumented) runable: boolean; - // (undocumented) - stepName: string; - // (undocumented) - tempDir: string; } // @public (undocumented) @@ -607,7 +639,7 @@ export const isDirectory: (p: string) => boolean; export const isFile: (p: string) => boolean; // @public (undocumented) -export interface ISimpleProcessorOptions { +export interface ISimpleProcessorOptions { // (undocumented) build?: (context: ITestContext, compiler: TCompiler) => Promise; // (undocumented) @@ -631,7 +663,7 @@ export interface ISnapshotProcessorOptions extends IBas } // @public (undocumented) -export interface IStatsAPITaskProcessorOptions { +export interface IStatsAPIProcessorOptions { // (undocumented) build?: (context: ITestContext, compiler: TCompiler) => Promise; // (undocumented) @@ -646,6 +678,10 @@ export interface IStatsAPITaskProcessorOptions { options?: (context: ITestContext) => TCompilerOptions; } +// @public (undocumented) +export interface IStatsProcessorOptions extends Omit, "defaultOptions" | "overrideOptions" | "runable"> { +} + // @public (undocumented) export const isValidCaseDirectory: (name: string) => boolean; @@ -805,6 +841,22 @@ export interface ITestRunner { run(file: string): Promise; } +// @public (undocumented) +export interface IWatchProcessorOptions extends Omit, "overrideOptinos" | "findBundle"> { + // (undocumented) + experiments?: TRspackExperiments; + // (undocumented) + optimization?: TRspackOptimization; + // (undocumented) + stepName: string; + // (undocumented) + tempDir: string; +} + +// @public (undocumented) +export interface IWatchStepProcessorOptions extends Omit, "experiments" | "optimization"> { +} + // @public (undocumented) export class MultipleRunnerFactory extends BasicRunnerFactory { // (undocumented) @@ -821,7 +873,7 @@ export class MultipleRunnerFactory extends BasicRunnerF } // @public (undocumented) -export class MultiTaskProcessor extends BasicTaskProcessor implements ITestProcessor { +export class MultiTaskProcessor extends BasicProcessor implements ITestProcessor { constructor(_multiOptions: IMultiTaskProcessorOptions); // (undocumented) config(context: ITestContext): Promise; @@ -854,37 +906,6 @@ export function replaceModuleArgument(raw: string): string; // @public (undocumented) export function replaceRuntimeModuleName(raw: string): string; -// @public (undocumented) -export class RspackBuiltinProcessor extends SnapshotProcessor { - constructor(_builtinOptions: IRspackBuiltinProcessorOptions); - // (undocumented) - protected _builtinOptions: IRspackBuiltinProcessorOptions; - // (undocumented) - static defaultOptions(context: ITestContext): TCompilerOptions; -} - -// @public (undocumented) -export class RspackConfigProcessor extends MultiTaskProcessor { - constructor(options: IRspackConfigProcessorOptions); - // (undocumented) - static defaultOptions(index: number, context: ITestContext): TCompilerOptions; - // (undocumented) - static findBundle(index: number, context: ITestContext, options: TCompilerOptions): string | string[] | undefined; - // (undocumented) - static overrideOptions(index: number, context: ITestContext, options: TCompilerOptions): void; -} - -// @public (undocumented) -export class RspackDiagnosticProcessor extends BasicTaskProcessor { - constructor(_diagnosticOptions: IRspackDiagnosticProcessorOptions); - // (undocumented) - check(env: ITestEnv, context: ITestContext): Promise; - // (undocumented) - static defaultOptions(context: ITestContext): TCompilerOptions; - // (undocumented) - protected _diagnosticOptions: IRspackDiagnosticProcessorOptions; -} - // @public (undocumented) export class RspackDiffConfigPlugin implements RspackPluginInstance { constructor(modifier?: ((options: RspackOptionsNormalized) => RspackOptionsNormalized) | undefined); @@ -895,99 +916,7 @@ export class RspackDiffConfigPlugin implements RspackPluginInstance { } // @public (undocumented) -export class RspackHashProcessor extends MultiTaskProcessor { - constructor(options: IRspackHashProcessorOptions); - // (undocumented) - check(env: ITestEnv, context: ITestContext): Promise; - // (undocumented) - static defaultOptions(index: number, context: ITestContext): TCompilerOptions; - // (undocumented) - static overrideOptions(index: number, context: ITestContext, options: TCompilerOptions): void; -} - -// @public (undocumented) -export class RspackHotProcessor extends BasicTaskProcessor { - constructor(_hotOptions: IRspackHotProcessorOptions); - // (undocumented) - static defaultOptions(hotOptions: IRspackHotProcessorOptions, updateOptions: TUpdateOptions): IBasicProcessorOptions["defaultOptions"]; - // (undocumented) - static findBundle(hotOptions: IRspackHotProcessorOptions): IBasicProcessorOptions["findBundle"]; - // (undocumented) - protected _hotOptions: IRspackHotProcessorOptions; - // (undocumented) - static overrideOptions(hotOptions: IRspackHotProcessorOptions, updateOptions: TUpdateOptions): IBasicProcessorOptions["overrideOptions"]; - // (undocumented) - run(env: ITestEnv, context: ITestContext): Promise; - // (undocumented) - protected runner: ITestRunner | null; - // (undocumented) - protected updateOptions: TUpdateOptions; -} - -// @public (undocumented) -export class RspackHotStepProcessor extends RspackHotProcessor { - constructor(_hotOptions: IRspackHotProcessorOptions); - // (undocumented) - check(env: ITestEnv, context: ITestContext): Promise; - // (undocumented) - protected _hotOptions: IRspackHotProcessorOptions; - // (undocumented) - protected matchStepSnapshot(env: ITestEnv, context: ITestContext, step: number, stats: StatsCompilation, runtime?: THotStepRuntimeData): void; - // (undocumented) - run(env: ITestEnv, context: ITestContext): Promise; -} - -// @public (undocumented) -export class RspackStatsProcessor extends MultiTaskProcessor { - constructor(options: IRspackStatsProcessorOptions); - // (undocumented) - after(context: ITestContext): Promise; - // (undocumented) - before(context: ITestContext): Promise; - // (undocumented) - check(env: ITestEnv, context: ITestContext): Promise; - // (undocumented) - compiler(context: ITestContext): Promise; - // (undocumented) - static defaultOptions(index: number, context: ITestContext): TCompilerOptions; - // (undocumented) - static overrideOptions(index: number, context: ITestContext, options: TCompilerOptions): void; -} - -// @public (undocumented) -export class RspackWatchProcessor extends MultiTaskProcessor { - constructor(_watchOptions: IRspackWatchProcessorOptions); - // (undocumented) - build(context: ITestContext): Promise; - // (undocumented) - check(env: ITestEnv, context: ITestContext): Promise; - // (undocumented) - compiler(context: ITestContext): Promise; - // (undocumented) - protected currentTriggerFilename: string | null; - // (undocumented) - protected lastHash: string | null; - // (undocumented) - static overrideOptions({ tempDir, name, experiments, optimization }: IRspackWatchProcessorOptions): (index: number, context: ITestContext, options: TCompilerOptions) => void; - // (undocumented) - run(env: ITestEnv, context: ITestContext): Promise; - // (undocumented) - protected _watchOptions: IRspackWatchProcessorOptions; -} - -// @public (undocumented) -export class RspackWatchStepProcessor extends RspackWatchProcessor { - constructor(_watchOptions: IRspackWatchStepProcessorOptions); - // (undocumented) - build(context: ITestContext): Promise; - // (undocumented) - compiler(context: ITestContext): Promise; - // (undocumented) - protected _watchOptions: IRspackWatchStepProcessorOptions; -} - -// @public (undocumented) -export class SimpleTaskProcessor implements ITestProcessor { +export class SimpleTaskProcessor implements ITestProcessor { constructor(_options: ISimpleProcessorOptions); // (undocumented) after(context: ITestContext): Promise; @@ -1014,7 +943,7 @@ export class SimpleTaskProcessor } // @public (undocumented) -export class SnapshotProcessor extends BasicTaskProcessor { +export class SnapshotProcessor extends BasicProcessor { constructor(_snapshotOptions: ISnapshotProcessorOptions); // (undocumented) check(env: ITestEnv, context: ITestContext): Promise; @@ -1023,8 +952,8 @@ export class SnapshotProcessor extends BasicTaskProcess } // @public (undocumented) -export class StatsAPITaskProcessor extends SimpleTaskProcessor { - constructor(_statsAPIOptions: IStatsAPITaskProcessorOptions); +export class StatsAPIProcessor extends SimpleTaskProcessor { + constructor(_statsAPIOptions: IStatsAPIProcessorOptions); // (undocumented) static addSnapshotSerializer(expectImpl: jest.Expect): void; // (undocumented) @@ -1034,7 +963,24 @@ export class StatsAPITaskProcessor extends SimpleTaskPr // (undocumented) run(env: ITestEnv, context: ITestContext): Promise; // (undocumented) - protected _statsAPIOptions: IStatsAPITaskProcessorOptions; + protected _statsAPIOptions: IStatsAPIProcessorOptions; +} + +// @public (undocumented) +export class StatsProcessor extends MultiTaskProcessor { + constructor(_statsOptions: IStatsProcessorOptions); + // (undocumented) + after(context: ITestContext): Promise; + // (undocumented) + before(context: ITestContext): Promise; + // (undocumented) + check(env: ITestEnv, context: ITestContext): Promise; + // (undocumented) + compiler(context: ITestContext): Promise; + // (undocumented) + static defaultOptions(index: number, context: ITestContext): TCompilerOptions; + // (undocumented) + static overrideOptions(index: number, context: ITestContext, options: TCompilerOptions): void; } // @public (undocumented) @@ -1070,7 +1016,7 @@ export type TCompareResult = { export type TCompiler = T extends ECompilerType.Rspack ? Compiler : Compiler_2; // @public (undocumented) -export type TCompilerCaseConfig = Omit & { +export type TCompilerCaseConfig = Omit, "name" | "compilerType"> & { description: string; }; @@ -1093,7 +1039,7 @@ export type TCompilerTypeId = ECompilerType.Rspack | ECompilerType.Webpack | "co export type TConfigCaseConfig = Omit, "validate">; // @public (undocumented) -export type TDefaultsCaseConfig = Omit & { +export type TDefaultsCaseConfig = Omit, "name" | "compilerType"> & { description: string; }; @@ -1118,7 +1064,7 @@ export type TDiffStatsItem = { export type TDimenTypeId = "modules" | "lines" | "lines-in-common"; // @public (undocumented) -export type TErrorCaseConfig = Omit, "name" | "compilerType"> & { +export type TErrorCaseConfig = Omit, "name" | "compilerType"> & { description: string; }; @@ -1234,10 +1180,10 @@ export type TModuleObject = { export type TModuleTypeId = "normal" | "runtime"; // @public (undocumented) -type TRspackExperiments = TCompilerOptions["experiments"]; +type TRspackExperiments = TCompilerOptions["experiments"]; // @public (undocumented) -type TRspackOptimization = TCompilerOptions["optimization"]; +type TRspackOptimization = TCompilerOptions["optimization"]; // @public (undocumented) export interface TRunnerFactory { @@ -1252,7 +1198,7 @@ export type TRunnerRequirer = (currentDirectory: string, modulePath: string[] | }) => Object | Promise; // @public (undocumented) -export type TStatsAPICaseConfig = Omit, "name" | "compilerType"> & { +export type TStatsAPICaseConfig = Omit, "name" | "compilerType"> & { description: string; }; @@ -1290,6 +1236,27 @@ export type TUpdateOptions = { updateIndex: number; }; +// @public (undocumented) +export class WatchProcessor extends MultiTaskProcessor { + constructor(_watchOptions: IWatchProcessorOptions); + // (undocumented) + build(context: ITestContext): Promise; + // (undocumented) + check(env: ITestEnv, context: ITestContext): Promise; + // (undocumented) + compiler(context: ITestContext): Promise; + // (undocumented) + protected currentTriggerFilename: string | null; + // (undocumented) + protected lastHash: string | null; + // (undocumented) + static overrideOptions({ tempDir, name, experiments, optimization }: IWatchProcessorOptions): (index: number, context: ITestContext, options: TCompilerOptions) => void; + // (undocumented) + run(env: ITestEnv, context: ITestContext): Promise; + // (undocumented) + protected _watchOptions: IWatchProcessorOptions; +} + // @public (undocumented) export class WatchRunnerFactory extends BasicRunnerFactory { // (undocumented) @@ -1298,6 +1265,17 @@ export class WatchRunnerFactory extends BasicRunnerFact protected getRunnerKey(file: string): string; } +// @public (undocumented) +export class WatchStepProcessor extends WatchProcessor { + constructor(_watchOptions: IWatchStepProcessorOptions); + // (undocumented) + build(context: ITestContext): Promise; + // (undocumented) + compiler(context: ITestContext): Promise; + // (undocumented) + protected _watchOptions: IWatchStepProcessorOptions; +} + // @public (undocumented) export class WebpackDiffConfigPlugin { constructor(modifier?: ((options: WebpackOptionsNormalized) => WebpackOptionsNormalized) | undefined); diff --git a/packages/rspack-test-tools/src/case/builtin.ts b/packages/rspack-test-tools/src/case/builtin.ts index bdf9cf2c0df..75e401a23d4 100644 --- a/packages/rspack-test-tools/src/case/builtin.ts +++ b/packages/rspack-test-tools/src/case/builtin.ts @@ -1,14 +1,12 @@ import path from "path"; -import { - IRspackBuiltinProcessorOptions, - RspackBuiltinProcessor -} from "../processor"; +import { BuiltinProcessor, IBuiltinProcessorOptions } from "../processor"; import { BasicCaseCreator } from "../test/creator"; +import { ECompilerType } from "../type"; const FILTERS: Record< string, - IRspackBuiltinProcessorOptions["snapshotFileFilter"] + IBuiltinProcessorOptions["snapshotFileFilter"] > = { "plugin-css": (file: string) => file.endsWith(".css"), "plugin-css-modules": (file: string) => @@ -27,10 +25,12 @@ const creator = new BasicCaseCreator({ const cat = path.basename(path.dirname(src)); const filter = FILTERS[cat]; return [ - new RspackBuiltinProcessor({ + new BuiltinProcessor({ name, snapshot: "output.snap.txt", - snapshotFileFilter: filter + snapshotFileFilter: filter, + compilerType: ECompilerType.Rspack, + configFiles: ["rspack.config.js", "webpack.config.js"] }) ]; } diff --git a/packages/rspack-test-tools/src/case/compiler.ts b/packages/rspack-test-tools/src/case/compiler.ts index 2a80419cd99..b9412b10471 100644 --- a/packages/rspack-test-tools/src/case/compiler.ts +++ b/packages/rspack-test-tools/src/case/compiler.ts @@ -3,7 +3,7 @@ import { getSimpleProcessorRunner } from "../test/simple"; import { ECompilerType } from "../type"; export type TCompilerCaseConfig = Omit< - ISimpleProcessorOptions, + ISimpleProcessorOptions, "name" | "compilerType" > & { description: string; diff --git a/packages/rspack-test-tools/src/case/config.ts b/packages/rspack-test-tools/src/case/config.ts index 45d308f90b8..d3e5f3dd787 100644 --- a/packages/rspack-test-tools/src/case/config.ts +++ b/packages/rspack-test-tools/src/case/config.ts @@ -1,7 +1,7 @@ -import { ECompilerType, TTestConfig } from ".."; -import { RspackConfigProcessor } from "../processor/config"; +import { ConfigProcessor } from "../processor/config"; import { MultipleRunnerFactory } from "../runner"; import { BasicCaseCreator } from "../test/creator"; +import { ECompilerType, TTestConfig } from "../type"; export type TConfigCaseConfig = Omit< TTestConfig, @@ -12,9 +12,11 @@ const creator = new BasicCaseCreator({ clean: true, describe: false, steps: ({ name }) => [ - new RspackConfigProcessor({ + new ConfigProcessor({ name, - runable: true + runable: true, + compilerType: ECompilerType.Rspack, + configFiles: ["rspack.config.js", "webpack.config.js"] }) ], runner: MultipleRunnerFactory diff --git a/packages/rspack-test-tools/src/case/defaults.ts b/packages/rspack-test-tools/src/case/defaults.ts index 32bbfc8d964..6b5dbc7518b 100644 --- a/packages/rspack-test-tools/src/case/defaults.ts +++ b/packages/rspack-test-tools/src/case/defaults.ts @@ -1,15 +1,15 @@ import path from "path"; import { - DefaultsConfigTaskProcessor, + DefaultsConfigProcessor, IDefaultsConfigProcessorOptions } from "../processor"; import { TestContext } from "../test/context"; -import { ITestEnv, ITestProcessor } from "../type"; +import { ECompilerType, ITestProcessor } from "../type"; export type TDefaultsCaseConfig = Omit< - IDefaultsConfigProcessorOptions, - "name" + IDefaultsConfigProcessorOptions, + "name" | "compilerType" > & { description: string; }; @@ -39,8 +39,9 @@ export function createDefaultsCase(name: string, src: string) { it(`should generate the correct defaults from ${caseConfig.description}`, async () => { await run( name, - new DefaultsConfigTaskProcessor({ + new DefaultsConfigProcessor({ name, + compilerType: ECompilerType.Rspack, ...caseConfig }) ); diff --git a/packages/rspack-test-tools/src/case/diagnostic.ts b/packages/rspack-test-tools/src/case/diagnostic.ts index 2b040e23973..cb681a49f13 100644 --- a/packages/rspack-test-tools/src/case/diagnostic.ts +++ b/packages/rspack-test-tools/src/case/diagnostic.ts @@ -1,12 +1,16 @@ -import { RspackDiagnosticProcessor } from "../processor"; +import { DiagnosticProcessor } from "../processor"; import { BasicCaseCreator } from "../test/creator"; +import { ECompilerType } from "../type"; const creator = new BasicCaseCreator({ clean: true, describe: false, steps: ({ name }) => [ - new RspackDiagnosticProcessor({ - name + new DiagnosticProcessor({ + name, + snapshot: "./stats.err", + configFiles: ["rspack.config.js", "webpack.config.js"], + compilerType: ECompilerType.Rspack }) ] }); diff --git a/packages/rspack-test-tools/src/case/error.ts b/packages/rspack-test-tools/src/case/error.ts index 2ba08493ed4..5bf1d6ed7e9 100644 --- a/packages/rspack-test-tools/src/case/error.ts +++ b/packages/rspack-test-tools/src/case/error.ts @@ -1,11 +1,11 @@ -import { ErrorTaskProcessor, IErrorTaskProcessorOptions } from "../processor"; +import { ErrorProcessor, IErrorProcessorOptions } from "../processor"; import { getSimpleProcessorRunner } from "../test/simple"; import { ECompilerType } from "../type"; let addedSerializer = false; export type TErrorCaseConfig = Omit< - IErrorTaskProcessorOptions, + IErrorProcessorOptions, "name" | "compilerType" > & { description: string; @@ -18,7 +18,7 @@ export function createErrorCase( testConfig: string ) { if (!addedSerializer) { - ErrorTaskProcessor.addSnapshotSerializer(expect); + ErrorProcessor.addSnapshotSerializer(expect); addedSerializer = true; } const caseConfig = require(testConfig); @@ -27,7 +27,7 @@ export function createErrorCase( it(caseConfig.description, async () => { await runner( name, - new ErrorTaskProcessor({ + new ErrorProcessor({ name: name, compilerType: ECompilerType.Rspack, ...caseConfig diff --git a/packages/rspack-test-tools/src/case/hash.ts b/packages/rspack-test-tools/src/case/hash.ts index 8d507b12a6c..0a9beceb153 100644 --- a/packages/rspack-test-tools/src/case/hash.ts +++ b/packages/rspack-test-tools/src/case/hash.ts @@ -1,4 +1,4 @@ -import { RspackHashProcessor } from "../processor"; +import { HashProcessor } from "../processor"; import { BasicCaseCreator } from "../test/creator"; import { ECompilerType, ITester, TTestConfig } from "../type"; @@ -26,8 +26,10 @@ const creator = new HashCaseCreator({ clean: true, describe: false, steps: ({ name }) => [ - new RspackHashProcessor({ - name + new HashProcessor({ + name, + compilerType: ECompilerType.Rspack, + configFiles: ["rspack.config.js", "webpack.config.js"] }) ] }); diff --git a/packages/rspack-test-tools/src/case/hot-step.ts b/packages/rspack-test-tools/src/case/hot-step.ts index 680cc6fdd4c..bdf187ddb3e 100644 --- a/packages/rspack-test-tools/src/case/hot-step.ts +++ b/packages/rspack-test-tools/src/case/hot-step.ts @@ -1,4 +1,4 @@ -import { RspackHotStepProcessor } from "../processor/hot-step"; +import { HotSnapshotProcessor } from "../processor/hot-step"; import { HotStepRunnerFactory } from "../runner"; import { BasicCaseCreator } from "../test/creator"; import { ECompilerType, TCompilerOptions } from "../type"; @@ -19,9 +19,11 @@ function getCreator(target: TTarget) { describe: false, target, steps: ({ name, target }) => [ - new RspackHotStepProcessor({ + new HotSnapshotProcessor({ name, - target: target as TTarget + target: target as TTarget, + compilerType: ECompilerType.Rspack, + configFiles: ["rspack.config.js", "webpack.config.js"] }) ], runner: HotStepRunnerFactory diff --git a/packages/rspack-test-tools/src/case/hot.ts b/packages/rspack-test-tools/src/case/hot.ts index 9466253c132..59704230db7 100644 --- a/packages/rspack-test-tools/src/case/hot.ts +++ b/packages/rspack-test-tools/src/case/hot.ts @@ -1,4 +1,4 @@ -import { RspackHotProcessor } from "../processor/hot"; +import { HotProcessor } from "../processor/hot"; import { HotRunnerFactory } from "../runner"; import { BasicCaseCreator } from "../test/creator"; import { ECompilerType, TCompilerOptions } from "../type"; @@ -19,9 +19,11 @@ function getCreator(target: TTarget) { describe: true, target, steps: ({ name, target }) => [ - new RspackHotProcessor({ + new HotProcessor({ name, - target: target as TTarget + target: target as TTarget, + compilerType: ECompilerType.Rspack, + configFiles: ["rspack.config.js", "webpack.config.js"] }) ], runner: HotRunnerFactory diff --git a/packages/rspack-test-tools/src/case/normal.ts b/packages/rspack-test-tools/src/case/normal.ts index 7f1155513ff..287641d1b38 100644 --- a/packages/rspack-test-tools/src/case/normal.ts +++ b/packages/rspack-test-tools/src/case/normal.ts @@ -1,18 +1,20 @@ import path from "path"; -import { RspackNormalProcessor } from "../processor/normal"; +import { NormalProcessor } from "../processor/normal"; import { NormalRunnerFactory } from "../runner"; import { BasicCaseCreator } from "../test/creator"; +import { ECompilerType } from "../type"; const creator = new BasicCaseCreator({ clean: true, describe: false, steps: ({ name }) => [ - new RspackNormalProcessor({ + new NormalProcessor({ name, root: path.resolve(__dirname, "../../tests/normalCases"), compilerOptions: {}, // do not used in rspack - runable: true + runable: true, + compilerType: ECompilerType.Rspack }) ], runner: NormalRunnerFactory diff --git a/packages/rspack-test-tools/src/case/stats-api.ts b/packages/rspack-test-tools/src/case/stats-api.ts index 81dc40a799d..10a4efe676a 100644 --- a/packages/rspack-test-tools/src/case/stats-api.ts +++ b/packages/rspack-test-tools/src/case/stats-api.ts @@ -1,14 +1,11 @@ -import { - IStatsAPITaskProcessorOptions, - StatsAPITaskProcessor -} from "../processor"; +import { IStatsAPIProcessorOptions, StatsAPIProcessor } from "../processor"; import { getSimpleProcessorRunner } from "../test/simple"; import { ECompilerType } from "../type"; let addedSerializer = false; export type TStatsAPICaseConfig = Omit< - IStatsAPITaskProcessorOptions, + IStatsAPIProcessorOptions, "name" | "compilerType" > & { description: string; @@ -21,7 +18,7 @@ export function createStatsAPICase( testConfig: string ) { if (!addedSerializer) { - StatsAPITaskProcessor.addSnapshotSerializer(expect); + StatsAPIProcessor.addSnapshotSerializer(expect); addedSerializer = true; } const caseConfig: TStatsAPICaseConfig = require(testConfig); @@ -30,7 +27,7 @@ export function createStatsAPICase( it(caseConfig.description, async () => { await runner( name, - new StatsAPITaskProcessor({ + new StatsAPIProcessor({ name: name, compilerType: ECompilerType.Rspack, ...caseConfig diff --git a/packages/rspack-test-tools/src/case/stats-output.ts b/packages/rspack-test-tools/src/case/stats-output.ts index a2971854b87..28ce83f7b66 100644 --- a/packages/rspack-test-tools/src/case/stats-output.ts +++ b/packages/rspack-test-tools/src/case/stats-output.ts @@ -1,12 +1,15 @@ -import { RspackStatsProcessor } from "../processor/stats"; +import { StatsProcessor } from "../processor/stats"; import { BasicCaseCreator } from "../test/creator"; +import { ECompilerType } from "../type"; const creator = new BasicCaseCreator({ clean: true, describe: false, steps: ({ name }) => [ - new RspackStatsProcessor({ - name + new StatsProcessor({ + name, + compilerType: ECompilerType.Rspack, + configFiles: ["rspack.config.js", "webpack.config.js"] }) ], description: name => `should print correct stats for ${name}` diff --git a/packages/rspack-test-tools/src/case/treeshaking.ts b/packages/rspack-test-tools/src/case/treeshaking.ts index 54f137ae3c2..b2f813ab517 100644 --- a/packages/rspack-test-tools/src/case/treeshaking.ts +++ b/packages/rspack-test-tools/src/case/treeshaking.ts @@ -1,5 +1,6 @@ -import { RspackTreeShakingProcessor } from "../processor/treeshaking"; +import { TreeShakingProcessor } from "../processor/treeshaking"; import { BasicCaseCreator } from "../test/creator"; +import { ECompilerType } from "../type"; const creator = new BasicCaseCreator({ clean: true, @@ -8,9 +9,10 @@ const creator = new BasicCaseCreator({ return `${name} with newTreeshaking should match snapshot`; }, steps: ({ name }) => [ - new RspackTreeShakingProcessor({ + new TreeShakingProcessor({ name, - snapshot: "treeshaking.snap.txt" + snapshot: "treeshaking.snap.txt", + compilerType: ECompilerType.Rspack }) ] }); diff --git a/packages/rspack-test-tools/src/case/watch.ts b/packages/rspack-test-tools/src/case/watch.ts index 6a8208e9761..5add70044bc 100644 --- a/packages/rspack-test-tools/src/case/watch.ts +++ b/packages/rspack-test-tools/src/case/watch.ts @@ -1,12 +1,10 @@ import fs from "fs"; import path from "path"; -import { - RspackWatchProcessor, - RspackWatchStepProcessor -} from "../processor/watch"; +import { WatchProcessor, WatchStepProcessor } from "../processor/watch"; import { WatchRunnerFactory } from "../runner"; import { BasicCaseCreator } from "../test/creator"; +import { ECompilerType } from "../type"; const creator = new BasicCaseCreator({ clean: true, @@ -28,17 +26,21 @@ const creator = new BasicCaseCreator({ return runs.map((run, index) => index === 0 - ? new RspackWatchProcessor({ + ? new WatchProcessor({ name, stepName: run.name, tempDir: temp!, - runable: true + runable: true, + compilerType: ECompilerType.Rspack, + configFiles: ["rspack.config.js", "webpack.config.js"] }) - : new RspackWatchStepProcessor({ + : new WatchStepProcessor({ name, stepName: run.name, tempDir: temp!, - runable: true + runable: true, + compilerType: ECompilerType.Rspack, + configFiles: ["rspack.config.js", "webpack.config.js"] }) ); } diff --git a/packages/rspack-test-tools/src/processor/basic.ts b/packages/rspack-test-tools/src/processor/basic.ts index bcf54976203..6cf64a2cf01 100644 --- a/packages/rspack-test-tools/src/processor/basic.ts +++ b/packages/rspack-test-tools/src/processor/basic.ts @@ -8,13 +8,10 @@ import { ITestContext, ITestEnv, ITestProcessor, - ITestRunner, TCompilerOptions } from "../type"; -export interface IBasicProcessorOptions< - T extends ECompilerType = ECompilerType.Rspack -> { +export interface IBasicProcessorOptions { defaultOptions?: (context: ITestContext) => TCompilerOptions; configFiles?: string[]; overrideOptions?: ( @@ -30,9 +27,7 @@ export interface IBasicProcessorOptions< name: string; } -export class BasicTaskProcessor - implements ITestProcessor -{ +export class BasicProcessor implements ITestProcessor { constructor(protected _options: IBasicProcessorOptions) {} async config(context: ITestContext) { diff --git a/packages/rspack-test-tools/src/processor/builtin.ts b/packages/rspack-test-tools/src/processor/builtin.ts index 0dd6bfa09db..df5d59faacc 100644 --- a/packages/rspack-test-tools/src/processor/builtin.ts +++ b/packages/rspack-test-tools/src/processor/builtin.ts @@ -5,168 +5,181 @@ import { merge } from "webpack-merge"; import { ECompilerType, ITestContext, TCompilerOptions } from "../type"; import { ISnapshotProcessorOptions, SnapshotProcessor } from "./snapshot"; -export interface IRspackBuiltinProcessorOptions { - name: string; - snapshot: string; - snapshotFileFilter?: ISnapshotProcessorOptions["snapshotFileFilter"]; -} +export interface IBuiltinProcessorOptions + extends Omit, "defaultOptions" | "runable"> {} -export class RspackBuiltinProcessor extends SnapshotProcessor { - constructor(protected _builtinOptions: IRspackBuiltinProcessorOptions) { +export class BuiltinProcessor< + T extends ECompilerType +> extends SnapshotProcessor { + constructor(protected _builtinOptions: IBuiltinProcessorOptions) { super({ - configFiles: ["rspack.config.js", "webpack.config.js"], - snapshotFileFilter: _builtinOptions.snapshotFileFilter, - snapshot: _builtinOptions.snapshot, - compilerType: ECompilerType.Rspack, - defaultOptions: RspackBuiltinProcessor.defaultOptions, - name: _builtinOptions.name, - runable: false + defaultOptions: BuiltinProcessor.defaultOptions( + _builtinOptions.compilerType + ), + runable: false, + ..._builtinOptions }); } - static defaultOptions( - context: ITestContext - ): TCompilerOptions { - let defaultOptions: TCompilerOptions = { - entry: { - main: { - import: "./index" - } - }, - output: { - publicPath: "/", - path: context.getDist(), - filename: "[name].js", - chunkFilename: "[name].js", - chunkFormat: "array-push", - cssFilename: "[name].css", - cssChunkFilename: "[name].css", - assetModuleFilename: "[hash][ext][query]", - sourceMapFilename: "[file].map", - chunkLoadingGlobal: "webpackChunkwebpack", - chunkLoading: "jsonp", - uniqueName: "__rspack_test__", - enabledLibraryTypes: ["system"], - strictModuleErrorHandling: false, - iife: true, - module: false, - asyncChunks: true, - scriptType: false, - globalObject: "self", - importFunctionName: "import", - wasmLoading: "fetch", - webassemblyModuleFilename: "[hash].module.wasm", - workerChunkLoading: "import-scripts", - workerWasmLoading: "fetch" - }, - module: { - rules: [ - { - test: /\.json$/, - type: "json" - }, - { - test: /\.mjs$/, - type: "js/esm" - }, - { - test: /\.cjs$/, - type: "js/dynamic" - }, - { - test: /\.js$/, - type: "js/auto" - }, - { - test: /\.css$/, - type: "css" - }, - { - test: /\.wasm$/, - type: "webassembly/async" + static defaultOptions( + compilerType: T + ): (context: ITestContext) => TCompilerOptions { + return (context: ITestContext) => { + let defaultOptions = { + entry: { + main: { + import: "./index" } - ] - }, - node: { - __dirname: "mock", - __filename: "mock", - global: "warn" - }, - optimization: { - runtimeChunk: { - name: "runtime" }, - minimize: false, - removeAvailableModules: true, - removeEmptyChunks: true, - moduleIds: "named", - chunkIds: "named", - sideEffects: false, - mangleExports: false, - usedExports: false, - concatenateModules: false, - nodeEnv: false - }, - resolve: { - extensions: [ - ".js", - ".jsx", - ".ts", - ".tsx", - ".json", - ".d.ts", - ".css", - ".wasm" - ] - }, - resolveLoader: { - extensions: [".js"] - }, - experiments: { - futureDefaults: true - }, - devtool: false, - context: context.getSource(), - plugins: [], - builtins: { - treeShaking: false - } - }; + output: { + publicPath: "/", + path: context.getDist(), + filename: "[name].js", + chunkFilename: "[name].js", + chunkFormat: "array-push", + cssFilename: "[name].css", + cssChunkFilename: "[name].css", + assetModuleFilename: "[hash][ext][query]", + sourceMapFilename: "[file].map", + chunkLoadingGlobal: "webpackChunkwebpack", + chunkLoading: "jsonp", + uniqueName: "__rspack_test__", + enabledLibraryTypes: ["system"], + strictModuleErrorHandling: false, + iife: true, + module: false, + asyncChunks: true, + scriptType: false, + globalObject: "self", + importFunctionName: "import", + wasmLoading: "fetch", + webassemblyModuleFilename: "[hash].module.wasm", + workerChunkLoading: "import-scripts", + workerWasmLoading: "fetch" + }, + module: { + rules: [ + { + test: /\.json$/, + type: "json" + }, + { + test: /\.mjs$/, + type: "js/esm" + }, + { + test: /\.cjs$/, + type: "js/dynamic" + }, + { + test: /\.js$/, + type: "js/auto" + }, + { + test: /\.css$/, + type: "css" + }, + { + test: /\.wasm$/, + type: "webassembly/async" + } + ] + }, + node: { + __dirname: "mock", + __filename: "mock", + global: "warn" + }, + optimization: { + runtimeChunk: { + name: "runtime" + }, + minimize: false, + removeAvailableModules: true, + removeEmptyChunks: true, + moduleIds: "named", + chunkIds: "named", + sideEffects: false, + mangleExports: false, + usedExports: false, + concatenateModules: false, + nodeEnv: false + }, + resolve: { + extensions: [ + ".js", + ".jsx", + ".ts", + ".tsx", + ".json", + ".d.ts", + ".css", + ".wasm" + ] + }, + resolveLoader: { + extensions: [".js"] + }, + experiments: { + futureDefaults: true + }, + devtool: false, + context: context.getSource(), + plugins: [], + builtins: { + treeShaking: false + } + } as TCompilerOptions; - const testConfigFile = context.getSource("rspack.config.js"); - if (fs.existsSync(testConfigFile)) { - let caseOptions = require(testConfigFile); - if (caseOptions.entry) { - delete defaultOptions.entry; - } - defaultOptions = merge(defaultOptions, caseOptions); - } + if (compilerType === ECompilerType.Rspack) { + let rspackDefaultOptions = + defaultOptions as TCompilerOptions; + const testConfigFile = context.getSource("rspack.config.js"); + if (fs.existsSync(testConfigFile)) { + let caseOptions = require(testConfigFile); + if (caseOptions.entry) { + delete rspackDefaultOptions.entry; + } + rspackDefaultOptions = merge(rspackDefaultOptions, caseOptions); + } - // TODO: remove builtin compatible code - const defineOptions = (defaultOptions.builtins as any)?.define; - if (defineOptions) { - defaultOptions.plugins!.push(new rspack.DefinePlugin(defineOptions)); - delete (defaultOptions.builtins as any)?.define; - } + // TODO: remove builtin compatible code + const defineOptions = (rspackDefaultOptions.builtins as any)?.define; + if (defineOptions) { + rspackDefaultOptions.plugins!.push( + new rspack.DefinePlugin(defineOptions) + ); + delete (rspackDefaultOptions.builtins as any)?.define; + } - const provideOptions = (defaultOptions.builtins as any)?.provide; - if (provideOptions) { - defaultOptions.plugins!.push(new rspack.ProvidePlugin(provideOptions)); - delete (defaultOptions.builtins as any)?.provide; - } + const provideOptions = (rspackDefaultOptions.builtins as any)?.provide; + if (provideOptions) { + rspackDefaultOptions.plugins!.push( + new rspack.ProvidePlugin(provideOptions) + ); + delete (rspackDefaultOptions.builtins as any)?.provide; + } - const htmlOptions = (defaultOptions.builtins as any)?.html; - if (htmlOptions) { - if (Array.isArray(htmlOptions)) { - for (let item of htmlOptions) { - defaultOptions.plugins!.push(new rspack.HtmlRspackPlugin(item)); + const htmlOptions = (rspackDefaultOptions.builtins as any)?.html; + if (htmlOptions) { + if (Array.isArray(htmlOptions)) { + for (let item of htmlOptions) { + rspackDefaultOptions.plugins!.push( + new rspack.HtmlRspackPlugin(item) + ); + } + } else { + rspackDefaultOptions.plugins!.push( + new rspack.HtmlRspackPlugin(htmlOptions) + ); + } + delete (rspackDefaultOptions.builtins as any)?.html; } - } else { - defaultOptions.plugins!.push(new rspack.HtmlRspackPlugin(htmlOptions)); + + defaultOptions = rspackDefaultOptions as TCompilerOptions; } - delete (defaultOptions.builtins as any)?.html; - } - return defaultOptions; + return defaultOptions; + }; } } diff --git a/packages/rspack-test-tools/src/processor/config.ts b/packages/rspack-test-tools/src/processor/config.ts index 1c998b698a9..65246a6cc00 100644 --- a/packages/rspack-test-tools/src/processor/config.ts +++ b/packages/rspack-test-tools/src/processor/config.ts @@ -2,36 +2,31 @@ import fs from "fs"; import path from "path"; import { parseResource } from "../helper/legacy/parseResource"; -import { - ECompilerType, - ITestContext, - TCompilerOptions, - TTestConfig -} from "../type"; -import { MultiTaskProcessor } from "./multi"; +import { ECompilerType, ITestContext, TCompilerOptions } from "../type"; +import { IMultiTaskProcessorOptions, MultiTaskProcessor } from "./multi"; -export interface IRspackConfigProcessorOptions { - name: string; - runable: boolean; -} +export interface IConfigProcessorOptions + extends Omit< + IMultiTaskProcessorOptions, + "defaultOptions" | "overrideOptions" | "findBundle" + > {} -export class RspackConfigProcessor extends MultiTaskProcessor { - constructor(options: IRspackConfigProcessorOptions) { +export class ConfigProcessor< + T extends ECompilerType +> extends MultiTaskProcessor { + constructor(protected _configOptions: IConfigProcessorOptions) { super({ - defaultOptions: RspackConfigProcessor.defaultOptions, - configFiles: ["rspack.config.js", "webpack.config.js"], - overrideOptions: RspackConfigProcessor.overrideOptions, - findBundle: RspackConfigProcessor.findBundle, - compilerType: ECompilerType.Rspack, - name: options.name, - runable: options.runable + defaultOptions: ConfigProcessor.defaultOptions, + overrideOptions: ConfigProcessor.overrideOptions, + findBundle: ConfigProcessor.findBundle, + ..._configOptions }); } - static findBundle( + static findBundle( index: number, context: ITestContext, - options: TCompilerOptions + options: TCompilerOptions ) { const testConfig = context.getTestConfig(); @@ -48,10 +43,10 @@ export class RspackConfigProcessor extends MultiTaskProcessor( index: number, context: ITestContext - ): TCompilerOptions { + ): TCompilerOptions { return { context: context.getSource(), mode: "production", @@ -69,12 +64,12 @@ export class RspackConfigProcessor extends MultiTaskProcessor; } - static overrideOptions( + static overrideOptions( index: number, context: ITestContext, - options: TCompilerOptions + options: TCompilerOptions ): void { if (!options.entry) { options.entry = "./index.js"; diff --git a/packages/rspack-test-tools/src/processor/defaults.ts b/packages/rspack-test-tools/src/processor/defaults.ts index 3c83d580f88..24619058400 100644 --- a/packages/rspack-test-tools/src/processor/defaults.ts +++ b/packages/rspack-test-tools/src/processor/defaults.ts @@ -39,21 +39,24 @@ class Diff { constructor(public value: string) {} } -export interface IDefaultsConfigProcessorOptions { - options?: (context: ITestContext) => TCompilerOptions; +export interface IDefaultsConfigProcessorOptions { + options?: (context: ITestContext) => TCompilerOptions; cwd?: string; name: string; diff: ( diff: jest.JestMatchers, - defaults: jest.JestMatchers> + defaults: jest.JestMatchers> ) => Promise; + compilerType: T; } -export class DefaultsConfigTaskProcessor extends SimpleTaskProcessor { - private defaultConfig: TCompilerOptions; +export class DefaultsConfigProcessor< + T extends ECompilerType +> extends SimpleTaskProcessor { + private defaultConfig: TCompilerOptions; constructor( - protected _defaultsConfigOptions: IDefaultsConfigProcessorOptions + protected _defaultsConfigOptions: IDefaultsConfigProcessorOptions ) { super({ options: context => { @@ -68,15 +71,12 @@ export class DefaultsConfigTaskProcessor extends SimpleTaskProcessor; } async compiler(context: ITestContext) {} @@ -85,7 +85,7 @@ export class DefaultsConfigTaskProcessor extends SimpleTaskProcessor - ): TCompilerOptions { + config: TCompilerOptions + ): TCompilerOptions { process.chdir(cwd); const { applyWebpackOptionsDefaults, getNormalizedWebpackOptions } = require("@rspack/core").config; diff --git a/packages/rspack-test-tools/src/processor/diagnostic.ts b/packages/rspack-test-tools/src/processor/diagnostic.ts index 2e8e3d7da22..25934e6eb18 100644 --- a/packages/rspack-test-tools/src/processor/diagnostic.ts +++ b/packages/rspack-test-tools/src/processor/diagnostic.ts @@ -9,7 +9,7 @@ import { ITestEnv, TCompilerOptions } from "../type"; -import { BasicTaskProcessor } from "./basic"; +import { BasicProcessor, IBasicProcessorOptions } from "./basic"; const serializer = require("jest-serializer-path"); const normalizePaths = serializer.normalizePaths; const rspackPath = path.resolve(__dirname, "../../../rspack"); @@ -23,18 +23,19 @@ declare var global: { updateSnapshot: boolean; }; -export interface IRspackDiagnosticProcessorOptions { - name: string; +export interface IDiagnosticProcessorOptions + extends Omit, "defaultOptions" | "runable"> { + snapshot: string; } -export class RspackDiagnosticProcessor extends BasicTaskProcessor { - constructor(protected _diagnosticOptions: IRspackDiagnosticProcessorOptions) { +export class DiagnosticProcessor< + T extends ECompilerType +> extends BasicProcessor { + constructor(protected _diagnosticOptions: IDiagnosticProcessorOptions) { super({ - defaultOptions: RspackDiagnosticProcessor.defaultOptions, - configFiles: ["rspack.config.js", "webpack.config.js"], - compilerType: ECompilerType.Rspack, - name: _diagnosticOptions.name, - runable: false + defaultOptions: DiagnosticProcessor.defaultOptions, + runable: false, + ..._diagnosticOptions }); } @@ -60,18 +61,20 @@ export class RspackDiagnosticProcessor extends BasicTaskProcessor s.trim()) .join(""); - const errorOutputPath = path.resolve(context.getSource(), `./stats.err`); + const errorOutputPath = path.resolve( + context.getSource(this._diagnosticOptions.snapshot) + ); if (!fs.existsSync(errorOutputPath) || global.updateSnapshot) { fs.writeFileSync(errorOutputPath, escapeEOL(output)); } else { const expectContent = fs.readFileSync(errorOutputPath, "utf-8"); - env.expect(escapeEOL(output)).toBe(escapeEOL(expectContent)); + expect(escapeEOL(output)).toBe(escapeEOL(expectContent)); } } - static defaultOptions( + static defaultOptions( context: ITestContext - ): TCompilerOptions { + ): TCompilerOptions { return { target: "node", context: context.getSource(), diff --git a/packages/rspack-test-tools/src/processor/diff.ts b/packages/rspack-test-tools/src/processor/diff.ts index 44ef1b905bc..e41a524ab83 100644 --- a/packages/rspack-test-tools/src/processor/diff.ts +++ b/packages/rspack-test-tools/src/processor/diff.ts @@ -17,7 +17,7 @@ import { TFileCompareResult, TModuleCompareResult } from "../type"; -import { BasicTaskProcessor } from "./basic"; +import { BasicProcessor } from "./basic"; export interface IDiffProcessorOptions extends IFormatCodeOptions { webpackPath: string; @@ -36,10 +36,10 @@ export interface IDiffProcessorOptions extends IFormatCodeOptions { } export class DiffProcessor implements ITestProcessor { private hashes: string[] = []; - private webpack: BasicTaskProcessor; - private rspack: BasicTaskProcessor; + private webpack: BasicProcessor; + private rspack: BasicProcessor; constructor(private options: IDiffProcessorOptions) { - this.webpack = new BasicTaskProcessor({ + this.webpack = new BasicProcessor({ defaultOptions: context => this.getDefaultOptions( ECompilerType.Webpack, @@ -52,7 +52,7 @@ export class DiffProcessor implements ITestProcessor { runable: false }); - this.rspack = new BasicTaskProcessor({ + this.rspack = new BasicProcessor({ defaultOptions: context => this.getDefaultOptions( ECompilerType.Rspack, diff --git a/packages/rspack-test-tools/src/processor/error.ts b/packages/rspack-test-tools/src/processor/error.ts index bd34422cfd8..edcc955d3b2 100644 --- a/packages/rspack-test-tools/src/processor/error.ts +++ b/packages/rspack-test-tools/src/processor/error.ts @@ -65,7 +65,7 @@ const prettyFormatOptions = { ] }; -export interface IErrorTaskProcessorOptions { +export interface IErrorProcessorOptions { name: string; compilerType: T; options?: ( @@ -76,10 +76,10 @@ export interface IErrorTaskProcessorOptions { check?: (stats: TStatsDiagnostics) => Promise; } -export class ErrorTaskProcessor< +export class ErrorProcessor< T extends ECompilerType > extends SimpleTaskProcessor { - constructor(protected _errorOptions: IErrorTaskProcessorOptions) { + constructor(protected _errorOptions: IErrorProcessorOptions) { super({ options: (context: ITestContext): TCompilerOptions => { let options = { diff --git a/packages/rspack-test-tools/src/processor/hash.ts b/packages/rspack-test-tools/src/processor/hash.ts index ff206d1bc04..afad25df4d2 100644 --- a/packages/rspack-test-tools/src/processor/hash.ts +++ b/packages/rspack-test-tools/src/processor/hash.ts @@ -2,27 +2,27 @@ import { ECompilerType, ITestContext, ITestEnv, - TCompilerOptions, - TCompilerStats, - TTestConfig + TCompilerOptions } from "../type"; -import { MultiTaskProcessor } from "./multi"; +import { IMultiTaskProcessorOptions, MultiTaskProcessor } from "./multi"; -export interface IRspackHashProcessorOptions { - name: string; -} +export interface IHashProcessorOptions + extends Omit< + IMultiTaskProcessorOptions, + "defaultOptions" | "overrideOptions" | "runable" + > {} const REG_ERROR_CASE = /error$/; -export class RspackHashProcessor extends MultiTaskProcessor { - constructor(options: IRspackHashProcessorOptions) { +export class HashProcessor< + T extends ECompilerType +> extends MultiTaskProcessor { + constructor(_hashOptions: IHashProcessorOptions) { super({ - defaultOptions: RspackHashProcessor.defaultOptions, - overrideOptions: RspackHashProcessor.overrideOptions, - compilerType: ECompilerType.Rspack, - configFiles: ["rspack.config.js", "webpack.config.js"], - name: options.name, - runable: false + defaultOptions: HashProcessor.defaultOptions, + overrideOptions: HashProcessor.overrideOptions, + runable: false, + ..._hashOptions }); } @@ -50,10 +50,10 @@ export class RspackHashProcessor extends MultiTaskProcessor( index: number, context: ITestContext - ): TCompilerOptions { + ): TCompilerOptions { return { context: context.getSource(), output: { @@ -61,10 +61,10 @@ export class RspackHashProcessor extends MultiTaskProcessor( index: number, context: ITestContext, - options: TCompilerOptions + options: TCompilerOptions ): void { if (!options.entry) { options.entry = "./index.js"; diff --git a/packages/rspack-test-tools/src/processor/hook.ts b/packages/rspack-test-tools/src/processor/hook.ts index d6bce35dadb..89bc63faf2d 100644 --- a/packages/rspack-test-tools/src/processor/hook.ts +++ b/packages/rspack-test-tools/src/processor/hook.ts @@ -176,38 +176,18 @@ export class HookCasesContext extends TestContext { } export interface IHookProcessorOptions - extends ISnapshotProcessorOptions { + extends Omit, "defaultOptions"> { options?: (context: ITestContext) => TCompilerOptions; compiler?: (context: ITestContext, compiler: TCompiler) => Promise; check?: (context: ITestContext) => Promise; } -export class HookTaskProcessor extends SnapshotProcessor { - constructor( - protected _hookOptions: IHookProcessorOptions - ) { +export class HookTaskProcessor< + T extends ECompilerType +> extends SnapshotProcessor { + constructor(protected _hookOptions: IHookProcessorOptions) { super({ - defaultOptions: context => { - return { - context: context.getSource(), - mode: "production", - target: "async-node", - devtool: false, - cache: false, - entry: "./hook", - output: { - path: context.getDist() - }, - optimization: { - minimize: false - }, - experiments: { - rspackFuture: { - newTreeshaking: true - } - } - }; - }, + defaultOptions: HookTaskProcessor.defaultOptions, ..._hookOptions }); } @@ -235,4 +215,28 @@ export class HookTaskProcessor extends SnapshotProcessor { await this._hookOptions.check(context); } } + + static defaultOptions( + context: ITestContext + ): TCompilerOptions { + return { + context: context.getSource(), + mode: "production", + target: "async-node", + devtool: false, + cache: false, + entry: "./hook", + output: { + path: context.getDist() + }, + optimization: { + minimize: false + }, + experiments: { + rspackFuture: { + newTreeshaking: true + } + } + } as TCompilerOptions; + } } diff --git a/packages/rspack-test-tools/src/processor/hot-step.ts b/packages/rspack-test-tools/src/processor/hot-step.ts index 7d76f814737..375ae656e45 100644 --- a/packages/rspack-test-tools/src/processor/hot-step.ts +++ b/packages/rspack-test-tools/src/processor/hot-step.ts @@ -1,4 +1,4 @@ -import { StatsCompilation } from "@rspack/core"; +import { Chunk, StatsCompilation } from "@rspack/core"; import fs from "fs-extra"; import path from "path"; @@ -9,13 +9,10 @@ import { ITestContext, ITestEnv, TCompilerOptions, - TCompilerStats + TCompilerStats, + TCompilerStatsCompilation } from "../type"; -import { - IRspackHotProcessorOptions, - RspackHotProcessor, - TUpdateOptions -} from "./hot"; +import { HotProcessor, IHotProcessorOptions, TUpdateOptions } from "./hot"; const escapeLocalName = (str: string) => str.split(/[-<>:"/|?*.]/).join("_"); @@ -28,7 +25,7 @@ declare var global: { const SELF_HANDLER = ( file: string, - options: TCompilerOptions + options: TCompilerOptions ): string[] => { let res: string[] = []; const hotUpdateGlobal = (_: string, modules: Record) => { @@ -59,14 +56,16 @@ const GET_MODULE_HANDLER = { type TSupportTarget = keyof typeof GET_MODULE_HANDLER; -export interface IRspackHotStepProcessorOptions - extends IRspackHotProcessorOptions {} +export interface IHotSnapshotProcessorOptions + extends IHotProcessorOptions {} -export class RspackHotStepProcessor extends RspackHotProcessor { +export class HotSnapshotProcessor< + T extends ECompilerType +> extends HotProcessor { private hashes: string[] = []; private entries: Record = {}; - constructor(protected _hotOptions: IRspackHotProcessorOptions) { + constructor(protected _hotOptions: IHotSnapshotProcessorOptions) { super(_hotOptions); } @@ -76,12 +75,15 @@ export class RspackHotStepProcessor extends RspackHotProcessor { "hotUpdateStepChecker", ( hotUpdateContext: TUpdateOptions, - stats: TCompilerStats, + stats: TCompilerStats, runtime: THotStepRuntimeData ) => { - const statsJson = stats.toJson({ assets: true, chunks: true }); - for (let entry of (stats?.compilation.chunks || []).filter(i => - i.hasRuntime() + const statsJson: TCompilerStatsCompilation = stats.toJson({ + assets: true, + chunks: true + }); + for (let entry of ((stats?.compilation.chunks as Chunk[]) || []).filter( + i => i.hasRuntime() )) { if (!this.entries[entry.id!]) { this.entries[entry.id!] = entry.runtime!; @@ -102,7 +104,7 @@ export class RspackHotStepProcessor extends RspackHotProcessor { "hotUpdateStepErrorChecker", ( _: TUpdateOptions, - stats: TCompilerStats, + stats: TCompilerStats, runtime: THotStepRuntimeData ) => { this.hashes.push(stats.hash!); @@ -119,7 +121,7 @@ export class RspackHotStepProcessor extends RspackHotProcessor { return; } const statsJson = stats.toJson({ assets: true, chunks: true }); - for (let entry of (stats?.compilation.chunks || []).filter(i => + for (let entry of ((stats?.compilation.chunks as Chunk[]) || []).filter(i => i.hasRuntime() )) { this.entries[entry.id!] = entry.runtime!; @@ -140,7 +142,7 @@ export class RspackHotStepProcessor extends RspackHotProcessor { env: ITestEnv, context: ITestContext, step: number, - stats: StatsCompilation, + stats: TCompilerStatsCompilation, runtime?: THotStepRuntimeData ) { const compiler = this.getCompiler(context); diff --git a/packages/rspack-test-tools/src/processor/hot.ts b/packages/rspack-test-tools/src/processor/hot.ts index b8fce316fcc..515dc45c334 100644 --- a/packages/rspack-test-tools/src/processor/hot.ts +++ b/packages/rspack-test-tools/src/processor/hot.ts @@ -8,39 +8,40 @@ import { ITestRunner, TCompilerOptions } from "../type"; -import { BasicTaskProcessor, IBasicProcessorOptions } from "./basic"; +import { BasicProcessor, IBasicProcessorOptions } from "./basic"; -export interface IRspackHotProcessorOptions { - name: string; - target: TCompilerOptions["target"]; +export interface IHotProcessorOptions + extends Omit< + IBasicProcessorOptions, + "defaultOptions" | "overrideOptions" | "runable" | "findBundle" + > { + target: TCompilerOptions["target"]; } export type TUpdateOptions = { updateIndex: number; }; -export class RspackHotProcessor extends BasicTaskProcessor { +export class HotProcessor extends BasicProcessor { protected updateOptions: TUpdateOptions; protected runner: ITestRunner | null = null; - constructor(protected _hotOptions: IRspackHotProcessorOptions) { + constructor(protected _hotOptions: IHotProcessorOptions) { const fakeUpdateLoaderOptions: TUpdateOptions = { updateIndex: 0 }; super({ - defaultOptions: RspackHotProcessor.defaultOptions( + defaultOptions: HotProcessor.defaultOptions( _hotOptions, fakeUpdateLoaderOptions ), - overrideOptions: RspackHotProcessor.overrideOptions( + overrideOptions: HotProcessor.overrideOptions( _hotOptions, fakeUpdateLoaderOptions ), - compilerType: ECompilerType.Rspack, - findBundle: RspackHotProcessor.findBundle(_hotOptions), - configFiles: ["rspack.config.js", "webpack.config.js"], - name: _hotOptions.name, - runable: true + findBundle: HotProcessor.findBundle(_hotOptions), + runable: true, + ..._hotOptions }); this.updateOptions = fakeUpdateLoaderOptions; } @@ -54,9 +55,9 @@ export class RspackHotProcessor extends BasicTaskProcessor await super.run(env, context); } - static findBundle( - hotOptions: IRspackHotProcessorOptions - ): IBasicProcessorOptions["findBundle"] { + static findBundle( + hotOptions: IHotProcessorOptions + ): IBasicProcessorOptions["findBundle"] { return context => { let files: string[] = []; let prefiles: string[] = []; @@ -83,37 +84,43 @@ export class RspackHotProcessor extends BasicTaskProcessor }; } - static defaultOptions( - hotOptions: IRspackHotProcessorOptions, + static defaultOptions( + hotOptions: IHotProcessorOptions, updateOptions: TUpdateOptions - ): IBasicProcessorOptions["defaultOptions"] { - return (context: ITestContext) => ({ - context: context.getSource(), - mode: "development", - devtool: false, - output: { - path: context.getDist(), - filename: "bundle.js", - chunkFilename: "[name].chunk.[fullhash].js", - publicPath: "https://test.cases/path/", - library: { type: "commonjs2" } - }, - optimization: { - moduleIds: "named" - }, - target: hotOptions.target, - plugins: [new rspack.HotModuleReplacementPlugin()] - }); + ): IBasicProcessorOptions["defaultOptions"] { + return (context: ITestContext) => { + const options = { + context: context.getSource(), + mode: "development", + devtool: false, + output: { + path: context.getDist(), + filename: "bundle.js", + chunkFilename: "[name].chunk.[fullhash].js", + publicPath: "https://test.cases/path/", + library: { type: "commonjs2" } + }, + optimization: { + moduleIds: "named" + }, + target: hotOptions.target + } as TCompilerOptions; + + if (hotOptions.compilerType === ECompilerType.Rspack) { + options.plugins ??= []; + (options as TCompilerOptions).plugins!.push( + new rspack.HotModuleReplacementPlugin() + ); + } + return options; + }; } - static overrideOptions( - hotOptions: IRspackHotProcessorOptions, + static overrideOptions( + hotOptions: IHotProcessorOptions, updateOptions: TUpdateOptions - ): IBasicProcessorOptions["overrideOptions"] { - return ( - context: ITestContext, - options: TCompilerOptions - ) => { + ): IBasicProcessorOptions["overrideOptions"] { + return (context: ITestContext, options: TCompilerOptions) => { if (!options.entry) { options.entry = "./index.js"; } @@ -131,8 +138,12 @@ export class RspackHotProcessor extends BasicTaskProcessor } ] }); - options.plugins ??= []; - options.plugins.push(new rspack.LoaderOptionsPlugin(updateOptions)); + if (hotOptions.compilerType === ECompilerType.Rspack) { + options.plugins ??= []; + (options as TCompilerOptions).plugins!.push( + new rspack.LoaderOptionsPlugin(updateOptions) + ); + } }; } } diff --git a/packages/rspack-test-tools/src/processor/multi.ts b/packages/rspack-test-tools/src/processor/multi.ts index c7b721cbca3..e40df4a91e6 100644 --- a/packages/rspack-test-tools/src/processor/multi.ts +++ b/packages/rspack-test-tools/src/processor/multi.ts @@ -5,14 +5,11 @@ import { ECompilerType, ITestContext, ITestProcessor, - ITestRunner, TCompilerOptions } from "../type"; -import { BasicTaskProcessor } from "./basic"; +import { BasicProcessor } from "./basic"; -export interface IMultiTaskProcessorOptions< - T extends ECompilerType = ECompilerType.Rspack -> { +export interface IMultiTaskProcessorOptions { defaultOptions?: ( index: number, context: ITestContext @@ -27,14 +24,14 @@ export interface IMultiTaskProcessorOptions< context: ITestContext, options: TCompilerOptions ) => string[] | string | void; - compilerType: ECompilerType.Rspack; + compilerType: T; name: string; configFiles?: string[]; runable: boolean; } -export class MultiTaskProcessor - extends BasicTaskProcessor +export class MultiTaskProcessor + extends BasicProcessor implements ITestProcessor { protected multiCompilerOptions: TCompilerOptions[] = []; diff --git a/packages/rspack-test-tools/src/processor/normal.ts b/packages/rspack-test-tools/src/processor/normal.ts index 6eeecfaa8a4..4907f3c3023 100644 --- a/packages/rspack-test-tools/src/processor/normal.ts +++ b/packages/rspack-test-tools/src/processor/normal.ts @@ -4,40 +4,42 @@ import path from "path"; import { ECompilerType, ITestContext, - ITestEnv, - ITestRunner, - TCompilerOptions, - TTestConfig + TCompiler, + TCompilerOptions } from "../type"; -import { BasicTaskProcessor } from "./basic"; +import { BasicProcessor } from "./basic"; -export interface IRspackNormalProcessorOptions { +export interface INormalProcessorOptions { name: string; root: string; - compilerOptions?: TCompilerOptions; + compilerOptions?: TCompilerOptions; runable: boolean; + compilerType: T; } -export class RspackNormalProcessor extends BasicTaskProcessor { - constructor(protected _normalOptions: IRspackNormalProcessorOptions) { +export class NormalProcessor< + T extends ECompilerType +> extends BasicProcessor { + constructor(protected _normalOptions: INormalProcessorOptions) { super({ - compilerType: ECompilerType.Rspack, + compilerType: _normalOptions.compilerType, findBundle: (context, options) => { const filename = options.output?.filename; return typeof filename === "string" ? filename : undefined; }, - defaultOptions: RspackNormalProcessor.defaultOptions(_normalOptions), + defaultOptions: NormalProcessor.defaultOptions(_normalOptions), name: _normalOptions.name, runable: _normalOptions.runable }); } - static defaultOptions({ + static defaultOptions({ compilerOptions, - root - }: IRspackNormalProcessorOptions) { - return (context: ITestContext): TCompilerOptions => { - let testConfig: TCompilerOptions = {}; + root, + compilerType + }: INormalProcessorOptions) { + return (context: ITestContext): TCompilerOptions => { + let testConfig: TCompilerOptions = {}; const testConfigPath = path.join(context.getSource(), "test.config.js"); if (fs.existsSync(testConfigPath)) { testConfig = require(testConfigPath); @@ -137,8 +139,9 @@ export class RspackNormalProcessor extends BasicTaskProcessor) { this.hooks.compilation.tap("TestCasesTest", compilation => { [ // CHANGE: the follwing hooks are not supported yet, so comment it out @@ -161,7 +164,7 @@ export class RspackNormalProcessor extends BasicTaskProcessor; }; } } diff --git a/packages/rspack-test-tools/src/processor/simple.ts b/packages/rspack-test-tools/src/processor/simple.ts index 0c29557eb34..1e0ba501cd5 100644 --- a/packages/rspack-test-tools/src/processor/simple.ts +++ b/packages/rspack-test-tools/src/processor/simple.ts @@ -8,9 +8,7 @@ import { TCompilerStats } from "../type"; -export interface ISimpleProcessorOptions< - T extends ECompilerType = ECompilerType.Rspack -> { +export interface ISimpleProcessorOptions { options?: (context: ITestContext) => TCompilerOptions; compilerType: T; name: string; @@ -23,7 +21,7 @@ export interface ISimpleProcessorOptions< ) => Promise; } -export class SimpleTaskProcessor +export class SimpleTaskProcessor implements ITestProcessor { constructor(protected _options: ISimpleProcessorOptions) {} diff --git a/packages/rspack-test-tools/src/processor/snapshot.ts b/packages/rspack-test-tools/src/processor/snapshot.ts index 65b672d44f6..68583f263fe 100644 --- a/packages/rspack-test-tools/src/processor/snapshot.ts +++ b/packages/rspack-test-tools/src/processor/snapshot.ts @@ -8,7 +8,7 @@ import { import { escapeEOL } from "../helper"; import { ECompilerType, ITestContext, ITestEnv } from "../type"; -import { BasicTaskProcessor, IBasicProcessorOptions } from "./basic"; +import { BasicProcessor, IBasicProcessorOptions } from "./basic"; declare var global: { updateSnapshot: boolean; @@ -22,7 +22,7 @@ export interface ISnapshotProcessorOptions export class SnapshotProcessor< T extends ECompilerType -> extends BasicTaskProcessor { +> extends BasicProcessor { constructor(protected _snapshotOptions: ISnapshotProcessorOptions) { super(_snapshotOptions); if (path.extname(_snapshotOptions.snapshot) === ".snap") { diff --git a/packages/rspack-test-tools/src/processor/stats-api.ts b/packages/rspack-test-tools/src/processor/stats-api.ts index 576f203f8b2..825fadd112b 100644 --- a/packages/rspack-test-tools/src/processor/stats-api.ts +++ b/packages/rspack-test-tools/src/processor/stats-api.ts @@ -12,7 +12,7 @@ import { import { SimpleTaskProcessor } from "./simple"; const serializer = require("jest-serializer-path"); -export interface IStatsAPITaskProcessorOptions { +export interface IStatsAPIProcessorOptions { options?: (context: ITestContext) => TCompilerOptions; name: string; compilerType: T; @@ -21,10 +21,10 @@ export interface IStatsAPITaskProcessorOptions { check?: (stats: TCompilerStats, compiler: TCompiler) => Promise; } -export class StatsAPITaskProcessor< +export class StatsAPIProcessor< T extends ECompilerType > extends SimpleTaskProcessor { - constructor(protected _statsAPIOptions: IStatsAPITaskProcessorOptions) { + constructor(protected _statsAPIOptions: IStatsAPIProcessorOptions) { super({ options: _statsAPIOptions.options, build: _statsAPIOptions.build, diff --git a/packages/rspack-test-tools/src/processor/stats.ts b/packages/rspack-test-tools/src/processor/stats.ts index 11e492ef810..74175f1d4e1 100644 --- a/packages/rspack-test-tools/src/processor/stats.ts +++ b/packages/rspack-test-tools/src/processor/stats.ts @@ -10,30 +10,31 @@ import { ECompilerType, ITestContext, ITestEnv, - TCompilerOptions, - TTestConfig + TCompilerOptions } from "../type"; -import { MultiTaskProcessor } from "./multi"; +import { IMultiTaskProcessorOptions, MultiTaskProcessor } from "./multi"; -export interface IRspackStatsProcessorOptions { - name: string; -} +export interface IStatsProcessorOptions + extends Omit< + IMultiTaskProcessorOptions, + "defaultOptions" | "overrideOptions" | "runable" + > {} const REG_ERROR_CASE = /error$/; const quoteMeta = (str: string) => { return str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&"); }; -export class RspackStatsProcessor extends MultiTaskProcessor { +export class StatsProcessor< + T extends ECompilerType +> extends MultiTaskProcessor { private stderr: any; - constructor(options: IRspackStatsProcessorOptions) { + constructor(_statsOptions: IStatsProcessorOptions) { super({ - defaultOptions: RspackStatsProcessor.defaultOptions, - overrideOptions: RspackStatsProcessor.overrideOptions, - compilerType: ECompilerType.Rspack, - configFiles: ["rspack.config.js", "webpack.config.js"], - name: options.name, - runable: false + defaultOptions: StatsProcessor.defaultOptions, + overrideOptions: StatsProcessor.overrideOptions, + runable: false, + ..._statsOptions }); } @@ -188,10 +189,10 @@ export class RspackStatsProcessor extends MultiTaskProcessor( index: number, context: ITestContext - ): TCompilerOptions { + ): TCompilerOptions { if (fs.existsSync(path.join(context.getSource(), "rspack.config.js"))) { return {}; } @@ -208,10 +209,10 @@ export class RspackStatsProcessor extends MultiTaskProcessor( index: number, context: ITestContext, - options: TCompilerOptions + options: TCompilerOptions ): void { if (!options.context) options.context = context.getSource(); if (!options.output) options.output = options.output || {}; diff --git a/packages/rspack-test-tools/src/processor/treeshaking.ts b/packages/rspack-test-tools/src/processor/treeshaking.ts index 242f47d3b1a..86bc6acc53d 100644 --- a/packages/rspack-test-tools/src/processor/treeshaking.ts +++ b/packages/rspack-test-tools/src/processor/treeshaking.ts @@ -1,31 +1,30 @@ -import { rspack } from "@rspack/core"; - import { ECompilerType, ITestContext, TCompilerOptions } from "../type"; -import { RspackBuiltinProcessor } from "./builtin"; -import { SnapshotProcessor } from "./snapshot"; +import { BuiltinProcessor } from "./builtin"; +import { ISnapshotProcessorOptions, SnapshotProcessor } from "./snapshot"; -export interface IRspackTreeShakingProcessorOptions { - name: string; - snapshot: string; -} +export interface ITreeShakingProcessorOptions + extends Omit< + ISnapshotProcessorOptions, + "defaultOptions" | "overrideOptions" | "runable" + > {} -export class RspackTreeShakingProcessor extends SnapshotProcessor { - constructor( - protected _treeShakingOptions: IRspackTreeShakingProcessorOptions - ) { +export class TreeShakingProcessor< + T extends ECompilerType +> extends SnapshotProcessor { + constructor(protected _treeShakingOptions: ITreeShakingProcessorOptions) { super({ - snapshot: _treeShakingOptions.snapshot, - compilerType: ECompilerType.Rspack, - defaultOptions: RspackBuiltinProcessor.defaultOptions, - overrideOptions: RspackTreeShakingProcessor.overrideOptions, - name: _treeShakingOptions.name, - runable: false + defaultOptions: BuiltinProcessor.defaultOptions( + _treeShakingOptions.compilerType + ), + overrideOptions: TreeShakingProcessor.overrideOptions, + runable: false, + ..._treeShakingOptions }); } - static overrideOptions( + static overrideOptions( context: ITestContext, - options: TCompilerOptions + options: TCompilerOptions ) { options.target = options.target || ["web", "es2022"]; options.optimization ??= {}; diff --git a/packages/rspack-test-tools/src/processor/watch.ts b/packages/rspack-test-tools/src/processor/watch.ts index 54060a15e6d..0cab485ff7c 100644 --- a/packages/rspack-test-tools/src/processor/watch.ts +++ b/packages/rspack-test-tools/src/processor/watch.ts @@ -7,11 +7,9 @@ import { ECompilerType, ITestContext, ITestEnv, - ITestRunner, - TCompilerOptions, - TTestConfig + TCompilerOptions } from "../type"; -import { MultiTaskProcessor } from "./multi"; +import { IMultiTaskProcessorOptions, MultiTaskProcessor } from "./multi"; // This file is used to port step number to rspack.config.js/webpack.config.js const currentWatchStepModulePath = path.resolve( @@ -19,31 +17,31 @@ const currentWatchStepModulePath = path.resolve( "../helper/util/currentWatchStep" ); -type TRspackExperiments = TCompilerOptions["experiments"]; -type TRspackOptimization = - TCompilerOptions["optimization"]; +type TRspackExperiments = TCompilerOptions["experiments"]; +type TRspackOptimization = TCompilerOptions["optimization"]; -export interface IRspackWatchProcessorOptions { - name: string; +export interface IWatchProcessorOptions + extends Omit< + IMultiTaskProcessorOptions, + "overrideOptinos" | "findBundle" + > { stepName: string; tempDir: string; experiments?: TRspackExperiments; optimization?: TRspackOptimization; - runable: boolean; } -export class RspackWatchProcessor extends MultiTaskProcessor { +export class WatchProcessor< + T extends ECompilerType +> extends MultiTaskProcessor { protected currentTriggerFilename: string | null = null; protected lastHash: string | null = null; - constructor(protected _watchOptions: IRspackWatchProcessorOptions) { + constructor(protected _watchOptions: IWatchProcessorOptions) { super({ - overrideOptions: RspackWatchProcessor.overrideOptions(_watchOptions), - compilerType: ECompilerType.Rspack, + overrideOptions: WatchProcessor.overrideOptions(_watchOptions), findBundle: () => "bundle.js", - configFiles: ["rspack.config.js", "webpack.config.js"], - name: _watchOptions.name, - runable: _watchOptions.runable + ..._watchOptions }); } @@ -97,16 +95,16 @@ export class RspackWatchProcessor extends MultiTaskProcessor({ tempDir, name, experiments, optimization - }: IRspackWatchProcessorOptions) { + }: IWatchProcessorOptions) { return ( index: number, context: ITestContext, - options: TCompilerOptions + options: TCompilerOptions ): void => { if (!options.mode) options.mode = "development"; if (!options.context) options.context = tempDir; @@ -144,15 +142,13 @@ export class RspackWatchProcessor extends MultiTaskProcessor + extends Omit, "experiments" | "optimization"> {} -export class RspackWatchStepProcessor extends RspackWatchProcessor { - constructor(protected _watchOptions: IRspackWatchStepProcessorOptions) { +export class WatchStepProcessor< + T extends ECompilerType +> extends WatchProcessor { + constructor(protected _watchOptions: IWatchStepProcessorOptions) { super(_watchOptions); } diff --git a/packages/rspack-test-tools/tests/Defaults.test.js b/packages/rspack-test-tools/tests/Defaults.test.js index 781179c5123..6c96a437297 100644 --- a/packages/rspack-test-tools/tests/Defaults.test.js +++ b/packages/rspack-test-tools/tests/Defaults.test.js @@ -1,14 +1,14 @@ const path = require("path"); const { - DefaultsConfigTaskProcessor, + DefaultsConfigProcessor, createDefaultsCase, describeByWalk } = require(".."); -DefaultsConfigTaskProcessor.addSnapshotSerializer(expect); +DefaultsConfigProcessor.addSnapshotSerializer(expect); describe("Base Defaults Snapshot", () => { - const baseConfig = DefaultsConfigTaskProcessor.getDefaultConfig( + const baseConfig = DefaultsConfigProcessor.getDefaultConfig( path.resolve(__dirname, ".."), { mode: "none" } ); From 4216cc44a8eb7aa43ecf7322e7007cdf530de7cd Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Tue, 21 May 2024 14:07:01 +0800 Subject: [PATCH 10/48] fix: optional context dependency (#6587) * fix: optional context dependency * fix: optional context dependency --- crates/rspack_core/src/context_module_factory.rs | 4 ++-- .../src/dependency/context_dependency.rs | 4 ++++ .../common_js_require_context_dependency.rs | 7 +++++++ .../context/import_context_dependency.rs | 7 +++++++ .../context/import_meta_context_dependency.rs | 14 +++++++++++++- .../context/require_context_dependency.rs | 14 +++++++++++++- .../common_js_imports_parse_plugin.rs | 10 +++++++++- ...import_meta_context_dependency_parser_plugin.rs | 8 ++++++-- .../src/parser_plugin/import_parser_plugin.rs | 1 + .../require_context_dependency_parser_plugin.rs | 1 + .../factorize/optional-context-dependency/index.js | 3 +++ .../optional-context-dependency/locale.js | 12 ++++++++++++ .../optional-context-dependency/stats.err | 1 + 13 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/index.js create mode 100644 packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/locale.js create mode 100644 packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/stats.err diff --git a/crates/rspack_core/src/context_module_factory.rs b/crates/rspack_core/src/context_module_factory.rs index 7cc71611d4b..cddbbdd80d1 100644 --- a/crates/rspack_core/src/context_module_factory.rs +++ b/crates/rspack_core/src/context_module_factory.rs @@ -212,7 +212,7 @@ impl ContextModuleFactory { let resolve_args = ResolveArgs { context: data.context.clone(), - importer: None, + importer: data.issuer_identifier.as_ref(), issuer: data.issuer.as_deref(), specifier, dependency_type: dependency.dependency_type(), @@ -220,7 +220,7 @@ impl ContextModuleFactory { span: dependency.span(), resolve_options: data.resolve_options.clone(), resolve_to_context: true, - optional: false, + optional: dependency.get_optional(), file_dependencies: &mut file_dependencies, missing_dependencies: &mut missing_dependencies, }; diff --git a/crates/rspack_core/src/dependency/context_dependency.rs b/crates/rspack_core/src/dependency/context_dependency.rs index 0d10dcc83be..d8370e9aa0e 100644 --- a/crates/rspack_core/src/dependency/context_dependency.rs +++ b/crates/rspack_core/src/dependency/context_dependency.rs @@ -6,6 +6,10 @@ pub trait ContextDependency: Dependency { fn get_context(&self) -> Option<&str>; fn resource_identifier(&self) -> &str; fn set_request(&mut self, request: String); + + fn get_optional(&self) -> bool { + false + } } pub trait AsContextDependency { diff --git a/crates/rspack_plugin_javascript/src/dependency/context/common_js_require_context_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/context/common_js_require_context_dependency.rs index 9d297344ffc..2007155ec71 100644 --- a/crates/rspack_plugin_javascript/src/dependency/context/common_js_require_context_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/context/common_js_require_context_dependency.rs @@ -16,6 +16,7 @@ pub struct CommonJsRequireContextDependency { options: ContextOptions, span: Option, resource_identifier: String, + optional: bool, } impl CommonJsRequireContextDependency { @@ -25,6 +26,7 @@ impl CommonJsRequireContextDependency { args_end: u32, options: ContextOptions, span: Option, + optional: bool, ) -> Self { let resource_identifier = create_resource_identifier_for_context_dependency(None, &options); Self { @@ -35,6 +37,7 @@ impl CommonJsRequireContextDependency { span, id: DependencyId::new(), resource_identifier, + optional, } } } @@ -81,6 +84,10 @@ impl ContextDependency for CommonJsRequireContextDependency { fn set_request(&mut self, request: String) { self.options.request = request; } + + fn get_optional(&self) -> bool { + self.optional + } } impl DependencyTemplate for CommonJsRequireContextDependency { diff --git a/crates/rspack_plugin_javascript/src/dependency/context/import_context_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/context/import_context_dependency.rs index 885bd58161f..a95b05ac538 100644 --- a/crates/rspack_plugin_javascript/src/dependency/context/import_context_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/context/import_context_dependency.rs @@ -16,6 +16,7 @@ pub struct ImportContextDependency { options: ContextOptions, span: Option, resource_identifier: String, + optional: bool, } impl ImportContextDependency { @@ -25,6 +26,7 @@ impl ImportContextDependency { args_end: u32, options: ContextOptions, span: Option, + optional: bool, ) -> Self { let resource_identifier = create_resource_identifier_for_context_dependency(None, &options); Self { @@ -35,6 +37,7 @@ impl ImportContextDependency { span, id: DependencyId::new(), resource_identifier, + optional, } } } @@ -81,6 +84,10 @@ impl ContextDependency for ImportContextDependency { fn set_request(&mut self, request: String) { self.options.request = request; } + + fn get_optional(&self) -> bool { + self.optional + } } impl DependencyTemplate for ImportContextDependency { diff --git a/crates/rspack_plugin_javascript/src/dependency/context/import_meta_context_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/context/import_meta_context_dependency.rs index 72105e39f04..6ca45a49ce6 100644 --- a/crates/rspack_plugin_javascript/src/dependency/context/import_meta_context_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/context/import_meta_context_dependency.rs @@ -13,10 +13,17 @@ pub struct ImportMetaContextDependency { options: ContextOptions, span: Option, resource_identifier: String, + optional: bool, } impl ImportMetaContextDependency { - pub fn new(start: u32, end: u32, options: ContextOptions, span: Option) -> Self { + pub fn new( + start: u32, + end: u32, + options: ContextOptions, + span: Option, + optional: bool, + ) -> Self { let resource_identifier = create_resource_identifier_for_context_dependency(None, &options); Self { start, @@ -25,6 +32,7 @@ impl ImportMetaContextDependency { span, id: DependencyId::new(), resource_identifier, + optional, } } } @@ -71,6 +79,10 @@ impl ContextDependency for ImportMetaContextDependency { fn set_request(&mut self, request: String) { self.options.request = request; } + + fn get_optional(&self) -> bool { + self.optional + } } impl DependencyTemplate for ImportMetaContextDependency { diff --git a/crates/rspack_plugin_javascript/src/dependency/context/require_context_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/context/require_context_dependency.rs index 63c0ca264e0..64f4bb03d88 100644 --- a/crates/rspack_plugin_javascript/src/dependency/context/require_context_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/context/require_context_dependency.rs @@ -13,10 +13,17 @@ pub struct RequireContextDependency { options: ContextOptions, span: Option, resource_identifier: String, + optional: bool, } impl RequireContextDependency { - pub fn new(start: u32, end: u32, options: ContextOptions, span: Option) -> Self { + pub fn new( + start: u32, + end: u32, + options: ContextOptions, + span: Option, + optional: bool, + ) -> Self { let resource_identifier = create_resource_identifier_for_context_dependency(None, &options); Self { start, @@ -25,6 +32,7 @@ impl RequireContextDependency { span, id: DependencyId::new(), resource_identifier, + optional, } } } @@ -71,6 +79,10 @@ impl ContextDependency for RequireContextDependency { fn set_request(&mut self, request: String) { self.options.request = request; } + + fn get_optional(&self) -> bool { + self.optional + } } impl DependencyTemplate for RequireContextDependency { diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs index b84f1eda547..a42fcf7b44e 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs @@ -41,7 +41,14 @@ fn create_commonjs_require_context_dependency( start: callee_start, end: callee_end, }; - CommonJsRequireContextDependency::new(callee_start, callee_end, args_end, options, span) + CommonJsRequireContextDependency::new( + callee_start, + callee_end, + args_end, + options, + span, + parser.in_try, + ) } pub struct CommonJsImportsParserPlugin; @@ -220,6 +227,7 @@ impl CommonJsImportsParserPlugin { end: ident.span().real_hi(), }, Some(ident.span().into()), + parser.in_try, ); parser.warning_diagnostics.push(Box::new( create_traceable_error( diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_context_dependency_parser_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_context_dependency_parser_plugin.rs index 53f8b3fda91..b01d1aaff8e 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_context_dependency_parser_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_context_dependency_parser_plugin.rs @@ -12,7 +12,10 @@ use crate::utils::eval::{self, BasicEvaluatedExpression}; use crate::utils::{get_bool_by_obj_prop, get_literal_str_by_obj_prop, get_regex_by_obj_prop}; use crate::visitors::{expr_name, JavascriptParser}; -fn create_import_meta_context_dependency(node: &CallExpr) -> Option { +fn create_import_meta_context_dependency( + node: &CallExpr, + optional: bool, +) -> Option { assert!(node.callee.is_expr()); let dyn_imported = node.args.first()?; if dyn_imported.spread.is_some() { @@ -90,6 +93,7 @@ fn create_import_meta_context_dependency(node: &CallExpr) -> Option 2 { None - } else if let Some(dep) = create_import_meta_context_dependency(expr) { + } else if let Some(dep) = create_import_meta_context_dependency(expr, parser.in_try) { parser.dependencies.push(Box::new(dep)); Some(true) } else { diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/import_parser_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/import_parser_plugin.rs index 35b84a3875d..72f291c20bc 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/import_parser_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/import_parser_plugin.rs @@ -141,6 +141,7 @@ impl JavascriptParserPlugin for ImportParserPlugin { end: node.span().real_hi(), }, Some(node.span.into()), + parser.in_try, ))); // FIXME: align `parser.walk_expression` to webpack, which put into `context_dependency_helper` parser.walk_expression(&dyn_imported.expr); diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/require_context_dependency_parser_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/require_context_dependency_parser_plugin.rs index 9446f0cca8a..c8af97be329 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/require_context_dependency_parser_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/require_context_dependency_parser_plugin.rs @@ -89,6 +89,7 @@ impl JavascriptParserPlugin for RequireContextDependencyParserPlugin { end: expr.span().real_hi(), }, Some(expr.span.into()), + parser.in_try, ))); return Some(true); } diff --git a/packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/index.js b/packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/index.js new file mode 100644 index 00000000000..a5c303a68f1 --- /dev/null +++ b/packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/index.js @@ -0,0 +1,3 @@ +import { loadLocale } from './locale'; + +loadLocale('lang'); \ No newline at end of file diff --git a/packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/locale.js b/packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/locale.js new file mode 100644 index 00000000000..e4e2c167555 --- /dev/null +++ b/packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/locale.js @@ -0,0 +1,12 @@ +const loadLocale = (name) => { + let locale; + try { + locale = require('./locale/' + name); + } catch (e) { + } + return locale; +}; + +module.exports = { + loadLocale, +} \ No newline at end of file diff --git a/packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/stats.err b/packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/stats.err new file mode 100644 index 00000000000..5756d68891d --- /dev/null +++ b/packages/rspack-test-tools/tests/diagnosticsCases/factorize/optional-context-dependency/stats.err @@ -0,0 +1 @@ +WARNING in ./locale.js⚠ Resolve error: Can't resolve './locale' in '/tests/diagnosticsCases/factorize/optional-context-dependency'╭─[2:1]2 let locale;3 try {4 locale = require('./locale/' + name);· ───────────────────────────5 } catch (e) {}6 return locale;╰────help: Found module './locale.js'. However, it's not possible to request this module without the extensionif its extension was not listed in the `resolve.extensions`. Here're some possible solutions:1. add the extension `".js"` to `resolve.extensions` in your rspack configuration2. use './locale.js' instead of './locale' \ No newline at end of file From 551ebe1d4ec13d8ad28978ddd67cfad115bdc78d Mon Sep 17 00:00:00 2001 From: Gengkun Date: Tue, 21 May 2024 14:50:15 +0800 Subject: [PATCH 11/48] refactor: create codegen dependencies (#6588) --- crates/rspack_core/src/normal_module.rs | 4 +--- crates/rspack_core/src/parser_and_generator.rs | 2 +- crates/rspack_plugin_asset/src/lib.rs | 1 + .../rspack_plugin_css/src/parser_and_generator/mod.rs | 10 ++++++---- .../src/parser_and_generator/mod.rs | 2 ++ crates/rspack_plugin_json/src/lib.rs | 1 + crates/rspack_plugin_wasm/src/parser_and_generator.rs | 1 + 7 files changed, 13 insertions(+), 8 deletions(-) diff --git a/crates/rspack_core/src/normal_module.rs b/crates/rspack_core/src/normal_module.rs index d84678bc000..17ca8f38480 100644 --- a/crates/rspack_core/src/normal_module.rs +++ b/crates/rspack_core/src/normal_module.rs @@ -487,8 +487,6 @@ impl Module for NormalModule { }); } - let mut code_generation_dependencies: Vec> = Vec::new(); - build_info.cacheable = loader_result.cacheable; build_info.file_dependencies = loader_result.file_dependencies; build_info.context_dependencies = loader_result.context_dependencies; @@ -502,6 +500,7 @@ impl Module for NormalModule { dependencies, blocks, presentational_dependencies, + code_generation_dependencies, analyze_result, side_effects_bailout, }, @@ -520,7 +519,6 @@ impl Module for NormalModule { resource_data: &self.resource_data, compiler_options: build_context.compiler_options, additional_data: loader_result.additional_data, - code_generation_dependencies: &mut code_generation_dependencies, build_info: &mut build_info, build_meta: &mut build_meta, })? diff --git a/crates/rspack_core/src/parser_and_generator.rs b/crates/rspack_core/src/parser_and_generator.rs index e661e76c18b..788270a7d30 100644 --- a/crates/rspack_core/src/parser_and_generator.rs +++ b/crates/rspack_core/src/parser_and_generator.rs @@ -31,7 +31,6 @@ pub struct ParseContext<'a> { pub resource_data: &'a ResourceData, pub compiler_options: &'a CompilerOptions, pub additional_data: AdditionalData, - pub code_generation_dependencies: &'a mut Vec>, pub build_info: &'a mut BuildInfo, pub build_meta: &'a mut BuildMeta, } @@ -67,6 +66,7 @@ pub struct ParseResult { pub dependencies: Vec, pub blocks: Vec, pub presentational_dependencies: Vec>, + pub code_generation_dependencies: Vec>, pub source: BoxSource, pub analyze_result: OptimizeAnalyzeResult, pub side_effects_bailout: Option, diff --git a/crates/rspack_plugin_asset/src/lib.rs b/crates/rspack_plugin_asset/src/lib.rs index 1517590f099..09515e2ab9a 100644 --- a/crates/rspack_plugin_asset/src/lib.rs +++ b/crates/rspack_plugin_asset/src/lib.rs @@ -320,6 +320,7 @@ impl ParserAndGenerator for AssetParserAndGenerator { blocks: vec![], source, presentational_dependencies: vec![], + code_generation_dependencies: vec![], analyze_result, side_effects_bailout: None, } diff --git a/crates/rspack_plugin_css/src/parser_and_generator/mod.rs b/crates/rspack_plugin_css/src/parser_and_generator/mod.rs index ebb1874527f..c545c5d096f 100644 --- a/crates/rspack_plugin_css/src/parser_and_generator/mod.rs +++ b/crates/rspack_plugin_css/src/parser_and_generator/mod.rs @@ -13,8 +13,9 @@ use rspack_core::{ SourceMapSource, SourceMapSourceOptions, }, BoxDependency, BuildExtraDataType, BuildMetaDefaultObject, BuildMetaExportsType, ChunkGraph, - CssExportsConvention, ErrorSpan, GenerateContext, LocalIdentName, Module, ModuleGraph, - ModuleType, ParseContext, ParseResult, ParserAndGenerator, SourceType, TemplateContext, + CssExportsConvention, ErrorSpan, GenerateContext, LocalIdentName, Module, ModuleDependency, + ModuleGraph, ModuleType, ParseContext, ParseResult, ParserAndGenerator, SourceType, + TemplateContext, }; use rspack_core::{ModuleInitFragments, RuntimeGlobals}; use rspack_error::{IntoTWithDiagnosticArray, Result, TWithDiagnosticArray}; @@ -90,7 +91,6 @@ impl ParserAndGenerator for CssParserAndGenerator { compiler_options, build_info, build_meta, - code_generation_dependencies, loaders, .. } = parse_context; @@ -127,6 +127,7 @@ impl ParserAndGenerator for CssParserAndGenerator { let mut exports_pairs = vec![]; let mut presentational_dependencies = None; + let mut code_generation_dependencies: Vec> = vec![]; let mut exports = if is_enable_css_modules { let mut stylesheet = swc_compiler.parse_file( &resource_path.to_string_lossy(), @@ -206,7 +207,7 @@ impl ParserAndGenerator for CssParserAndGenerator { let mut dependencies = analyze_dependencies( &new_stylesheet_ast, - code_generation_dependencies, + &mut code_generation_dependencies, &mut diagnostic_vec, &source_code, module_user_request, @@ -276,6 +277,7 @@ impl ParserAndGenerator for CssParserAndGenerator { dependencies, blocks: vec![], presentational_dependencies: presentational_dependencies.unwrap_or_default(), + code_generation_dependencies, source: new_source, analyze_result: Default::default(), side_effects_bailout: None, diff --git a/crates/rspack_plugin_javascript/src/parser_and_generator/mod.rs b/crates/rspack_plugin_javascript/src/parser_and_generator/mod.rs index d581c82fe17..b49a806401f 100644 --- a/crates/rspack_plugin_javascript/src/parser_and_generator/mod.rs +++ b/crates/rspack_plugin_javascript/src/parser_and_generator/mod.rs @@ -122,6 +122,7 @@ impl ParserAndGenerator for JavaScriptParserAndGenerator { dependencies: vec![], blocks: vec![], presentational_dependencies: vec![], + code_generation_dependencies: vec![], analyze_result: Default::default(), side_effects_bailout: None, } @@ -308,6 +309,7 @@ impl ParserAndGenerator for JavaScriptParserAndGenerator { dependencies, blocks, presentational_dependencies, + code_generation_dependencies: vec![], analyze_result, side_effects_bailout, } diff --git a/crates/rspack_plugin_json/src/lib.rs b/crates/rspack_plugin_json/src/lib.rs index b086163b3e6..816f4037253 100644 --- a/crates/rspack_plugin_json/src/lib.rs +++ b/crates/rspack_plugin_json/src/lib.rs @@ -118,6 +118,7 @@ impl ParserAndGenerator for JsonParserAndGenerator { vec![] }, blocks: vec![], + code_generation_dependencies: vec![], source: box_source, analyze_result: Default::default(), side_effects_bailout: None, diff --git a/crates/rspack_plugin_wasm/src/parser_and_generator.rs b/crates/rspack_plugin_wasm/src/parser_and_generator.rs index ff22b13feff..16af6d6a063 100644 --- a/crates/rspack_plugin_wasm/src/parser_and_generator.rs +++ b/crates/rspack_plugin_wasm/src/parser_and_generator.rs @@ -94,6 +94,7 @@ impl ParserAndGenerator for AsyncWasmParserAndGenerator { dependencies, blocks: vec![], presentational_dependencies: vec![], + code_generation_dependencies: vec![], source, analyze_result: Default::default(), side_effects_bailout: None, From ee13ed6b53cf39c1bcb52289064880f1aef190e3 Mon Sep 17 00:00:00 2001 From: gaoyuan <9aoyuao@gmail.com> Date: Tue, 21 May 2024 15:06:55 +0800 Subject: [PATCH 12/48] release: 0.7.0-beta.1 (#6586) --- crates/node_binding/package.json | 2 +- npm/darwin-arm64/package.json | 2 +- npm/darwin-x64/package.json | 2 +- npm/linux-x64-gnu/package.json | 2 +- npm/win32-x64-msvc/package.json | 2 +- package.json | 2 +- packages/create-rspack/package.json | 2 +- packages/rspack-cli/package.json | 2 +- packages/rspack-dev-server/package.json | 2 +- packages/rspack-plugin-minify/package.json | 2 +- packages/rspack-plugin-react-refresh/package.json | 2 +- packages/rspack-test-tools/package.json | 4 ++-- packages/rspack/package.json | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/node_binding/package.json b/crates/node_binding/package.json index 93022ba30ea..929fe15839e 100644 --- a/crates/node_binding/package.json +++ b/crates/node_binding/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "description": "Node binding for rspack", "main": "binding.js", diff --git a/npm/darwin-arm64/package.json b/npm/darwin-arm64/package.json index f40a2a9ad23..e8814967cd2 100644 --- a/npm/darwin-arm64/package.json +++ b/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-darwin-arm64", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.darwin-arm64.node", diff --git a/npm/darwin-x64/package.json b/npm/darwin-x64/package.json index 42f97086f35..6be6ea9503b 100644 --- a/npm/darwin-x64/package.json +++ b/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-darwin-x64", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.darwin-x64.node", diff --git a/npm/linux-x64-gnu/package.json b/npm/linux-x64-gnu/package.json index 1a616595d65..ec00f184d6e 100644 --- a/npm/linux-x64-gnu/package.json +++ b/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-linux-x64-gnu", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.linux-x64-gnu.node", diff --git a/npm/win32-x64-msvc/package.json b/npm/win32-x64-msvc/package.json index 859c12cd22c..f43f9b8371a 100644 --- a/npm/win32-x64-msvc/package.json +++ b/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-win32-x64-msvc", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.win32-x64-msvc.node", diff --git a/package.json b/package.json index b8bd3d9c544..a7d1d391652 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "monorepo", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "description": "A Fast Rust-based web bundler", "private": true, diff --git a/packages/create-rspack/package.json b/packages/create-rspack/package.json index f36e04c518b..9b105bcb1a4 100644 --- a/packages/create-rspack/package.json +++ b/packages/create-rspack/package.json @@ -1,6 +1,6 @@ { "name": "create-rspack", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "main": "index.js", "bin": { diff --git a/packages/rspack-cli/package.json b/packages/rspack-cli/package.json index 166398dff03..b1fe446bbd2 100644 --- a/packages/rspack-cli/package.json +++ b/packages/rspack-cli/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/cli", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "description": "CLI for rspack", "bin": { diff --git a/packages/rspack-dev-server/package.json b/packages/rspack-dev-server/package.json index 1e84d00c6a8..6d186905ff9 100644 --- a/packages/rspack-dev-server/package.json +++ b/packages/rspack-dev-server/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/dev-server", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "description": "Development server for rspack", "main": "./dist/index.js", diff --git a/packages/rspack-plugin-minify/package.json b/packages/rspack-plugin-minify/package.json index fe10637e6f8..37cbb8cd3dd 100644 --- a/packages/rspack-plugin-minify/package.json +++ b/packages/rspack-plugin-minify/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/plugin-minify", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "description": "Minify plugin for rspack", "main": "src/index.js", diff --git a/packages/rspack-plugin-react-refresh/package.json b/packages/rspack-plugin-react-refresh/package.json index 1cb8b0ca242..4dfddafa0c7 100644 --- a/packages/rspack-plugin-react-refresh/package.json +++ b/packages/rspack-plugin-react-refresh/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/plugin-react-refresh", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "description": "React refresh plugin for rspack", "main": "dist/index.js", diff --git a/packages/rspack-test-tools/package.json b/packages/rspack-test-tools/package.json index 2075996427e..017c5c2f931 100644 --- a/packages/rspack-test-tools/package.json +++ b/packages/rspack-test-tools/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/test-tools", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "license": "MIT", "description": "Test tools for rspack", "main": "dist/index.js", @@ -89,4 +89,4 @@ "peerDependencies": { "@rspack/core": ">=0.7.0" } -} \ No newline at end of file +} diff --git a/packages/rspack/package.json b/packages/rspack/package.json index e500e19648a..a6ea510ad7b 100644 --- a/packages/rspack/package.json +++ b/packages/rspack/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/core", - "version": "0.7.0-beta.0", + "version": "0.7.0-beta.1", "webpackVersion": "5.75.0", "license": "MIT", "description": "A Fast Rust-based Web Bundler", From c3bef0e02a087d29e55931bcde8d0c44ceeac77d Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Tue, 21 May 2024 16:45:26 +0800 Subject: [PATCH 13/48] test: fix hot snapshot recovery checker (#6589) * test: fix hot snapshot recovery checker * test: fix hot snapshot recovery checker --- .../rspack-test-tools/src/runner/hot-step.ts | 25 +++++++++++++++++++ .../css/recovery/__snapshots__/web/2.snap.txt | 11 ++++---- .../tests/hotCases/css/recovery/index.js | 2 -- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/packages/rspack-test-tools/src/runner/hot-step.ts b/packages/rspack-test-tools/src/runner/hot-step.ts index b3e42a546aa..f195e976c21 100644 --- a/packages/rspack-test-tools/src/runner/hot-step.ts +++ b/packages/rspack-test-tools/src/runner/hot-step.ts @@ -1,5 +1,6 @@ import { StatsCompilation } from "@rspack/core"; +import checkArrayExpectation from "../helper/legacy/checkArrayExpectation"; import { ECompilerType, ITestEnv, @@ -61,6 +62,30 @@ export class HotStepRunnerFactory< stats as TCompilerStats, runner.getGlobal("__HMR_UPDATED_RUNTIME__") as THotStepRuntimeData ); + if ( + checkArrayExpectation( + source, + jsonStats, + "error", + "errors" + hotUpdateContext.updateIndex, + "Error", + callback + ) + ) { + return; + } + if ( + checkArrayExpectation( + source, + jsonStats, + "warning", + "warnings" + hotUpdateContext.updateIndex, + "Warning", + callback + ) + ) { + return; + } callback(null, jsonStats as StatsCompilation); } catch (e) { callback(e as Error); diff --git a/packages/rspack-test-tools/tests/hotCases/css/recovery/__snapshots__/web/2.snap.txt b/packages/rspack-test-tools/tests/hotCases/css/recovery/__snapshots__/web/2.snap.txt index a3f288dbbd5..05a2c4bc1dc 100644 --- a/packages/rspack-test-tools/tests/hotCases/css/recovery/__snapshots__/web/2.snap.txt +++ b/packages/rspack-test-tools/tests/hotCases/css/recovery/__snapshots__/web/2.snap.txt @@ -6,7 +6,7 @@ ## Asset Files - Bundle: bundle.js - Manifest: main.LAST_HASH.hot-update.json, size: 28 -- Update: main.LAST_HASH.hot-update.js, size: 201 +- Update: main.LAST_HASH.hot-update.js, size: 209 ## Manifest @@ -30,16 +30,15 @@ #### Changed Content ```js -self["webpackHotUpdate"]('main', { - -},function(__webpack_require__) { +"use strict"; +self["webpackHotUpdate"]('main', {},function(__webpack_require__) { // webpack/runtime/get_full_hash -!function() { +(() => { __webpack_require__.h = function () { return "CURRENT_HASH"; }; -}(); +})(); } ); diff --git a/packages/rspack-test-tools/tests/hotCases/css/recovery/index.js b/packages/rspack-test-tools/tests/hotCases/css/recovery/index.js index c8295366634..69d09ffd8d9 100644 --- a/packages/rspack-test-tools/tests/hotCases/css/recovery/index.js +++ b/packages/rspack-test-tools/tests/hotCases/css/recovery/index.js @@ -7,8 +7,6 @@ it("css recovery", done => { expect(String(err)).toContain("Module build failed"); NEXT(require("../../update")(done, true, () => done())); }, - true, - () => done() ) ); }); From 38ebda0dc1e23d49285caaf9037830d69e006146 Mon Sep 17 00:00:00 2001 From: jinrui Date: Tue, 21 May 2024 17:12:56 +0800 Subject: [PATCH 14/48] fix: panic when update entry dependency (#6591) --- .../make/cutout/clean_isolated_module.rs | 10 +++----- .../src/compiler/make/cutout/mod.rs | 24 ++++++++++--------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/crates/rspack_core/src/compiler/make/cutout/clean_isolated_module.rs b/crates/rspack_core/src/compiler/make/cutout/clean_isolated_module.rs index f54c5cf009a..9e5a6d2ddf0 100644 --- a/crates/rspack_core/src/compiler/make/cutout/clean_isolated_module.rs +++ b/crates/rspack_core/src/compiler/make/cutout/clean_isolated_module.rs @@ -3,7 +3,7 @@ use std::collections::VecDeque; use rustc_hash::FxHashSet as HashSet; use super::super::MakeArtifact; -use crate::{DependencyId, ModuleIdentifier}; +use crate::ModuleIdentifier; #[derive(Debug, Default)] pub struct CleanIsolatedModule { @@ -24,14 +24,10 @@ impl CleanIsolatedModule { } } - pub fn analyze_removed_deps(&mut self, artifact: &MakeArtifact, dep_id: &DependencyId) { - let module_graph = artifact.get_module_graph(); - let connection = module_graph - .connection_by_dependency(dep_id) - .expect("should have connection"); + pub fn add_need_check_module(&mut self, module_identifier: ModuleIdentifier) { self .need_check_isolated_module_ids - .insert(*connection.module_identifier()); + .insert(module_identifier); } pub fn fix_artifact(self, artifact: &mut MakeArtifact) { diff --git a/crates/rspack_core/src/compiler/make/cutout/mod.rs b/crates/rspack_core/src/compiler/make/cutout/mod.rs index 8e86aa273c8..85abf17ff6b 100644 --- a/crates/rspack_core/src/compiler/make/cutout/mod.rs +++ b/crates/rspack_core/src/compiler/make/cutout/mod.rs @@ -100,24 +100,26 @@ impl Cutout { force_build_deps.extend(artifact.revoke_modules(force_build_modules)); if !next_entry_deps.is_empty() { - let mut old_entry_deps = std::mem::take(&mut artifact.entry_dependencies); + let mut remove_entry_deps = std::mem::take(&mut artifact.entry_dependencies); for dep_id in &next_entry_deps { - if old_entry_deps.contains(dep_id) { - old_entry_deps.remove(dep_id); + if remove_entry_deps.contains(dep_id) { + remove_entry_deps.remove(dep_id); } else { force_build_deps.insert((*dep_id, None)); } } + artifact.entry_dependencies = next_entry_deps; - for dep_id in old_entry_deps { - self - .clean_isolated_module - .analyze_removed_deps(artifact, &dep_id); + for dep_id in remove_entry_deps { let mut module_graph = artifact.get_module_graph_mut(); - let con_id = *module_graph - .connection_id_by_dependency_id(&dep_id) - .expect("should have connection"); - module_graph.revoke_connection(&con_id, true); + // connection may have been deleted by revoke module + if let Some(con) = module_graph.connection_by_dependency(&dep_id) { + self + .clean_isolated_module + .add_need_check_module(*con.module_identifier()); + let con_id = con.id; + module_graph.revoke_connection(&con_id, true); + } force_build_deps.remove(&(dep_id, None)); } } From c7db90a5ced174e9598139f8ed65165e5b7ed203 Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Tue, 21 May 2024 18:27:53 +0800 Subject: [PATCH 15/48] test: check hot step match (#6592) --- packages/rspack-test-tools/etc/api.md | 3 + packages/rspack-test-tools/src/case/diff.ts | 94 +++++++++---------- .../src/case/stats-output.ts | 2 +- .../rspack-test-tools/src/helper/directory.ts | 2 +- .../src/processor/hot-step.ts | 2 +- .../rspack-test-tools/src/processor/hot.ts | 26 ++++- .../rspack-test-tools/src/processor/stats.ts | 2 +- .../src/runner/runner/basic.ts | 4 +- .../__snapshots__/StatsOutput.test.js.snap | 72 +++++++------- .../compilerCases/splitchunks-minchunks.js | 4 +- .../tests/hotCases/chunk/issue-4476/file.js | 2 - .../chunk/multi-chunk-single-runtime/file.js | 2 - .../multi-chunk-single-runtime/main/index.js | 2 +- .../tests/hotCases/chunk/multi-chunk/file.js | 2 - .../multi-chunk-single-runtime/file.js | 2 - .../runtime/dispose-removed-chunk/a.js | 1 - .../runtime/update-multiple-times/file.js | 2 - 17 files changed, 117 insertions(+), 107 deletions(-) diff --git a/packages/rspack-test-tools/etc/api.md b/packages/rspack-test-tools/etc/api.md index a9804919707..cfbe5ffe3f0 100644 --- a/packages/rspack-test-tools/etc/api.md +++ b/packages/rspack-test-tools/etc/api.md @@ -364,6 +364,8 @@ export class HookTaskProcessor extends SnapshotProcesso export class HotProcessor extends BasicProcessor { constructor(_hotOptions: IHotProcessorOptions); // (undocumented) + afterAll(context: ITestContext): Promise; + // (undocumented) static defaultOptions(hotOptions: IHotProcessorOptions, updateOptions: TUpdateOptions): IBasicProcessorOptions["defaultOptions"]; // (undocumented) static findBundle(hotOptions: IHotProcessorOptions): IBasicProcessorOptions["findBundle"]; @@ -1234,6 +1236,7 @@ export type TTestRunResult = Record; // @public (undocumented) export type TUpdateOptions = { updateIndex: number; + totalIndex: number; }; // @public (undocumented) diff --git a/packages/rspack-test-tools/src/case/diff.ts b/packages/rspack-test-tools/src/case/diff.ts index 0b4427c5f4f..4821219c0c0 100644 --- a/packages/rspack-test-tools/src/case/diff.ts +++ b/packages/rspack-test-tools/src/case/diff.ts @@ -41,61 +41,55 @@ export function createDiffCase(name: string, src: string, dist: string) { steps: [processor] }); - describe(name, () => { - beforeAll(async () => { - rimraf.sync(dist); - await tester.prepare(); - }); + beforeAll(async () => { + rimraf.sync(dist); + await tester.prepare(); + }); - do { - const prefix = `[${name}][${tester.step + 1}]:`; - describe(`${prefix}build`, () => { - beforeAll(async () => { - await tester.compile(); - }); - checkBundleFiles( - "webpack", - path.join(dist, "webpack"), - caseConfig.files! - ); - checkBundleFiles( - "rspack", - path.join(dist, "rspack"), - caseConfig.files! - ); + do { + const prefix = path.basename(name); + describe(`${prefix}:build`, () => { + beforeAll(async () => { + await tester.compile(); }); - describe(`${prefix}check`, () => { - beforeAll(async () => { - compareMap.clear(); - await tester.check(env); - }); - for (let file of caseConfig.files!) { - describe(`Comparing "${file}"`, () => { - let moduleResults: TModuleCompareResult[] = []; - let runtimeResults: TModuleCompareResult[] = []; - beforeAll(() => { - const fileResult = compareMap.get(file); - if (!fileResult) { - throw new Error(`File ${file} has no results`); - } - moduleResults = fileResult.modules; - runtimeResults = fileResult.runtimeModules; - }); - if (caseConfig.modules) { - checkCompareResults("modules", () => moduleResults); - } - if (caseConfig.runtimeModules) { - checkCompareResults("runtime modules", () => runtimeResults); + checkBundleFiles( + "webpack", + path.join(dist, "webpack"), + caseConfig.files! + ); + checkBundleFiles("rspack", path.join(dist, "rspack"), caseConfig.files!); + }); + describe(`${prefix}:check`, () => { + beforeAll(async () => { + compareMap.clear(); + await tester.check(env); + }); + for (let file of caseConfig.files!) { + describe(`Comparing "${file}"`, () => { + let moduleResults: TModuleCompareResult[] = []; + let runtimeResults: TModuleCompareResult[] = []; + beforeAll(() => { + const fileResult = compareMap.get(file); + if (!fileResult) { + throw new Error(`File ${file} has no results`); } + moduleResults = fileResult.modules; + runtimeResults = fileResult.runtimeModules; }); - } - const env = createLazyTestEnv(1000); - }); - } while (tester.next()); - - afterAll(async () => { - await tester.resume(); + if (caseConfig.modules) { + checkCompareResults("modules", () => moduleResults); + } + if (caseConfig.runtimeModules) { + checkCompareResults("runtime modules", () => runtimeResults); + } + }); + } + const env = createLazyTestEnv(1000); }); + } while (tester.next()); + + afterAll(async () => { + await tester.resume(); }); } diff --git a/packages/rspack-test-tools/src/case/stats-output.ts b/packages/rspack-test-tools/src/case/stats-output.ts index 28ce83f7b66..ba15a052e82 100644 --- a/packages/rspack-test-tools/src/case/stats-output.ts +++ b/packages/rspack-test-tools/src/case/stats-output.ts @@ -12,7 +12,7 @@ const creator = new BasicCaseCreator({ configFiles: ["rspack.config.js", "webpack.config.js"] }) ], - description: name => `should print correct stats for ${name}` + description: () => `should print correct stats for` }); export function createStatsOutputCase(name: string, src: string, dist: string) { diff --git a/packages/rspack-test-tools/src/helper/directory.ts b/packages/rspack-test-tools/src/helper/directory.ts index b0f37248d4d..ffca9ee44d8 100644 --- a/packages/rspack-test-tools/src/helper/directory.ts +++ b/packages/rspack-test-tools/src/helper/directory.ts @@ -64,7 +64,7 @@ export function describeByWalk( dist = path.join(sourceBase, caseName, relativeDist); } } - createCase(folder, source, dist); + createCase(name, source, dist); }); } }); diff --git a/packages/rspack-test-tools/src/processor/hot-step.ts b/packages/rspack-test-tools/src/processor/hot-step.ts index 375ae656e45..6baa3dcf6e4 100644 --- a/packages/rspack-test-tools/src/processor/hot-step.ts +++ b/packages/rspack-test-tools/src/processor/hot-step.ts @@ -155,7 +155,7 @@ export class HotSnapshotProcessor< const snapshotPath = context.getSource( `__snapshots__/${compilerOptions.target}/${step}.snap.txt` ); - const title = `Case ${this._options.name}: Step ${step}`; + const title = `Case ${path.basename(this._options.name)}: Step ${step}`; const hotUpdateFile: Array<{ name: string; content: string; diff --git a/packages/rspack-test-tools/src/processor/hot.ts b/packages/rspack-test-tools/src/processor/hot.ts index 515dc45c334..1c574b878d4 100644 --- a/packages/rspack-test-tools/src/processor/hot.ts +++ b/packages/rspack-test-tools/src/processor/hot.ts @@ -1,4 +1,5 @@ import { rspack } from "@rspack/core"; +import fs from "fs-extra"; import path from "path"; import { @@ -20,6 +21,7 @@ export interface IHotProcessorOptions export type TUpdateOptions = { updateIndex: number; + totalIndex: number; }; export class HotProcessor extends BasicProcessor { @@ -28,7 +30,8 @@ export class HotProcessor extends BasicProcessor { constructor(protected _hotOptions: IHotProcessorOptions) { const fakeUpdateLoaderOptions: TUpdateOptions = { - updateIndex: 0 + updateIndex: 0, + totalIndex: 0 }; super({ defaultOptions: HotProcessor.defaultOptions( @@ -47,6 +50,18 @@ export class HotProcessor extends BasicProcessor { } async run(env: ITestEnv, context: ITestContext) { + const changedFiles: string[] = require( + context.getSource("changed-file.js") + ); + this.updateOptions.totalIndex = changedFiles.reduce( + (res: number, file: string) => { + return Math.max( + fs.readFileSync(file, "utf-8").split("---").length, + res + ); + }, + 0 + ); context.setValue( this._options.name, "hotUpdateContext", @@ -84,6 +99,15 @@ export class HotProcessor extends BasicProcessor { }; } + async afterAll(context: ITestContext) { + await super.afterAll(context); + if (this.updateOptions.updateIndex + 1 !== this.updateOptions.totalIndex) { + throw new Error( + `Should run all hot steps (${this.updateOptions.updateIndex + 1} / ${this.updateOptions.totalIndex}): ${this._options.name}` + ); + } + } + static defaultOptions( hotOptions: IHotProcessorOptions, updateOptions: TUpdateOptions diff --git a/packages/rspack-test-tools/src/processor/stats.ts b/packages/rspack-test-tools/src/processor/stats.ts index 74175f1d4e1..7f5856dbbb5 100644 --- a/packages/rspack-test-tools/src/processor/stats.ts +++ b/packages/rspack-test-tools/src/processor/stats.ts @@ -177,7 +177,7 @@ export class StatsProcessor< .replace(/Rspack [^ )]+(\)?) compiled/g, "Rspack x.x.x$1 compiled") .replace( new RegExp(quoteMeta(testPath), "g"), - "Xdir/" + this._options.name + "Xdir/" + path.basename(this._options.name) ) .replace(/(\w)\\(\w)/g, "$1/$2") .replace(/, additional resolving: X ms/g, "") diff --git a/packages/rspack-test-tools/src/runner/runner/basic.ts b/packages/rspack-test-tools/src/runner/runner/basic.ts index 2503d5aa66a..8d5ee3faa0c 100644 --- a/packages/rspack-test-tools/src/runner/runner/basic.ts +++ b/packages/rspack-test-tools/src/runner/runner/basic.ts @@ -60,7 +60,9 @@ export abstract class BasicRunner< constructor(protected _options: IBasicRunnerOptions) {} run(file: string): Promise { - this.globalContext = this.createGlobalContext(); + if (!this.globalContext) { + this.globalContext = this.createGlobalContext(); + } this.baseModuleScope = this.createBaseModuleScope(); if (typeof this._options.testConfig.moduleScope === "function") { this._options.testConfig.moduleScope(this.baseModuleScope); diff --git a/packages/rspack-test-tools/tests/__snapshots__/StatsOutput.test.js.snap b/packages/rspack-test-tools/tests/__snapshots__/StatsOutput.test.js.snap index e1ca012926c..8734f08b87b 100644 --- a/packages/rspack-test-tools/tests/__snapshots__/StatsOutput.test.js.snap +++ b/packages/rspack-test-tools/tests/__snapshots__/StatsOutput.test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`statsOutput statsOutput/auxiliary-files-test should print correct stats for auxiliary-files-test 1`] = ` +exports[`statsOutput statsOutput/auxiliary-files-test should print correct stats for 1`] = ` "PublicPath: auto asset a09d8e0f399c215faa79.png 7 bytes {909} [emitted] [from: raw.png] (name: main) asset bundle.js 2.58 KiB {909} [emitted] (name: main) @@ -36,7 +36,7 @@ webpack/runtime/auto_public_path {909} Rspack compiled successfully (ecb93a91f44e8655019a)" `; -exports[`statsOutput statsOutput/builtin-swc-loader-parse-error should print correct stats for builtin-swc-loader-parse-error 1`] = ` +exports[`statsOutput statsOutput/builtin-swc-loader-parse-error should print correct stats for 1`] = ` "ERROR in ./index.ts × Module build failed: ├─▶ × @@ -53,7 +53,7 @@ exports[`statsOutput statsOutput/builtin-swc-loader-parse-error should print cor Rspack compiled with 1 error" `; -exports[`statsOutput statsOutput/css-concat-error should print correct stats for css-concat-error 1`] = ` +exports[`statsOutput statsOutput/css-concat-error should print correct stats for 1`] = ` "PublicPath: auto asset main.js 49 bytes [emitted] (name: main) Entrypoint main 49 bytes = main.js @@ -63,7 +63,7 @@ ERROR in × Resolve error: Can't resolve './src' in 'Xdir/css-concat-error' Rspack x.x.x compiled with 1 error in X s (ab49ea8e12ee2eaedeac)" `; -exports[`statsOutput statsOutput/filename should print correct stats for filename 1`] = ` +exports[`statsOutput statsOutput/filename should print correct stats for 1`] = ` "PublicPath: auto asset 521.xxxx.js 335 bytes [emitted] asset 909.xxxx.js 8.78 KiB [emitted] (name: main) @@ -74,7 +74,7 @@ runtime modules 11 modules Rspack x.x.x compiled successfully in X s (1441f057611125a5f036)" `; -exports[`statsOutput statsOutput/hot+production should print correct stats for hot+production 1`] = ` +exports[`statsOutput statsOutput/hot+production should print correct stats for 1`] = ` "PublicPath: auto asset main.js 32.3 KiB [emitted] (name: main) Entrypoint main 32.3 KiB = main.js @@ -83,20 +83,20 @@ runtime modules 11 modules Rspack x.x.x compiled successfully in X s (4a3dde925f48823cbd0d)" `; -exports[`statsOutput statsOutput/ignore-plugin should print correct stats for ignore-plugin 1`] = ` +exports[`statsOutput statsOutput/ignore-plugin should print correct stats for 1`] = ` "runtime modules 1 module ./index.js ./locals/en.js Xdir/ignore-plugin/locals|sync|/^\\\\.\\\\/.*$/" `; -exports[`statsOutput statsOutput/ignore-warning should print correct stats for ignore-warning 1`] = `"Rspack compiled successfully"`; +exports[`statsOutput statsOutput/ignore-warning should print correct stats for 1`] = `"Rspack compiled successfully"`; -exports[`statsOutput statsOutput/issue-3558 should print correct stats for issue-3558 1`] = `"Rspack compiled successfully"`; +exports[`statsOutput statsOutput/issue-3558 should print correct stats for 1`] = `"Rspack compiled successfully"`; -exports[`statsOutput statsOutput/legacy-ie-css-warning should print correct stats for legacy-ie-css-warning 1`] = `"Rspack compiled successfully"`; +exports[`statsOutput statsOutput/legacy-ie-css-warning should print correct stats for 1`] = `"Rspack compiled successfully"`; -exports[`statsOutput statsOutput/let-keyword-as-variable-name-error should print correct stats for let-keyword-as-variable-name-error 1`] = ` +exports[`statsOutput statsOutput/let-keyword-as-variable-name-error should print correct stats for 1`] = ` "ERROR in ./index.js × Module parse failed: ╰─▶ × JavaScript parsing error: \`let\` cannot be used as an identifier in strict mode @@ -122,7 +122,7 @@ ERROR in ./index.js Rspack compiled with 2 errors" `; -exports[`statsOutput statsOutput/limit-chunk-count-plugin should print correct stats for limit-chunk-count-plugin 1`] = ` +exports[`statsOutput statsOutput/limit-chunk-count-plugin should print correct stats for 1`] = ` "1 chunks: PublicPath: auto asset bundle1.js 3.69 KiB [emitted] (name: main) @@ -184,7 +184,7 @@ exports[`statsOutput statsOutput/limit-chunk-count-plugin should print correct s 4 chunks (Rspack x.x.x) compiled successfully in X s (b301d29aba57cb3237c3)" `; -exports[`statsOutput statsOutput/logging-loader should print correct stats for logging-loader 1`] = ` +exports[`statsOutput statsOutput/logging-loader should print correct stats for 1`] = ` "DEBUG LOG from TestLoader|Xdir/logging-loader/index.js <-> group info something @@ -193,7 +193,7 @@ exports[`statsOutput statsOutput/logging-loader should print correct stats for l " `; -exports[`statsOutput statsOutput/minify-error should print correct stats for minify-error 1`] = ` +exports[`statsOutput statsOutput/minify-error should print correct stats for 1`] = ` "ERROR in × JavaScript parsing error: Expected a semicolon ╭─[1:1] 1 │ const a {} @@ -205,12 +205,12 @@ exports[`statsOutput statsOutput/minify-error should print correct stats for min Rspack compiled with 1 error" `; -exports[`statsOutput statsOutput/named-chunk-group should print correct stats for named-chunk-group 1`] = ` +exports[`statsOutput statsOutput/named-chunk-group should print correct stats for 1`] = ` "Entrypoint main 8.77 KiB = main.js Chunk Group cimanyd 335 bytes = cimanyd.js" `; -exports[`statsOutput statsOutput/nonexistent-import-source-error should print correct stats for nonexistent-import-source-error 1`] = ` +exports[`statsOutput statsOutput/nonexistent-import-source-error should print correct stats for 1`] = ` "ERROR in ./index.js × Resolve error: Can't resolve 'not-exist' in 'Xdir/nonexistent-import-source-error' ╭──── @@ -221,7 +221,7 @@ exports[`statsOutput statsOutput/nonexistent-import-source-error should print co Rspack compiled with 1 error" `; -exports[`statsOutput statsOutput/optimization-runtime-chunk should print correct stats for optimization-runtime-chunk 1`] = ` +exports[`statsOutput statsOutput/optimization-runtime-chunk should print correct stats for 1`] = ` "Entrypoint e1 4.01 KiB = e1~runtime.js 3.68 KiB e1.js 336 bytes Entrypoint e2 4.01 KiB = e2~runtime.js 3.68 KiB e2.js 336 bytes chunk e1.js (e1) [entry] @@ -230,7 +230,7 @@ chunk e2.js (e2) [entry] chunk e2~runtime.js (e2~runtime) [initial]" `; -exports[`statsOutput statsOutput/optimization-runtime-chunk-multiple should print correct stats for optimization-runtime-chunk-multiple 1`] = ` +exports[`statsOutput statsOutput/optimization-runtime-chunk-multiple should print correct stats for 1`] = ` "Entrypoint e1 4.01 KiB = runtime~e1.js 3.68 KiB e1.js 336 bytes Entrypoint e2 4.01 KiB = runtime~e2.js 3.68 KiB e2.js 336 bytes chunk e1.js (e1) [entry] @@ -239,7 +239,7 @@ chunk runtime~e1.js (runtime~e1) [initial] chunk runtime~e2.js (runtime~e2) [initial]" `; -exports[`statsOutput statsOutput/optimization-runtime-chunk-single should print correct stats for optimization-runtime-chunk-single 1`] = ` +exports[`statsOutput statsOutput/optimization-runtime-chunk-single should print correct stats for 1`] = ` "Entrypoint e1 4.01 KiB = runtime.js 3.68 KiB e1.js 336 bytes Entrypoint e2 4.01 KiB = runtime.js 3.68 KiB e2.js 336 bytes chunk e1.js (e1) [entry] @@ -247,7 +247,7 @@ chunk e2.js (e2) [entry] chunk runtime.js (runtime) [initial]" `; -exports[`statsOutput statsOutput/optimization-runtime-chunk-true should print correct stats for optimization-runtime-chunk-true 1`] = ` +exports[`statsOutput statsOutput/optimization-runtime-chunk-true should print correct stats for 1`] = ` "Entrypoint e1 4.01 KiB = runtime~e1.js 3.68 KiB e1.js 336 bytes Entrypoint e2 4.01 KiB = runtime~e2.js 3.68 KiB e2.js 336 bytes chunk e1.js (e1) [entry] @@ -256,7 +256,7 @@ chunk runtime~e1.js (runtime~e1) [initial] chunk runtime~e2.js (runtime~e2) [initial]" `; -exports[`statsOutput statsOutput/parse-error should print correct stats for parse-error 1`] = ` +exports[`statsOutput statsOutput/parse-error should print correct stats for 1`] = ` "ERROR in ./b.js × Module parse failed: ╰─▶ × JavaScript parsing error: Expected ';', '}' or @@ -275,7 +275,7 @@ exports[`statsOutput statsOutput/parse-error should print correct stats for pars Rspack compiled with 1 error" `; -exports[`statsOutput statsOutput/performance-disabled should print correct stats for performance-disabled 1`] = ` +exports[`statsOutput statsOutput/performance-disabled should print correct stats for 1`] = ` "PublicPath: auto asset 697.js 128 bytes [emitted] asset 753.js 128 bytes [emitted] @@ -291,7 +291,7 @@ runtime modules 12 modules Rspack x.x.x compiled successfully in X s" `; -exports[`statsOutput statsOutput/performance-error should print correct stats for performance-error 1`] = ` +exports[`statsOutput statsOutput/performance-error should print correct stats for 1`] = ` "PublicPath: auto asset 697.js 128 bytes [emitted] asset 753.js 128 bytes [emitted] @@ -317,7 +317,7 @@ ERROR in × entrypoint size limit: The following entrypoint(s) combined asset si Rspack x.x.x compiled with 2 errors in X s" `; -exports[`statsOutput statsOutput/performance-no-hints should print correct stats for performance-no-hints 1`] = ` +exports[`statsOutput statsOutput/performance-no-hints should print correct stats for 1`] = ` "PublicPath: auto asset 697.js 128 bytes [emitted] asset 753.js 128 bytes [emitted] @@ -333,7 +333,7 @@ runtime modules 12 modules Rspack x.x.x compiled successfully in X s" `; -exports[`statsOutput statsOutput/prefetch-preload-mixed should print correct stats for prefetch-preload-mixed 1`] = ` +exports[`statsOutput statsOutput/prefetch-preload-mixed should print correct stats for 1`] = ` "chunk a1.js (a1) <{74}> chunk c2.js (c2) <{76}> chunk c1.js (c1) <{76}> @@ -347,7 +347,7 @@ chunk b1.js (b1) <{751}> chunk main.js (main) >{74}< >{751}< >{76}< (prefetch: {74} {751} {76}) [entry]" `; -exports[`statsOutput statsOutput/reasons should print correct stats for reasons 1`] = ` +exports[`statsOutput statsOutput/reasons should print correct stats for 1`] = ` "./a.js cjs self exports reference self cjs require ./a @@ -355,7 +355,7 @@ exports[`statsOutput statsOutput/reasons should print correct stats for reasons entry ./index" `; -exports[`statsOutput statsOutput/resolve-overflow-error should print correct stats for resolve-overflow-error 1`] = ` +exports[`statsOutput statsOutput/resolve-overflow-error should print correct stats for 1`] = ` "PublicPath: auto asset main.js 378 bytes [emitted] (name: main) Entrypoint main 378 bytes = main.js @@ -373,7 +373,7 @@ ERROR in ./index.js Rspack x.x.x compiled with 1 error in X s (e320e5265f17893abcb2)" `; -exports[`statsOutput statsOutput/resolve-unexpected-exports-in-pkg-error should print correct stats for resolve-unexpected-exports-in-pkg-error 1`] = ` +exports[`statsOutput statsOutput/resolve-unexpected-exports-in-pkg-error should print correct stats for 1`] = ` "PublicPath: auto asset bundle.js 945 bytes [emitted] (name: main) Entrypoint main 945 bytes = bundle.js @@ -386,14 +386,14 @@ ERROR in ./index.js Rspack x.x.x compiled with 1 error in X s (65e45aeef39f4464d5f7)" `; -exports[`statsOutput statsOutput/runtime-modules should print correct stats for runtime-modules 1`] = ` +exports[`statsOutput statsOutput/runtime-modules should print correct stats for 1`] = ` "./index.js webpack/runtime/has_own_property webpack/runtime/make_namespace_object webpack/runtime/define_property_getters" `; -exports[`statsOutput statsOutput/runtime-specific-exports should print correct stats for runtime-specific-exports 1`] = ` +exports[`statsOutput statsOutput/runtime-specific-exports should print correct stats for 1`] = ` "PublicPath: auto asset main.js 1.79 KiB [emitted] (name: main) Entrypoint main 1.79 KiB = main.js @@ -409,7 +409,7 @@ Entrypoint main 1.79 KiB = main.js Rspack x.x.x compiled successfully in X s (a74012a3fffb51e812fe)" `; -exports[`statsOutput statsOutput/side-effects-bailouts should print correct stats for side-effects-bailouts 1`] = ` +exports[`statsOutput statsOutput/side-effects-bailouts should print correct stats for 1`] = ` "PublicPath: auto asset main.js 1.86 KiB {909} [emitted] (name: main) Entrypoint main 1.86 KiB = main.js @@ -444,7 +444,7 @@ webpack/runtime/define_property_getters {909} 1970-04-20 12:42:42: Rspack x.x.x compiled successfully in X s (60c70856f42105a844ca)" `; -exports[`statsOutput statsOutput/simple-export should print correct stats for simple-export 1`] = ` +exports[`statsOutput statsOutput/simple-export should print correct stats for 1`] = ` "PublicPath: auto asset bundle.js 1.25 KiB [emitted] (name: main) Entrypoint main 1.25 KiB = bundle.js @@ -453,7 +453,7 @@ runtime modules 3 modules Rspack x.x.x compiled successfully in X s (2291cf9010086b87df21)" `; -exports[`statsOutput statsOutput/simple-module-source should print correct stats for simple-module-source 1`] = ` +exports[`statsOutput statsOutput/simple-module-source should print correct stats for 1`] = ` "PublicPath: auto asset bundle.js 2.1 KiB [emitted] (name: main) Entrypoint main 2.1 KiB = bundle.js @@ -464,7 +464,7 @@ orphan modules [orphan] 1 module Rspack compiled successfully (bf8a828b2158bcb51e2e)" `; -exports[`statsOutput statsOutput/stats-hooks should print correct stats for stats-hooks 1`] = ` +exports[`statsOutput statsOutput/stats-hooks should print correct stats for 1`] = ` "PublicPath: auto asset main.js 99 bytes [emitted111] (name: main) [testA: aaaaaa] Entrypoint main 99 bytes = main.js @@ -472,7 +472,7 @@ Entrypoint main 99 bytes = main.js Rspack compiled successfully (f4dda9cb00eba2407136)" `; -exports[`statsOutput statsOutput/try-require-module should print correct stats for try-require-module 1`] = ` +exports[`statsOutput statsOutput/try-require-module should print correct stats for 1`] = ` "WARNING in ./index.js ⚠ Resolve error: Can't resolve './missing-module' in 'Xdir/try-require-module' ╭─[1:1] @@ -485,7 +485,7 @@ exports[`statsOutput statsOutput/try-require-module should print correct stats f Rspack compiled with 1 warning" `; -exports[`statsOutput statsOutput/try-require-resolve-module should print correct stats for try-require-resolve-module 1`] = ` +exports[`statsOutput statsOutput/try-require-resolve-module should print correct stats for 1`] = ` "WARNING in ./index.js ⚠ Resolve error: Can't resolve './missing-module' in 'Xdir/try-require-resolve-module' ╭─[1:1] @@ -498,7 +498,7 @@ exports[`statsOutput statsOutput/try-require-resolve-module should print correct Rspack compiled with 1 warning" `; -exports[`statsOutput statsOutput/try-require-resolve-weak-module should print correct stats for try-require-resolve-weak-module 1`] = ` +exports[`statsOutput statsOutput/try-require-resolve-weak-module should print correct stats for 1`] = ` "WARNING in ./index.js ⚠ Resolve error: Can't resolve './missing-module' in 'Xdir/try-require-resolve-weak-module' ╭─[1:1] diff --git a/packages/rspack-test-tools/tests/compilerCases/splitchunks-minchunks.js b/packages/rspack-test-tools/tests/compilerCases/splitchunks-minchunks.js index 5079ccf3a20..88a7cb20e0b 100644 --- a/packages/rspack-test-tools/tests/compilerCases/splitchunks-minchunks.js +++ b/packages/rspack-test-tools/tests/compilerCases/splitchunks-minchunks.js @@ -1,5 +1,3 @@ -const path = require("path"); - /** @type {import('../..').TCompilerCaseConfig} */ module.exports = { description: "splitChunks.minChunks equals 0", @@ -24,7 +22,7 @@ module.exports = { }); }, async check(context) { - const errors = context.getError(path.basename(__filename)); + const errors = context.getError('compiler/splitchunks-minchunks'); expect(Array.isArray(errors)).toBeTruthy(); expect(errors.length).toBe(1); expect(errors[0].toString()).toContain( diff --git a/packages/rspack-test-tools/tests/hotCases/chunk/issue-4476/file.js b/packages/rspack-test-tools/tests/hotCases/chunk/issue-4476/file.js index 77e3c4ea564..bd816eaba4c 100644 --- a/packages/rspack-test-tools/tests/hotCases/chunk/issue-4476/file.js +++ b/packages/rspack-test-tools/tests/hotCases/chunk/issue-4476/file.js @@ -1,3 +1 @@ module.exports = 1; ---- -module.exports = 2; diff --git a/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk-single-runtime/file.js b/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk-single-runtime/file.js index 17fcb32fec0..bee27fc5256 100644 --- a/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk-single-runtime/file.js +++ b/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk-single-runtime/file.js @@ -5,5 +5,3 @@ module.exports = 2; module.exports = 3; --- module.exports = 4; ---- -module.exports = 5; diff --git a/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk-single-runtime/main/index.js b/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk-single-runtime/main/index.js index d4cb1e67f52..926debd9c04 100644 --- a/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk-single-runtime/main/index.js +++ b/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk-single-runtime/main/index.js @@ -6,7 +6,7 @@ it("should accept a dependencies multiple times", (done) => { var oldValue = value; value = require("../file"); expect(value).toBe(oldValue + 1); - if(value < 4) + if (value < 4) NEXT(require("../../../update")(done)); else done(); diff --git a/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk/file.js b/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk/file.js index 17fcb32fec0..bee27fc5256 100644 --- a/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk/file.js +++ b/packages/rspack-test-tools/tests/hotCases/chunk/multi-chunk/file.js @@ -5,5 +5,3 @@ module.exports = 2; module.exports = 3; --- module.exports = 4; ---- -module.exports = 5; diff --git a/packages/rspack-test-tools/tests/hotCases/newTreeshaking/multi-chunk-single-runtime/file.js b/packages/rspack-test-tools/tests/hotCases/newTreeshaking/multi-chunk-single-runtime/file.js index 17fcb32fec0..bee27fc5256 100644 --- a/packages/rspack-test-tools/tests/hotCases/newTreeshaking/multi-chunk-single-runtime/file.js +++ b/packages/rspack-test-tools/tests/hotCases/newTreeshaking/multi-chunk-single-runtime/file.js @@ -5,5 +5,3 @@ module.exports = 2; module.exports = 3; --- module.exports = 4; ---- -module.exports = 5; diff --git a/packages/rspack-test-tools/tests/hotCases/runtime/dispose-removed-chunk/a.js b/packages/rspack-test-tools/tests/hotCases/runtime/dispose-removed-chunk/a.js index 98290c901ba..b92e0f484b0 100644 --- a/packages/rspack-test-tools/tests/hotCases/runtime/dispose-removed-chunk/a.js +++ b/packages/rspack-test-tools/tests/hotCases/runtime/dispose-removed-chunk/a.js @@ -5,4 +5,3 @@ export default "version a1"; export default "version a2"; --- export default "version a2"; ---- diff --git a/packages/rspack-test-tools/tests/hotCases/runtime/update-multiple-times/file.js b/packages/rspack-test-tools/tests/hotCases/runtime/update-multiple-times/file.js index 17fcb32fec0..bee27fc5256 100644 --- a/packages/rspack-test-tools/tests/hotCases/runtime/update-multiple-times/file.js +++ b/packages/rspack-test-tools/tests/hotCases/runtime/update-multiple-times/file.js @@ -5,5 +5,3 @@ module.exports = 2; module.exports = 3; --- module.exports = 4; ---- -module.exports = 5; From 6c67a2a33cbdb4885adcc49837e66127adfb25f7 Mon Sep 17 00:00:00 2001 From: Hana Date: Wed, 22 May 2024 10:23:41 +0800 Subject: [PATCH 16/48] revert: revert swc comment preserver (#6389) (#6598) --- crates/rspack_plugin_javascript/src/visitors/mod.rs | 4 ++-- .../builtins-define/__snapshots__/output.snap.txt | 6 ++---- .../provide/__snapshots__/output.snap.txt | 3 +-- .../configCases/parsing/preserve-all-comments/index.js | 8 ++++---- .../duplicate/output.snap.txt | 3 +-- .../__snapshots__/treeshaking.snap.txt | 5 ++--- plugin-test/css-extract/enforceEsm.test.js | 5 ++++- 7 files changed, 16 insertions(+), 18 deletions(-) diff --git a/crates/rspack_plugin_javascript/src/visitors/mod.rs b/crates/rspack_plugin_javascript/src/visitors/mod.rs index a039e6786e2..18c4ff0af88 100644 --- a/crates/rspack_plugin_javascript/src/visitors/mod.rs +++ b/crates/rspack_plugin_javascript/src/visitors/mod.rs @@ -12,7 +12,7 @@ use swc_core::ecma::transforms::base::pass::Optional; use swc_core::ecma::visit::Fold; pub use self::dependency::*; -use self::swc_visitor::dropped_comments_preserver; +// use self::swc_visitor::dropped_comments_preserver; pub use self::JavascriptParser; /// Webpack builtin plugins @@ -71,7 +71,7 @@ pub fn run_before_pass( let comments = program.comments.take(); { let mut pass = chain!( - dropped_comments_preserver(comments.clone()), + // dropped_comments_preserver(comments.clone()), swc_visitor::resolver(unresolved_mark, top_level_mark, false), builtins_webpack_plugin(options, unresolved_mark, diagnostics), swc_visitor::hygiene(false, top_level_mark), diff --git a/packages/rspack-test-tools/tests/builtinCases/plugin-javascript/builtins-define/__snapshots__/output.snap.txt b/packages/rspack-test-tools/tests/builtinCases/plugin-javascript/builtins-define/__snapshots__/output.snap.txt index 273c6af0f81..392938f81a6 100644 --- a/packages/rspack-test-tools/tests/builtinCases/plugin-javascript/builtins-define/__snapshots__/output.snap.txt +++ b/packages/rspack-test-tools/tests/builtinCases/plugin-javascript/builtins-define/__snapshots__/output.snap.txt @@ -157,8 +157,7 @@ assert.deepStrictEqual(301, 301); assert.deepStrictEqual("302", "302"); assert.deepStrictEqual(303, 303); assert.deepStrictEqual(304, 304); -assert.deepStrictEqual(303..P4, undefined); -// "303.P4" +assert.deepStrictEqual(303..P4, undefined); // "303.P4" try { error_count += 1; P4.P1; @@ -260,8 +259,7 @@ __webpack_require__.d(__webpack_exports__, { }); const DO_NOT_CONVERTED7 = 402; const DO_NOT_CONVERTED9 = 403; -/* harmony default export */ __webpack_exports__["default"] = (401); -// DO_NOT_CONVERTED8 +/* harmony default export */ __webpack_exports__["default"] = (401); // DO_NOT_CONVERTED8 }), diff --git a/packages/rspack-test-tools/tests/builtinCases/plugin-javascript/provide/__snapshots__/output.snap.txt b/packages/rspack-test-tools/tests/builtinCases/plugin-javascript/provide/__snapshots__/output.snap.txt index 4d4c71a6fdd..90a71825408 100644 --- a/packages/rspack-test-tools/tests/builtinCases/plugin-javascript/provide/__snapshots__/output.snap.txt +++ b/packages/rspack-test-tools/tests/builtinCases/plugin-javascript/provide/__snapshots__/output.snap.txt @@ -170,8 +170,7 @@ process.title = "browser"; process.browser = true; process.env = {}; process.argv = []; -process.version = ""; -// empty string to avoid regexp issues +process.version = ""; // empty string to avoid regexp issues process.versions = {}; function noop() {} process.on = noop; diff --git a/packages/rspack-test-tools/tests/configCases/parsing/preserve-all-comments/index.js b/packages/rspack-test-tools/tests/configCases/parsing/preserve-all-comments/index.js index d9f7a28f453..53a54d2edbe 100644 --- a/packages/rspack-test-tools/tests/configCases/parsing/preserve-all-comments/index.js +++ b/packages/rspack-test-tools/tests/configCases/parsing/preserve-all-comments/index.js @@ -1,7 +1,7 @@ it("should preserve all comments", () => { require("./a"); - const fs = require("fs"); - let file = fs.readFileSync(__filename, "utf8"); - expect(file).toContain("c" + " outer"); - expect(file).toContain("c" + " inner"); + // const fs = require("fs"); + // let file = fs.readFileSync(__filename, "utf8"); + // expect(file).toContain("c" + " outer"); + // expect(file).toContain("c" + " inner"); }) diff --git a/packages/rspack-test-tools/tests/hookCases/normalModuleFactory#afterResolve/duplicate/output.snap.txt b/packages/rspack-test-tools/tests/hookCases/normalModuleFactory#afterResolve/duplicate/output.snap.txt index 3ba57a43768..798a9615b2c 100644 --- a/packages/rspack-test-tools/tests/hookCases/normalModuleFactory#afterResolve/duplicate/output.snap.txt +++ b/packages/rspack-test-tools/tests/hookCases/normalModuleFactory#afterResolve/duplicate/output.snap.txt @@ -80,8 +80,7 @@ var __webpack_exports__ = {}; /* harmony import */var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("fs"); /* harmony import */var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__); - -// b.js will be transform to c.js + // b.js will be transform to c.js it("should remove duplicate request modules generate by after resolve hook", ()=>{ diff --git a/packages/rspack-test-tools/tests/treeShakingCases/webpack-innergraph-try-globals/__snapshots__/treeshaking.snap.txt b/packages/rspack-test-tools/tests/treeShakingCases/webpack-innergraph-try-globals/__snapshots__/treeshaking.snap.txt index ddddeb7f02c..7f4bda7041f 100644 --- a/packages/rspack-test-tools/tests/treeShakingCases/webpack-innergraph-try-globals/__snapshots__/treeshaking.snap.txt +++ b/packages/rspack-test-tools/tests/treeShakingCases/webpack-innergraph-try-globals/__snapshots__/treeshaking.snap.txt @@ -32,9 +32,8 @@ try { var c = b; const a = 42; var ok2 = false; - eval(""); -} // TODO terser has a bug and incorrectly remove this code, eval opts out -catch (e) { + eval(""); // TODO terser has a bug and incorrectly remove this code, eval opts out +} catch (e) { var ok2 = true; } diff --git a/plugin-test/css-extract/enforceEsm.test.js b/plugin-test/css-extract/enforceEsm.test.js index a69d1da524f..a546a3e70da 100644 --- a/plugin-test/css-extract/enforceEsm.test.js +++ b/plugin-test/css-extract/enforceEsm.test.js @@ -65,5 +65,8 @@ it('should keep empty module when options.esModule is equal "false"', async () = expect( modules.filter(m => m.moduleType !== "runtime" && !m.orphan).length ).toBe(2); - expect(source("./simple.css", stats)).toMatchInlineSnapshot(`""`); + expect(source("./simple.css", stats)).toMatchInlineSnapshot(` + "// extracted by css-extract-rspack-plugin + " + `); }); From 7bd5f7da696d8bb69947ca76ee6eb27d2390daf7 Mon Sep 17 00:00:00 2001 From: Gengkun Date: Wed, 22 May 2024 11:02:05 +0800 Subject: [PATCH 17/48] fix: context module after resolve (#6595) --- Cargo.lock | 2 +- crates/node_binding/Cargo.toml | 1 - crates/node_binding/binding.d.ts | 6 ++--- .../node_binding/src/plugins/interceptor.rs | 5 ++-- .../raw_builtins/raw_lazy_compilation.rs | 6 ++--- .../src/options/raw_module/mod.rs | 10 ++----- crates/rspack_binding_values/Cargo.toml | 1 + .../src/context_module_factory.rs | 4 ++- crates/rspack_binding_values/src/lib.rs | 2 ++ crates/rspack_binding_values/src/regex.rs | 26 +++++++++++++++++++ crates/rspack_core/src/compiler/mod.rs | 1 + crates/rspack_core/src/context_module.rs | 1 + .../rspack_core/src/context_module_factory.rs | 5 +++- .../src/dependency/context/mod.rs | 2 +- crates/rspack_regex/src/lib.rs | 26 ++++++++++++------- .../critical-warning/rspack.config.js | 5 ---- .../context-module/without-extension/index.js | 5 ++++ .../without-extension/rspack.config.js | 15 +++++++++++ .../context-module/without-extension/sub/a.js | 1 + packages/rspack/src/Compiler.ts | 12 +++++++-- .../lazy-compilation/lazyCompilation.ts | 4 +-- .../builtin-plugin/lazy-compilation/plugin.ts | 6 ++--- 22 files changed, 102 insertions(+), 44 deletions(-) create mode 100644 crates/rspack_binding_values/src/regex.rs create mode 100644 packages/rspack-test-tools/tests/configCases/context-module/without-extension/index.js create mode 100644 packages/rspack-test-tools/tests/configCases/context-module/without-extension/rspack.config.js create mode 100644 packages/rspack-test-tools/tests/configCases/context-module/without-extension/sub/a.js diff --git a/Cargo.lock b/Cargo.lock index 202b57293f2..ea523bd76a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2870,6 +2870,7 @@ dependencies = [ "rspack_core", "rspack_error", "rspack_napi", + "rspack_regex", "rustc-hash", "serde", ] @@ -3137,7 +3138,6 @@ dependencies = [ "rspack_hook", "rspack_identifier", "rspack_napi", - "rspack_regex", "rspack_tracing", "tokio", "tracing", diff --git a/crates/node_binding/Cargo.toml b/crates/node_binding/Cargo.toml index cd82e107569..f3c6877b463 100644 --- a/crates/node_binding/Cargo.toml +++ b/crates/node_binding/Cargo.toml @@ -24,7 +24,6 @@ rspack_hook = { path = "../rspack_hook" } rspack_identifier = { path = "../rspack_identifier" } rspack_napi = { path = "../rspack_napi" } rspack_tracing = { path = "../rspack_tracing" } -rspack_regex = { path = "../rspack_regex" } tokio = { workspace = true, features = ["rt", "rt-multi-thread"] } async-trait = { workspace = true } diff --git a/crates/node_binding/binding.d.ts b/crates/node_binding/binding.d.ts index a70b0db259e..6d06a43bf2a 100644 --- a/crates/node_binding/binding.d.ts +++ b/crates/node_binding/binding.d.ts @@ -301,7 +301,7 @@ export interface JsContextModuleFactoryAfterResolveData { resource: string context: string request: string - regExp?: string + regExp?: RawRegex } export interface JsContextModuleFactoryBeforeResolveData { @@ -1231,7 +1231,7 @@ export interface RawReactOptions { refresh?: boolean } -export interface RawRegexMatcher { +export interface RawRegex { source: string flags: string } @@ -1288,7 +1288,7 @@ export interface RawRspackFuture { export interface RawRuleSetCondition { type: "string" | "regexp" | "logical" | "array" | "function" stringMatcher?: string - regexpMatcher?: RawRegexMatcher + regexpMatcher?: RawRegex logicalMatcher?: Array arrayMatcher?: Array funcMatcher?: (value: string) => boolean diff --git a/crates/node_binding/src/plugins/interceptor.rs b/crates/node_binding/src/plugins/interceptor.rs index 0937ea7df60..0e5f7e2ff4f 100644 --- a/crates/node_binding/src/plugins/interceptor.rs +++ b/crates/node_binding/src/plugins/interceptor.rs @@ -45,7 +45,6 @@ use rspack_core::{ use rspack_hook::{Hook, Interceptor}; use rspack_identifier::IdentifierSet; use rspack_napi::threadsafe_function::ThreadsafeFunction; -use rspack_regex::RspackRegex; #[napi(object)] pub struct JsTap { @@ -1246,7 +1245,7 @@ impl ContextModuleFactoryAfterResolve for ContextModuleFactoryAfterResolveTap { resource: d.resource.to_owned(), context: d.context.to_owned(), request: d.request.to_owned(), - reg_exp: d.reg_exp.clone().map(|r| r.to_string()), + reg_exp: d.reg_exp.clone().map(|r| r.into()), }) } }; @@ -1258,7 +1257,7 @@ impl ContextModuleFactoryAfterResolve for ContextModuleFactoryAfterResolveTap { context: d.context, request: d.request, reg_exp: match d.reg_exp { - Some(r) => Some(RspackRegex::new(&r)?), + Some(r) => Some(r.try_into()?), None => None, }, }; diff --git a/crates/rspack_binding_options/src/options/raw_builtins/raw_lazy_compilation.rs b/crates/rspack_binding_options/src/options/raw_builtins/raw_lazy_compilation.rs index 5a74ea15191..da102234beb 100644 --- a/crates/rspack_binding_options/src/options/raw_builtins/raw_lazy_compilation.rs +++ b/crates/rspack_binding_options/src/options/raw_builtins/raw_lazy_compilation.rs @@ -3,7 +3,7 @@ use napi::{ Either, }; use napi_derive::napi; -use rspack_binding_values::{JsModule, ToJsModule}; +use rspack_binding_values::{JsModule, RawRegex, ToJsModule}; use rspack_core::ModuleIdentifier; use rspack_napi::threadsafe_function::ThreadsafeFunction; use rspack_plugin_lazy_compilation::{ @@ -12,11 +12,9 @@ use rspack_plugin_lazy_compilation::{ }; use rspack_regex::RspackRegex; -use crate::RawRegexMatcher; - #[derive(Debug)] pub struct RawLazyCompilationTest>>( - pub Either, + pub Either, ); impl FromNapiValue for RawLazyCompilationTest { diff --git a/crates/rspack_binding_options/src/options/raw_module/mod.rs b/crates/rspack_binding_options/src/options/raw_module/mod.rs index 6c4094db46e..bc69f1a5c7f 100644 --- a/crates/rspack_binding_options/src/options/raw_module/mod.rs +++ b/crates/rspack_binding_options/src/options/raw_module/mod.rs @@ -7,6 +7,7 @@ use derivative::Derivative; use napi::bindgen_prelude::Either3; use napi::Either; use napi_derive::napi; +use rspack_binding_values::RawRegex; use rspack_core::{ AssetGeneratorDataUrl, AssetGeneratorDataUrlFnArgs, AssetGeneratorDataUrlOptions, AssetGeneratorOptions, AssetInlineGeneratorOptions, AssetParserDataUrl, @@ -90,19 +91,12 @@ impl Debug for RawModuleRuleUses { } } -#[derive(Debug)] -#[napi(object)] -pub struct RawRegexMatcher { - pub source: String, - pub flags: String, -} - #[napi(object, object_to_js = false)] pub struct RawRuleSetCondition { #[napi(ts_type = r#""string" | "regexp" | "logical" | "array" | "function""#)] pub r#type: String, pub string_matcher: Option, - pub regexp_matcher: Option, + pub regexp_matcher: Option, pub logical_matcher: Option>, pub array_matcher: Option>, #[napi(ts_type = r#"(value: string) => boolean"#)] diff --git a/crates/rspack_binding_values/Cargo.toml b/crates/rspack_binding_values/Cargo.toml index f0bacd650d1..ae3e8095f6d 100644 --- a/crates/rspack_binding_values/Cargo.toml +++ b/crates/rspack_binding_values/Cargo.toml @@ -12,5 +12,6 @@ napi-derive = { workspace = true } rspack_core = { path = "../rspack_core" } rspack_error = { path = "../rspack_error" } rspack_napi = { path = "../rspack_napi" } +rspack_regex = { path = "../rspack_regex" } rustc-hash = { workspace = true } serde = { workspace = true } diff --git a/crates/rspack_binding_values/src/context_module_factory.rs b/crates/rspack_binding_values/src/context_module_factory.rs index d061d21046f..53efd945cc3 100644 --- a/crates/rspack_binding_values/src/context_module_factory.rs +++ b/crates/rspack_binding_values/src/context_module_factory.rs @@ -1,6 +1,8 @@ use napi::bindgen_prelude::Either; use napi_derive::napi; +use crate::RawRegex; + #[napi(object)] pub struct JsContextModuleFactoryBeforeResolveData { pub context: String, @@ -15,7 +17,7 @@ pub struct JsContextModuleFactoryAfterResolveData { pub resource: String, pub context: String, pub request: String, - pub reg_exp: Option, + pub reg_exp: Option, } pub type JsContextModuleFactoryAfterResolveResult = diff --git a/crates/rspack_binding_values/src/lib.rs b/crates/rspack_binding_values/src/lib.rs index dd35fc923b4..2eea928b733 100644 --- a/crates/rspack_binding_values/src/lib.rs +++ b/crates/rspack_binding_values/src/lib.rs @@ -10,6 +10,7 @@ mod filename; mod module; mod normal_module_factory; mod path_data; +mod regex; mod source; mod stats; mod utils; @@ -25,6 +26,7 @@ pub use filename::*; pub use module::*; pub use normal_module_factory::*; pub use path_data::*; +pub use regex::*; pub use source::*; pub use stats::*; pub use utils::*; diff --git a/crates/rspack_binding_values/src/regex.rs b/crates/rspack_binding_values/src/regex.rs new file mode 100644 index 00000000000..27a1552527b --- /dev/null +++ b/crates/rspack_binding_values/src/regex.rs @@ -0,0 +1,26 @@ +use napi_derive::napi; +use rspack_regex::RspackRegex; + +#[derive(Debug)] +#[napi(object)] +pub struct RawRegex { + pub source: String, + pub flags: String, +} + +impl From for RawRegex { + fn from(value: RspackRegex) -> Self { + Self { + source: value.source().to_string(), + flags: value.flags().to_string(), + } + } +} + +impl TryFrom for RspackRegex { + type Error = rspack_error::Error; + + fn try_from(value: RawRegex) -> Result { + Self::with_flags(&value.source, &value.flags) + } +} diff --git a/crates/rspack_core/src/compiler/mod.rs b/crates/rspack_core/src/compiler/mod.rs index ff3b73ab30b..80e47cd46a7 100644 --- a/crates/rspack_core/src/compiler/mod.rs +++ b/crates/rspack_core/src/compiler/mod.rs @@ -440,6 +440,7 @@ where self.plugin_driver.clone(), )), context_module_factory: Arc::new(ContextModuleFactory::new( + self.resolver_factory.clone(), self.loader_resolver_factory.clone(), self.plugin_driver.clone(), )), diff --git a/crates/rspack_core/src/context_module.rs b/crates/rspack_core/src/context_module.rs index 37560ff757d..a5f120788f3 100644 --- a/crates/rspack_core/src/context_module.rs +++ b/crates/rspack_core/src/context_module.rs @@ -161,6 +161,7 @@ pub struct ContextModuleOptions { pub resolve_options: Option>, } +#[derive(Debug)] pub enum FakeMapValue { Bit(FakeNamespaceObjectMode), Map(HashMap), diff --git a/crates/rspack_core/src/context_module_factory.rs b/crates/rspack_core/src/context_module_factory.rs index cddbbdd80d1..d14476a361d 100644 --- a/crates/rspack_core/src/context_module_factory.rs +++ b/crates/rspack_core/src/context_module_factory.rs @@ -75,6 +75,7 @@ pub struct ContextModuleFactoryHooks { #[derive(Debug)] pub struct ContextModuleFactory { + resolver_factory: Arc, loader_resolver_factory: Arc, plugin_driver: SharedPluginDriver, } @@ -101,10 +102,12 @@ impl ModuleFactory for ContextModuleFactory { impl ContextModuleFactory { pub fn new( + resolver_factory: Arc, loader_resolver_factory: Arc, plugin_driver: SharedPluginDriver, ) -> Self { Self { + resolver_factory, loader_resolver_factory, plugin_driver, } @@ -296,7 +299,7 @@ impl ContextModuleFactory { let module = ContextModule::new( context_module_options.clone(), - self.loader_resolver_factory.clone(), + self.resolver_factory.clone(), ); Ok(Some(ModuleFactoryResult::new_with_module(Box::new(module)))) } diff --git a/crates/rspack_plugin_javascript/src/dependency/context/mod.rs b/crates/rspack_plugin_javascript/src/dependency/context/mod.rs index 0ebdbb39030..f9fabd252fe 100644 --- a/crates/rspack_plugin_javascript/src/dependency/context/mod.rs +++ b/crates/rspack_plugin_javascript/src/dependency/context/mod.rs @@ -21,7 +21,7 @@ fn create_resource_identifier_for_context_dependency( let regexp = options .reg_exp .as_ref() - .map(|r| r.to_string()) + .map(|r| r.to_source_string()) .unwrap_or_default(); let include = options.include.as_deref().unwrap_or_default(); let exclude = options.exclude.as_deref().unwrap_or_default(); diff --git a/crates/rspack_regex/src/lib.rs b/crates/rspack_regex/src/lib.rs index af5fa4ad416..4434936723a 100644 --- a/crates/rspack_regex/src/lib.rs +++ b/crates/rspack_regex/src/lib.rs @@ -1,6 +1,6 @@ #![feature(let_chains)] -use std::fmt::{Debug, Display}; +use std::fmt::Debug; use rspack_error::Error; use swc_core::ecma::ast::Regex as SwcRegex; @@ -20,7 +20,7 @@ pub struct RspackRegex { impl Debug for RspackRegex { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("RspackRegex") - .field(&self.to_string()) + .field(&self.to_source_string()) .finish() } } @@ -48,27 +48,35 @@ impl RspackRegex { }) } + pub fn source(&self) -> &str { + &self.source + } + + pub fn flags(&self) -> &str { + &self.flags + } + pub fn new(expr: &str) -> Result { Self::with_flags(expr, "") } + // https://github.com/webpack/webpack/blob/4baf1c075d59babd028f8201526cb8c4acfd24a0/lib/dependencies/ContextDependency.js#L30 + pub fn to_source_string(&self) -> String { + format!("/{}/{}", self.source, self.flags) + } + + // https://github.com/webpack/webpack/blob/4baf1c075d59babd028f8201526cb8c4acfd24a0/lib/ContextModule.js#L192 pub fn to_pretty_string(&self, strip_slash: bool) -> String { if strip_slash { format!("{}{}", self.source, self.flags) } else { - self.to_string() + self.to_source_string() } .replace('!', "%21") .replace('|', "%7C") } } -impl Display for RspackRegex { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "/{}/{}", self.source, self.flags) - } -} - impl TryFrom<&SwcRegex> for RspackRegex { type Error = Error; diff --git a/packages/rspack-test-tools/tests/configCases/context-module/critical-warning/rspack.config.js b/packages/rspack-test-tools/tests/configCases/context-module/critical-warning/rspack.config.js index 0f3729b75f9..d37cadb2595 100644 --- a/packages/rspack-test-tools/tests/configCases/context-module/critical-warning/rspack.config.js +++ b/packages/rspack-test-tools/tests/configCases/context-module/critical-warning/rspack.config.js @@ -8,9 +8,4 @@ module.exports = { } } }, - plugins: [ - function (compiler) { - console.log(compiler.options) - } - ] } diff --git a/packages/rspack-test-tools/tests/configCases/context-module/without-extension/index.js b/packages/rspack-test-tools/tests/configCases/context-module/without-extension/index.js new file mode 100644 index 00000000000..c249d05b9ce --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/context-module/without-extension/index.js @@ -0,0 +1,5 @@ +it("should import context module", async () => { + const n = "a" + const { default: a1 } = await import(`./sub/${n}`); + expect(a1).toBe("a") +}) diff --git a/packages/rspack-test-tools/tests/configCases/context-module/without-extension/rspack.config.js b/packages/rspack-test-tools/tests/configCases/context-module/without-extension/rspack.config.js new file mode 100644 index 00000000000..5bf1baaa08b --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/context-module/without-extension/rspack.config.js @@ -0,0 +1,15 @@ +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + plugins: [ + function(compiler) { + compiler.hooks.contextModuleFactory.tap( + "test", + contextModuleFactory => { + contextModuleFactory.hooks.afterResolve.tap("test", resolveData => { + // do nothing + }); + } + ); + } + ] +} diff --git a/packages/rspack-test-tools/tests/configCases/context-module/without-extension/sub/a.js b/packages/rspack-test-tools/tests/configCases/context-module/without-extension/sub/a.js new file mode 100644 index 00000000000..3ea9a15ea83 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/context-module/without-extension/sub/a.js @@ -0,0 +1 @@ +export default "a" diff --git a/packages/rspack/src/Compiler.ts b/packages/rspack/src/Compiler.ts index da76aebc3ac..406caffe34a 100644 --- a/packages/rspack/src/Compiler.ts +++ b/packages/rspack/src/Compiler.ts @@ -1063,7 +1063,10 @@ class Compiler { ? ({ resource: bindingData.resource, regExp: bindingData.regExp - ? new RegExp(bindingData.regExp) + ? new RegExp( + bindingData.regExp.source, + bindingData.regExp.flags + ) : undefined, request: bindingData.request, context: bindingData.context, @@ -1077,7 +1080,12 @@ class Compiler { resource: ret.resource, context: ret.context, request: ret.request, - regExp: ret.regExp?.toString() + regExp: ret.regExp + ? { + source: ret.regExp.source, + flags: ret.regExp.flags + } + : undefined } satisfies binding.JsContextModuleFactoryAfterResolveData) : false; return result; diff --git a/packages/rspack/src/builtin-plugin/lazy-compilation/lazyCompilation.ts b/packages/rspack/src/builtin-plugin/lazy-compilation/lazyCompilation.ts index 538d4d1b4e7..4d676e0c72e 100644 --- a/packages/rspack/src/builtin-plugin/lazy-compilation/lazyCompilation.ts +++ b/packages/rspack/src/builtin-plugin/lazy-compilation/lazyCompilation.ts @@ -1,4 +1,4 @@ -import { BuiltinPluginName, JsModule, RawRegexMatcher } from "@rspack/binding"; +import { BuiltinPluginName, JsModule, RawRegex } from "@rspack/binding"; import { create } from "../base"; @@ -13,7 +13,7 @@ export const BuiltinLazyCompilationPlugin = create( cacheable: boolean, entries: boolean, imports: boolean, - test?: RawRegexMatcher | ((m: JsModule) => boolean) + test?: RawRegex | ((m: JsModule) => boolean) ) => ({ module, cacheable, imports, entries, test }), "thisCompilation" ); diff --git a/packages/rspack/src/builtin-plugin/lazy-compilation/plugin.ts b/packages/rspack/src/builtin-plugin/lazy-compilation/plugin.ts index fd908a731b0..b5282db9bdd 100644 --- a/packages/rspack/src/builtin-plugin/lazy-compilation/plugin.ts +++ b/packages/rspack/src/builtin-plugin/lazy-compilation/plugin.ts @@ -1,4 +1,4 @@ -import { JsModule, RawRegexMatcher } from "@rspack/binding"; +import { JsModule, RawRegex } from "@rspack/binding"; import type { Compiler } from "../.."; import getBackend, { @@ -12,14 +12,14 @@ export default class LazyCompilationPlugin { cacheable: boolean; entries: boolean; imports: boolean; - test?: RawRegexMatcher | ((m: JsModule) => boolean); + test?: RawRegex | ((m: JsModule) => boolean); backend?: LazyCompilationDefaultBackendOptions; constructor( cacheable: boolean, entries: boolean, imports: boolean, - test?: RawRegexMatcher | ((m: JsModule) => boolean), + test?: RawRegex | ((m: JsModule) => boolean), backend?: LazyCompilationDefaultBackendOptions ) { this.cacheable = cacheable; From ab5cf59073a886324fdde464822d7e9a3ffd4eb6 Mon Sep 17 00:00:00 2001 From: gaoyuan <9aoyuao@gmail.com> Date: Wed, 22 May 2024 14:33:33 +0800 Subject: [PATCH 18/48] docs: add moment-locales-webpack-plugin support status (#6601) --- website/components/CommunityCompatibleTable.tsx | 6 ++++++ website/components/i18n/en.json | 1 + website/components/i18n/zh.json | 1 + 3 files changed, 8 insertions(+) diff --git a/website/components/CommunityCompatibleTable.tsx b/website/components/CommunityCompatibleTable.tsx index 14ec71fb1b5..a86a628d527 100644 --- a/website/components/CommunityCompatibleTable.tsx +++ b/website/components/CommunityCompatibleTable.tsx @@ -63,6 +63,12 @@ export const CommunityPluginCompatibleTable: React.FC = () => { url: 'https://github.com/johnagan/clean-webpack-plugin', status: CompatibleStatus.Compatible, }, + { + name: 'moment-locales-webpack-plugin', + url: 'https://www.npmjs.com/package/moment-locales-webpack-plugin', + status: CompatibleStatus.Compatible, + description: i18n[lang]['moment-locales-webpack-plugin-desc'], + }, { name: 'copy-webpack-plugin', url: 'https://www.npmjs.com/package/copy-webpack-plugin', diff --git a/website/components/i18n/en.json b/website/components/i18n/en.json index b28407c759c..89c748288b3 100644 --- a/website/components/i18n/en.json +++ b/website/components/i18n/en.json @@ -12,6 +12,7 @@ "tsconfig-paths-webpack-plugin-desc": "Use [resolve.tsconfigPath](/config/resolve#resolvetsconfigpath) instead", "image-minimizer-webpack-plugin-desc": "Only supports using [loader](https://www.npmjs.com/package/image-minimizer-webpack-plugin#standalone-loader) standalone", "case-sensitive-paths-webpack-plugin-desc": "`useBeforeEmitHook` option not supported", + "moment-locales-webpack-plugin-desc": "Support for this plugin was implemented in v0.7.0, please upgrade the Rspack version to use it", "resolve-plugin-un-support-desc": "`resolve.plugins` option not supported", "webpack-virtual-modules-desc": "Use [rspack-plugin-virtual-module](https://github.com/rspack-contrib/rspack-plugins/tree/main/packages/plugin-virtual-module) instead", "webpack-manifest-plugin-desc": "Use [rspack-manifest-plugin](https://github.com/rspack-contrib/rspack-manifest-plugin) instead", diff --git a/website/components/i18n/zh.json b/website/components/i18n/zh.json index 3bb0932fe13..0c5bc663f6a 100644 --- a/website/components/i18n/zh.json +++ b/website/components/i18n/zh.json @@ -11,6 +11,7 @@ "terser-webpack-plugin-desc": "使用 [SwcJsMinimizerRspackPlugin](/plugins/rspack/swc-js-minimizer-rspack-plugin) 替代", "tsconfig-paths-webpack-plugin-desc": "使用 [resolve.tsconfigPath](/config/resolve#resolvetsconfigpath) 替代", "case-sensitive-paths-webpack-plugin-desc": "不支持 `useBeforeEmitHook` 选项", + "moment-locales-webpack-plugin-desc": "在 v0.7.0 已实现对该插件的支持,请升级 Rspack 版本来使用", "image-minimizer-webpack-plugin-desc": "仅支持 [loader](https://www.npmjs.com/package/image-minimizer-webpack-plugin#standalone-loader) 用法", "resolve-plugin-un-support-desc": "不支持 `resolve.plugins`", "webpack-virtual-modules-desc": "使用 [rspack-plugin-virtual-module](https://github.com/rspack-contrib/rspack-plugins/tree/main/packages/plugin-virtual-module) 替代", From a19d601eb37b504a5e25b5133c0dee344b68141b Mon Sep 17 00:00:00 2001 From: Fy <1114550440@qq.com> Date: Wed, 22 May 2024 15:06:08 +0800 Subject: [PATCH 19/48] fix: fix module type export name (#6600) --- .../src/module_library_plugin.rs | 11 +++++++---- .../output-module/rspack-issue-6572/index.js | 4 ++++ .../output-module/rspack-issue-6572/lib.js | 3 +++ .../rspack-issue-6572/rspack.config.js | 16 ++++++++++++++++ 4 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/index.js create mode 100644 packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/lib.js create mode 100644 packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/rspack.config.js diff --git a/crates/rspack_plugin_library/src/module_library_plugin.rs b/crates/rspack_plugin_library/src/module_library_plugin.rs index 40728a65ff2..3eb54068a52 100644 --- a/crates/rspack_plugin_library/src/module_library_plugin.rs +++ b/crates/rspack_plugin_library/src/module_library_plugin.rs @@ -59,12 +59,15 @@ impl JavascriptModulesPluginPlugin for ModuleLibraryJavascriptModulesPluginPlugi let exports_info = module_graph.get_exports_info(&args.module); for id in exports_info.get_ordered_exports() { let info = id.get_export_info(&module_graph); - let info_name = info.name.as_ref().expect("name can't be empty").as_str(); - let name = to_identifier(info_name); - let var_name = format!("__webpack_exports__{name}"); + let chunk = args.compilation.chunk_by_ukey.expect_get(args.chunk); + let info_name = info.name.as_ref().expect("should have name"); + let used_name = info + .get_used_name(info.name.as_ref(), Some(&chunk.runtime)) + .expect("name can't be empty"); + let var_name = format!("__webpack_exports__{}", to_identifier(info_name)); source.add(RawSource::from(format!( "var {var_name} = __webpack_exports__{};\n", - property_access(&vec![info_name], 0) + property_access(&vec![used_name], 0) ))); exports.push(format!("{var_name} as {}", info_name)); } diff --git a/packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/index.js b/packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/index.js new file mode 100644 index 00000000000..4a7c5321a4c --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/index.js @@ -0,0 +1,4 @@ +it("should have valid export", async () => { + const exports = await import('./lib') + expect(exports).toContain('hello') +}); diff --git a/packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/lib.js b/packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/lib.js new file mode 100644 index 00000000000..44f11e8d0d5 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/lib.js @@ -0,0 +1,3 @@ +export function hello() { + console.log('hello world'); +} diff --git a/packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/rspack.config.js b/packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/rspack.config.js new file mode 100644 index 00000000000..56a602daeaf --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/output-module/rspack-issue-6572/rspack.config.js @@ -0,0 +1,16 @@ +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + mode: "production", + optimization: { + minimize: false, + }, + output: { + library: { + type: "module", + }, + filename: "[name].mjs", + module: true, + chunkFormat: "module", + chunkLoading: "import", + } +}; From 77ab6305a2a15f983e89e06a0d6b9893b82acab1 Mon Sep 17 00:00:00 2001 From: jinrui Date: Wed, 22 May 2024 15:10:10 +0800 Subject: [PATCH 20/48] feat: remove snapshot config (#6593) * feat: remove snapshot config * fix: ci * fix: update api doc * doc: update snapshot doc --- crates/node_binding/binding.d.ts | 6 - .../src/options/raw_snapshot.rs | 32 +----- crates/rspack_core/src/options/snapshot.rs | 21 +--- .../tests/__snapshots__/Defaults.test.js.snap | 11 +- .../cache/issues-6381/rspack.config.js | 10 +- .../cache/issuse-3254/rspack.config.js | 9 +- .../tests/defaultsCases/mode/production.js | 6 - .../tests/defaultsCases/mode/undefined.js | 6 - packages/rspack/etc/api.md | 104 +----------------- packages/rspack/src/config/adapter.ts | 23 +--- packages/rspack/src/config/defaults.ts | 27 +---- packages/rspack/src/config/normalization.ts | 11 +- packages/rspack/src/config/zod.ts | 15 +-- website/docs/en/config/_meta.json | 1 - website/docs/en/config/cache.mdx | 14 +-- website/docs/en/config/snapshot.mdx | 58 ---------- website/docs/zh/config/_meta.json | 1 - website/docs/zh/config/cache.mdx | 14 +-- website/docs/zh/config/snapshot.mdx | 58 ---------- 19 files changed, 21 insertions(+), 406 deletions(-) delete mode 100644 website/docs/en/config/snapshot.mdx delete mode 100644 website/docs/zh/config/snapshot.mdx diff --git a/crates/node_binding/binding.d.ts b/crates/node_binding/binding.d.ts index 6d06a43bf2a..418f13bb4d9 100644 --- a/crates/node_binding/binding.d.ts +++ b/crates/node_binding/binding.d.ts @@ -1316,13 +1316,7 @@ export interface RawSizeLimitsPluginOptions { } export interface RawSnapshotOptions { - resolve: RawSnapshotStrategy - module: RawSnapshotStrategy -} -export interface RawSnapshotStrategy { - hash: boolean - timestamp: boolean } export interface RawSourceMapDevToolPluginOptions { diff --git a/crates/rspack_binding_options/src/options/raw_snapshot.rs b/crates/rspack_binding_options/src/options/raw_snapshot.rs index 45f53f2a037..8d368ad436c 100644 --- a/crates/rspack_binding_options/src/options/raw_snapshot.rs +++ b/crates/rspack_binding_options/src/options/raw_snapshot.rs @@ -1,36 +1,12 @@ use napi_derive::napi; -use rspack_core::{SnapshotOptions, SnapshotStrategy}; +use rspack_core::SnapshotOptions; #[derive(Debug, Default)] #[napi(object)] -pub struct RawSnapshotStrategy { - pub hash: bool, - pub timestamp: bool, -} - -impl From for SnapshotStrategy { - fn from(value: RawSnapshotStrategy) -> Self { - Self { - hash: value.hash, - timestamp: value.timestamp, - } - } -} - -#[derive(Debug, Default)] -#[napi(object)] -pub struct RawSnapshotOptions { - pub resolve: RawSnapshotStrategy, - pub module: RawSnapshotStrategy, -} +pub struct RawSnapshotOptions; impl From for SnapshotOptions { - fn from(value: RawSnapshotOptions) -> Self { - let RawSnapshotOptions { resolve, module } = value; - - SnapshotOptions { - resolve: resolve.into(), - module: module.into(), - } + fn from(_value: RawSnapshotOptions) -> Self { + SnapshotOptions } } diff --git a/crates/rspack_core/src/options/snapshot.rs b/crates/rspack_core/src/options/snapshot.rs index ef35597e6a5..a616dade4c4 100644 --- a/crates/rspack_core/src/options/snapshot.rs +++ b/crates/rspack_core/src/options/snapshot.rs @@ -1,21 +1,2 @@ #[derive(Debug, Clone, Default)] -pub struct SnapshotStrategy { - pub hash: bool, - pub timestamp: bool, -} - -#[derive(Debug, Clone, Default)] -pub struct SnapshotOptions { - // Snapshots for resolving of build dependencies when using the persistent cache. - // pub resolve_build_dependencies: SnapshotStrategy, - // Snapshots for build dependencies when using the persistent cache. - // pub build_dependencies: SnapshotStrategy, - /// Snapshots for resolving of requests. - pub resolve: SnapshotStrategy, - /// Snapshots for building modules. - pub module: SnapshotStrategy, - // An array of paths that are managed by a package manager and contain a version or a hash in their paths. - // immutable_paths: Vec, - // An array of paths that are managed by a package manager. - // managed_paths: Vec, -} +pub struct SnapshotOptions; diff --git a/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap b/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap index fa7d4c5f9e0..230873cec70 100644 --- a/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap +++ b/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap @@ -523,16 +523,7 @@ Object { "index", ], }, - "snapshot": Object { - "module": Object { - "hash": false, - "timestamp": true, - }, - "resolve": Object { - "hash": false, - "timestamp": true, - }, - }, + "snapshot": Object {}, "stats": Object {}, "target": "web", "watch": false, diff --git a/packages/rspack-test-tools/tests/configCases/cache/issues-6381/rspack.config.js b/packages/rspack-test-tools/tests/configCases/cache/issues-6381/rspack.config.js index 70bba7f35c2..37e459caf35 100644 --- a/packages/rspack-test-tools/tests/configCases/cache/issues-6381/rspack.config.js +++ b/packages/rspack-test-tools/tests/configCases/cache/issues-6381/rspack.config.js @@ -1,12 +1,4 @@ /** @type {import("@rspack/core").Configuration} */ module.exports = { - cache: true, - snapshot: { - module: { - timestamp: true, - }, - resolve: { - timestamp: true, - }, - }, + cache: true }; diff --git a/packages/rspack-test-tools/tests/configCases/cache/issuse-3254/rspack.config.js b/packages/rspack-test-tools/tests/configCases/cache/issuse-3254/rspack.config.js index ae51cb66e13..37e459caf35 100644 --- a/packages/rspack-test-tools/tests/configCases/cache/issuse-3254/rspack.config.js +++ b/packages/rspack-test-tools/tests/configCases/cache/issuse-3254/rspack.config.js @@ -1,11 +1,4 @@ /** @type {import("@rspack/core").Configuration} */ module.exports = { - cache: true, - snapshot: { - module: { timestamp: true, hash: true }, - resolve: { - timestamp: true, - hash: true - } - } + cache: true }; diff --git a/packages/rspack-test-tools/tests/defaultsCases/mode/production.js b/packages/rspack-test-tools/tests/defaultsCases/mode/production.js index da347f9187a..7156ce0cc8d 100644 --- a/packages/rspack-test-tools/tests/defaultsCases/mode/production.js +++ b/packages/rspack-test-tools/tests/defaultsCases/mode/production.js @@ -52,11 +52,5 @@ module.exports = { + "maxAssetSize": 250000, + "maxEntrypointSize": 250000, + }, - @@ ... @@ - - "hash": false, - + "hash": true, - @@ ... @@ - - "hash": false, - + "hash": true, `) }; diff --git a/packages/rspack-test-tools/tests/defaultsCases/mode/undefined.js b/packages/rspack-test-tools/tests/defaultsCases/mode/undefined.js index f5dbbf6f6d9..eb0452e51f3 100644 --- a/packages/rspack-test-tools/tests/defaultsCases/mode/undefined.js +++ b/packages/rspack-test-tools/tests/defaultsCases/mode/undefined.js @@ -52,11 +52,5 @@ module.exports = { + "maxAssetSize": 250000, + "maxEntrypointSize": 250000, + }, - @@ ... @@ - - "hash": false, - + "hash": true, - @@ ... @@ - - "hash": false, - + "hash": true, `) }; diff --git a/packages/rspack/etc/api.md b/packages/rspack/etc/api.md index c4e2b40d338..0dc58da4c60 100644 --- a/packages/rspack/etc/api.md +++ b/packages/rspack/etc/api.md @@ -9092,46 +9092,7 @@ export const rspackOptions: z.ZodObject<{ optimizationBailout?: boolean | undefined; orphanModules?: boolean | undefined; }>]>>; - snapshot: z.ZodOptional; - timestamp: z.ZodOptional; - }, "strict", z.ZodTypeAny, { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - }, { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - }>>; - resolve: z.ZodOptional; - timestamp: z.ZodOptional; - }, "strict", z.ZodTypeAny, { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - }, { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - }>>; - }, "strict", z.ZodTypeAny, { - module?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; - resolve?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; - }, { - module?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; - resolve?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; - }>>; + snapshot: z.ZodOptional>; optimization: z.ZodOptional>; chunkIds: z.ZodOptional>; @@ -10383,16 +10344,7 @@ export const rspackOptions: z.ZodObject<{ optimizationBailout?: boolean | undefined; orphanModules?: boolean | undefined; } | undefined; - snapshot?: { - module?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; - resolve?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; - } | undefined; + snapshot?: {} | undefined; optimization?: { moduleIds?: "named" | "deterministic" | undefined; chunkIds?: "named" | "deterministic" | undefined; @@ -10826,16 +10778,7 @@ export const rspackOptions: z.ZodObject<{ optimizationBailout?: boolean | undefined; orphanModules?: boolean | undefined; } | undefined; - snapshot?: { - module?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; - resolve?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; - } | undefined; + snapshot?: {} | undefined; optimization?: { moduleIds?: "named" | "deterministic" | undefined; chunkIds?: "named" | "deterministic" | undefined; @@ -11397,46 +11340,7 @@ export const sharing: { export type SnapshotOptions = z.infer; // @public (undocumented) -const snapshotOptions: z.ZodObject<{ - module: z.ZodOptional; - timestamp: z.ZodOptional; - }, "strict", z.ZodTypeAny, { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - }, { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - }>>; - resolve: z.ZodOptional; - timestamp: z.ZodOptional; - }, "strict", z.ZodTypeAny, { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - }, { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - }>>; -}, "strict", z.ZodTypeAny, { - module?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; - resolve?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; -}, { - module?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; - resolve?: { - hash?: boolean | undefined; - timestamp?: boolean | undefined; - } | undefined; -}>; +const snapshotOptions: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>; // @public (undocumented) interface SourceMap { diff --git a/packages/rspack/src/config/adapter.ts b/packages/rspack/src/config/adapter.ts index 4428d92e548..6a83ea83b03 100644 --- a/packages/rspack/src/config/adapter.ts +++ b/packages/rspack/src/config/adapter.ts @@ -807,28 +807,9 @@ function getRawOptimization( } function getRawSnapshotOptions( - snapshot: SnapshotOptions + _snapshot: SnapshotOptions ): RawOptions["snapshot"] { - const { resolve, module } = snapshot; - assert(!isNil(resolve) && !isNil(module)); - const { timestamp: resolveTimestamp, hash: resolveHash } = resolve; - const { timestamp: moduleTimestamp, hash: moduleHash } = module; - assert( - !isNil(resolveTimestamp) && - !isNil(resolveHash) && - !isNil(moduleTimestamp) && - !isNil(moduleHash) - ); - return { - resolve: { - timestamp: resolveTimestamp, - hash: resolveHash - }, - module: { - timestamp: moduleTimestamp, - hash: moduleHash - } - }; + return {}; } function getRawExperiments( diff --git a/packages/rspack/src/config/defaults.ts b/packages/rspack/src/config/defaults.ts index e2de2bbc547..048e08049fc 100644 --- a/packages/rspack/src/config/defaults.ts +++ b/packages/rspack/src/config/defaults.ts @@ -200,30 +200,9 @@ const applyExperimentsDefaults = ( }; const applySnapshotDefaults = ( - snapshot: SnapshotOptions, - { production }: { production: boolean } -) => { - if (typeof snapshot.module === "object") { - D(snapshot.module, "timestamp", false); - D(snapshot.module, "hash", false); - } else { - F(snapshot, "module", () => - production - ? { timestamp: true, hash: true } - : { timestamp: true, hash: false } - ); - } - if (typeof snapshot.resolve === "object") { - D(snapshot.resolve, "timestamp", false); - D(snapshot.resolve, "hash", false); - } else { - F(snapshot, "resolve", () => - production - ? { timestamp: true, hash: true } - : { timestamp: true, hash: false } - ); - } -}; + _snapshot: SnapshotOptions, + _env: { production: boolean } +) => {}; const applyJavascriptParserOptionsDefaults = ( parserOptions: JavascriptParserOptions, diff --git a/packages/rspack/src/config/normalization.ts b/packages/rspack/src/config/normalization.ts index 1861ca7f2ac..55fce188809 100644 --- a/packages/rspack/src/config/normalization.ts +++ b/packages/rspack/src/config/normalization.ts @@ -248,16 +248,7 @@ export const getNormalizedRspackOptions = ( ...node } ), - snapshot: nestedConfig(config.snapshot, snapshot => ({ - resolve: optionalNestedConfig(snapshot.resolve, resolve => ({ - timestamp: resolve.timestamp, - hash: resolve.hash - })), - module: optionalNestedConfig(snapshot.module, module => ({ - timestamp: module.timestamp, - hash: module.hash - })) - })), + snapshot: nestedConfig(config.snapshot, _snapshot => ({})), cache: optionalNestedConfig(config.cache, cache => cache), stats: nestedConfig(config.stats, stats => { if (stats === false) { diff --git a/packages/rspack/src/config/zod.ts b/packages/rspack/src/config/zod.ts index 0d4ef82cf28..ea0f348a2b2 100644 --- a/packages/rspack/src/config/zod.ts +++ b/packages/rspack/src/config/zod.ts @@ -988,20 +988,7 @@ export type Node = z.infer; //#endregion //#region Snapshot -const snapshotOptions = z.strictObject({ - module: z - .strictObject({ - hash: z.boolean().optional(), - timestamp: z.boolean().optional() - }) - .optional(), - resolve: z - .strictObject({ - hash: z.boolean().optional(), - timestamp: z.boolean().optional() - }) - .optional() -}); +const snapshotOptions = z.strictObject({}); export type SnapshotOptions = z.infer; //#endregion diff --git a/website/docs/en/config/_meta.json b/website/docs/en/config/_meta.json index 0916c0471ef..33223af371f 100644 --- a/website/docs/en/config/_meta.json +++ b/website/docs/en/config/_meta.json @@ -12,7 +12,6 @@ "plugins", "dev-server", "cache", - "snapshot", "devtool", "target", "watch", diff --git a/website/docs/en/config/cache.mdx b/website/docs/en/config/cache.mdx index 200ca472671..dcbc6fdb22a 100644 --- a/website/docs/en/config/cache.mdx +++ b/website/docs/en/config/cache.mdx @@ -1,18 +1,6 @@ # Cache -Rspack will cache snapshots and intermediate products during the build process and use them in the next build to improve the speed of the build. Rspack will perform caching operations in the following process: - -- resolve module - -At this stage, Rspack will cache the results of module resolve requests and generate snapshots. When rebuilding, it will directly reuse valid snapshots to obtain results. For more snapshot configurations, refer to [snapshot.resolve](config/snapshot#snapshotresolve). - -- build module - -At this stage, Rspack will cache the results of module build and generate snapshots. When rebuilding, it will directly reuse valid snapshots to obtain results. For more snapshot configurations, refer to [snapshot.module](config/snapshot#snapshotmodule). - -- module code generation - -At this stage, Rspack will cache the final code generated by the module, and if the module has not changed, it will directly reuse the generated code when rebuilding. +Rspack will cache snapshots and intermediate products during the build process and use them in the next build to improve the speed of the build. :::info Cache Type Rspack currently only supports memory cache, persistent cache is under planning, for more details refer to [persistent-cache-support](/misc/planning/roadmap#persistent-cache-support). diff --git a/website/docs/en/config/snapshot.mdx b/website/docs/en/config/snapshot.mdx deleted file mode 100644 index 815435dad5b..00000000000 --- a/website/docs/en/config/snapshot.mdx +++ /dev/null @@ -1,58 +0,0 @@ -import WebpackLicense from '@components/webpack-license'; - - - -# Snapshot - -Used to decide how the file system snapshots are created and invalidated. - -- **Type:** - -```ts -type Snapshot = { - module?: { - hash?: boolean; - timestamp?: boolean; - }; - resolve?: { - hash?: boolean; - timestamp?: boolean; - }; -}; -``` - -### snapshot.resolve - -- **Type:** `object = {hash?: boolean, timestamp?: boolean}` - -- **Default:** `{ hash: false, timestamp: true }` - -Snapshots for resolving of requests. When both hash and timestamp are false, the snapshot will be valid forever. - -- hash: Compare content hashes to determine invalidation (more expensive than timestamp, but changes less often). -- timestamp: Compare timestamps to determine invalidation. - -### snapshot.module - -- **Type:** `object = {hash?: boolean, timestamp?: boolean}` - -- **Default:** `{ hash: false, timestamp: true }` - -Snapshots for building modules. When both hash and timestamp are false, the snapshot will be valid forever. - -- hash: Compare content hashes to determine invalidation (more expensive than timestamp, but changes less often). -- timestamp: Compare timestamps to determine invalidation. - -## Usage - -You can set the snapshot directly in `rspack.config.js`: - -```ts title="rspack.config.js" -module.exports = { - snapshot: { - resolve: { - hash: true, - }, - }, -}; -``` diff --git a/website/docs/zh/config/_meta.json b/website/docs/zh/config/_meta.json index 0916c0471ef..33223af371f 100644 --- a/website/docs/zh/config/_meta.json +++ b/website/docs/zh/config/_meta.json @@ -12,7 +12,6 @@ "plugins", "dev-server", "cache", - "snapshot", "devtool", "target", "watch", diff --git a/website/docs/zh/config/cache.mdx b/website/docs/zh/config/cache.mdx index e2cecf1f2dd..7813572ff27 100644 --- a/website/docs/zh/config/cache.mdx +++ b/website/docs/zh/config/cache.mdx @@ -1,18 +1,6 @@ # Cache -缓存:该选项可以开启或者关闭 Rspack 构建过程中对快照及中间产物的缓存,如果开启,在下次构建中可以使用它们来提升构建的速度。Rspack 在以下过程中会进行缓存操作。 - -- 模块解析 - -在此阶段 Rspack 会缓存模块解析请求的结果并生成快照,在重新构建时会直接复用有效的快照来获取结果,更多快照的配置参考 [snapshot.resolve](config/snapshot#snapshotresolve) - -- 模块构建 - -在此阶段 Rspack 会缓存模块构建的结果并生成快照,在重新构建时会直接复用有效的快照来获取结果,更多快照的配置参考 [snapshot.module](config/snapshot#snapshotmodule) - -- 模块代码生成 - -在此阶段 Rspack 会缓存模块最终生成的代码,在重新构建时若模块没有改动则直接复用结果代码。 +缓存:该选项可以开启或者关闭 Rspack 构建过程中对快照及中间产物的缓存,如果开启,在下次构建中可以使用它们来提升构建的速度。 :::info 缓存类型 rspack 当前仅支持内存缓存(Memory Cache),持久化缓存(Persistent Cache)正在规划中,更多细节参考 [Persistent Cache 支持](/misc/planning/roadmap#persistent-cache-支持)。 diff --git a/website/docs/zh/config/snapshot.mdx b/website/docs/zh/config/snapshot.mdx deleted file mode 100644 index d75e87f15e6..00000000000 --- a/website/docs/zh/config/snapshot.mdx +++ /dev/null @@ -1,58 +0,0 @@ -import WebpackLicense from '@components/webpack-license'; - - - -# Snapshot - -缓存快照:该选项用于决定“如何创建缓存使用的文件系统快照”及“如何检验快照是否有效”。 - -- **类型:** - -```ts -type Snapshot = { - module?: { - hash?: boolean; - timestamp?: boolean; - }; - resolve?: { - hash?: boolean; - timestamp?: boolean; - }; -}; -``` - -### snapshot.resolve - -- **类型:** `object = {hash?: boolean, timestamp?: boolean}` - -- **默认值:** `{ hash: false, timestamp: true }` - -解析请求的快照,当 hash 和 timestamp 同时为 false 时快照将一直有效。 - -- hash:通过比较文件内容哈希来判断是否无效。(比 timestamp 更耗时,但更改的频率较低)。 -- timestamp:通过比较文件修改的时间戳来判断是否有效。 - -### snapshot.module - -- **类型:** `object = {hash?: boolean, timestamp?: boolean}` - -- **默认值:** `{ hash: false, timestamp: true }` - -构建模块的快照,当 hash 和 timestamp 同时为 false 时快照将一直有效。 - -- hash:通过比较文件内容哈希来判断是否无效。(比 timestamp 更耗时,但更改的频率较低)。 -- timestamp:通过比较文件修改的时间戳来判断是否有效。 - -## 用法 - -你可以在 rspack.config.js 中直接设置 snapshot: - -```ts title="rspack.config.js" -module.exports = { - snapshot: { - resolve: { - hash: true, - }, - }, -}; -``` From 43819223d3d0e4ed27c93f47723d53e7216d30d6 Mon Sep 17 00:00:00 2001 From: Soon Date: Wed, 22 May 2024 15:51:18 +0800 Subject: [PATCH 21/48] docs: translate the dev guide (#6584) * docs: translate the dev guide * docs: update * docs: update * docs: update * docs: update * docs: update * docs: update * docs: update * docs: VSCode -> VS Code Co-authored-by: neverland * docs: VSCode -> VS Code * docs: VSCode -> VS COde * Update website/docs/zh/contribute/development/profiling.md Co-authored-by: neverland * docs: dot --------- Co-authored-by: neverland --- .../en/contribute/development/debugging.md | 24 +-- .../contribute/development/prerequisites.md | 2 +- website/docs/zh/_meta.json | 5 + website/docs/zh/contribute/_meta.json | 13 ++ .../zh/contribute/architecture/_meta.json | 1 + .../contribute/architecture/builtin-plugin.md | 58 +++++ .../contribute/architecture/rspack-loader.md | 80 +++++++ .../docs/zh/contribute/development/_meta.json | 10 + .../zh/contribute/development/building.md | 22 ++ .../zh/contribute/development/debugging.md | 202 ++++++++++++++++++ .../contribute/development/prerequisites.md | 32 +++ .../zh/contribute/development/profiling.md | 126 +++++++++++ .../zh/contribute/development/releasing.md | 33 +++ .../contribute/development/testing-rspack.mdx | 2 +- .../development/testing-webpack.mdx | 2 +- .../zh/contribute/development/testing.mdx | 2 +- website/docs/zh/contribute/index.mdx | 89 ++++++++ 17 files changed, 687 insertions(+), 16 deletions(-) create mode 100644 website/docs/zh/contribute/_meta.json create mode 100644 website/docs/zh/contribute/architecture/_meta.json create mode 100644 website/docs/zh/contribute/architecture/builtin-plugin.md create mode 100644 website/docs/zh/contribute/architecture/rspack-loader.md create mode 100644 website/docs/zh/contribute/development/_meta.json create mode 100644 website/docs/zh/contribute/development/building.md create mode 100644 website/docs/zh/contribute/development/debugging.md create mode 100644 website/docs/zh/contribute/development/prerequisites.md create mode 100644 website/docs/zh/contribute/development/profiling.md create mode 100644 website/docs/zh/contribute/development/releasing.md create mode 100644 website/docs/zh/contribute/index.mdx diff --git a/website/docs/en/contribute/development/debugging.md b/website/docs/en/contribute/development/debugging.md index ba2315dc8cc..d18255b9586 100644 --- a/website/docs/en/contribute/development/debugging.md +++ b/website/docs/en/contribute/development/debugging.md @@ -1,11 +1,11 @@ # Debugging -## Debugging with VSCode +## Debugging with VS Code 1. Install `go install github.com/go-delve/delve/cmd/dlv@latest` -2. Install VSCode extension [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) and [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) +2. Install VS Code extension [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) and [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) 3. build `@rspack/cli` and napi binding by run `pnpm install && pnpm -w build:cli:debug` -4. In VSCode's `Run and Debug` tab, select `debug-rspack` to start debugging the initial launch of `@rspack/cli`. This task can be configured in `.vscode/launch.json`, which launches the Node and Rust debugger together. +4. In VS Code's `Run and Debug` tab, select `debug-rspack` to start debugging the initial launch of `@rspack/cli`. This task can be configured in `.vscode/launch.json`, which launches the Node and Rust debugger together. ## Tracing @@ -108,7 +108,7 @@ npm run build:binding:debug npm run build:js ``` -### Configure `launch.json` in vscode +### Configure `launch.json` in VS Code It's necessary to configure two debug configurations within in `.vscode/launch.json.` @@ -116,11 +116,11 @@ It's necessary to configure two debug configurations within in `.vscode/launch.j ```jsonc { - "name": "attach:node”, - "request": "attach", // refer: https://code.visualstudio.com/docs/editor/debugging#_launch-versus-attach-configurations + "name": "attach:node", + "request": "attach", // refer: https://code.visualstudio.com/docs/editor/debugging#_launch-versus-attach-configurations "type": "node", // `9229` is the default port of message - "port": 9229 + "port": 9229, } ``` @@ -129,9 +129,9 @@ It's necessary to configure two debug configurations within in `.vscode/launch.j ```jsonc { "name": "launch:rust-from-node", - "request": "launch”, - "type": "lldb", // it means we use `lldb` to launch the binary file of `node` - "program": "node”, + "request": "launch", + "type": "lldb", // it means we use `lldb` to launch the binary file of `node` + "program": "node", "args": [ "--inspect", "--enable-source-maps", @@ -140,8 +140,8 @@ It's necessary to configure two debug configurations within in `.vscode/launch.j "-c", "${workspaceFolder}/examples/basic/rspack.config.js", ], - // `cwd` is just for repack find the correctly entry. - "cwd": "${workspaceFolder}/examples/basic/" + // `cwd` is just for repack find the correctly entry. + "cwd": "${workspaceFolder}/examples/basic/", } ``` diff --git a/website/docs/en/contribute/development/prerequisites.md b/website/docs/en/contribute/development/prerequisites.md index 850600dbfae..51b6aeb51f5 100644 --- a/website/docs/en/contribute/development/prerequisites.md +++ b/website/docs/en/contribute/development/prerequisites.md @@ -5,7 +5,7 @@ Rspack is built using [Rust](https://rust-lang.org/) and [NAPI-RS](https://napi. ## Setup Rust - Install Rust using [rustup](https://rustup.rs/). -- If you are using VSCode, we recommend installing the [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) extension. +- If you are using VS Code, we recommend installing the [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) extension. ## Setup Node.js diff --git a/website/docs/zh/_meta.json b/website/docs/zh/_meta.json index de15496964a..61ebc98a9d9 100644 --- a/website/docs/zh/_meta.json +++ b/website/docs/zh/_meta.json @@ -28,5 +28,10 @@ "text": "关于", "link": "/misc/faq", "activeMatch": "/misc" + }, + { + "text": "贡献", + "link": "/contribute/index", + "activeMatch": "/contribute" } ] diff --git a/website/docs/zh/contribute/_meta.json b/website/docs/zh/contribute/_meta.json new file mode 100644 index 00000000000..c23c9b2274f --- /dev/null +++ b/website/docs/zh/contribute/_meta.json @@ -0,0 +1,13 @@ +[ + "index", + { + "type": "dir", + "name": "development", + "label": "开发" + }, + { + "type": "dir", + "name": "architecture", + "label": "架构" + } +] diff --git a/website/docs/zh/contribute/architecture/_meta.json b/website/docs/zh/contribute/architecture/_meta.json new file mode 100644 index 00000000000..e4a3fe0cabd --- /dev/null +++ b/website/docs/zh/contribute/architecture/_meta.json @@ -0,0 +1 @@ +["builtin-plugin", "rspack-loader"] diff --git a/website/docs/zh/contribute/architecture/builtin-plugin.md b/website/docs/zh/contribute/architecture/builtin-plugin.md new file mode 100644 index 00000000000..ccc7943c6b9 --- /dev/null +++ b/website/docs/zh/contribute/architecture/builtin-plugin.md @@ -0,0 +1,58 @@ +# Builtin 插件 + +Builtin 插件使用 [rspack_macros](https://github.com/web-infra-dev/rspack/tree/7cc39cc4bb6f73791a5bcb175137ffd84b105da5/crates/rspack_macros) 来帮助你避免写重复的代码, 你可以使用 [cargo-expand](https://github.com/dtolnay/cargo-expand) 或者 [rust-analyzer expand macro](https://rust-analyzer.github.io/manual.html#expand-macro-recursively) 来检查展开后的代码,并且开发/测试这些宏, 你可以使用 [rspack_macros_test](https://github.com/web-infra-dev/rspack/tree/7cc39cc4bb6f73791a5bcb175137ffd84b105da5/crates/rspack_macros_test) 来开始. + +一个小例子如下: + +```rust +use rspack_hook::{plugin, plugin_hook}; +use rspack_core::{Plugin, PluginContext, ApplyContext, CompilerOptions}; +use rspack_core::CompilerCompilation; +use rspack_error::Result; + +// define the plugin +#[plugin] +pub struct MyPlugin { + options: MyPluginOptions +} + +// define the plugin hook +#[plugin_hook(CompilerCompilation for MuPlugin)] +async fn compilation(&self, compilation: &mut Compilation) -> Result<()> { + // do something... +} + +// implement apply method for the plugin +impl Plugin for MyPlugin { + fn apply(&self, ctx: PluginContext<&mut ApplyContext>, _options: &mut CompilerOptions) -> Result<()> { + ctx.context.compiler_hooks.tap(compilation::new(self)) + Ok(()) + } +} +``` + +并且这里也有 [一个例子](https://github.com/web-infra-dev/rspack/blob/7cc39cc4bb6f73791a5bcb175137ffd84b105da5/crates/rspack_plugin_ignore/src/lib.rs). + +如果你需要的钩子还没有定义,你可以通过 `rspack_hook::define_hook`, `compiler.hooks.assetEmitted` 来定义它,例如: + +```rust +// this will allow you define hook's arguments without limit +define_hook!(CompilerShouldEmit: AsyncSeriesBail(compilation: &mut Compilation) -> bool); +// ------------------ --------------- ----------------------------- ------- +// hook name exec kind hook arguments return value (Result>) + +#[derive(Debug, Default)] +pub struct CompilerHooks { + // ... + // and add it here + pub asset_emitted: CompilerAssetEmittedHook, +} +``` + +执行的类型有 5 种: + +- AsyncSeries,返回值为 `Result<()>` +- AsyncSeriesBail,返回值为 `Result>` +- AsyncParallel,返回值为 `Result<()>` +- SyncSeries,返回值为 `Result<()>` +- SyncSeriesBail,返回值为 `Result>` diff --git a/website/docs/zh/contribute/architecture/rspack-loader.md b/website/docs/zh/contribute/architecture/rspack-loader.md new file mode 100644 index 00000000000..d743a012f11 --- /dev/null +++ b/website/docs/zh/contribute/architecture/rspack-loader.md @@ -0,0 +1,80 @@ +# Rspack loader + +## 相关的 PRs + +- [rspack#2780](https://github.com/web-infra-dev/rspack/pull/2789) +- [rspack#2808](https://github.com/web-infra-dev/rspack/pull/2808) + +旧的架构是一个非常简单的版本,仅支持正常阶段的 loader。不考虑 pitch 的 loader。 +旧版本的基本概念是将普通 loader 转换为可以从 Rust 端调用的 native 函数。 +此外,出于性能考虑,Rspack 还从 JS 端编写了 loader 来缓解 Node/Rust 通信的性能问题。 + +在这个新架构中,loader 不会直接转换为 native 函数。相反,它与 webpack 的 loader-runner 解析其 loader 的方式几乎相同,通过利用标识符(identifier)。 +每次 Rspack 想要调用 JS loader 时,标识符都会被传递给 Node 侧的 handler 进行处理。这个实现还保留了由于性能问题编写 JS loader 的特性。 + +## 概述级解释 + +重构不会引入任何其他重大更改。所以它是向后兼容的。 +架构的改变也帮助我们实现了具有可组合性的 Pitch loader。 + +### Pitching loader + +Pitching loader 是一种改变 loader pipeline 流程的技术。 +它通常和内联 loader 的语法一起使用来创建另一个 loader pipeline。 +style-loader 等其他可能会消费以下 loader 的处理结果的 loader 可能会使用此技术。 +还有其他技术可以实现相同的功能,但这不属于本文的主题。 + +查看 [Pitching loader](https://webpack.js.org/api/loaders/#pitching-loader) 来获得更多信息。 + +## 参考级解释 + +### loader 执行的操作 + +在 loader 的原始实现中,Rspack首先会转换普通的 loader, +然后将其传递给 Rust 端。在构建模块的过程中,将直接调用这些 loader: + +![旧架构](https://user-images.githubusercontent.com/10465670/233357319-e80f6b32-331c-416d-b4b5-30f3e0e394bd.png) + +loader 运行程序仅位于 Rust 端,并直接从 Rust 端执行 loader。 +这种机制对于我们使用 webpack 的 loader-runner 来组合 loader 有很大的限制。 + +在新架构中,我们将把来自 Rust 核心的 loader 请求委托给位于 JS 端的调度程序。 +调度程序将规范化 loader 并使用修改后的 webpack loader-runner 执行这些 loader: + +![image](https://user-images.githubusercontent.com/10465670/233357805-923e0a27-609d-409a-b38d-96a083613235.png) + +normal 或者 pitch 的 loader 函数不会传递到 Rust 端。相反,每个 JS loader 都有 +它的唯一的标识符。如果一个模块请求 loader 来处理该模块, +Rspack 会将带有选项的标识符传递给 JS 端,以指示 Webpack(如 loader-runner) +处理转换。这也降低了编写我们自己的 loader 编译的复杂度。 + +### 传递 options 选项 + +选项通常会转换为 query,但有些选项包含无法序列化的字段,Rspack 会复用 webpack 创建的**_loader ident_** 作为唯一标识选项 +并在以后的加载过程中恢复它。 + +### 针对 pitching 的优化 + +正如我们之前所知,每个 loader 都有两个步骤:pitch 和 normal。 + +对于性能友好的互操作性,我们必须尽可能减少 Rust 和 JS 之间的通信。 + +通常情况下,loader 的执行步骤会是这样的: + +![image](https://user-images.githubusercontent.com/10465670/233360942-7517f22e-3861-47cb-be9e-6dd5f5e02a4a.png) + +上面 loader 的执行顺序如下所示: + +``` +loader-A(pitch) + loader-B(pitch) + loader-C(pitch) + loader-B(normal) +loader-A(normal) +``` + +上面的例子不包含任何 JS loader,但是如果我们将这些 loader 标记为注册在 JS 端: + +![image](https://user-images.githubusercontent.com/10465670/233362338-93e922f6-8812-4ca9-9d80-cf294e4f2ff8.png) + +执行顺序不会改变,但 Rspack 会将步骤 2/3/4 组合在一起,仅执行一次循环通讯。 diff --git a/website/docs/zh/contribute/development/_meta.json b/website/docs/zh/contribute/development/_meta.json new file mode 100644 index 00000000000..73c545f9117 --- /dev/null +++ b/website/docs/zh/contribute/development/_meta.json @@ -0,0 +1,10 @@ +[ + "prerequisites", + "building", + "testing", + "testing-webpack", + "testing-rspack", + "debugging", + "profiling", + "releasing" +] diff --git a/website/docs/zh/contribute/development/building.md b/website/docs/zh/contribute/development/building.md new file mode 100644 index 00000000000..448e9df5c25 --- /dev/null +++ b/website/docs/zh/contribute/development/building.md @@ -0,0 +1,22 @@ +# Building + +请查看 [准备工作](./prerequisites) 安装 Rust 和 Node.js 环境。 + +## 安装 Node.js 依赖 + +通过 [pnpm](https://pnpm.io/) 安装 Node.js 依赖。 + +```bash +# enable pnpm with corepack +corepack enable + +# Install dependencies +pnpm i +``` + +## 构建 Rspack + +- 执行 `cargo build` 编译 Rust 代码。 +- 执行 `pnpm run build:cli:debug` 编译 Node.js 和 Rust 代码。 + +被编译的二进制产物位于 `packages/rspack-cli/bin/rspack` 。 diff --git a/website/docs/zh/contribute/development/debugging.md b/website/docs/zh/contribute/development/debugging.md new file mode 100644 index 00000000000..5bb1102545b --- /dev/null +++ b/website/docs/zh/contribute/development/debugging.md @@ -0,0 +1,202 @@ +# Debugging + +## 通过 VS Code 调试 + +1. 安装 `go install github.com/go-delve/delve/cmd/dlv@latest` +2. 安装 VS Code 扩展 [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) 和 [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) +3. 通过执行 `pnpm install && pnpm -w build:cli:debug` 构建 `@rspack/cli` 和 napi binding +4. 在 VS Code 的 `Run and Debug` 栏中, 选择 `debug-rspack` 开始调试 `@rspack/cli` 的启动过程。 该任务可以在 `.vscode/launch.json` 中配置,会同时启动 Node 和 Rust 的调试器。 + +## Tracing + +[`tracing`](https://crates.io/crates/tracing) 被用于度量(instrumenting) Rspack。 + +被支持的 tracing 等级有: + +- release 版本是 `INFO`, `WARN` and `ERROR` +- debug 版本是 `TRACE`, `DEBUG`, `INFO`, `WARN` and `ERROR` + +使用 `RSPACK_PROFILE` 环境变量来展示 trace 信息。 + +```bash +RSPACK_PROFILE=TRACE=layer=logger rspack build +# filter for an event +RSPACK_PROFILE='TRACE=layer=logger&filter=rspack_core::compiler::compilation' rspack build +# with logger level +RSPACK_PROFILE='TRACE=layer=logger&filter=rspack_core::compiler::compilation=info' rspack build +# filter logs across multiple modules +RSPACK_PROFILE='TRACE=layer=logger&filter=rspack_core::compiler::compilation,rspack_core::build_chunk_graph::code_splitter' rspack build +# [fn_name] will show: +# - all functions calls to `fn_name` +# - the arguments(except for these in the `skip` list) +# - everything until this function returns +RSPACK_PROFILE='TRACE=layer=logger&filter=[build_chunk_graph]' rspack build +# compilation::chunk_asset is a custom instrument name +RSPACK_PROFILE='TRACE=layer=logger&filter=[compilation:chunk_asset]' rspack build +# log a specific function by their arguments +RSPACK_PROFILE='TRACE=layer=logger&filter=[compilation:chunk_asset{filename="main\.js"}]' rspack build +# It support regexp expression +RSPACK_PROFILE='TRACE=layer=logger&filter=[compilation:chunk_asset{filename=".*\.js"}]' rspack build +# disable ansi color escape codes +NO_COLOR=1 RSPACK_PROFILE=TRACE=layer=logger rspack build +``` + +### Resolver + +`oxc_resolver` 为了调试也会有一些 tracing 信息。 + +```bash +RSPACK_PROFILE='TRACE=filter=oxc_resolver=trace&layer=logger' rspack build +``` + +## rust-lldb + +`rust-lldb` 可用于从 debug 版本中获取 panic 信息 + +```bash +rust-lldb -- node /path/to/rspack build +``` + +启动后,按住 `r` 来执行程序。 + +例如,`examples/arco-pro` 运行崩溃了并且没有任何信息在[这个修复](https://github.com/web-infra-dev/rspack/pull/3195/files) 之前: + +``` +rspack/examples/arco-pro ❯ node ../../packages/rspack-cli/bin/rspack build +Rspack ██████████████████████░░░░░░░░░░░░░░░░░░ 56% building ./pages/welcome +zsh: bus error node ../../packages/rspack-cli/bin/rspack build +``` + +使用 `rust-lldb` + +```bash +rspack/examples/arco-pro ❯ rust-lldb -- node ../../packages/rspack-cli/bin/rspack build +``` + +按下 `r` 然后会打印: + +``` +Process 23110 stopped +* thread #10, name = 'tokio-runtime-worker', stop reason = EXC_BAD_ACCESS (code=2, address=0x70000cc66560) + frame #0: 0x0000000140d0db4b rspack.darwin-x64.node`swc_ecma_parser::parser::expr::ops::_$LT$impl$u20$swc_ecma_parser..parser..Parser$LT$I$GT$$GT$::parse_unary_expr::h29f49330a806839c(self=0x0000000000000000) at ops.rs:244 + 241 /// Parse unary expression and update expression. + 242 /// + 243 /// spec: 'UnaryExpression' +-> 244 pub(in crate::parser) fn parse_unary_expr(&mut self) -> PResult> { + 245 trace_cur!(self, parse_unary_expr); + 246 let start = cur_pos!(self); + 247 +Target 0: (node) stopped. +``` + +## 混合调试 + +本节旨在说明 JavaScript 和 Rust 混合调试的方法。 + +### 准备工作 + +为了说明这个过程,我将使用一个例子。首先介绍一下我使用的环境和例子。 + +- System: macos +- IDE: vscode +- Debugging target: `rspack build ${projectRoot}/basic` + +首先,您需要在调试模式下构建 rspack。为此,请在项目的根目录中执行以下命令: + +```bash +npm run build:binding:debug +npm run build:js +``` + +### 在 VS Code 中设置 `launch.json` + +需要在 `.vscode/launch.json` 中配置两个调试配置。 + +- 给 node 添加 attach: + +```jsonc +{ + "name": "attach:node", + "request": "attach", // refer: https://code.visualstudio.com/docs/editor/debugging#_launch-versus-attach-configurations + "type": "node", + // `9229` is the default port of message + "port": 9229, +} +``` + +- 和 lldb 的 launch 配置 + +```jsonc +{ + "name": "launch:rust-from-node", + "request": "launch", + "type": "lldb", // it means we use `lldb` to launch the binary file of `node` + "program": "node", + "args": [ + "--inspect", + "--enable-source-maps", + "${workspaceFolder}/packages/rspack-cli/bin/rspack", + "build", + "-c", + "${workspaceFolder}/examples/basic/rspack.config.js", + ], + // `cwd` is just for repack find the correctly entry. + "cwd": "${workspaceFolder}/examples/basic/", +} +``` + +之后,我们可以利用 [compounds](https://code.visualstudio.com/docs/editor/debugging#_compound-launch-configurations) 合并这两个命令: + +```json +{ + "name": "mix-debug", + "configurations": ["attach:node", "launch:rust-from-node"] +} +``` + +最终,你的 `launch.json` 应如下所示: + +```json +{ + "configurations": [ + { + "name": "attach:node", + "request": "attach", + "type": "node", + "port": 9229 + }, + { + "name": "launch:rust-from-node", + "request": "launch", + "type": "lldb", + "program": "node", + "args": [ + "--inspect", + "--enable-source-maps", + "${workspaceFolder}/packages/rspack-cli/bin/rspack", + "build", + "-c", + "${workspaceFolder}/examples/basic/rspack.config.js" + ], + "cwd": "${workspaceFolder}/examples/basic/" + } + ], + "compounds": [ + { + "name": "mix-debug", + "configurations": ["attach:node", "launch:rust-from-node"] + } + ] +} +``` + +### Debugging 尝试 + +接下来,我们可以引入一些断点并开始调试。 + +结果如下: + + diff --git a/website/docs/zh/contribute/development/prerequisites.md b/website/docs/zh/contribute/development/prerequisites.md new file mode 100644 index 00000000000..6c7b5de257c --- /dev/null +++ b/website/docs/zh/contribute/development/prerequisites.md @@ -0,0 +1,32 @@ +# 准备工作 + +Rspack 使用 [Rust](https://rust-lang.org/) 和 [NAPI-RS](https://napi.rs/) 构建,然后被发布为 [Node.js](https://nodejs.org/) 包。 + +## 安装 Rust + +- 使用 [rustup](https://rustup.rs/) 安装 Rust。 +- 如果你在使用 VS Code,我们推荐安装 [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) 扩展。 + +## 设置 Node.js + +### 安装 Node.js + +我们建议使用 Node.js 20 的 LTS 版本。 + +使用以下命令检查当前 Node.js 版本: + +```bash +node -v +``` + +如果你当前环境中没有安装 Node.js,你可以使用 [nvm](https://github.com/nvm-sh/nvm) 或者 [fnm](https://github.com/Schniz/fnm) 来安装它。 + +这里有一个如何通过 nvm 安装的示例: + +```bash +# Install Node.js LTS +nvm install 20 --lts + +# Switch to Node.js LTS +nvm use 20 +``` diff --git a/website/docs/zh/contribute/development/profiling.md b/website/docs/zh/contribute/development/profiling.md new file mode 100644 index 00000000000..ce69a2cf710 --- /dev/null +++ b/website/docs/zh/contribute/development/profiling.md @@ -0,0 +1,126 @@ +# Profiling + +在本节中,我们将探讨如何分析 Rspack Profile 以识别性能瓶颈。 + +通过检查 Rspack 将时间花在哪里,我们可以深入了解如何提高性能。 + +由于不同的分析器有不同的优势,使用多个分析器是一个好的选择。 + + + +## Tracing + +[`tracing`](https://crates.io/crates/tracing) 被用于度量(instrumenting) Rspack。 + +被支持 tracing 等级有: + +- release 版本是 `INFO`, `WARN` and `ERROR` +- debug 版本是 `TRACE`, `DEBUG`, `INFO`, `WARN` and `ERROR` + +两种方式开启 tracing: + +- 如果你正在使用 `@rspack/cli`,你可以通过 `RSPACK_PROFILE` 环境变量来开启它。 +- 如果你正在使用 `@rspack/core` 而不是 `@rspack/cli`,你可以通过`experimental_registerGlobalTrace` 和 `experimental_cleanupGlobalTrace` 开启,查看 [我们如何使用这两个函数在 `@rspack/cli` 中实现 `RSPACK_PROFILE`](https://github.com/web-infra-dev/rspack/blob/25df2981ce1f0232ab05109c0995a249f57e2a09/packages/rspack-cli/src/utils/profile.ts#L186-L187) 获取更多信息。 + +### Chrome + +[`tracing-chrome`](https://crates.io/crates/tracing-chrome) 支持以图形方式查看 tracing 信息。 + +![image](https://github.com/SyMind/rspack-dev-guide/assets/19852293/1af08ba1-a2e9-4e3e-99ab-87c1e62e067b) + +在运行 Rspack 之前设置环境变量 `RSPACK_PROFILE=TRACE=layer=chrome`,例如 + +```bash +RSPACK_PROFILE=TRACE=layer=chrome rspack build +``` + +产生了一个 trace 文件 (`.rspack-profile-${timestamp}/trace.json`) 在目前的工作目录。 + +JSON 跟踪文件可以在 `chrome://tracing` 或者 [ui.perfetto.dev](https://ui.perfetto.dev) 查看。 + +### Terminal + +可以通过 `RSPACK_PROFILE=TRACE=layer=logger` 在终端内查看细粒度的 tracing 事件数值,例如 + +```bash +RSPACK_PROFILE=TRACE=layer=logger rspack build +``` + +将打印传递给 Rspack 的选项以及每个单独的 tracing 事件. + +### Nodejs Profiling + +如果我们发现性能瓶颈在JS端(比如js loader),那么我们需要进一步分析 js 端,可以使用 Nodejs Profiling 来分析。例如 + +```bash +node --cpu-prof {rspack_bin_path} -c rspack.config.js +``` + +或者 + +```bash +RSPACK_PROFILE=JSCPU rspack build +``` + +这将生成一个 cpu 配置文件,例如 `CPU.20230522.154658.14577.0.001.cpuprofile`,并且我们可以使用 speedscope 来可视化 profile,例如 + +```bash +npm install -g speedscope +speedscope CPU.20230522.154658.14577.0.001.cpuprofile +``` + +## Mac Xcode Instruments + +如果您使用的是 Mac,则 Xcode Instruments 工具可用于生成 CPU profile 文件。 + +![image](https://github.com/SyMind/rspack-dev-guide/assets/19852293/124e3aee-944a-4509-bb93-1c9213f026d3) + +安装 Xcode Instruments,仅需要安装命令行工具: + +```bash +xcode-select --install +``` + +对于普通 Rust 构建, [`cargo instruments`](https://github.com/cmyr/cargo-instruments) 可以用作胶水用于分析和创建 tracing 文件。 + +由于 Rspack 需要相当长的时间来构建,因此您可以使用以下过程而无需调用 `cargo Instruments`。 +它具有相同的效果。 + +在根工作区的 `Cargo.toml`,在 `[profile.release]` 部分中打开调试符号并禁用符号剥离 + +```toml +[profile.release] +debug = 1 # debug info with line tables only +strip = false # do not strip symbols +``` + +然后构建项目 + +```bash +pnpm run build:cli:release +``` + +一旦项目构建完成,最后的二进制文件位于 `packages/rspack-cli/bin/rspack`。 + +`cargo Instruments` 在内部调用 `xcrun` 命令, +这意味着我们可以在我们自己使用 Rspack 的项目中运行以下命令。 + +```bash +xcrun xctrace record --template 'Time Profile' --output . --launch -- /path/to/rspack/packages/rspack-cli/bin/rspack build +``` + +它产生以下输出 + +``` +Starting recording with the Time Profiler template. Launching process: rspack. +Ctrl-C to stop the recording +Target app exited, ending recording... +Recording completed. Saving output file... +Output file saved as: Launch_rspack_2023-04-24_11.32.06_9CFE3A63.trace +``` + +我们可以打开 trace file 通过 + +```bash +open Launch_rspack_2023-04-24_11.32.06_9CFE3A63.trace +``` diff --git a/website/docs/zh/contribute/development/releasing.md b/website/docs/zh/contribute/development/releasing.md new file mode 100644 index 00000000000..ec07ccdccdd --- /dev/null +++ b/website/docs/zh/contribute/development/releasing.md @@ -0,0 +1,33 @@ +# Releasing + +所有发布都是通过 GitHub Action 自动进行的。 + +所有 `@rspack/cli` 的发版可以在 [npm versions page](https://www.npmjs.com/package/@rspack/cli?activeTab=versions) 找到。它们被打上了 tag + +- `latest` 和语义化版本 `x.y.z` +- `nightly` +- `canary` + +## latest 的全量发布 + +[全量发布工作流](https://github.com/web-infra-dev/rspack/actions/workflows/release.yml?query=is%3Asuccess) +目前在每个周二被手动触发,配合全量发布的 release notes。 + +下面的 9 个目标产物会被构建 + +- x86_64-unknown-linux-gnu +- aarch64-unknown-linux-gnu +- x86_64-unknown-linux-musl +- aarch64-unknown-linux-musl +- i686-pc-windows-msvc +- x86_64-pc-windows-msvc +- aarch64-pc-windows-msvc +- x86_64-apple-darwin +- aarch64-apple-darwin + +## Nightly + +[nightly 发布工作流](https://github.com/web-infra-dev/rspack/actions/workflows/release-nightly.yml?query=is%3Asuccess) +在每天的 UTC 16:00:07 被触发,是 北京时间的凌晨 00:07 (偏移奇数分钟以避免 cron 作业同时触发)。 + +nightly 构建完全复制了全量发布构建,以便尽早发现错误。 diff --git a/website/docs/zh/contribute/development/testing-rspack.mdx b/website/docs/zh/contribute/development/testing-rspack.mdx index 2213878ac2c..50d7dcea3b2 100644 --- a/website/docs/zh/contribute/development/testing-rspack.mdx +++ b/website/docs/zh/contribute/development/testing-rspack.mdx @@ -1,4 +1,4 @@ -# Rspack 测试 +# Testing Rspack Rspack 的测试用例包括如下: diff --git a/website/docs/zh/contribute/development/testing-webpack.mdx b/website/docs/zh/contribute/development/testing-webpack.mdx index dde7b28b479..6c7e879b8d1 100644 --- a/website/docs/zh/contribute/development/testing-webpack.mdx +++ b/website/docs/zh/contribute/development/testing-webpack.mdx @@ -1,4 +1,4 @@ -# Webpack 测试 +# Testing Webpack ## 运行 Webpack 用例 diff --git a/website/docs/zh/contribute/development/testing.mdx b/website/docs/zh/contribute/development/testing.mdx index c42ecbf766e..8cdd32a06b9 100644 --- a/website/docs/zh/contribute/development/testing.mdx +++ b/website/docs/zh/contribute/development/testing.mdx @@ -1,4 +1,4 @@ -# 测试 +# Testing 由于 Rspack 使用 Rust + TypeScript 代码混合编写,因此会针对两者使用不同的测试方案。 diff --git a/website/docs/zh/contribute/index.mdx b/website/docs/zh/contribute/index.mdx new file mode 100644 index 00000000000..44ae303a0d3 --- /dev/null +++ b/website/docs/zh/contribute/index.mdx @@ -0,0 +1,89 @@ +# 总览 + +我们非常感谢您有兴趣为 Rspack 做出贡献! +每一项贡献都很重要,并帮助我们将 Rspack 提升到一个新的水平。 + +## 提出问题 + +如果您遇到任何问题,请随时在 [Discord](https://discord.gg/79ZZ66GH9E) 中的 support 频道或 [Github discussion board](https://github.com/web-infra-dev/rspack/discussions) 提问。 + +### 最小复现 + +[rspack 复现模版](https://github.com/web-infra-dev/rspack-repro) 可以被用于创建一个最小复现示例。 +一个最小复现示例 (MRE) 是一段这样的代码: + +- 短 +- 独立的 +- 展示遇到的问题 + +MRE 至关重要,因为它使我们能够快速理解并重现您的问题。 +这反过来又增加了在更短的时间内获得有用且准确的响应的可能性。 +值得注意的是,MRE 不应包含与不相关功能相关的无关代码, +而应该只关注手头的问题。 + +> 请查看来自 Stack Overflow 的 [如何创建最小的、可重复的示例](https://stackoverflow.com/help/minimal-reproducible-example)。 + +## 我应该做什么? + +### Good First Issue + +如果您想深入了解代码库并开始使用, +建议查看我们的 标有 [good first issue 标签](https://github.com/web-infra-dev/rspack/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22) 的 issue 列表。 +这将帮助您熟悉该项目并开始做出贡献。 + +### Tracking Issue + +如果您有兴趣了解我们项目的方向并希望解决与我们优先事项相符的问题, +我们的 [正在跟踪 issues 列表](https://github.com/web-infra-dev/rspack/issues?q=is%3Aopen+label%3A%22tracking+issue%22+sort%3Aupdated-desc) 概括了我们的进展和当前目标。 + +## 提出 pull request + +1. [Fork](https://help.github.com/articles/fork-a-repo/) Rspack 的仓库到你自己的 GitHub 个人账户中。 +2. [Clone](https://help.github.com/articles/cloning-a-repository/) 下这个仓库到本地。 +3. 从 `main` 签出一个新的分支。 +4. 搭建开发环境,可以阅读 [准备工作](/contribute/development/prerequisites) 部分来了解。 +5. 如果您修复了错误或添加了需要被测试的代码,则需要添加一些测试。 +6. 确保所有测试都通过,您可以阅读下面的 [Testing](/contribute/development/testing) 部分来了解。 +7. 执行 `pnpm run lint:js` 和 `pnpm run lint:rs` 来检查代码风格。 +8. 提交 Pull Request, 确保所有的 CI 都通过. +9. maintainers 之后会检查你的 Pull Request。 + +提交 Pull Request 时,请注意以下事项: + +- 保持 PR 足够小,以便每个 PR 只解决一个问题或添加一个功能。 +- 请在 PR 中包含适当的描述,并链接相关问题。 + +### PR 标题的格式 + +PR 标题的格式遵循常规提交格式。 + +一个示例 + +``` +feat(ui): Add `Button` component +^ ^ ^ +| | |__ Subject +| |_______ Scope +|____________ Type +``` + +你的 PR + +- 必须含有 `Type` +- 可选地含有 `Scope` + - `Scope` 应该是小写的 +- 必须含有 `Subject` + +## 其他贡献方式 + +我们一直在寻找贡献者,这不仅仅是我们的主存储库。 + +尝试其他这些可以参与进来的方式,可以从现在就行动起来。 + +- 文档站在 [web-infra-dev/rspack/website](https://github.com/web-infra-dev/rspack/tree/main/website) +- 社区的 packages 在 [github.com/rspack-contrib](https://github.com/rspack-contrib) +- 欢迎添加 Rspack 相关项目给 [awesome-rspack](https://github.com/web-infra-dev/awesome-rspack) + +--- + +提醒一下,所有贡献者都应该遵循我们的 [Code of Conduct](https://github.com/web-infra-dev/rspack/blob/main/CODE_OF_CONDUCT.md). From e7588befa6c4cf64f8371c7631fd413e3da5e064 Mon Sep 17 00:00:00 2001 From: Soon Date: Wed, 22 May 2024 16:16:59 +0800 Subject: [PATCH 22/48] docs: fix the