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 an import with a special scheme, url:.

However, there's a bug in the implementation that causes it to fail with CSS.

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-loader and file-loader can be used together to import CSS files and obtain a URL for them. The result is a stylesheet URL, which can either be injected via <link rel="stylesheet"> or passed through style-loader to inject it automatically.