tooling.report

feature

URL

Can CSS be imported to produce a stylesheet URL?

Person in shorts with blue hair walking left

Introduction

Importing CSS from JavaScript and getting back a URL is a convenient way let the browser handle the work of downloading and applying stylesheets, while still being able to control when and where that work happens. CSS has a smaller per-byte performance impact than JavaScript, so it's often a good idea to avoid inlining CSS into JavaScript bundles.

In the future, it may be possible to explicitly specify how a non-JavaScript import should be handled using something like Module Attributes.

The Test

In this test, a CSS file is imported by a JavaScript module, resulting in the stylesheet being processed by the build tool and a URL returned. That URL can then be injected into the page using <link rel=stylesheet>.

index.js

import cssUrl from './styles.css';
document.head.insertAdjacentHTML(
  'afterend',
  `<link rel="stylesheet" href="${cssUrl}">`,
);

styles.css

.class-name-1 {
  color: green;
}
.class-name-2 {
  background: green;
}

The resulting bundle should include the generated CSS URL, available to the module as cssURL. The stylesheet should also be minified (rules deduplicated, whitespace removed, etc) in order to pass this test.

Conclusion

browserify

Browserify’s urify-emitter plugin emits files into the specified directory and replaces references to that file with the path of the emitted file. An additional gulp task can be used to minify the CSS using gulp-clean-css.

parcel

Parcel supports this out-of-the box via the URL constructor.

Issues

rollup

There are plugins for postcss such as rollup-plugin-postcss, but it's also reasonable to create your own small plugin and use postcss directly.

webpack

CSS files processed using css-loader can be passed through extract-loader to obtain the stylesheet text as a string. Setting the module's type option to "asset/resource" makes it possible to obtain the URL for the stylesheet asset using new URL('./x.css', import.meta.url) or import url from './x.css'.