@lynx-js/rspeedy
Version:
A webpack/rspack-based frontend toolchain for Lynx
1,726 lines (1,695 loc) • 115 kB
TypeScript
/**
* @packageDocumentation
*
* The document contains all the configurations of the `@lynx-js/rspeedy` package.
*
* @example
*
* Use `lynx.config.ts` with {@link defineConfig} to get better TypeScript intellisense.
*
* ```ts
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* entry: './src/index.tsx',
* })
* ```
*/
import type { CompressOptions } from '@rsbuild/core';
import type { CreateRsbuildOptions } from '@rsbuild/core';
import type { DataUriLimit } from '@rsbuild/core';
import type { DistPathConfig } from '@rsbuild/core';
import type { InlineChunkConfig } from '@rsbuild/core';
import type { Linter } from '@rsdoctor/types';
import { logger } from '@rsbuild/core';
import type { PerformanceConfig } from '@rsbuild/core';
import type { Plugin } from '@rsdoctor/types';
import type { ProxyConfig } from '@rsbuild/core';
import type { RsbuildConfig } from '@rsbuild/core';
import type { RsbuildEntry } from '@rsbuild/core';
import type { RsbuildInstance } from '@rsbuild/core';
import { RsbuildPlugin } from '@rsbuild/core';
import { RsbuildPluginAPI } from '@rsbuild/core';
import type { RsbuildPlugins } from '@rsbuild/core';
import { version as rsbuildVersion } from '@rsbuild/core';
import { Rspack } from '@rsbuild/core';
import { rspack } from '@rsbuild/core';
import type { ServerConfig } from '@rsbuild/core';
import type { ToolsConfig } from '@rsbuild/core';
import type { WatchFiles } from '@rsbuild/core';
/**
* {@inheritdoc Performance.buildCache}
*
* @beta
*/
export declare interface BuildCache {
/**
* Add additional cache digests, the previous build cache will be invalidated
* when any value in the array changes.
*
* @defaultValue undefined
*
* @example
*
* Add `process.env.SOME_ENV` to the cache digest.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* performance: {
* buildCache: {
* cacheDigest: [process.env.SOME_ENV],
* },
* },
* })
* ```
*/
cacheDigest?: Array<string | undefined> | undefined;
/**
* The output directory of the cache files.
*
* @defaultValue 'node_modules/.cache'
*/
cacheDirectory?: string | undefined;
/**
* An array of files containing build dependencies.
* Rspack will use the hash of each of these files to invalidate the persistent cache.
*
* @defaultValue `['package.json', 'tsconfig.json' (or source.tsconfigPath), '.env', '.env.*', 'tailwindcss.config.*']`; when using the Rspeedy CLI with `performance.buildCache` enabled, the loaded `lynx.config.*` file is also added.
*
* @example
*
* Add `postcss.config.js` to the build dependencies.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* performance: {
* buildCache: {
* buildDependencies: ['postcss.config.js'],
* },
* },
* })
* ```
*/
buildDependencies?: string[] | undefined;
}
/**
* The name of the bundle files.
*
* It can be a string with placeholders (`[name]`, `[contenthash]`,
* `[platform]`), or a function that returns a string based on the
* {@link BundleFilenameContext}.
*
* @public
*/
export declare type BundleFilename = string | ((context: BundleFilenameContext) => string);
/**
* The context passed to the {@link Filename.bundle} function.
*
* @public
*/
export declare interface BundleFilenameContext {
/**
* Whether the filename is being resolved for a lazy bundle (async chunk)
* instead of the main bundle of an entry.
*
* This allows you to control the main bundle and the lazy bundles with a
* single function, without needing a dedicated `lazyBundle` field.
*/
lazyBundle: boolean;
/**
* The name of the entry.
*
* It is `undefined` for lazy bundles, since a lazy bundle name is resolved
* per async chunk (use the `[name]` placeholder in the returned string
* instead).
*/
entryName?: string | undefined;
/**
* The environment (platform) name, e.g. `'lynx'` or `'web'`.
*/
platform: string;
}
/**
* {@inheritdoc Performance.chunkSplit}
*
* @deprecated Use the top-level {@link Config.splitChunks} option instead.
*
* @public
*/
export declare interface ChunkSplit {
/**
* The ChunkSplitting strategy.
*
* @defaultValue In Rsbuild's default chunk splitting behavior, the strategy is `'split-by-experience'`.
*
* @remarks
*
* - `split-by-experience`(Rsbuild default): an empirical splitting strategy, automatically splits some commonly used npm packages into chunks of moderate size.
*
* - `split-by-module`: split by NPM package granularity, each NPM package corresponds to a chunk.
*
* - `split-by-size`: automatically split according to module size.
*
* - `all-in-one`: bundle all codes into one chunk.
*
* - `single-vendor`: bundle all NPM packages into a single chunk.
*
* - `custom`: custom chunk splitting strategy.
*
* @example
*
* - Use `all-in-one` to put all modules in one chunk.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* performance: {
* chunkSplit: {
* strategy: 'all-in-one',
* },
* },
* })
* ```
*
* @example
*
* - Use `single-vendor` to put all third-party dependencies in one chunk. And source code in another chunk.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* performance: {
* chunkSplit: {
* strategy: 'single-vendor',
* },
* },
* })
* ```
*/
strategy?: 'all-in-one' | 'split-by-module' | 'split-by-experience' | 'single-vendor' | undefined;
/**
* Custom Rspack chunk splitting config can be specified.
*
* @defaultValue undefined
*
* @example
*
* - Split `@lynx-js/react` and `react-router` into chunk `lib-react`.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* performance: {
* chunkSplit: {
* strategy: 'split-by-experience',
* override: {
* cacheGroups: {
* react: {
* test: /node_modules[\\/](@lynx-js[\\/]react|react-router)[\\/]/,
* name: 'lib-react',
* },
* },
* },
* },
* },
* })
* ```
*/
override?: Rspack.Configuration extends {
optimization?: {
splitChunks?: infer P;
} | undefined;
} ? P : never;
}
/**
* {@inheritdoc Performance.chunkSplit}
*
* @deprecated Use the top-level {@link Config.splitChunks} option instead.
*
* @public
*/
export declare interface ChunkSplitBySize {
/**
* {@inheritdoc ChunkSplit.strategy}
*/
strategy: 'split-by-size';
/**
* The minimum size of a chunk, unit in bytes.
*
* @defaultValue 10000
*
* @example
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* performance: {
* chunkSplit: {
* strategy: 'split-by-size',
* minSize: 20000,
* },
* },
* })
* ```
*/
minSize?: number | undefined;
/**
* The maximum size of a chunk, unit in bytes.
*
* @defaultValue `Number.POSITIVE_INFINITY`
*
* @example
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* performance: {
* chunkSplit: {
* strategy: 'split-by-size',
* maxSize: 50000,
* },
* },
* })
* ```
*/
maxSize?: number | undefined;
/**
* {@inheritdoc ChunkSplit.override}
*
* @defaultValue undefined
*/
override?: Rspack.Configuration extends {
optimization?: {
splitChunks?: infer P;
} | undefined;
} ? P : never;
}
/**
* {@inheritdoc Performance.chunkSplit}
*
* @deprecated Use the top-level {@link Config.splitChunks} option instead.
*
* @public
*/
export declare interface ChunkSplitCustom {
/**
* {@inheritdoc ChunkSplit.strategy}
*/
strategy: 'custom';
/**
* {@inheritdoc ChunkSplit.override}
*
* @defaultValue undefined
*
* @example
*
* - Split `@lynx-js/react` and `react-router` into chunk `lib-react`.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* performance: {
* chunkSplit: {
* strategy: 'custom',
* splitChunks: {
* cacheGroups: {
* react: {
* test: /node_modules[\\/](@lynx-js[\\/]react|react-router)[\\/]/,
* name: 'lib-react',
* },
* },
* },
* },
* },
* })
* ```
*/
splitChunks?: Rspack.Configuration extends {
optimization?: {
splitChunks?: infer P;
} | undefined;
} ? P : never;
}
/**
* The `Config` is the configuration that `rspeedy` uses.
*
* @public
*/
export declare interface Config {
/**
* The {@link Dev} option is used to control the behavior related with development. Including: HMR, DevServer, etc.
*
* @defaultValue undefined
*/
dev?: Dev | undefined;
/**
* The {@link Config.environments} option is used to set the output environment.
*
* @defaultValue When this option is unset, Rspeedy passes `{ lynx: {} }` to Rsbuild.
*
* @remarks
*
* Normally you don't need this if you are not using Lynx for Web.
*
* @example
*
* - Using different entries for Lynx and Web.
*
* ```ts
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* environments: {
* lynx: {},
* web: {
* source: { entry: { web: './src/index.web.jsx' } },
* },
* },
* source: {
* entry: './src/index.jsx',
* },
* })
* ```
*
* @example
*
* - Building Web-only outputs.
*
* ```ts
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* environments: {
* web: {
* source: { entry: { web: './src/index.web.jsx' } },
* },
* },
* })
* ```
*/
environments?: RsbuildConfig['environments'] | undefined;
/**
* Specify the build mode for Rsbuild and Rspack, as each mode has different default behavior and optimizations.
*
* @defaultValue Depends on `process.env.NODE_ENV`: `'production'` when `NODE_ENV` is `'production'`, `'development'` when `NODE_ENV` is `'development'`, and `'none'` otherwise. When using Rspeedy's CLI, `rspeedy dev` and `rspeedy preview` default to `'development'`, while `rspeedy build` defaults to `'production'`.
*
* @example
*
* If the value of `mode` is `'development'`:
*
* - Enable HMR and register the {@link https://rspack.rs/plugins/webpack/hot-module-replacement-plugin | HotModuleReplacementPlugin}.
*
* - Generate JavaScript and CSS source maps. In Lynx environments, all `.map` assets are removed before emit. See {@link Output.sourceMap} for details.
*
* - The `process.env.NODE_ENV` in the source code will be replaced with `'development'`.
*
* - The `import.meta.env.MODE` in the source code will be replaced with `'development'`.
*
* - The `import.meta.env.DEV` in the source code will be replaced with `true`.
*
* - The `import.meta.env.PROD` in the source code will be replaced with `false`.
*
* @example
*
* If the value of `mode` is `'production'`:
*
* - Enable JavaScript code minification and register the {@link https://rspack.rs/plugins/rspack/swc-js-minimizer-rspack-plugin | SwcJsMinimizerRspackPlugin}.
*
* - Generated JavaScript and CSS filenames will have hash suffixes, see {@link Output.filenameHash}.
*
* - Generated CSS Modules classnames will be shorter, see {@link CssModules.localIdentName}.
*
* - Generate JavaScript and CSS source maps. In Lynx environments, all `.map` assets are removed before emit. See {@link Output.sourceMap}.
*
* - The `process.env.NODE_ENV` in the source code will be replaced with `'production'`.
*
* - The `import.meta.env.MODE` in the source code will be replaced with `'production'`.
*
* - The `import.meta.env.DEV` in the source code will be replaced with `false`.
*
* - The `import.meta.env.PROD` in the source code will be replaced with `true`.
*/
mode?: 'development' | 'production' | 'none' | undefined;
/**
* The {@link Output} option is used to set how and where should the bundles and assets output.
*
* @defaultValue undefined
*/
output?: Output | undefined;
/**
* The {@link Performance} option is used to optimize the build-time and runtime performance.
*
* @defaultValue undefined
*/
performance?: Performance | undefined;
/**
* The {@link Resolve} option is used to control the resolution behavior of Rspack.
*
* @defaultValue undefined
*/
resolve?: Resolve | undefined;
/**
* The {@link Server} option changes the behavior of dev-server.
*
* @defaultValue undefined
*/
server?: Server | undefined;
/**
* The {@link Source} option changes the behavior of source files.
*
* @defaultValue undefined
*/
source?: Source | undefined;
/**
* Configure chunk splitting.
*
* @defaultValue Rspeedy defaults this to `false`; if configured, Rsbuild handles it with its top-level `splitChunks` option.
*
* See {@link https://rsbuild.rs/config/split-chunks | Rsbuild - splitChunks} for details.
*/
splitChunks?: RsbuildConfig['splitChunks'] | undefined;
/**
* The {@link Tools} options changes the behavior of various building tools.
*
* @defaultValue undefined
*/
tools?: Tools | undefined;
/**
* The `plugins` option is used to customize the build process in a variety of ways.
*
* @defaultValue undefined
*
* @remarks
* Rspeedy uses the plugin APIs from {@link https://rsbuild.rs/plugins/dev/index | Rsbuild}. See the corresponding document for developing a plugin.
*/
plugins?: RsbuildPlugins | undefined;
}
/**
* Parameters for the function exported from `lynx.config.js`.
*
* @public
*/
export declare interface ConfigParams {
/**
* The value of `process.env['NODE_ENV']`
*
* @defaultValue When `loadConfig` evaluates a config function, this value is `process.env.NODE_ENV ?? 'production'`
*
* @remarks
* Common values include (non-exhaustive):
* - `'production'`
*
* - `'development'`
*
* - `'test'`
*/
env: 'production' | 'development' | 'test' | (string & Record<never, never>);
/**
* The CLI command of Rspeedy.
*
* @defaultValue When `loadConfig` evaluates a config function, this value is `process.argv[2] ?? 'build'`
*
* @remarks
*
* Possible values:
*
* - `'build'`
*
* - `'dev'`
*
* - `'inspect'`
*
* - `'preview'`
*/
command: 'build' | 'dev' | 'inspect' | 'preview' | (string & Record<never, never>);
}
/**
* The type of the console method.
*
* @public
*/
export declare type ConsoleType = 'log' | 'warn' | 'error' | 'info' | 'debug' | 'profile' | 'profileEnd' | (string & Record<never, never>);
/**
* The `createRspeedy` method can let you create a Rspeedy instance and you can customize the build or development process in Node.js Runtime.
*
* @param options - {@link CreateRspeedyOptions}
* @returns - Rspeedy instance.
*
* @example
*
* ```ts
* import { createRspeedy } from '@lynx-js/rspeedy'
*
* void async function () {
* const rspeedy = await createRspeedy({})
* await rspeedy.build()
* }()
* ```
*
* @public
*/
export declare function createRspeedy({ cwd, rspeedyConfig, loadEnv, environment, callerName, }: CreateRspeedyOptions): Promise<RspeedyInstance>;
/**
* The options of `createRspeedy` method.
*
* @public
*/
export declare interface CreateRspeedyOptions {
/**
* The root path of the current build.
*/
cwd?: string;
/**
* The config of Rspeedy.
*/
rspeedyConfig?: Config;
/**
* Rspeedy automatically loads the .env file by default, utilizing the [Rsbuild API](https://rsbuild.rs/api/javascript-api/core#load-env-variables).
* You can use the environment variables defined in the .env file within your code by accessing them via `import.meta.env.FOO` or `process.env.Foo`.
* @see https://rsbuild.rs/guide/advanced/env-vars#env-file
* @defaultValue true
*/
loadEnv?: CreateRsbuildOptions['loadEnv'];
/**
* Only build specified environments.
* For example, passing `['lynx']` will only build the `lynx` environment.
* If not specified or passing an empty array, all environments will be built.
* @see https://rsbuild.rs/guide/advanced/environments#build-specified-environment
* @defaultValue []
*/
environment?: CreateRsbuildOptions['environment'];
/**
* The name of the framework or tool that is currently invoking Rsbuild.
* This allows plugins to tailor their behavior based on the calling context.
*
* @example
*
* Rsbuild plugins can access this value via `api.context.callerName`.
*
* ```js
* export function myPlugin() {
* return {
* name: 'my-plugin',
* setup(api) {
* // Log the name of the tool invoking Rsbuild
* console.log(`Called by: ${api.context.callerName}`);
*
* // Conditionally apply plugin logic based on caller
* if (api.context.callerName === 'rspeedy') {
* api.modifyRsbuildConfig((config) => {
* // Apply rspeedy-specific config changes
* return config;
* });
* } else if (api.context.callerName === 'rslib') {
* api.modifyRsbuildConfig((config) => {
* // Apply rslib-specific config changes
* return config;
* });
* }
* }
* };
* }
* ```
*
* @defaultValue 'rspeedy'
*/
callerName?: string;
}
/**
* {@inheritdoc Tools.cssExtract}
*
* @public
*/
export declare interface CssExtract {
/**
* {@inheritdoc @lynx-js/css-extract-webpack-plugin#LoaderOptions}
*
* @defaultValue undefined
*/
loaderOptions?: CssExtractRspackLoaderOptions | undefined;
/**
* {@inheritdoc @lynx-js/css-extract-webpack-plugin#CssExtractRspackPluginOptions}
*
* @defaultValue undefined
*/
pluginOptions?: CssExtractRspackPluginOptions | undefined;
}
/**
* {@inheritdoc @lynx-js/css-extract-webpack-plugin#LoaderOptions}
*
* @public
*/
export declare interface CssExtractRspackLoaderOptions {
/**
* The same as {@link https://github.com/webpack-contrib/mini-css-extract-plugin#esModule}.
* By default, `@lynx-js/css-extract-webpack-plugin` generates JS modules that use the ES modules syntax.
* There are some cases in which using ES modules is beneficial,
* like in the case of module concatenation and tree shaking.
*
* @example
* You can enable a CommonJS syntax using:
*
* ```js
* import {CssExtractRspackPlugin} from "@lynx-js/css-extract-webpack-plugin";
* export default {
* plugins: [new CssExtractRspackPlugin()],
* module: {
* rules: [
* {
* test: /\.css$/i,
* use: [
* {
* loader: CssExtractRspackPlugin.loader,
* options: {
* esModule: false,
* },
* },
* "css-loader",
* ],
* },
* ],
* },
* };
* ```
*
* @public
*
* @defaultValue true
*/
esModule?: boolean | undefined;
}
/**
* {@inheritdoc @lynx-js/css-extract-webpack-plugin#CssExtractRspackPluginOptions}
*
* @public
*/
export declare interface CssExtractRspackPluginOptions {
/**
* {@inheritdoc @lynx-js/css-extract-webpack-plugin#CssExtractRspackPluginOptions.ignoreOrder}
*
* @defaultValue undefined
*/
ignoreOrder?: boolean | undefined;
/**
* {@inheritdoc @lynx-js/css-extract-webpack-plugin#CssExtractRspackPluginOptions.pathinfo}
*
* @defaultValue undefined
*/
pathinfo?: boolean | undefined;
}
/**
* {@inheritdoc Tools.cssLoader}
*
* @public
*/
export declare interface CssLoader {
/**
* The option `importLoaders` allows you to configure how many loaders before `css-loader` should be applied to `@imported` resources and CSS modules imports.
*
* @defaultValue `1` when compiling CSS files and `2` when compiling Sass or Less files
*
* @remarks
*
* See {@link https://github.com/webpack-contrib/css-loader?tab=readme-ov-file#importloaders | css-loader#import-loaders} for details.
*/
importLoaders?: 0 | 1 | 2 | undefined;
/**
* The {@link CssLoaderModules | cssLoader.modules} option enables/disables the CSS Modules specification and setup basic behavior.
*
* @defaultValue Enables CSS Modules with automatic `*.module.*` detection, camelCase exports, `namedExport: false`, and `localIdentName` inherited from `output.cssModules.localIdentName`.
*
* @example
*
* Using `false` value to increase performance because we avoid parsing CSS Modules features, it will be useful for developers who use vanilla css or use other technologies.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* tools: {
* cssLoader: {
* modules: false,
* },
* },
* })
* ```
*
* @example
*
* Using `() => true` value to enable CSS Modules for all files.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* tools: {
* cssLoader: {
* modules: () => true,
* },
* },
* })
* ```
*
* @example
*
* Using object value to enable CSS Modules based-on {@link CssLoaderModules.auto} option and setup more configurations about CSS Modules.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* tools: {
* cssLoader: {
* modules: {
* namedExport: true,
* },
* },
* },
* })
* ```
*/
modules?: boolean | CssLoaderModules | undefined;
}
/**
* {@inheritdoc CssLoader.modules}
*
* @public
*/
export declare interface CssLoaderModules {
/**
* {@inheritdoc CssModules.auto}
*
* @defaultValue true
*/
auto?: boolean | RegExp | ((filename: string) => boolean) | undefined;
/**
* {@inheritdoc CssModules.exportLocalsConvention}
*
* @defaultValue `'camelCase'`
*/
exportLocalsConvention?: CssModuleLocalsConvention | undefined;
/**
* {@inheritdoc CssModules.localIdentName}
*
* @defaultValue `'[local]-[hash:base64:6]'`
*/
localIdentName?: string | undefined;
/**
* Enables/disables ES modules named export for locals.
*
* @defaultValue false
*
* @example
*
* - `style.css`
*
* ```css
* .foo-baz {
* color: red;
* }
* .bar {
* color: blue;
* }
* .default {
* color: green;
* }
* ```
*
* - `index.js`
*
* ```js
* import * as styles from "./styles.css";
*
* // If using `exportLocalsConvention: "as-is"` (default value):
* console.log(styles["foo-baz"], styles.bar);
*
* // If using `exportLocalsConvention: "camel-case-only"`:
* console.log(styles.fooBaz, styles.bar);
*
* // For the `default` class name
* console.log(styles["_default"]);
* ```
*/
namedExport?: boolean | undefined;
}
/**
* {@inheritdoc CssModules.exportLocalsConvention}
*
* @public
*/
export declare type CssModuleLocalsConvention = 'asIs' | 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly';
/**
* {@inheritdoc Output.cssModules}
*
* @public
*/
export declare interface CssModules {
/**
* The `auto` option allows CSS modules to be automatically enabled based on their filenames.
*
* @defaultValue true
*
* @remarks
*
* Given the various `auto` values, the behavior is described as follows:
*
* - `true`: enable CSS modules for all files matching `/\.module\.\w+$/i.test(filename)` RegExp.
*
* - `false`: disable CSS modules.
*
* - `RegExp`: enable CSS modules for all files matching the `auto.test(filename)` RegExp.
*
* - `function`: enable CSS modules based on the filter function.
*
* See {@link https://github.com/webpack-contrib/css-loader?tab=readme-ov-file#auto | css-loader#auto} for details.
*
* @example
*
* Enable CSS module for `*.module.css` and `shared/*.css`:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* output: {
* cssModules: {
* auto: (filename) => {
* return filename.includes('.module.') || filename.includes('shared/')
* },
* },
* },
* })
* ```
*/
auto?: boolean | RegExp | ((filename: string) => boolean) | undefined;
/**
* Allows exporting names from global class names, so you can use them via import.
*
* @defaultValue false
*
* @remarks
*
* See {@link https://github.com/webpack-contrib/css-loader?tab=readme-ov-file#exportglobals | css-loader#exportGlobals} for details.
*/
exportGlobals?: boolean | undefined;
/**
* The style of exported class names.
*
* @defaultValue `'camelCase'`
*
* @remarks
*
* Given the various `exportLocalsConvention` values, the behavior is described as follows:
*
* - `'asIs'`: Class names will be exported as is.
*
* - `'camelCase'`: Class names will be camelized, the original class name will not to be removed from the locals
*
* - `'camelCaseOnly'`: Class names will be camelized, the original class name will be removed from the locals
*
* - `'dashes'`: Only dashes in class names will be camelized
*
* - `'dashesOnly'`: Dashes in class names will be camelized, the original class name will be removed from the locals
*
* See {@link https://github.com/webpack-contrib/css-loader?tab=readme-ov-file#exportlocalsconvention | css-loader#exportLocalsConvention} for details.
*/
exportLocalsConvention?: CssModuleLocalsConvention | undefined;
/**
* Sets the format of the className generated by CSS Modules after compilation.
*
* @defaultValue `'[local]-[hash:base64:6]'`
*
* @remarks
*
* Available placeholders:
*
* - `[local]`: Original class name
*
* - `[hash]`: Hash of the class name
*
* - `[path]`: File path
*
* - `[name]`: File name
*
* - `[ext]`: File extension
*
* See {@link https://github.com/webpack-contrib/css-loader?tab=readme-ov-file#localIdentName | css-loader#localIdentName} for details.
*
* @example
*
* Use only hash for shorter class names:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* output: {
* cssModules: {
* localIdentName: '[hash:base64:8]',
* },
* },
* })
* ```
*
* @example
*
* Include file name for debugging:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* output: {
* cssModules: {
* localIdentName: '[name]__[local]--[hash:base64:5]',
* },
* },
* })
* ```
*/
localIdentName?: string | undefined;
}
/**
* {@inheritdoc Source.decorators}
*
* @public
*/
export declare interface Decorators {
/**
* Specify the decorator syntax version to be used.
*
* @defaultValue `'2022-03'`
*
* @remarks
*
* If you want to know the differences between different decorators versions, you can refer to: {@link https://github.com/tc39/proposal-decorators?tab=readme-ov-file#how-does-this-proposal-compare-to-other-versions-of-decorators | How does this proposal compare to other versions of decorators?}
*
* @example
*
* `'2022-03'` corresponds to the Stage 3 decorator proposal, equivalent to the decorator syntax supported by TypeScript 5.0 by default.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* source: {
* decorators: { version: '2022-03' },
* },
* })
* ```
*
* @example
*
* `'legacy'` corresponds to TypeScript's `experimentalDecorators: true`.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* source: {
* decorators: { version: 'legacy' },
* },
* })
* ```
*/
version?: 'legacy' | '2022-03';
}
/**
* The `defineConfig` method is a helper function used to get TypeScript intellisense.
*
* @param config - The config of Rspeedy.
* @returns - The identical config as the input config.
*
* @example
*
* Use `defineConfig` in `lynx.config.ts`:
*
* ```ts
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* // autocompletion works here!
* })
* ```
*
* @public
*/
export declare function defineConfig(config: Config): Config;
/**
* The `defineConfig` method is a helper function used to get TypeScript intellisense.
*
* @param config - The function that returns a config of Rspeedy.
* @returns - The identical function as the input.
*
* @example
*
* Use `defineConfig` in `lynx.config.ts`:
*
* ```ts
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig(() => {
* return {
* // autocompletion works here!
* }
* })
* ```
*
* @example
*
* Use `defineConfig` with parameters in `lynx.config.ts`:
*
* ```ts
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig(({ env }) => {
* const isTest = env === 'test'
* return {
* output: {
* minify: isTest ? false : true,
* },
* }
* })
* ```
*
* @public
*/
export declare function defineConfig(config: (params: ConfigParams) => Config): (params: ConfigParams) => Config;
/**
* The `defineConfig` method is a helper function used to get TypeScript intellisense.
*
* @param config - The promise that resolves to a config of Rspeedy.
* @returns - The identical promise as the input.
*
* @example
*
* Use `defineConfig` in `lynx.config.ts`:
*
* ```ts
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig(
* import('@lynx-js/react-rsbuild-plugin').then(({ pluginReactLynx }) => ({
* plugins: [pluginReactLynx()],
* })),
* );
* ```
*
* @public
*/
export declare function defineConfig(config: Promise<Config>): Promise<Config>;
/**
* The `defineConfig` method is a helper function used to get TypeScript intellisense.
*
* @param config - The function that returns a promise that resolves to a config of Rspeedy.
* @returns - The identical function as the input.
*
* @example
*
* Use `defineConfig` in `lynx.config.ts`:
*
* ```ts
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig(async () => {
* const foo = await bar()
* return {
* // autocompletion works here!
* }
* })
* ```
*
* @example
*
* Use `defineConfig` with parameters in `lynx.config.ts`:
*
* ```ts
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig(async ({ env }) => {
* const foo = await bar()
* const isTest = env === 'test'
* return {
* output: {
* minify: isTest ? false : true,
* },
* }
* })
* ```
*
* @public
*/
export declare function defineConfig(config: (params: ConfigParams) => Promise<Config>): (params: ConfigParams) => Promise<Config>;
/**
* {@inheritdoc Config.dev}
* @public
*/
export declare interface Dev {
/**
* The {@link Dev.assetPrefix} is used to set the URL prefix for static assets during development.
*
* @defaultValue undefined
*
* @remarks
*
* During `rspeedy dev`, if this option is not set to `false`, the dev plugin normalizes it to `http://<detected-host>:<port>/` and appends `server.base` when configured.
*
* The functionality of {@link Dev.assetPrefix} is basically the same as the {@link https://rspack.rs/config/output#outputpublicpath | output.publicPath}
* config in Rspack. With the following differences:
*
* - `dev.assetPrefix` only takes effect during development.
*
* - `dev.assetPrefix` automatically appends a trailing `/` by default.
*
* - The value of `dev.assetPrefix` is written to the `process.env.ASSET_PREFIX` environment variable.
*
* @example
*
* If `dev.assetPrefix` is set to true, the URL prefix will be `http://<host>:<port>/`:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* dev: {
* assetPrefix: true,
* },
* })
* ```
*
* @example
*
* If `dev.assetPrefix` is set to a string, the value will be used as a prefix and automatically appended to the static resource URL.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* dev: {
* assetPrefix: 'https://example.com/assets/',
* },
* })
* ```
*
* @example
*
* The port number that Rspeedy server listens on may change. For example, if the port is in use, Rspeedy will automatically increment the port number until it finds an available port.
*
* To avoid `dev.assetPrefix` becoming invalid due to port changes, you can use one of the following methods:
*
* - Enable `server.strictPort`.
*
* - Use the `<port>` placeholder to refer to the current port number. Rspeedy will replace the placeholder with the actual port number it is listening on.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* dev: {
* assetPrefix: 'https://example.com:<port>/assets/',
* },
* })
* ```
*/
assetPrefix?: string | boolean | undefined;
/**
* Configuration of the development client.
*
* @defaultValue undefined
*/
client?: DevClient | undefined;
/**
* Whether to enable Hot Module Replacement (HMR).
*
* @defaultValue true
*
* @remarks
*
* By default, Rspeedy uses HMR as the preferred method to update modules. If HMR is disabled or cannot be used in certain scenarios, it will automatically fallback to {@link Dev.liveReload}.
*
* To completely disable both HMR and live reload, set both `dev.hmr` and `dev.liveReload` to `false`. Then, no WebSocket requests will be made to the dev server on the page, and the page will not automatically refresh when file changes.
*
* @example
*
* Disable HMR:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* dev: {
* hmr: false,
* },
* })
* ```
*
* @example
*
* Disable both HMR and live reload:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* dev: {
* hmr: false,
* liveReload: false,
* },
* })
* ```
*/
hmr?: boolean | undefined;
/**
* Whether to enable live reload functionality.
*
* @defaultValue true
*
* Live reload is used as a fallback when {@link Dev.hmr} is disabled or cannot be used in certain scenarios. When enabled, the page will automatically refresh when source files are changed.
*
* To completely disable both HMR and live reload, set both `dev.hmr` and `dev.liveReload` to `false`. Then, no WebSocket requests will be made to the dev server on the page, and the page will not automatically refresh when file changes.
*
* @example
*
* Disable live reload:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* dev: {
* liveReload: false,
* },
* })
* ```
*
* @example
*
* Disable both HMR and live reload:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* dev: {
* hmr: false,
* liveReload: false,
* },
* })
* ```
*/
liveReload?: boolean | undefined;
/**
* Watch specified files and directories for changes. When a file change is detected, it can trigger a page reload or restart the dev server.
*
* @defaultValue undefined
*
* @example
*
* - Specify the files and directories watched for changes.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* dev: {
* watchFiles: {
* paths: ['src/**', 'public/**'],
* },
* },
* })
* ```
*
* @example
*
* - Use {@link https://github.com/paulmillr/chokidar#api | chokidar} options for watching.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* dev: {
* watchFiles: {
* paths: ['src/**', 'public/**'],
* options: { usePolling: false },
* },
* },
* })
* ```
*/
watchFiles?: WatchFiles | WatchFiles[] | undefined;
/**
* Used to control whether the build artifacts of the development environment are written to the disk.
*
* @defaultValue true
*
* @remarks
*
* This is bypassed to {@link https://github.com/webpack/webpack-dev-middleware?tab=readme-ov-file#writetodisk | `webpack-dev-middleware`}.
*
* Setting `writeToDisk: true` won't change the behavior of the `webpack-dev-middleware`, and bundle files accessed through the browser will still be served from memory.
*
* This option also accepts a `Function` value, which can be used to filter which files are written to disk.
*
* The function follows the same premise as `Array#filter` in which a return value of `false` will not write the file, and a return value of `true` will write the file to disk.
*
* @example
* ```js
* // lynx.config.ts
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* dev: {
* writeToDisk: (filePath) => /superman\.css$/.test(filePath),
* },
* })
* ```
*/
writeToDisk?: boolean | ((filename: string) => boolean) | undefined;
/**
* Whether to display progress bar during compilation.
*
* @defaultValue true
*
* @example
*
* Disable the progress bar.
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* dev: {
* progressBar: false,
* },
* })
* ```
*
* @example
*
* Modify the progress bar `id`
*
* To modify the text displayed on the left side of the progress bar, set the `id` option:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* dev: {
* progressBar: {
* id: 'Some Text'
* },
* },
* })
* ```
*/
progressBar?: boolean | {
id?: string;
} | undefined;
}
/**
* {@inheritdoc Dev.client}
*
* @public
*/
export declare interface DevClient {
/**
* The path to websocket.
*
* @defaultValue `require.resolve('@lynx-js/websocket')`
*/
websocketTransport?: string | undefined;
}
/**
* {@inheritdoc Output.distPath}
*
* @public
*/
export declare interface DistPath extends DistPathConfig {
/**
* The output directory of the intermediate files.
*
* @deprecated
*
* This option is never read and will be removed in the future version.
*
* @defaultValue `'.rspeedy'`
*/
intermediate?: string | undefined;
}
/**
* {@inheritdoc Source.entry}
*
* @example
*
* - Use a single entry:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* source: {
* entry: './src/pages/main/index.js',
* }
* })
* ```
*
* @example
*
* - Use a single entry with multiple entry modules:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* source: {
* entry: ['./src/prefetch.js', './src/pages/main/index.js'],
* }
* })
* ```
*
* @example
*
* - Use multiple entries(with multiple entry modules):
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* source: {
* entry: {
* foo: './src/pages/foo/index.js',
* bar: ['./src/pages/bar/index.js', './src/post.js'], // multiple entry modules is allowed
* }
* }
* })
* ```
*
* @example
*
* - Use multiple entries with {@link EntryDescription}:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* source: {
* entry: {
* foo: './src/pages/foo/index.js',
* bar: {
* import: ['./src/prefetch.js', './src/pages/bar'],
* }
* }
* }
* })
* ```
* @public
*/
export declare type Entry = string | string[] | Record<string, string | string[] | EntryDescription>;
/**
* The `EntryDescription` describes a entry. It is useful when the project has multiple entries with different configuration.
*
* @remarks
* It is similar with the {@link https://rspack.rs/config/entry#entry-description-object | Entry Description Object} of Rspack.
* But only a few properties that Lynx supports is allowed.
*
* @public
*/
export declare interface EntryDescription {
/**
* The path to the entry module(s).
*
* @defaultValue `'./src/index.js'`
*/
import?: string | string[] | undefined;
/**
* This is an important option when using on-demand-loading or loading external resources like images, files, etc. If an incorrect value is specified you'll receive 404 errors while loading these resources.
*
* @defaultValue undefined
*
* @see https://webpack.js.org/configuration/output/#outputpublicpath
*/
publicPath?: string | undefined;
}
/**
* The exposed API of Rspeedy. Can be used in Rsbuild plugin with {@link https://rsbuild.rs/plugins/dev/core#apiuseexposed | api.useExposed}.
*
* @public
*
* @example
*
* ```ts
* import type { ExposedAPI } from '@lynx-js/rspeedy'
* const RsbuildPlugin = {
* name: 'my-rsbuild-plugin',
* pre: ['lynx:rsbuild:plugin-api'],
* setup(api) {
* const rspeedyAPI = api.useExposed<ExposedAPI>(Symbol.for('rspeedy.api'))
* },
* }
* ```
*/
export declare interface ExposedAPI {
/**
* The user config.
*/
config: Config;
/**
* Print debug logs.
*
* @param message - The printed message.
*/
debug: (message: string | (() => string)) => void;
/**
* Exit the process.
*
* @param code - The exit code.
*/
exit: (code?: number) => Promise<void> | void;
/**
* Get the Rspeedy logger.
*/
logger: typeof logger;
/**
* The version of Rspeedy.
*/
version: string;
/**
* Used for plugin qrcode get entry points from self-defined environments rather than default lynx environment.
*/
entries?: RsbuildEntry;
}
/**
* {@inheritdoc Output.filename}
*
* @public
*/
export declare interface Filename {
/**
* The name of the bundle files.
*
* @defaultValue `'[name].[platform].bundle'`
*
* @remarks
*
* The following placeholder is supported:
*
* - `[name]`: the name of the entry.
* - `[contenthash]`: the contenthash of the bundle.
* - `[platform]`: the environment name of the bundle.
*
* @example
*
* - Using content hash in bundle filename:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* output: {
* filename: {
* bundle: '[name].[contenthash].bundle',
* },
* },
* })
* ```
*
* @example
*
* - Using content hash with length in bundle filename:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* output: {
* filename: {
* bundle: '[name].[contenthash:8].bundle',
* },
* },
* })
* ```
*
* @example
*
* - Using a function to control the main bundle and the lazy bundles
* separately (e.g. emit lazy bundles into another directory with a git
* commit hash appended):
*
* ```js
* import { execSync } from 'node:child_process'
*
* import { defineConfig } from '@lynx-js/rspeedy'
*
* const gitHash = execSync('git rev-parse --short HEAD').toString().trim()
*
* export default defineConfig({
* output: {
* filename: {
* bundle: ({ lazyBundle, platform }) =>
* lazyBundle
* ? `my-lazy-bundles/[name].[fullhash]-${gitHash}.bundle`
* : `[name].${platform}.bundle`,
* },
* },
* })
* ```
*/
bundle?: BundleFilename | undefined;
/**
* The name of the template files.
*
* @deprecated
*
* Use {@link Filename.bundle} instead.
*
* @defaultValue `'[name].[platform].bundle'`
*
* @remarks
*
* The following placeholder is supported:
*
* - `[name]`: the name of the entry.
* - `[contenthash]`: the contenthash of the template.
*
* @example
*
* - Using content hash in bundle filename:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* output: {
* filename: {
* template: '[name].[contenthash].bundle',
* },
* },
* })
* ```
*
* @example
*
* - Using content hash with length in bundle filename:
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
*
* export default defineConfig({
* output: {
* filename: {
* template: '