diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
deleted file mode 100644
index 1183492..0000000
--- a/.github/workflows/main.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-name: CI
-on:
- # To be fixed
- # push:
- # branches:
- # - main
- # pull_request:
- # branches:
- # - main
-jobs:
- build:
- name: test Node ${{ matrix.node }} ${{ matrix.os }}
- timeout-minutes: 15
-
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- node: ['18.x']
- os: [ubuntu-latest, windows-latest]
-
- steps:
- - name: Checkout repo
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
-
- - name: Use Node ${{ matrix.node }}
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
- with:
- node-version: ${{ matrix.node }}
- package-manager-cache: false
-
- - name: Install Pnpm
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
- with:
- run_install: true
-
- - name: Test
- run: npm test -- --forceExit || npm test -- --forceExit || npm test -- --forceExit
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..4563fbe
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,36 @@
+name: Test
+
+on:
+ pull_request:
+ branches: [main]
+ push:
+ branches: [main]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ test:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest]
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
+
+ - name: Setup Node.js
+ uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
+ with:
+ node-version: 24.19.0
+ package-manager-cache: false
+
+ - name: Install Pnpm
+ uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
+ with:
+ run_install: true
+
+ - name: Run Test
+ run: node --run test
diff --git a/.gitignore b/.gitignore
index 85be321..481f90c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
node_modules/
/dist/
/coverage/
+/examples/*/dist/
npm-debug.*.log
yarn.lock
package-lock.json
diff --git a/examples/README.md b/examples/README.md
index 22bdf5b..599b807 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -10,7 +10,7 @@ Custom Template | [custom-template](./custom-template)
Custom Script / Link tag position | [custom-insertion-point](./custom-insertion-position)
Default | [default](./default)
Favicon | [favicon](./favicon.)
-Html Loader | [html-loader](./html-loader)
+HTML Template | [html-loader](./html-loader)
Inline | [inline](./inline)
Javascript-advanced | [javascript-advanced](./javascript-advanced)
Javascript | [javascript](./javascript)
diff --git a/examples/build-examples.js b/examples/build-examples.js
deleted file mode 100644
index 0e45b0b..0000000
--- a/examples/build-examples.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * This file is just a helper to compile all examples.
- *
- * You could do the same by going into each example and execute
- * `webpack`
- */
-var webpackMajorVersion = require('webpack/package.json').version.split('.')[0];
-
-var fs = require('fs');
-var path = require('path');
-var rimraf = require('rimraf');
-var webpack = require('webpack');
-
-var examples = fs.readdirSync(__dirname).filter(function (file) {
- return fs.statSync(path.join(__dirname, file)).isDirectory();
-});
-
-examples.forEach(function (exampleName) {
- var examplePath = path.join(__dirname, exampleName);
- var configFile = path.join(examplePath, 'webpack.config.js');
-
- var config = require(configFile);
- if (Number(webpackMajorVersion) >= 4) {
- config.plugins.unshift(new webpack.LoaderOptionsPlugin({
- options: {
- context: process.cwd() // or the same value as `context`
- }
- }));
- config.mode = 'production';
- config.optimization = config.optimization || {};
- config.optimization.minimizer = [];
- }
-
- rimraf.sync(path.join(examplePath, 'dist', 'webpack-' + webpackMajorVersion));
- webpack(config, function (err, stats) {
- if (err) {
- console.error(err.stack || err);
- if (err.details) {
- console.error(err.details);
- }
- return;
- }
-
- const info = stats.toJson();
-
- if (stats.hasErrors()) {
- console.error(info.errors);
- }
-
- if (stats.hasWarnings()) {
- console.warn(info.warnings);
- }
- });
-});
diff --git a/examples/build-examples.mjs b/examples/build-examples.mjs
new file mode 100644
index 0000000..a2af8c3
--- /dev/null
+++ b/examples/build-examples.mjs
@@ -0,0 +1,54 @@
+import { readdir, rm } from 'node:fs/promises';
+import path from 'node:path';
+import { fileURLToPath, pathToFileURL } from 'node:url';
+import { rspack, rspackVersion } from '@rspack/core';
+
+const examplesDirectory = fileURLToPath(new URL('.', import.meta.url));
+const rspackMajorVersion = rspackVersion.split('.')[0];
+const examples = (await readdir(examplesDirectory, { withFileTypes: true }))
+ .filter((entry) => entry.isDirectory())
+ .map((entry) => entry.name);
+
+async function buildExample(exampleName) {
+ const examplePath = path.join(examplesDirectory, exampleName);
+ const configUrl = pathToFileURL(path.join(examplePath, 'rspack.config.mjs'));
+ const { default: config } = await import(configUrl.href);
+
+ config.mode = 'production';
+ config.optimization = config.optimization || {};
+ config.optimization.minimizer = [];
+
+ await rm(path.join(examplePath, 'dist', `rspack-${rspackMajorVersion}`), {
+ force: true,
+ recursive: true,
+ });
+
+ return new Promise((resolve, reject) => {
+ rspack(config, (error, stats) => {
+ if (error) {
+ reject(error);
+ return;
+ }
+
+ if (!stats || stats.hasErrors()) {
+ reject(
+ new Error(
+ stats
+ ? stats.toString({ colors: true })
+ : 'Rspack did not return compilation stats.',
+ ),
+ );
+ return;
+ }
+
+ resolve();
+ });
+ });
+}
+
+try {
+ await Promise.all(examples.map(buildExample));
+} catch (error) {
+ console.error(error);
+ process.exitCode = 1;
+}
diff --git a/examples/chunk-optimization/dist/webpack-5/219.js b/examples/chunk-optimization/dist/webpack-5/219.js
deleted file mode 100644
index ab35797..0000000
--- a/examples/chunk-optimization/dist/webpack-5/219.js
+++ /dev/null
@@ -1,351 +0,0 @@
-"use strict";
-(self["webpackChunk"] = self["webpackChunk"] || []).push([[219],{
-
-/***/ 609:
-/***/ ((module) => {
-
-
-
-/*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
-*/
-// css base code, injected by the css-loader
-// eslint-disable-next-line func-names
-module.exports = function (cssWithMappingToString) {
- var list = []; // return the list of modules as css string
-
- list.toString = function toString() {
- return this.map(function (item) {
- var content = cssWithMappingToString(item);
-
- if (item[2]) {
- return "@media ".concat(item[2], " {").concat(content, "}");
- }
-
- return content;
- }).join('');
- }; // import a list of modules into the list
- // eslint-disable-next-line func-names
-
-
- list.i = function (modules, mediaQuery, dedupe) {
- if (typeof modules === 'string') {
- // eslint-disable-next-line no-param-reassign
- modules = [[null, modules, '']];
- }
-
- var alreadyImportedModules = {};
-
- if (dedupe) {
- for (var i = 0; i < this.length; i++) {
- // eslint-disable-next-line prefer-destructuring
- var id = this[i][0];
-
- if (id != null) {
- alreadyImportedModules[id] = true;
- }
- }
- }
-
- for (var _i = 0; _i < modules.length; _i++) {
- var item = [].concat(modules[_i]);
-
- if (dedupe && alreadyImportedModules[item[0]]) {
- // eslint-disable-next-line no-continue
- continue;
- }
-
- if (mediaQuery) {
- if (!item[2]) {
- item[2] = mediaQuery;
- } else {
- item[2] = "".concat(mediaQuery, " and ").concat(item[2]);
- }
- }
-
- list.push(item);
- }
- };
-
- return list;
-};
-
-/***/ }),
-
-/***/ 62:
-/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
-
-
-
-var isOldIE = function isOldIE() {
- var memo;
- return function memorize() {
- if (typeof memo === 'undefined') {
- // Test for IE <= 9 as proposed by Browserhacks
- // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
- // Tests for existence of standard globals is to allow style-loader
- // to operate correctly into non-standard environments
- // @see https://github.com/webpack-contrib/style-loader/issues/177
- memo = Boolean(window && document && document.all && !window.atob);
- }
-
- return memo;
- };
-}();
-
-var getTarget = function getTarget() {
- var memo = {};
- return function memorize(target) {
- if (typeof memo[target] === 'undefined') {
- var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself
-
- if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {
- try {
- // This will throw an exception if access to iframe is blocked
- // due to cross-origin restrictions
- styleTarget = styleTarget.contentDocument.head;
- } catch (e) {
- // istanbul ignore next
- styleTarget = null;
- }
- }
-
- memo[target] = styleTarget;
- }
-
- return memo[target];
- };
-}();
-
-var stylesInDom = [];
-
-function getIndexByIdentifier(identifier) {
- var result = -1;
-
- for (var i = 0; i < stylesInDom.length; i++) {
- if (stylesInDom[i].identifier === identifier) {
- result = i;
- break;
- }
- }
-
- return result;
-}
-
-function modulesToDom(list, options) {
- var idCountMap = {};
- var identifiers = [];
-
- for (var i = 0; i < list.length; i++) {
- var item = list[i];
- var id = options.base ? item[0] + options.base : item[0];
- var count = idCountMap[id] || 0;
- var identifier = "".concat(id, " ").concat(count);
- idCountMap[id] = count + 1;
- var index = getIndexByIdentifier(identifier);
- var obj = {
- css: item[1],
- media: item[2],
- sourceMap: item[3]
- };
-
- if (index !== -1) {
- stylesInDom[index].references++;
- stylesInDom[index].updater(obj);
- } else {
- stylesInDom.push({
- identifier: identifier,
- updater: addStyle(obj, options),
- references: 1
- });
- }
-
- identifiers.push(identifier);
- }
-
- return identifiers;
-}
-
-function insertStyleElement(options) {
- var style = document.createElement('style');
- var attributes = options.attributes || {};
-
- if (typeof attributes.nonce === 'undefined') {
- var nonce = true ? __webpack_require__.nc : 0;
-
- if (nonce) {
- attributes.nonce = nonce;
- }
- }
-
- Object.keys(attributes).forEach(function (key) {
- style.setAttribute(key, attributes[key]);
- });
-
- if (typeof options.insert === 'function') {
- options.insert(style);
- } else {
- var target = getTarget(options.insert || 'head');
-
- if (!target) {
- throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");
- }
-
- target.appendChild(style);
- }
-
- return style;
-}
-
-function removeStyleElement(style) {
- // istanbul ignore if
- if (style.parentNode === null) {
- return false;
- }
-
- style.parentNode.removeChild(style);
-}
-/* istanbul ignore next */
-
-
-var replaceText = function replaceText() {
- var textStore = [];
- return function replace(index, replacement) {
- textStore[index] = replacement;
- return textStore.filter(Boolean).join('\n');
- };
-}();
-
-function applyToSingletonTag(style, index, remove, obj) {
- var css = remove ? '' : obj.media ? "@media ".concat(obj.media, " {").concat(obj.css, "}") : obj.css; // For old IE
-
- /* istanbul ignore if */
-
- if (style.styleSheet) {
- style.styleSheet.cssText = replaceText(index, css);
- } else {
- var cssNode = document.createTextNode(css);
- var childNodes = style.childNodes;
-
- if (childNodes[index]) {
- style.removeChild(childNodes[index]);
- }
-
- if (childNodes.length) {
- style.insertBefore(cssNode, childNodes[index]);
- } else {
- style.appendChild(cssNode);
- }
- }
-}
-
-function applyToTag(style, options, obj) {
- var css = obj.css;
- var media = obj.media;
- var sourceMap = obj.sourceMap;
-
- if (media) {
- style.setAttribute('media', media);
- } else {
- style.removeAttribute('media');
- }
-
- if (sourceMap && typeof btoa !== 'undefined') {
- css += "\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), " */");
- } // For old IE
-
- /* istanbul ignore if */
-
-
- if (style.styleSheet) {
- style.styleSheet.cssText = css;
- } else {
- while (style.firstChild) {
- style.removeChild(style.firstChild);
- }
-
- style.appendChild(document.createTextNode(css));
- }
-}
-
-var singleton = null;
-var singletonCounter = 0;
-
-function addStyle(obj, options) {
- var style;
- var update;
- var remove;
-
- if (options.singleton) {
- var styleIndex = singletonCounter++;
- style = singleton || (singleton = insertStyleElement(options));
- update = applyToSingletonTag.bind(null, style, styleIndex, false);
- remove = applyToSingletonTag.bind(null, style, styleIndex, true);
- } else {
- style = insertStyleElement(options);
- update = applyToTag.bind(null, style, options);
-
- remove = function remove() {
- removeStyleElement(style);
- };
- }
-
- update(obj);
- return function updateStyle(newObj) {
- if (newObj) {
- if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) {
- return;
- }
-
- update(obj = newObj);
- } else {
- remove();
- }
- };
-}
-
-module.exports = function (list, options) {
- options = options || {}; // Force single-tag solution on IE6-9, which has a hard limit on the # of