Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

svelte-loader

sveltejs109.6kMIT3.2.4

A webpack loader for svelte

svelte, sveltejs, webpack-loader

readme

Undecided yet what bundler to use? We suggest using SvelteKit, or Vite with vite-plugin-svelte.

svelte-loader

Build Status

A webpack loader for svelte.

Install

npm install --save svelte svelte-loader

Usage

Configure inside your webpack.config.js:

  ...
  resolve: {
    // see below for an explanation
    alias: {
      svelte: path.resolve('node_modules', 'svelte/src/runtime') // Svelte 3: path.resolve('node_modules', 'svelte')
    },
    extensions: ['.mjs', '.js', '.svelte'],
    mainFields: ['svelte', 'browser', '...'],
    conditionNames: ['svelte', 'browser', '...'],
  },
  module: {
    rules: [
      ...
      // The following two loader entries are only needed if you use Svelte 5+ with TypeScript.
      // Also make sure your tsconfig.json includes `"target": "ESNext"` in order to not downlevel syntax
      {
        test: /\.svelte\.ts$/,
        use: [ "svelte-loader", "ts-loader"],
      },
      // This is the config for other .ts files - the regex makes sure to not process .svelte.ts files twice
      {
        test: /(?<!\.svelte)\.ts$/,
        loader: "ts-loader",
      },
      {
        // Svelte 5+:
        test: /\.(svelte|svelte\.js)$/,
        // Svelte 3 or 4:
        // test: /\.svelte$/,
        // In case you write Svelte in HTML (not recommended since Svelte 3):
        // test: /\.(html|svelte)$/,
        use: 'svelte-loader'
      },
      {
        // required to prevent errors from Svelte on Webpack 5+, omit on Webpack 4
        test: /node_modules\/svelte\/.*\.mjs$/,
        resolve: {
          fullySpecified: false
        }
      }
      ...
    ]
  }
  ...

Check out the example project.

resolve.alias

The resolve.alias option is used to make sure that only one copy of the Svelte runtime is bundled in the app, even if you are npm linking in dependencies with their own copy of the svelte package. Having multiple copies of the internal scheduler in an app, besides being inefficient, can also cause various problems.

resolve.mainFields

Webpack's resolve.mainFields option determines which fields in package.json are used to resolve identifiers. If you're using Svelte components installed from npm, you should specify this option so that your app can use the original component source code, rather than consuming the already-compiled version (which is less efficient).

resolve.conditionNames

Webpack's resolve.conditionNames option determines which fields in the exports in package.json are used to resolve identifiers. If you're using Svelte components installed from npm, you should specify this option so that your app can use the original component source code, rather than consuming the already-compiled version (which is less efficient).

Extracting CSS

If your Svelte components contain <style> tags, by default the compiler will add JavaScript that injects those styles into the page when the component is rendered. That's not ideal, because it adds weight to your JavaScript, prevents styles from being fetched in parallel with your code, and can even cause CSP violations.

A better option is to extract the CSS into a separate file. Using the emitCss option as shown below would cause a virtual CSS file to be emitted for each Svelte component. The resulting file is then imported by the component, thus following the standard Webpack compilation flow. Add MiniCssExtractPlugin to the mix to output the css to a separate file.

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  ...
  module: {
    rules: [
      ...
      {
        test: /\.(svelte|svelte\.js)$/,
        use: {
          loader: 'svelte-loader',
          options: {
            emitCss: true,
          },
        },
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              url: false, // necessary if you use url('/path/to/some/asset.png|jpg|gif')
            }
          }
        ]
      },
      ...
    ]
  },
  ...
  plugins: [
    new MiniCssExtractPlugin('styles.css'),
    ...
  ]
  ...

Additionally, if you're using multiple entrypoints, you may wish to change new MiniCssExtractPlugin('styles.css') for new MiniCssExtractPlugin('[name].css') to generate one CSS file per entrypoint.

Warning: in production, if you have set sideEffects: false in your package.json, MiniCssExtractPlugin has a tendency to drop CSS, regardless of whether it's included in your svelte components.

Alternatively, if you're handling styles in some other way and just want to prevent the CSS being added to your JavaScript bundle, use

...
use: {
  loader: 'svelte-loader',
  options: {
    compilerOptions: {
      css: false
    }
  },
},
...

Source maps

JavaScript source maps are enabled by default, you just have to use an appropriate webpack devtool.

To enable CSS source maps, you'll need to use emitCss and pass the sourceMap option to the css-loader. The above config should look like this:

module.exports = {
    ...
    devtool: "source-map", // any "source-map"-like devtool is possible
    ...
    module: {
      rules: [
        ...
        {
          test: /\.css$/,
          use: [
            MiniCssExtractPlugin.loader,
            {
              loader: 'css-loader',
              options: {
                sourceMap: true
              }
            }
          ]
        },
        ...
      ]
    },
    ...
    plugins: [
      new MiniCssExtractPlugin('styles.css'),
      ...
    ]
    ...
};

This should create an additional styles.css.map file.

Svelte Compiler options

You can specify additional arbitrary compilation options with the compilerOptions config key, which are passed directly to the underlying Svelte compiler:

...
use: {
  loader: 'svelte-loader',
  options: {
    compilerOptions: {
      // additional compiler options here
      generate: 'ssr', // for example, SSR can be enabled here
    }
  },
},
...

Using preprocessors like TypeScript

Install svelte-preprocess and add it to the loader options:

const sveltePreprocess = require('svelte-preprocess');
...
use: {
  loader: 'svelte-loader',
  options: {
    preprocess: sveltePreprocess()
  },
},
...

Now you can use other languages inside the script and style tags. Make sure to install the respective transpilers and add a lang tag indicating the language that should be preprocessed. In the case of TypeScript, install typescript and add lang="ts" to your script tags.

Hot Reload

Hot Module Reloading is currently not supported for Svelte 5+

This loader supports component-level HMR via the community supported svelte-hmr package. This package serves as a testbed and early access for Svelte HMR, while we figure out how to best include HMR support in the compiler itself (which is tricky to do without unfairly favoring any particular dev tooling). Feedback, suggestion, or help to move HMR forward is welcomed at svelte-hmr (for now).

Configure inside your webpack.config.js:

// It is recommended to adjust svelte options dynamically, by using
// environment variables
const mode = process.env.NODE_ENV || 'development';
const prod = mode === 'production';

module.exports = {
  ...
  module: {
    rules: [
      ...
      {
        test: /\.(svelte|svelte\.js)$/,
        use: {
          loader: 'svelte-loader',
          options: {
            compilerOptions: {
              // NOTE Svelte's dev mode MUST be enabled for HMR to work
              dev: !prod, // Default: false
            },

            // NOTE emitCss: true is currently not supported with HMR
            // Enable it for production to output separate css file
            emitCss: prod, // Default: false
            // Enable HMR only for dev mode
            hotReload: !prod, // Default: false
            // Extra HMR options, the defaults are completely fine
            // You can safely omit hotOptions altogether
            hotOptions: {
              // Prevent preserving local component state
              preserveLocalState: false,

              // If this string appears anywhere in your component's code, then local
              // state won't be preserved, even when noPreserveState is false
              noPreserveStateKey: '@!hmr',

              // Prevent doing a full reload on next HMR update after fatal error
              noReload: false,

              // Try to recover after runtime errors in component init
              optimistic: false,

              // --- Advanced ---

              // Prevent adding an HMR accept handler to components with
              // accessors option to true, or to components with named exports
              // (from <script context="module">). This have the effect of
              // recreating the consumer of those components, instead of the
              // component themselves, on HMR updates. This might be needed to
              // reflect changes to accessors / named exports in the parents,
              // depending on how you use them.
              acceptAccessors: true,
              acceptNamedExports: true,
            }
          }
        }
      }
      ...
    ]
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    ...
  ]
}

You also need to add the HotModuleReplacementPlugin. There are multiple ways to achieve this.

If you're using webpack-dev-server, you can just pass it the hot option to add the plugin automatically.

Otherwise, you can add it to your webpack config directly:

const webpack = require('webpack');

module.exports = {
  ...
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    ...
  ]
}

CSS @import in components

It is advised to inline any css @import in component's style tag before it hits css-loader.

This ensures equal css behavior when using HMR with emitCss: false and production.

Install svelte-preprocess, postcss, postcss-import, postcss-load-config.

Configure svelte-preprocess:

const sveltePreprocess = require('svelte-preprocess');
...
module.exports = {
  ...
  module: {
    rules: [
      ...
      {
        test: /\.(svelte|svelte\.js)$/,
        use: {
          loader: 'svelte-loader',
          options: {
            preprocess: sveltePreprocess({
              postcss: true
            })
          }
        }
      }
      ...
    ]
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    ...
  ]
}
...

Create postcss.config.js:

module.exports = {
  plugins: [
    require('postcss-import')
  ]
}

If you are using autoprefixer for .css, then it is better to exclude emitted css, because it was already processed with postcss through svelte-preprocess before emitting.

  ...
  module: {
    rules: [
      ...
      {
        test: /\.css$/,
        exclude: /svelte\.\d+\.css/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader'
        ]
      },
      {
        test: /\.css$/,
        include: /svelte\.\d+\.css/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'
        ]
      },
      ...
    ]
  },
  ...

This ensures that global css is being processed with postcss through webpack rules, and svelte component's css is being processed with postcss through svelte-preprocess.

License

MIT

changelog

svelte-loader changelog

3.2.4

  • Don't call callback twice, masking potential errors

3.2.3

  • Svelte 5: Don't compile .svelte/.../.xxx.js/ts files

3.2.2

  • Svelte 5: Also compile .svelte.xxx.js/ts files

3.2.1

  • Handle sourcemaps being falsy
  • Handle ESM config when checking for conditionNames

3.2.0

  • Compile .svelte.js/ts files when using Svelte 5

3.1.9

  • Handle emitCSS to css option transformation correctly for Svelte 4

3.1.8

  • Get ready for Svelte 4

3.1.7

  • More robust conditionNames: ['svelte'] detection (#226)

3.1.6

  • Detect missing conditionNames: ['svelte'] (#225)

3.1.5

  • Bump loader-utils dependency

3.1.4

  • Bump loader-utils dependency

3.1.3

  • Prevent webpack process crashing on undefined dependencies (#197)

3.1.2

  • Update to latest svelte-hmr package fixing Webpack 4 support
  • Fix sourcemap breakpoints (#183)

3.1.1

  • Fix empty sourcesContent (#177)

3.1.0

  • Pass preprocessor source maps to compiler (#172)
  • Recompile style imports after an error (#173)

3.0.0

  • Breaking: compiler options must now be specified under compilerOptions (#159)
  • Breaking: removed support for deprecated style, script, and markup options, which are now located under the preprocess configuration (#158)
  • Breaking: dropped Svelte 2 support (#150)
  • Breaking: dropped Node 8 support (#157)
  • Add Webpack 5 support (#151)
    • Webpack 5 requires an additional rule in webpack.config.js to load the Svelte runtime correctly
  • Replace broken Svelte 2 HMR with the implementation from rixo/svelte-loader-hot (#156)
  • Add Node 14 support and remove virtual modules implementation (fixes #125, #131)

Thanks to @non25, @Smittyvb, @rixo, and the numerous others who contributed to this major release!

2.13.6

  • Check whether the filesystem implements purge before calling it (#81)

2.13.5

  • Fix onwarn with Svelte 3 (#104)

2.13.4

  • Fix webpack 3 bug (#89)

2.13.2

  • Fix compileOptions.filename (#79)

2.13.1

  • v3 fixes (#78)

2.13.0

  • Handle dependencies returned from preprocess (#75)

2.12.0

  • Support Svelte 3

2.11.0

  • Resolve svelte/shared.js before injecting import declaration (#65)

2.10.1

  • Support for older webpack versions (#63)

2.10.0

  • Add options.externalDependencies (#66)

2.9.1

  • Posixify CSS paths on Windows (#64)

2.9.0

  • Fix peer dependency to squelch version mismatch warnings (#57)
  • Fix CSS filenames (#45, #56)
  • Use virtual filesystem to preserve relative paths in CSS (#45

2.8.1

  • Fix HMR on Windows (#52)

2.8.0

  • Deprecate options.markup, options.style and options.script in favour of options.preprocess.* (#41)

2.7.0

  • Use resolved path for hot-api.js, to allowed linked components (#49)

2.6.0

  • Prevent future post-1.60 deprecation warnings (#48)

2.5.1

  • Wrap components with proxies when hot reloading (#44)

2.5.0

  • Emit warnings to webpack (#35)

2.4.0

  • Component-level hot reloading support (#40)

2.3.3

  • Posixify paths to tmp CSS files (#34)

2.3.2

  • Use bare identifier for shared helpers (#33)
  • Use forward-slashes for generated CSS imports (#34)

2.3.1

  • Coerce utimes arguments to dates (#32)

2.3.0

  • Add preprocess support (#31)

2.2.2

  • Deterministic filenames for CSS output (#30)

2.2.1

  • Fix git fail

2.2.0

  • Add emitCss option (#28)

2.1.0

  • Include code frame in error message (#26)

2.0.1

  • Resolve shared helpers path (#19)

2.0.0

  • Pass through all options, overriding format and shared (#17)
  • Auto-generate best configuration for detected webpack version

1.3.1

  • Update loader-utils dependency

1.3.0

  • Pass through options.generate (#10)

1.2.0

  • Add option to specify shared output (svelte#218)

1.1.0

1.0.1

  • Add svelte as peerDependency

1.0.0

  • First release