github web-infra-dev/rspack v0.4.2

latest releases: v1.1.1, v1.1.0, v1.1.0-beta.0...
11 months ago

Highlights

experiments.rspackFuture.newTreeshaking

the new tree shaking implementation specifically addressing compatibility issues with webpack architecture and optimizing for reduced output size.
(see below for a detailed explanation)

optimization.mangleExports

allow rspack to control export mangling.
(see below for a detailed explanation)

What's Changed

Exciting New Features 🎉

  • feat: JsAsset remove version field by @jerrykingxyz in #4836
  • feat: support ecosystem-ci suiteRef trigger by @ahabhgk in #4847
  • feat: do not convert panics to results by @h-a-n-a in #4848
  • feat: implement ChunkGraph.getChunkModulesIterable and ChunkGraph.getChunkEntryModulesIterable by @xc2 in #4855
  • feat(runtime-diff): alignment of wasm async loading runtime module by @LingyuCoder in #4863
  • feat: align webpack - allow false for optimization.splitChunks on options validation by @xc2 in #4883
  • feat: mangle exports by @IWANABETHATGUY in #4805
  • feat: support scriptType by @faga295 in #4814
  • feat: extract data from mf generated code by @ahabhgk in #4799

Bug Fixes 🐞

New Contributors

Full Changelog: v0.4.1...v0.4.2


experiments.rspackFuture.newTreeshaking

This quarter, substantial efforts were dedicated to enhancing tree shaking. While the older tree shaking method remains applicable in most scenarios, it lacks full compatibility with webpack architecture, resulting in divergent behaviors compared to webpack. Additionally, it may produce larger output in certain scenarios when contrasted with webpack. For example, efforts were made to address these issues and optimize tree shaking for improved performance and compatibility.

One of the noteworthy enhancements is the reduction in generated output size. The revamped tree shaking is designed to produce leaner output, particularly when compared to certain scenarios with the previous tree shaking implementation. Here is an example:

source

// index.js
import { a } from './lib.js'
a

// lib.js

export * from './a.js'

// a.js

export const a = 3;
export const b = 3;

package.json

{
  "sideEffects": false
}

rspack.config.js

const rspack = require("@rspack/core");
/** @type {import('@rspack/core').Configuration} */
const config = {
        entry: "./src/index.js",
        plugins: [
        ],
        experiments: {
                rspackFuture: {
                        newTreeshaking: false // `newTreeshaking` disable by default
                }
        },
        optimization: {
                moduleIds:"named", // use nanmed moduleIds and disable `minize` for better demonstration
                minimize: false
        },
};
module.exports = config;

Since the whole module is side effects free, we could directly import a from a.js . This could eliminate lib.js in output.

with old tree shaking

// skip runtime code ...
var __webpack_modules__ = {
"./src/a.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
  a: function() { return a; }
});
 const a = 3;
 const b = 3;
}),
"./src/index.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */var _lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib */"./src/lib.js");

_lib__WEBPACK_IMPORTED_MODULE_0__.a;
}),
"./src/lib.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */var _a__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./a */"./src/a.js");
__webpack_require__.es(_a__WEBPACK_IMPORTED_MODULE_0__, __webpack_exports__);

}),

}

with new tree shaking

enable experiments.rspackFuture.newTreeshaking

const rspack = require("@rspack/core");
/** @type {import('@rspack/core').Configuration} */
const config = {
        // ...
        experiments: {
                rspackFuture: {
-                        newTreeshaking: false
+                        newTreeshaking: true 
                }
        },
        // ...
};
module.exports = config;
output 
 var __webpack_modules__ = {
"./src/a.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
  a: function() { return a; }
});
 const a = 3;
 const b = 3;
}),
"./src/index.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */var _lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib */"./src/a.js");

_lib__WEBPACK_IMPORTED_MODULE_0__.a;
}),

}

The new treeshaking implementation is still undergoing stability testing; hence, it remains disabled by default. If you wish to experiment with it, you can enable it by using the following:

const rspack = require("@rspack/core");
/** @type {import('@rspack/core').Configuration} */
const config = {
        // ...
        experiments: {
                rspackFuture: {
                        newTreeshaking: true 
                }
        },
        // ...
};
module.exports = config; 

more details you could refer:
https://www.rspack.dev/config/experiments.html#experimentsrspackfuturenewtreeshaking
and related options:

  1. usedExports
  2. innerGraph
  3. providedExports
  4. sideEffects

optimization.mangleExports

optimization.mangleExports allows to control export mangling.
Reuse the previous example, making slight modifications for a better explanation.

// index.js
- import { aaa } from './lib.js'
+ import { aaa } from './lib.js'
- a
+ aaa

// lib.js

export * from './a.js'

// a.js

- export const aaa = 3;
+ export const aaa = 3;
export const b = 3;

Enable experiments.rspackFuture.newTreeshaking and optimization.mangleExports

Output

The export of module src/a.js was condensed into a single letter, leading to a decrease in the overall output size.

var __webpack_modules__ = {
"./src/a.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
  P: function() { return aaa; }
});
 const aaa = 3;
 const b = 3;
}),
"./src/index.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */var _lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib */"./src/a.js");

_lib__WEBPACK_IMPORTED_MODULE_0__.P;
}),

}

Note this feature is not stable yet, and requires experiments.rspackFuture.newTreeshaking to be enabled.

Don't miss a new rspack release

NewReleases is sending notifications on new releases.