diff --git a/e2e/cases/assets/styles-as-assets/index.test.ts b/e2e/cases/assets/styles-as-assets/index.test.ts new file mode 100644 index 0000000000..b0daeceac3 --- /dev/null +++ b/e2e/cases/assets/styles-as-assets/index.test.ts @@ -0,0 +1,49 @@ +import { build, rspackOnlyTest } from '@e2e/helper'; +import { expect } from '@playwright/test'; + +rspackOnlyTest( + 'should allow to use `new URL` to reference styles as assets', + async ({ page }) => { + const rsbuild = await build({ + cwd: __dirname, + page, + }); + + const files = await rsbuild.unwrapOutputJSON(); + const filenames = Object.keys(files); + + const test1 = filenames.find((filename) => + filename.includes('dist/static/assets/test1.css'), + ); + const test2 = filenames.find((filename) => + filename.includes('dist/static/assets/test2.less'), + ); + const test3 = filenames.find((filename) => + filename.includes('dist/static/assets/test3.scss'), + ); + const test4 = filenames.find((filename) => + filename.includes('dist/static/assets/test4.styl'), + ); + + expect(test1).toBeDefined(); + expect(test2).toBeDefined(); + expect(test3).toBeDefined(); + expect(test4).toBeDefined(); + expect(files[test1!]).toContain('body{color:red}'); + expect(files[test2!]).toContain('& .foo'); + expect(files[test3!]).toContain('& .foo'); + expect(files[test4!]).toContain('& .foo'); + expect(await page.evaluate('window.test1')).toBe( + `http://localhost:${rsbuild.port}/static/assets/test1.css`, + ); + expect(await page.evaluate('window.test2')).toBe( + `http://localhost:${rsbuild.port}/static/assets/test2.less`, + ); + expect(await page.evaluate('window.test3')).toBe( + `http://localhost:${rsbuild.port}/static/assets/test3.scss`, + ); + expect(await page.evaluate('window.test4')).toBe( + `http://localhost:${rsbuild.port}/static/assets/test4.styl`, + ); + }, +); diff --git a/e2e/cases/assets/styles-as-assets/rsbuild.config.ts b/e2e/cases/assets/styles-as-assets/rsbuild.config.ts new file mode 100644 index 0000000000..cef5ad3233 --- /dev/null +++ b/e2e/cases/assets/styles-as-assets/rsbuild.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from '@rsbuild/core'; +import { pluginLess } from '@rsbuild/plugin-less'; +import { pluginSass } from '@rsbuild/plugin-sass'; +import { pluginStylus } from '@rsbuild/plugin-stylus'; + +export default defineConfig({ + plugins: [pluginLess(), pluginSass(), pluginStylus()], + output: { + filenameHash: false, + }, +}); diff --git a/e2e/cases/assets/styles-as-assets/src/index.js b/e2e/cases/assets/styles-as-assets/src/index.js new file mode 100644 index 0000000000..fa0697e1e7 --- /dev/null +++ b/e2e/cases/assets/styles-as-assets/src/index.js @@ -0,0 +1,4 @@ +window.test1 = new URL('./test1.css', import.meta.url).href; +window.test2 = new URL('./test2.less', import.meta.url).href; +window.test3 = new URL('./test3.scss', import.meta.url).href; +window.test4 = new URL('./test4.styl', import.meta.url).href; diff --git a/e2e/cases/assets/styles-as-assets/src/test1.css b/e2e/cases/assets/styles-as-assets/src/test1.css new file mode 100644 index 0000000000..60f1eab971 --- /dev/null +++ b/e2e/cases/assets/styles-as-assets/src/test1.css @@ -0,0 +1,3 @@ +body { + color: red; +} diff --git a/e2e/cases/assets/styles-as-assets/src/test2.less b/e2e/cases/assets/styles-as-assets/src/test2.less new file mode 100644 index 0000000000..7d6fe107fa --- /dev/null +++ b/e2e/cases/assets/styles-as-assets/src/test2.less @@ -0,0 +1,5 @@ +body { + & .foo { + color: blue; + } +} diff --git a/e2e/cases/assets/styles-as-assets/src/test3.scss b/e2e/cases/assets/styles-as-assets/src/test3.scss new file mode 100644 index 0000000000..d5ba54b3fe --- /dev/null +++ b/e2e/cases/assets/styles-as-assets/src/test3.scss @@ -0,0 +1,5 @@ +body { + & .foo { + color: green; + } +} diff --git a/e2e/cases/assets/styles-as-assets/src/test4.styl b/e2e/cases/assets/styles-as-assets/src/test4.styl new file mode 100644 index 0000000000..d9609bedbf --- /dev/null +++ b/e2e/cases/assets/styles-as-assets/src/test4.styl @@ -0,0 +1,5 @@ +body { + & .foo { + color: yellow; + } +} diff --git a/packages/compat/webpack/tests/__snapshots__/default.test.ts.snap b/packages/compat/webpack/tests/__snapshots__/default.test.ts.snap index f4066cd773..4023046435 100644 --- a/packages/compat/webpack/tests/__snapshots__/default.test.ts.snap +++ b/packages/compat/webpack/tests/__snapshots__/default.test.ts.snap @@ -43,6 +43,9 @@ exports[`applyDefaultPlugins > should apply default plugins correctly 1`] = ` "test": /\\\\\\.m\\?js/, }, { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -428,6 +431,9 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when produ "test": /\\\\\\.m\\?js/, }, { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -808,6 +814,9 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when targe "test": /\\\\\\.m\\?js/, }, { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -1135,6 +1144,9 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when targe "test": /\\\\\\.m\\?js/, }, { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, diff --git a/packages/core/src/plugins/css.ts b/packages/core/src/plugins/css.ts index 4b207a2fda..d00dd5db28 100644 --- a/packages/core/src/plugins/css.ts +++ b/packages/core/src/plugins/css.ts @@ -9,14 +9,11 @@ import { getCssExtractPlugin } from '../pluginHelper'; import type { CSSLoaderModulesMode, CSSLoaderOptions, - ModifyChainUtils, NormalizedEnvironmentConfig, PostCSSLoaderOptions, PostCSSOptions, - RsbuildContext, RsbuildPlugin, Rspack, - RspackChain, } from '../types'; const getCSSModulesLocalIdentName = ( @@ -229,138 +226,123 @@ const getCSSLoaderOptions = ({ return cssLoaderOptions; }; -async function applyCSSRule({ - rule, - config, - context, - utils: { target, isProd, CHAIN_ID, environment }, -}: { - rule: RspackChain.Rule; - config: NormalizedEnvironmentConfig; - context: RsbuildContext; - utils: ModifyChainUtils; -}) { - const emitCss = config.output.emitCss ?? target === 'web'; - - // Create Rspack rule - // Order: style-loader/CssExtractRspackPlugin -> css-loader -> postcss-loader - if (emitCss) { - // use style-loader - if (config.output.injectStyles) { - const styleLoaderOptions = reduceConfigs({ - initial: {}, - config: config.tools.styleLoader, - }); - rule - .use(CHAIN_ID.USE.STYLE) - .loader(getCompiledPath('style-loader')) - .options(styleLoaderOptions); - } - // use CssExtractRspackPlugin loader - else { - rule - .use(CHAIN_ID.USE.MINI_CSS_EXTRACT) - .loader(getCssExtractPlugin().loader) - .options(config.tools.cssExtract.loaderOptions); - } - } else { - rule - .use(CHAIN_ID.USE.IGNORE_CSS) - .loader(path.join(LOADER_PATH, 'ignoreCssLoader.cjs')); - } - - // Number of loaders applied before css-loader for `@import` at-rules - let importLoaders = 0; - - rule.use(CHAIN_ID.USE.CSS).loader(getCompiledPath('css-loader')); - - if (emitCss) { - // `builtin:lightningcss-loader` is not supported when using webpack - if ( - context.bundlerType === 'rspack' && - config.tools.lightningcssLoader !== false - ) { - importLoaders++; - - const userOptions = - config.tools.lightningcssLoader === true - ? {} - : config.tools.lightningcssLoader; - - const initialOptions: Rspack.LightningcssLoaderOptions = { - targets: environment.browserslist, - }; - - if (config.mode === 'production' && config.output.injectStyles) { - initialOptions.minify = true; - } - - const loaderOptions = reduceConfigs({ - initial: initialOptions, - config: userOptions, - }); - - rule - .use(CHAIN_ID.USE.LIGHTNINGCSS) - .loader('builtin:lightningcss-loader') - .options(loaderOptions); - } - - const postcssLoaderOptions = await getPostcssLoaderOptions({ - config, - root: context.rootPath, - }); - - // enable postcss-loader if using PostCSS plugins - if ( - typeof postcssLoaderOptions.postcssOptions === 'function' || - postcssLoaderOptions.postcssOptions?.plugins?.length - ) { - importLoaders++; - rule - .use(CHAIN_ID.USE.POSTCSS) - .loader(getCompiledPath('postcss-loader')) - .options(postcssLoaderOptions); - } - } - - const localIdentName = getCSSModulesLocalIdentName(config, isProd); - const cssLoaderOptions = getCSSLoaderOptions({ - config, - importLoaders, - localIdentName, - emitCss, - }); - rule.use(CHAIN_ID.USE.CSS).options(cssLoaderOptions); - - // CSS imports should always be treated as sideEffects - rule.merge({ sideEffects: true }); - - // Enable preferRelative by default, which is consistent with the default behavior of css-loader - // see: https://github.com/webpack-contrib/css-loader/blob/579fc13/src/plugins/postcss-import-parser.js#L234 - rule.resolve.preferRelative(true); -} - export const pluginCss = (): RsbuildPlugin => ({ name: 'rsbuild:css', setup(api) { api.modifyBundlerChain({ order: 'pre', - handler: async (chain, utils) => { - const rule = chain.module.rule(utils.CHAIN_ID.RULE.CSS); - const { config } = utils.environment; + handler: async (chain, { target, isProd, CHAIN_ID, environment }) => { + const rule = chain.module.rule(CHAIN_ID.RULE.CSS); + const { config } = environment; rule .test(CSS_REGEX) // specify type to allow enabling Rspack `experiments.css` - .type('javascript/auto'); - - await applyCSSRule({ - rule, - utils, + .type('javascript/auto') + // When using `new URL('./path/to/foo.css', import.meta.url)`, + // the module should be treated as an asset module rather than a JS module. + .dependency({ not: 'url' }); + + const emitCss = config.output.emitCss ?? target === 'web'; + + // Create Rspack rule + // Order: style-loader/CssExtractRspackPlugin -> css-loader -> postcss-loader + if (emitCss) { + // use style-loader + if (config.output.injectStyles) { + const styleLoaderOptions = reduceConfigs({ + initial: {}, + config: config.tools.styleLoader, + }); + rule + .use(CHAIN_ID.USE.STYLE) + .loader(getCompiledPath('style-loader')) + .options(styleLoaderOptions); + } + // use CssExtractRspackPlugin loader + else { + rule + .use(CHAIN_ID.USE.MINI_CSS_EXTRACT) + .loader(getCssExtractPlugin().loader) + .options(config.tools.cssExtract.loaderOptions); + } + } else { + rule + .use(CHAIN_ID.USE.IGNORE_CSS) + .loader(path.join(LOADER_PATH, 'ignoreCssLoader.cjs')); + } + + // Number of loaders applied before css-loader for `@import` at-rules + let importLoaders = 0; + + rule.use(CHAIN_ID.USE.CSS).loader(getCompiledPath('css-loader')); + + if (emitCss) { + // `builtin:lightningcss-loader` is not supported when using webpack + if ( + api.context.bundlerType === 'rspack' && + config.tools.lightningcssLoader !== false + ) { + importLoaders++; + + const userOptions = + config.tools.lightningcssLoader === true + ? {} + : config.tools.lightningcssLoader; + + const initialOptions: Rspack.LightningcssLoaderOptions = { + targets: environment.browserslist, + }; + + if (config.mode === 'production' && config.output.injectStyles) { + initialOptions.minify = true; + } + + const loaderOptions = + reduceConfigs({ + initial: initialOptions, + config: userOptions, + }); + + rule + .use(CHAIN_ID.USE.LIGHTNINGCSS) + .loader('builtin:lightningcss-loader') + .options(loaderOptions); + } + + const postcssLoaderOptions = await getPostcssLoaderOptions({ + config, + root: api.context.rootPath, + }); + + // enable postcss-loader if using PostCSS plugins + if ( + typeof postcssLoaderOptions.postcssOptions === 'function' || + postcssLoaderOptions.postcssOptions?.plugins?.length + ) { + importLoaders++; + rule + .use(CHAIN_ID.USE.POSTCSS) + .loader(getCompiledPath('postcss-loader')) + .options(postcssLoaderOptions); + } + } + + const localIdentName = getCSSModulesLocalIdentName(config, isProd); + const cssLoaderOptions = getCSSLoaderOptions({ config, - context: api.context, + importLoaders, + localIdentName, + emitCss, }); + rule.use(CHAIN_ID.USE.CSS).options(cssLoaderOptions); + + // CSS imports should always be treated as sideEffects + rule.merge({ sideEffects: true }); + + // Enable preferRelative by default, which is consistent with the default behavior of css-loader + // see: https://github.com/webpack-contrib/css-loader/blob/579fc13/src/plugins/postcss-import-parser.js#L234 + rule.resolve.preferRelative(true); }, }); }, diff --git a/packages/core/tests/__snapshots__/builder.test.ts.snap b/packages/core/tests/__snapshots__/builder.test.ts.snap index 26702ed9e3..2e7dbf3d0d 100644 --- a/packages/core/tests/__snapshots__/builder.test.ts.snap +++ b/packages/core/tests/__snapshots__/builder.test.ts.snap @@ -30,6 +30,9 @@ exports[`should use Rspack as the default bundler > apply Rspack correctly 1`] = "test": /\\\\\\.m\\?js/, }, { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, diff --git a/packages/core/tests/__snapshots__/css.test.ts.snap b/packages/core/tests/__snapshots__/css.test.ts.snap index b6b3be6db7..bfd510aa11 100644 --- a/packages/core/tests/__snapshots__/css.test.ts.snap +++ b/packages/core/tests/__snapshots__/css.test.ts.snap @@ -5,6 +5,9 @@ exports[`plugin-css > should use custom cssModules rule when using output.cssMod "module": { "rules": [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -55,6 +58,9 @@ exports[`plugin-css injectStyles > should apply ignoreCssLoader when injectStyle "module": { "rules": [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -95,6 +101,9 @@ exports[`plugin-css injectStyles > should use css-loader + style-loader when inj "module": { "rules": [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -143,6 +152,9 @@ exports[`plugin-css injectStyles > should use css-loader + style-loader when inj exports[`should ensure isolation of PostCSS config objects between different builds 1`] = ` [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -201,6 +213,9 @@ exports[`should ensure isolation of PostCSS config objects between different bui exports[`should ensure isolation of PostCSS config objects between different builds 2`] = ` [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, diff --git a/packages/core/tests/__snapshots__/default.test.ts.snap b/packages/core/tests/__snapshots__/default.test.ts.snap index a7655e9d86..5db72f613a 100644 --- a/packages/core/tests/__snapshots__/default.test.ts.snap +++ b/packages/core/tests/__snapshots__/default.test.ts.snap @@ -30,6 +30,9 @@ exports[`applyDefaultPlugins > should apply default plugins correctly 1`] = ` "test": /\\\\\\.m\\?js/, }, { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -444,6 +447,9 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when prod "test": /\\\\\\.m\\?js/, }, { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -894,6 +900,9 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when targe "test": /\\\\\\.m\\?js/, }, { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -1247,6 +1256,9 @@ exports[`tools.rspack > should match snapshot 1`] = ` "test": /\\\\\\.m\\?js/, }, { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, diff --git a/packages/core/tests/__snapshots__/environments.test.ts.snap b/packages/core/tests/__snapshots__/environments.test.ts.snap index c1398201a3..2eff21eea3 100644 --- a/packages/core/tests/__snapshots__/environments.test.ts.snap +++ b/packages/core/tests/__snapshots__/environments.test.ts.snap @@ -1199,6 +1199,9 @@ exports[`environment config > tools.rspack / bundlerChain can be configured in e "test": /\\\\\\.m\\?js/, }, { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -1548,6 +1551,9 @@ exports[`environment config > tools.rspack / bundlerChain can be configured in e "test": /\\\\\\.m\\?js/, }, { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, diff --git a/packages/plugin-less/src/index.ts b/packages/plugin-less/src/index.ts index bf85e05de3..faedc1f1e5 100644 --- a/packages/plugin-less/src/index.ts +++ b/packages/plugin-less/src/index.ts @@ -160,9 +160,10 @@ export const pluginLess = ( rule.exclude.add(pluginOptions.exclude); } + // Copy the builtin CSS rules const cssRule = chain.module.rules.get(CHAIN_ID.RULE.CSS); + rule.dependency(cssRule.get('dependency')); - // Copy the builtin CSS rules for (const id of Object.keys(cssRule.uses.entries())) { const loader = cssRule.uses.get(id); const options = loader.get('options') ?? {}; diff --git a/packages/plugin-less/tests/__snapshots__/index.test.ts.snap b/packages/plugin-less/tests/__snapshots__/index.test.ts.snap index 5865ee4a66..3559927522 100644 --- a/packages/plugin-less/tests/__snapshots__/index.test.ts.snap +++ b/packages/plugin-less/tests/__snapshots__/index.test.ts.snap @@ -3,6 +3,9 @@ exports[`plugin-less > should add less-loader 1`] = ` [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -58,6 +61,9 @@ exports[`plugin-less > should add less-loader 1`] = ` exports[`plugin-less > should add less-loader and css-loader when injectStyles 1`] = ` [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -113,6 +119,9 @@ exports[`plugin-less > should add less-loader and css-loader when injectStyles 1 exports[`plugin-less > should add less-loader with excludes 1`] = ` [ { + "dependency": { + "not": "url", + }, "exclude": [ /node_modules/, ], @@ -171,6 +180,9 @@ exports[`plugin-less > should add less-loader with excludes 1`] = ` exports[`plugin-less > should add less-loader with tools.less 1`] = ` [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -226,6 +238,9 @@ exports[`plugin-less > should add less-loader with tools.less 1`] = ` exports[`plugin-less > should allow to use Less plugins 1`] = ` [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, diff --git a/packages/plugin-sass/src/index.ts b/packages/plugin-sass/src/index.ts index 0d189da0b0..4532314f5f 100644 --- a/packages/plugin-sass/src/index.ts +++ b/packages/plugin-sass/src/index.ts @@ -123,9 +123,10 @@ export const pluginSass = ( rule.exclude.add(pluginOptions.exclude); } + // Copy the builtin CSS rules const cssRule = chain.module.rules.get(CHAIN_ID.RULE.CSS); + rule.dependency(cssRule.get('dependency')); - // Copy the builtin CSS rules for (const id of Object.keys(cssRule.uses.entries())) { const loader = cssRule.uses.get(id); const options = loader.get('options') ?? {}; diff --git a/packages/plugin-sass/tests/__snapshots__/index.test.ts.snap b/packages/plugin-sass/tests/__snapshots__/index.test.ts.snap index db5e5aaf04..5e6b50eab0 100644 --- a/packages/plugin-sass/tests/__snapshots__/index.test.ts.snap +++ b/packages/plugin-sass/tests/__snapshots__/index.test.ts.snap @@ -3,6 +3,9 @@ exports[`plugin-sass > should add sass-loader 1`] = ` [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -63,6 +66,9 @@ exports[`plugin-sass > should add sass-loader 1`] = ` exports[`plugin-sass > should add sass-loader and css-loader when injectStyles 1`] = ` [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -123,6 +129,9 @@ exports[`plugin-sass > should add sass-loader and css-loader when injectStyles 1 exports[`plugin-sass > should add sass-loader with excludes 1`] = ` [ { + "dependency": { + "not": "url", + }, "exclude": [ /node_modules/, ], @@ -186,6 +195,9 @@ exports[`plugin-sass > should add sass-loader with excludes 1`] = ` exports[`plugin-sass > should allow to use legacy API and mute deprecation warnings 1`] = ` [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, diff --git a/packages/plugin-stylus/src/index.ts b/packages/plugin-stylus/src/index.ts index ff47f2736d..0cd6337560 100644 --- a/packages/plugin-stylus/src/index.ts +++ b/packages/plugin-stylus/src/index.ts @@ -55,9 +55,10 @@ export const pluginStylus = (options?: PluginStylusOptions): RsbuildPlugin => ({ .resolve.preferRelative(true) .end(); + // Copy the builtin CSS rules const cssRule = chain.module.rules.get(CHAIN_ID.RULE.CSS); + rule.dependency(cssRule.get('dependency')); - // Copy the builtin CSS rules for (const id of Object.keys(cssRule.uses.entries())) { const loader = cssRule.uses.get(id); const options = loader.get('options') ?? {}; diff --git a/packages/plugin-stylus/tests/__snapshots__/index.test.ts.snap b/packages/plugin-stylus/tests/__snapshots__/index.test.ts.snap index 37a334f490..92e6d79fe3 100644 --- a/packages/plugin-stylus/tests/__snapshots__/index.test.ts.snap +++ b/packages/plugin-stylus/tests/__snapshots__/index.test.ts.snap @@ -3,6 +3,9 @@ exports[`plugin-stylus > should add stylus loader config correctly 1`] = ` [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, @@ -51,6 +54,9 @@ exports[`plugin-stylus > should add stylus loader config correctly 1`] = ` exports[`plugin-stylus > should allow to configure stylus options 1`] = ` [ { + "dependency": { + "not": "url", + }, "resolve": { "preferRelative": true, }, diff --git a/website/docs/en/guide/basic/static-assets.mdx b/website/docs/en/guide/basic/static-assets.mdx index 8012a53339..f2d4dfafda 100644 --- a/website/docs/en/guide/basic/static-assets.mdx +++ b/website/docs/en/guide/basic/static-assets.mdx @@ -65,6 +65,15 @@ const fooTs = new URL('./foo.ts', import.meta.url).href; console.log(fooTs); // "/static/foo.[hash].ts" ``` +Similarly, when using `new URL()` to reference `.css` or `.scss` files, they will be treated as URL assets and will not be processed by Rsbuild's built-in CSS loaders. + +```tsx +// foo.css will remain the original content and be output to the dist directory +const fooCss = new URL('./foo.css', import.meta.url).href; + +console.log(fooCss); // "/static/foo.[hash].css" +``` + ## Import Assets in CSS file In CSS files, you can reference static assets in relative paths: diff --git a/website/docs/zh/guide/basic/static-assets.mdx b/website/docs/zh/guide/basic/static-assets.mdx index 4fd680a866..a04e67c9ba 100644 --- a/website/docs/zh/guide/basic/static-assets.mdx +++ b/website/docs/zh/guide/basic/static-assets.mdx @@ -65,6 +65,15 @@ const fooTs = new URL('./foo.ts', import.meta.url).href; console.log(fooTs); // "/static/foo.[hash].ts" ``` +同理,当使用 `new URL()` 引用 `.css` 或 `.scss` 文件时,它们将被视为 URL assets,不会经过 Rsbuild 内置的 CSS loaders 处理。 + +```tsx +// foo.css 文件将保持原始内容被输出到产物目录下 +const fooCss = new URL('./foo.css', import.meta.url).href; + +console.log(fooCss); // "/static/foo.[hash].css" +``` + ## 在 CSS 文件中引用 在 CSS 文件中,可以引用相对路径下的静态资源: