rollup-plugin-svelte compiles Svelte components, and the CSS handling is the part to read
Compile Svelte components with Rollup
At a glance
- What is it?
- rollup-plugin-svelte is the Rollup plugin that turns Svelte components into JavaScript and CSS, with support for preprocessing, server-side rendering, custom elements and the svelte export condition. Its own README suggests you use SvelteKit or Vite instead if you have not chosen a bundler yet.
- Who is it for?
- rollup-plugin-svelte suits a team that has deliberately chosen Rollup as its bundler and wants Svelte components compiled through the standard Svelte compiler options rather than a framework's own build layer. It does not suit a project still deciding on a bundler, because the plugin's own documentation points you at SvelteKit or Vite with vite-plugin-svelte instead.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 156 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The plugin's own documentation tells you to use something else
The first line of the project documentation is a recommendation, and it is worth taking seriously.
It says that if you are undecided yet what bundler to use, we suggest using SvelteKit or Vite with vite-plugin-svelte. The plugin then describes itself as compile Svelte components, which is the whole of it.
That is a useful signal about the state of the project. rollup-plugin-svelte is not the recommended path for a new Svelte project. It is the path for a project that already has a Rollup build, or that needs Svelte components inside a larger Rollup-based pipeline, for example a library or a site with a bespoke bundling setup. The framework route handles the compiler options, the dev server and the CSS pipeline for you, and this plugin is the low-level option for when you want to drive those yourself.
The repository layout confirms the scope. Apart from the usual metadata files there is index.js, index.d.ts, a test/ directory, a CHANGELOG.md, a LICENSE, and both .eslintrc and eslint.config.mjs. There is no documentation directory and no example application. The whole plugin is one entry point with a type declaration beside it.
The package manifest is at version 7.2.3, the author is Rich Harris, and the description is Compile Svelte components with Rollup.
Installation needs Svelte alongside the plugin
The installation is a dev dependency, and it has to be two packages:
npm install --save-dev svelte rollup-plugin-svelteThe note explains why: we need to install Svelte as well as the plugin, as it is a peer dependency. The manifest confirms it, with peerDependencies listing rollup at >=2.0.0 and svelte at >=3.5.0.
Those two peer ranges are the compatibility contract, and they are worth checking against your own project before anything else. Rollup 2 is the floor, so a project on Rollup 1 is out. Svelte 3.5 is the floor, so a project on Svelte 2 is out, and a project on Svelte 5 is inside the range but is testing a combination the plugin's own development setup does not use, since the devDependency pins svelte at ^4.0.0 and rollup at ^2.33.3.
That last point is the honest caveat. The plugin is developed and tested against Svelte 4 and Rollup 2, and while the peer ranges allow newer versions, the supported combinations are wider than the tested ones.
The runtime dependencies are only two. @rollup/pluginutils provides the standard plugin helpers, and resolve.exports handles the exports field resolution that the svelte export condition depends on.
The engines field requires Node >=10, which is a low bar that tells you the plugin does not lean on modern Node APIs.
The build and test scripts are minimal by design. The lint script runs eslint on index.js, the test script runs node test/index.js, and prepublishOnly runs both, so linting and testing are enforced before publish rather than by a separate CI step.
The config surface is the Svelte compiler options plus a handful of Rollup specifics
The usage example is a full rollup.config.js, and it is the best available description of the plugin's surface.
// rollup.config.js
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
export default {
input: 'src/main.js',
output: {
file: 'public/bundle.js',
format: 'iife'
},
plugins: [
svelte({Inside the options there are four groups.
The first controls which files are compiled. extensions adds custom file extensions, so a .my-custom-extension file is treated as a component, and include and exclude restrict compilation to a subset, for example 'src/components/**/*.svelte'.
The second is preprocess, where you pass options to svelte.preprocess, with a style callback that receives the content and returns a transformation.
The third is emitCss, described as emitting CSS as files for other plugins to process, with a default of true, although the example sets it to false.
The fourth is compilerOptions, where you can pass any of the Svelte compiler options. The example shows generate set to ssr to use the server-side rendering compiler rather than the client-side one, hydratable true to ensure extra attributes are added to head elements for hydration, and customElement false, which you can set to true to compile components to custom elements, aka web elements.
The fifth is onwarn, a hook that intercepts warnings, with the example squelching a warning whose code is a11y-distributing-elements, and passing everything else to Rollup's normal handler.
CSS emission is the setting that will break your build if you get it wrong
The CSS behaviour is where this plugin has a sharp edge, and the documentation is explicit about it in a way that is worth quoting.
By default, when emitCss is true, the CSS styles are emitted into a virtual file, allowing another Rollup plugin to take responsibility for the new stylesheet. And here is the warning: emitting CSS files requires that you use a Rollup plugin to handle the CSS. Otherwise, your builds will fail.
The reason is mechanical. This plugin adds an import statement to import the emitted CSS file. It is not valid JavaScript to import a CSS file into a JS file, but it allows the CSS to be linked to its respective JS file, and it is a common pattern that other Rollup CSS plugins know how to handle.
So the plugin deliberately emits something the JavaScript runtime cannot execute, on the assumption that a downstream plugin will intercept it. The named candidates are rollup-plugin-css-only and rollup-plugin-postcss. If you do not install one, the failure is at build time, which is the good case, but it is a failure that looks like a plugin bug rather than a missing dependency.
The alternative is emitCss: false, and the documentation explains the trade honestly. If you set emitCss to false and your Svelte components contain style tags, the compiler will add JavaScript that injects those styles into the page when the component is rendered. That is not the default, because it adds weight to your JavaScript, prevents styles from being fetched in parallel with your code, and can even cause CSP violations.
That last point is the one to remember. emitCss false is not a smaller configuration, it is a different runtime architecture with a security policy consequence.
The svelte export condition keeps one copy of Svelte in the bundle
The plugin's most interesting feature is the handling of the svelte export condition, and it addresses a real problem in component library distribution.
If you are importing a component from your node_modules folder, and that component's package.json has a svelte property in its exports condition, then this plugin together with @rollup/plugin-node-resolve and its exportConditions option containing the svelte condition will ensure that your app imports the uncompiled component source code.
The consequence is a smaller, faster app, because the code is deduplicated and shared functions get optimized quicker. The second consequence is more important: it makes it less likely that you will run into bugs caused by your app using a different version of Svelte to the component.
That second problem is the classic component library failure mode. A library ships compiled output, your app has its own Svelte version, and the two disagree about the runtime internals at runtime. Pointing the export condition at the source sidesteps it, provided the library author did the same thing on their side.
The other half of the contract is the publishing side. If you are publishing a component to npm, you should ship the uncompiled source, together with the compiled distributable for people who aren't using Svelte elsewhere in their app, and include the svelte property in the exports of your package.json.
The shape of that exports entry is the whole mechanism:
{
"name": "some-component",
// this means 'some-component' resolves to 'some-component/src/SomeComponent.svelte'
"exports": {
".": {
"svelte": "./src/MyComponent.svelte"
}
}
}For a package with several components, the documentation offers two options. You can create an index.js file that re-exports all the components, and point the svelte condition at that file. Using a single index.js allows multiple components to be imported with a single line, but may load more slowly during development. An export per file may load more quickly during development but requires a separate import statement for each file.
The resolve.exports dependency is there to read those exports maps correctly.
Preprocessing can declare extra files as watch dependencies
The preprocessing section is short and covers one behaviour that is easy to miss.
If you are using the preprocess feature, then your callback responses may, in addition to the code and map values described in the Svelte compile docs, also optionally include a dependencies array. This should be the paths of additional files that the preprocessor result in some way depends upon. In Rollup 0.61 and later, in watch mode, any changes to these additional files will also trigger re-builds.
So a preprocessor that pulls in, say, a design token file or a partial file, can declare that dependency and the dev server will rebuild when it changes. Without the declaration, editing the token file leaves the page showing stale values until you touch a component file, which is the kind of small friction that makes people distrust their build tool.
The mechanism depends on the Rollup version, which the documentation dates to 0.61 and later. The plugin's own peer dependency floor is Rollup 2, so the behaviour is always available in a supported install.
The server-side rendering option is worth pairing with this. Setting generate to ssr in compilerOptions switches to the server-side rendering compiler, and hydratable true ensures that extra attributes are added to head elements for hydration, which is what lets the client-side runtime pick up where the server left off. The customElement option is a third mode, compiling components to custom elements, aka web elements, for use outside a Svelte app.
Where rollup-plugin-svelte is the wrong tool
The first wrong-tool case is a new project without a bundler decision. The documentation's own first sentence sends you to SvelteKit or Vite, and that advice is correct. A framework's build layer handles the dev server with hot reloading, the CSS handling, the browser targets and the compiler options, and none of that is what this plugin is for. Using rollup-plugin-svelte means assembling a Rollup pipeline by hand, and the CSS requirement above is the first thing you will hit.
The second wrong-tool case is a project that wants the framework conventions. SvelteKit gives you file-based routing, server endpoints and a build that knows about the runtime. A Rollup config with this plugin gives you a bundle. If what you are building is an application rather than a library or an embedded widget, the framework route is a better fit.
The third wrong-tool case is a project on Svelte 5 that wants the newest compiler behaviour. The peer range allows svelte >=3.5.0, but the development dependency is svelte ^4.0.0, and the compiler option names in the documentation are the Svelte 3 and 4 ones. Newer Svelte versions change how components are compiled and how runes work, and the plugin's own testing does not cover that.
For the alternative approach, the difference in approach is between a bundler plugin and a framework build tool. vite-plugin-svelte wraps the same Svelte compiler but is integrated into Vite's dev server, so the component graph is known ahead of time and the browser is told what changed. This plugin hands compiled output to Rollup and lets Rollup's watcher figure out what to rebuild. The difference in approach is that Rollup has no notion of a component, so the plugin has to translate that concept itself, which is where the preprocessor dependency declaration and the export condition handling come from.
There is also the option of not using a bundler at all for a small component, where a single file compiled with the Svelte compiler and loaded directly is simpler than any build configuration.
MIT licensed, a small codebase, and a last push in May 2026
The licence is MIT, and the documentation says so in a single line at the end.
The plugin is a small artefact by design. The published files list in the manifest contains only index.js, index.d.ts, README.md and LICENSE, so the install footprint is one JavaScript file and its type declaration, plus two runtime dependencies. The type declaration is wired into the manifest through the types field, so TypeScript users get the plugin options typed without a separate @types package.
On maintenance, the last push to the repository was on 2026-05-20, and the repository has no GitHub releases, so there is no tag history to read. The version in the manifest is 7.2.3, and the CHANGELOG.md in the tree is the changelog.
The development tooling is current even for a small project. The lint script runs eslint against index.js only, and the repository carries both .eslintrc and eslint.config.mjs, which is the flat-config migration in progress that most projects now have. The test script runs node test/index.js directly with uvu, the assertion library, and there is a source-map dev dependency for the tests. The uvu choice is worth noting: it is a small test runner that needs no configuration, which fits a project whose whole test surface is a single directory.
The peer dependency range of rollup >=2.0.0 is the practical constraint on upgrades. Rollup 3 and 4 exist, and the plugin declares compatibility with them, but the dev dependency still pins ^2.33.3, so the plugin is not continuously exercised against the Rollup versions most new projects use. If you are on Rollup 4, that is the combination to verify first.
Editorial conclusion
rollup-plugin-svelte suits a team that has deliberately chosen Rollup as its bundler and wants Svelte components compiled through the standard Svelte compiler options rather than a framework's own build layer. It does not suit a project still deciding on a bundler, because the plugin's own documentation points you at SvelteKit or Vite with vite-plugin-svelte instead. Before adopting, decide how you will handle CSS, because emitting CSS files requires a second Rollup plugin and turning emission off injects styles at runtime, and check the peer dependency ranges of rollup and svelte against your own versions.
Frequently asked questions
How do I install rollup-plugin-svelte?
Run `npm install --save-dev svelte rollup-plugin-svelte`. Svelte is a peer dependency, so it has to be installed alongside the plugin, and the peer ranges are rollup >=2.0.0 and svelte >=3.5.0.
What happens to CSS in rollup-plugin-svelte?
With emitCss true, the default, the CSS is emitted into a virtual file and this plugin adds an import statement for it, which is not valid JavaScript, so a Rollup plugin such as rollup-plugin-css-only or rollup-plugin-postcss must handle it or the build fails. With emitCss false the compiler injects the styles at render time instead, which adds weight to the JavaScript and can cause CSP violations.
What is the svelte export condition for?
If a component's package.json exports a svelte condition pointing at the uncompiled source, this plugin together with @rollup/plugin-node-resolve and its exportConditions option makes your app import that source, so the code is deduplicated and your app and the component share one version of Svelte.
Should I use rollup-plugin-svelte for a new Svelte project?
Probably not. The project's own documentation suggests SvelteKit or Vite with vite-plugin-svelte if you have not yet chosen a bundler. This plugin makes sense when you already have a Rollup build and want to drive the Svelte compiler yourself.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sveltejs-rollup-plugin-svelte)Was this useful?