GithubHelp home page GithubHelp logo

svelte-loader's Introduction

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', 'module', 'main'],
    conditionNames: ['svelte', 'browser', 'import']
  },
  module: {
    rules: [
      ...
      {
        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: /\.(html|svelte)$/,
        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

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: /\.(html|svelte)$/,
        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: /\.(html|svelte)$/,
        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

svelte-loader's People

Contributors

artefall avatar benmccann avatar bryanwood avatar conduitry avatar crisfole avatar cristinecula avatar ctm-balfre-robert avatar dependabot[bot] avatar dummdidumm avatar egoist avatar ekhaled avatar esarbanis avatar halfnelson avatar ikrestov avatar jacwright avatar jesseskinner avatar kaisermann avatar malkomalko avatar merceyz avatar nikku avatar non25 avatar oscard0m avatar rich-harris avatar rix1 avatar shancarter avatar simulatedgreg avatar syvb avatar vperron avatar wabain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

svelte-loader's Issues

DIsable css "css-unused-selector" warning

I'm not sure how unused rules are treated., but according to sveltejs/svelte#729 it's removed?

My problem is I'm using scss and a lot of things get imported, so a lot of unused rules appear as a side effect. Is there no way to disabled those css-unused-selector warnings? Thanks

Long variable names

This might be something with my webpack configuration rather than a problem with the loader, but I thought I would check.

I have an existing app I am wanting to migrate to using svelte but the components are bloating my JavaScript file. I am not using Uglify currently for certain reasons and would like to find out if this could be fixed easily.

A simple <h1>Hello {{name}}!</h1> component looks like this:

(function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__ = __webpack_require__(283);
/* src/test.svelte generated by Svelte v1.40.2 */


function create_main_fragment(state, component) {
	var h1, text, text_1, text_2;

	return {
		c: function create() {
			h1 = Object(__WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["c" /* createElement */])("h1");
			text = Object(__WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["d" /* createText */])("Hello ");
			text_1 = Object(__WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["d" /* createText */])(state.name);
			text_2 = Object(__WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["d" /* createText */])("!");
		},

		m: function mount(target, anchor) {
			Object(__WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["g" /* insertNode */])(h1, target, anchor);
			Object(__WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["a" /* appendNode */])(text, h1);
			Object(__WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["a" /* appendNode */])(text_1, h1);
			Object(__WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["a" /* appendNode */])(text_2, h1);
		},

		p: function update(changed, state) {
			if (changed.name) {
				text_1.data = state.name;
			}
		},

		u: function unmount() {
			Object(__WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["e" /* detachNode */])(h1);
		},

		d: __WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["h" /* noop */]
	};
}

function Test(options) {
	Object(__WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["f" /* init */])(this, options);
	this._state = options.data || {};

	this._fragment = create_main_fragment(this._state, this);

	if (options.target) {
		this._fragment.c();
		this._fragment.m(options.target, options.anchor || null);
	}
}

Object(__WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["b" /* assign */])(Test.prototype, __WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__["i" /* proto */]);
/* harmony default export */ __webpack_exports__["default"] = (Test);

/***/ })

You can see the export is named __WEBPACK_IMPORTED_MODULE_0__Users_jacob_wright_Personal_Projects_dabble_dabble_node_modules_svelte_shared_js__ and really bloats the JavaScript. Does anyone know how this might be reduced or if I have a setting causing this? I don't see it anywhere else in my file.

Per component compiler options

Similar to #76 but extended.

While configuring Svelte via Webpack using svelte-loader, I see that you can set compiler options. The option that I am most interested in is customElement. It seems that you can either have Svelte compile down to only custom elements or only Svelte class objects, but not both.

In trying to configure only one component, I came across <svelte:options> which you can specify the tag name of the custom element. Is there a way to selectively compile a Svelte component to a custom element in an "opt-in" style like <svelte:options>?

How to use svelte store

Is it possible to enable store using this loader? The docs say you need to pass an option to the compiler, but I'm not sure of the syntax to use here.

Cannot build svelte components in production

I am trying to use svelte for building components and a legacy Backbone application.

The application is currently built using webpack. I added:

      rules: [
        {
          test: /\.svelte$/,
          exclude: /node_modules/,
          use: 'svelte-loader',
        },
      ]

to my webpack.config and everything seems to work fine in development, but when I build for production I get the following error:

ERROR in vendor-53f438ed5305e5f2fa59.js from UglifyJs
Unexpected token: operator (>) [/Users/dc/Projects/web/d3m/node_modules/svelte/internal.js:6,0][vendor-53f438ed5305e5f2fa59.js:46867,20]

ERROR in main-83daa955f5b3660f5e3c.js from UglifyJs
Unexpected token: punc (() [main-83daa955f5b3660f5e3c.js:84246,3]

Any thoughts on what might cause something like this?

Update: I am using webpack 3.8.1

Error messages are not detailed enough

When building with webpack (either in dev mode or as a build step), these are the sorts of error messages I see, missing line or column information or more detailed context:

ERROR in ./components/Contour.html
Module build failed: Error: ParseError: Unexpected token
    at Object.module.exports (../node_modules/svelte-loader/index.js:36:19)
 @ ./components/contour.js 3:15-40

I made an attempt at a [PR}(https://github.com//pull/26) to get more context, and it works locally but I seem to have screwed something up.

Unrecognized option 'resolve'

image

I'm considering using Svelte 3 as a replacement to JQuery. As an example for myself how that could work, I am trying to implement simple filter (text input that filters elements by name). I want to plant this filter deep inside existing HTML layout (actually, Handlebars layout).

Here's my webpack config:

{
  resolve: {
    alias: {
      App: path.resolve(__dirname, 'app/'),
    },
    mainFields: ['svelte', 'browser', 'module', 'main'],
  },
  entry: {
    app: './app/app.js',
    vendor: ['jquery', 'what-input'],
    main: './scss/main.scss',
  },
  output: {
    filename: `./js/[name]-${release_id}.bundle.min.js`,
    sourceMapFilename: `./maps/[name]-${release_id}.map`,
  },
  module: {
    rules: [
      {
        test: /\.svelte$/,
        exclude: /node_modules/,
        use: {
          loader: 'svelte-loader',
          options: {
            emitCss: false,
            hotReload: false, // svelte 3 not yet supported
          },
        },
      },
      // Transpire JS to es2015
      // Babel required for Foundation6. http://foundation.zurb.com/sites/docs/javascript.html
      {
        test: /\.js$/,
        // exclude: /(node_modules)/,
        // Excluding node_modules also excludes processing external dependencies
        use: [{
          loader: 'babel-loader',
          options: {
            presets: [
              ['env', {
                targets: {
                  browsers: browserslist,
                },
                useBuiltIns: true,
                debug: false,
              }],
            ],
          },
        }],
      },
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          // use: ['css-loader', 'sass-loader']
          use: [
            { loader: 'css-loader', options: { sourceMap: true } }, // Load CSS into Webpack
            // postcss-loader autoprefixes CSS
            // Not sure if needed. Installed based on usage notes here: http://foundation.zurb.com/sites/docs/sass.html
            {
              loader: 'postcss-loader',
              options: {
                plugins: () => [
                  precss,
                  autoprefixer,
                  postcssPresetEnv(),
                ],
              },
            },
            // Compiles Sass to CSS
            {
              loader: 'sass-loader',
              options: {
                includePaths: ['node_modules/motion-ui/src'],
                sourceMap: true,
                outputStyle: 'compact',
              },
            },
          ],
        }),
      },
      {
        test: /\.(png|woff|woff2|eot|ttf|svg)$/,
        use: 'url-loader?limit=100000',
      },
    ],
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery',
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
    }),
    new ExtractTextPlugin(`./css/[name]-${release_id}.css`),
  ],
}

My component file is called diagrams-filter.svelte and looks as dumb as it could be:

This is a Filter

<script>
  console.log('filter fired')
</script>

I import this component like this:

import DiagramsFilter from './diagrams-filter.svelte'

const data = getData()

const filter = new DiagramsFilter({
  target: document.querySelector('DiagramsFilter'),
  props: {
    l: data.l,
    l_prefix: data.l_prefix,
    diagrams: data.pages,
  },
})

And in my Handlebars template I have an element with DiagramsFilter id:

<div id="DiagramsFilter"></div>

What am I doing wrong? Or maybe I'm trying to do something that is not possible? Or maybe I'm trying to do something that is just not yet supported? Or it is just a bug?

Any advice will be appreciated. Thank you.

emitCss broken in v2

The ast.hash property was removed in v2, as we thought it wasn't being used anywhere (initially it was used for scoping styles, but then the scoping hash was generated from just the CSS rather than the entire component).

Turns out it was being used in svelte-loader, to provide a filename for the temporary CSS file. So now we have a bundle of different components importing svelte-undefined.css, with predictable results — only one file matches that path.

A temporary workaround is to disable emitCss.

The easy fix would be to reinstate ast.hash, or (better) compute it here. But it would be nice to have a fix that also covered #45, which probably means writing the CSS files back into the source directory:

src
  .App.css
  .Thing.css
  App.html
  Thing.html

I don't know if there's a way to clean up those files after webpack is done with them (or create them in some 'virtual' form so they don't clutter the filesystem in the first place?

svelte3 support

Have this error with svelte3:

proxy.js:135 TypeError: Class constructor SvelteComponentDev cannot be invoked without 'new' at new Layout (_layout.html:2) at proxyComponent._register (proxy.js:128) at new proxyComponent (proxy.js:54) at render (client.js:183) at client.js:148

looks like problem with svelte-dev-helper. How i can resolve it?

bind:this in loop raise error

In svelte 3 it should be possible to use bind:this in a loop (cf sveltejs/svelte#368)

but I get a compilation error when I bind a component in the loop

I get the error :

ERROR in ./src/Main.svelte
Module build failed (from ./node_modules/svelte-loader/index.js):
Error: TypeError: TypeError: Cannot read property 'name' of null
    at preprocess.then.catch.err (/home/oli/Documents/bakino/work/svelte_bug/node_modules/svelte-loader/index.js:180:12)
    at <anonymous>
 @ ./src/app.js 1:0-34 14:15-19

Here is a sample code to reproduce :
Component Todo.svelte

<script>
   export let todo
</script>
<div>
   I am a todo {todo.name}
</div>

Component Main.svelte

<script>
    import Todo from './Todo.svelte' ;

    export let data = { todos: [] } ;
    let todos = [] ;
</script>
<div>
    <h1>A todo list</h1>
    {#each data.todos as todo, i}
        <div>
            <!-- the bind:this={todos[i]} generate the error, remove it and no more error -->
            <Todo todo={todo} bind:this={todos[i]}></Todo>
        </div>
    {/each}
</div>

app.js

import Main from "./Main.svelte" ;

let container = document.createElement("div") ;

let data = {
    todos: [
        {name : "first"},
        {name : "second"},
        {name : "third"},
        {name : "fourth"},
    ]
}

let view = new Main({
    target: container ,
    props: {
        data: data,
    }
});

webpack config

module.exports = {
    resolve: {
        // see below for an explanation
        mainFields: ['svelte', 'browser', 'module', 'main']
    },
    //compile controller JS
    entry: './src/app.js',
    mode: "development",//MODE,
    devtool: "source-map", // Default development sourcemap
    module: {
        rules: [
            {
                test: /\.svelte$/,
                exclude: /node_modules/,
                use: 'svelte-loader',
            }
        ]
    },
    resolve: {
        extensions: [".js", ".json"]
    },
    output: {
        filename: '[name]_bundle.js',
    }
} ;

How to apply babel loader?

I am working on a project with majority of users coming from developing countries, so I have to support transpiling to ES5.

I can't find any documentation on how to set up webpack configurations (yes i'm using the sapper webpack template) to support old browsers, so here I am asking for some help. Thanks in advance!

CRLF line endings causes svelte-loader to fail to compile await blocks correctly.

If you have a component .html source file that has CRLF line endings with an {{#await}} block when compiled with svelte-loader you will get an error like this:

ERROR in ./example.html
Module parse failed: Unexpected token (86:3)
You may need an appropriate loader to handle this file type.
|
  // (2:{{then result}}ing</p>
| function create_pending_block(state, _, component) {
|       var p;
|
 @ ./index.js 1:0-37

Error doesn't occur when line endings are switched to LF.

I've made a repository with an example:
https://github.com/bryanwood/svelte-crlf-await-block

Can workaround this by using LF for line endings.

svelte version: 1.49.3
svelte-loader version: 2.3.2
webpack version: 3.10.0

Changes to imported SCSS in style tag is not triggering a recompile / hot reload

Hey there,

I feel like I'm missing something, but I have a pretty common use case where I'm importing a SCSS file into my component's <style>. The file is importing just fine and my changes in the imported SCSS are reflected whenever I save my Component.html file, but any changes to the .scss file I'm importing doesn't trigger a compile + reload or HMR.

<div class="thing"></div>

<style lang="text/scss">
  @import 'styles/pages/thing.scss';
</script>
  • Do I need to manually trigger a Svelte compile through sass-loader somehow? If so, does that even make sense when using svelte-loader?
  • Is there some magic I need to do in svelte-loader's preprocess.style option?
  • I should note that hotReload is also enabled, and emitCSS is only enabled for production, not when using webpack-dev-server.

Any suggestions? And please let me know if I can provide more information to help figure this one out. :) Thanks!

onMount failing

👋

To reproduce: https://github.com/syfgkjasdkn/onMount-trouble

The problem

When I add onMount(...) to a component which is loaded with svelte-loader, the app fails at runtime with the following error:

Uncaught TypeError: Object(...) is not a function
    at instance (App.svelte:70)
    at init (internal.js:1374)
    at new App (App.svelte:85)
    at eval (main.js:4)
    at Module../src/main.js (app.js:133)
    at __webpack_require__ (app.js:20)
    at eval (main.js:1)
    at Object.0 (app.js:144)
    at __webpack_require__ (app.js:20)
    at app.js:84

The "offending" part (App.svelte:70) is:

Object(svelte__WEBPACK_IMPORTED_MODULE_1__["onMount"])(() => { // x error happens here
  console.log("mounted");
});

Svelte dependency old version

I've tried to build a project using this loader, but it didn't compile properly. It is compiling with svelte 1.6.0.

Not sure why svelte is defined as dependency and peerDependency. But it's not taking the peerDep.

Unexpected token {

I cloned this repo, installed dependencies for the webpack2 example, and ran npm run bundle. This was the output of the error message. I was getting this same error when trying to use the loader on a personal project, but wasn't sure if I had mis-configured something.

I am running Linux Mint 18, 64-bit.

/home/eric/repos/svelte-loader/example/webpack2/webpack.config.js:1
(function (exports, require, module, __filename, __dirname) { const { readFileSync } = require('fs');
                                                                    ^

SyntaxError: Unexpected token {
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:373:25)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at requireConfig (/home/eric/repos/svelte-loader/example/webpack2/node_modules/webpack/bin/convert-argv.js:96:18)
    at /home/eric/repos/svelte-loader/example/webpack2/node_modules/webpack/bin/convert-argv.js:109:17
    at Array.forEach (native)

I tried changing line 1 of the webpack.config.js file to read as follows:

const readFileSync = require('fs').readFileSync;

This was the new error message when I retried the bundle:

loaderUtils.parseQuery() received a non-string value which can be problematic, see https://github.com/webpack/loader-utils/issues/56
parseQuery() will be replaced with getOptions() in the next major version of loader-utils.
Hash: c658534462e32519a92a
Version: webpack 2.5.1
Time: 723ms
   Asset     Size  Chunks             Chunk Names
index.js  10.5 kB       0  [emitted]  index
   [0] ./src/index.js 248 bytes {0} [built]
   [1] ./src/counter.html 2.69 kB {0} [built] [failed] [1 error]
   [2] multi ./src/index.js 28 bytes {0} [built]

ERROR in ./src/counter.html
Module build failed: SyntaxError: Unexpected token {
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:373:25)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at loadLoader (/home/eric/repos/svelte-loader/example/webpack2/node_modules/loader-runner/lib/loadLoader.js:13:17)
    at iteratePitchingLoaders (/home/eric/repos/svelte-loader/example/webpack2/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
    at iteratePitchingLoaders (/home/eric/repos/svelte-loader/example/webpack2/node_modules/loader-runner/lib/LoaderRunner.js:165:10)
    at /home/eric/repos/svelte-loader/example/webpack2/node_modules/loader-runner/lib/LoaderRunner.js:173:18
    at loadLoader (/home/eric/repos/svelte-loader/example/webpack2/node_modules/loader-runner/lib/loadLoader.js:36:3)
    at iteratePitchingLoaders (/home/eric/repos/svelte-loader/example/webpack2/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
    at runLoaders (/home/eric/repos/svelte-loader/example/webpack2/node_modules/loader-runner/lib/LoaderRunner.js:362:2)
    at NormalModule.doBuild (/home/eric/repos/svelte-loader/example/webpack2/node_modules/webpack/lib/NormalModule.js:179:3)
    at NormalModule.build (/home/eric/repos/svelte-loader/example/webpack2/node_modules/webpack/lib/NormalModule.js:268:15)
    at Compilation.buildModule (/home/eric/repos/svelte-loader/example/webpack2/node_modules/webpack/lib/Compilation.js:146:10)
    at factoryCallback (/home/eric/repos/svelte-loader/example/webpack2/node_modules/webpack/lib/Compilation.js:329:11)
    at /home/eric/repos/svelte-loader/example/webpack2/node_modules/webpack/lib/NormalModuleFactory.js:253:5
    at /home/eric/repos/svelte-loader/example/webpack2/node_modules/webpack/lib/NormalModuleFactory.js:99:14
    at /home/eric/repos/svelte-loader/example/webpack2/node_modules/tapable/lib/Tapable.js:204:11
    at NormalModuleFactory.<anonymous> (/home/eric/repos/svelte-loader/example/webpack2/node_modules/webpack/lib/CompatibilityPlugin.js:52:5)
    at NormalModuleFactory.applyPluginsAsyncWaterfall (/home/eric/repos/svelte-loader/example/webpack2/node_modules/tapable/lib/Tapable.js:208:13)
    at /home/eric/repos/svelte-loader/example/webpack2/node_modules/webpack/lib/NormalModuleFactory.js:74:11
    at /home/eric/repos/svelte-loader/example/webpack2/node_modules/webpack/lib/NormalModuleFactory.js:205:8
    at nextTickCallbackWith0Args (node.js:436:9)
    at process._tickCallback (node.js:365:13)
 @ ./src/index.js 3:0-32
 @ multi ./src/index.js

File names can only contain /a-zA-Z_$0-9/ so '图片.svelte' is not permitted

using characters other than alphanumeric plus _ or $ in file names of sapper routes gives the following error.

ERROR in ./src/routes/你好.svelte
Module build failed (from ./node_modules/svelte-loader/index.js):
Error: TypeError: TypeError: Cannot read property 'toUpperCase' of undefined
    at /home/james/www/sapper-v3-webpack/node_modules/svelte-loader/index.js:200:16
 @ ./src/node_modules/@sapper/internal/manifest-client.mjs 30:12-86
 @ ./src/node_modules/@sapper/app.mjs
 @ ./src/client.js
> Encountered errors while building app

It looks like the sanitize function at line 137 converted my filename to an empty string before trying to capitalize it. Seems to me like more character sets should be allowed.

also https://github.com/lovell/limax was mentioned in the chat

hotReload: true breaks styles with emitCss

Changing the contents of a <style> block causes the existing styles for that component to be removed. Something to do with the hash no longer matching.

Without emitCss, it works as expected, so a possible workaround is to only use emitCss in production. Far from ideal though.

Allow for server side web pack builds.

See this for a why. Essentially it allows for quicker startup times and a simpler build chain for isomorphic apps.

Currently with svelte-loader it will always compile to the DOM/browser version of svelte.
It would be awesome if this loader could pickup on the web pack target (node/browser) and automatically provide the appropriate compilation. Alternatively there could be a flag in the options to allow for this (i.e generate: 'dom'|'ssr').

breaks when used in webpack <=3, with svelte v3

Sorry for the annoying issue :-/

TLDR :

It's a cross bug between :

  • the changes between svelte v2 and svelte v3 compiler strategy in options handling
  • a mocha test written the old way.
  • the usage of both this.options and loader-utils.getOptions(this) to handle options.
    ** this.options was deprecated in webpack3 and removed in webpack4.
    ** loader-utils.getOptions(this) is the right way to do. It appeared in version 1.0.0 (21 Feb 2017) of loader-utils and seems supported since webpack v1

edit: proposed pull request : #90
edit: related issue : #88
edit: possibly related issue/pr : #87

Below, all the analysis I did investigating the issue. Sorry, it's a bit verbose.


Context :
Our big project is stuck to webpack 3 at the moment (due to a bug in webpack 4 that will be resolved in webpack 5).

This loader seems to break in webpack3. We have been able to reconstruct a minimal case (using the svelte-app template and making a dichotomy with webpack3 vs webpack4)

  • with webpack3, the loader breaks at the same line as our big project :
    let { js, css, warnings } = normalize(compile(processed.toString(), compileOptions));
  • with webpack4 everything compile fine.

The kind of errors we have :

ERROR in ./src/App.svelte
Module build failed: Error: Error: Error: Unrecognized option 'entry'
    at preprocess.then.catch.err (/ABSOLUTE_PATH/test_svelte3_webpack3/node_modules/svelte-loader/index.js:182:12)
 @ ./src/main.js 1:0-31

On our other project, it's not entry but context.


After further analysis, it seems that the svelte V3 compiler doesn't like the configuration feeded to it when it comes from webpack 3. The validate_options() function of the compiler reject it.

Config is inited here :

const options = Object.assign({}, this.options, getOptions(this));
where this.options is :

  • with webpack 3 : the webpack big config object
  • with webpack 4 : undefined (because it was finally deprecated)

Config is transformed along the way (into a compileOptions object) and, after that, it's used here :

let { js, css, warnings } = normalize(compile(processed.toString(), compileOptions));

In the minimal test case we have :

compileOptions with webpack 3 and svelte 3

{
  "filename": "/workspace_absolute_path/test_svelte3_webpack3/src/App.svelte",
  "format": "esm",
  "entry": "./src/main.js",
  "module": {
    "rules": [
      { "test": {}, "use": [{ "loader": "svelte-loader", "options": {} }] }
    ],
    "unknownContextRequest": ".",
    "unknownContextRegExp": false,
    "unknownContextRecursive": true,
    "unknownContextCritical": true,
    "exprContextRequest": ".",
    "exprContextRegExp": false,
    "exprContextRecursive": true,
    "exprContextCritical": true,
    "wrappedContextRegExp": {},
    "wrappedContextRecursive": true,
    "wrappedContextCritical": false,
    "strictExportPresence": false,
    "strictThisContextOnImports": false,
    "unsafeCache": true
  },
  "output": {
    "path": "/workspace_absolute_path/test_svelte3_webpack3/public",
    "filename": "bundle.js",
    "chunkFilename": "[id].bundle.js",
    "library": "",
    "hotUpdateFunction": "webpackHotUpdate",
    "jsonpFunction": "webpackJsonp",
    "libraryTarget": "var",
    "sourceMapFilename": "[file].map[query]",
    "hotUpdateChunkFilename": "[id].[hash].hot-update.js",
    "hotUpdateMainFilename": "[hash].hot-update.json",
    "crossOriginLoading": false,
    "jsonpScriptType": "text/javascript",
    "chunkLoadTimeout": 120000,
    "hashFunction": "md5",
    "hashDigest": "hex",
    "hashDigestLength": 20,
    "devtoolLineToLine": false,
    "strictModuleExceptionHandling": false
  },
  "context": "/workspace_absolute_path/test_svelte3_webpack3",
  "devtool": false,
  "cache": true,
  "target": "web",
  "node": {
    "console": false,
    "process": true,
    "global": true,
    "Buffer": true,
    "setImmediate": true,
    "__filename": "mock",
    "__dirname": "mock"
  },
  "performance": {
    "maxAssetSize": 250000,
    "maxEntrypointSize": 250000,
    "hints": false
  },
  "resolve": {
    "unsafeCache": true,
    "modules": ["node_modules"],
    "extensions": [".js", ".json"],
    "mainFiles": ["index"],
    "aliasFields": ["browser"],
    "mainFields": ["browser", "module", "main"],
    "cacheWithContext": false
  },
  "resolveLoader": {
    "unsafeCache": true,
    "mainFields": ["loader", "main"],
    "extensions": [".js", ".json"],
    "mainFiles": ["index"],
    "cacheWithContext": false
  }
}

compileOptions with webpack 4 and svelte 3

{"filename":"/workspace_absolute_path/test_svelte3_webpack3/src/App.svelte","format":"esm"}

externalDependencies not working

Hello! I'm currently running the below webpack config to run sass and postcss with preprocess, but the externalDependencies option seems to do nothing when any .scss files are changed.

const chalk = require('chalk');
const fg = require('fast-glob');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const postcss = require('postcss');
const sass = require('node-sass');
const webpack = require('webpack');

const CONFIG = {
  dist: 'dist',
  source: {
    js: 'src/js',
    css: 'src/sass',
    html: 'src/views',
  },
};

module.exports = {
    devServer: {
        contentBase: [
          path.join(__dirname, CONFIG.source.css),
          path.join(__dirname, CONFIG.source.html),
          path.join(__dirname, CONFIG.source.js),
        ],
        open: true,
        overlay: true,
        port: 3777,
        watchContentBase: true,
    },
    entry: path.resolve(__dirname, CONFIG.source.js, 'main.js'),
    mode: 'development',
    module: {
        rules: [
            {
                exclude: /node_modules/,
                test: /\.svelte$/,
                use: {
                    loader: 'svelte-loader',
                    options: {
                      externalDependencies: fg.sync(path.resolve(`${CONFIG.source.css}/**/*.scss`)),
                      preprocess: {
                        style: async ({content, attributes, filename}) => {
                          if(!attributes.lang || !/scss|sass/.test(attributes.lang)) {
                            console.error(chalk.red(
                              `\n${chalk.bold('ERROR')}: No lang attribute passed to styles under ${filename}\n`
                            ));

                            return;
                          }

                          content = await sass.renderSync({
                            data: content,
                            outputStyle : 'compressed',
                            includePaths: [path.resolve(__dirname, `${CONFIG.source.js}`)],
                          }).css.toString();

                          return await postcss([
                            require('autoprefixer')({
                              browsers: ['> 1%', 'IE >= 9', 'last 4 versions'],
                            }),
                            require('postcss-pxtorem')({
                              rootValue: 16,
                              unitPrecision: 5,
                              propList: ['*'],
                              replace: true,
                              mediaQuery: false,
                              minPixelValue: 0,
                            }),
                          ])
                          .process(content, { from: filename })
                          .then(result => {
                            return {
                              code: result.css,
                              map: null,
                            }
                          })
                          .catch(err => {
                            console.error(chalk.bold.red(err));

                            return;
                          });
                        }
                      }
                    }
                },
            },
        ],
    },
    output: {
        filename: '[name]-[hash].js',
        path: path.resolve(__dirname, CONFIG.dist),
    },
    plugins: [
        new HTMLWebpackPlugin({
            template: path.resolve(__dirname, CONFIG.source.html, 'index.html')
        }),
        new webpack.HotModuleReplacementPlugin(),
    ],
    resolve: {
        extensions: ['.svelte', '.js'],
        mainFields: ['svelte', 'browser', 'module', 'main'],
    },
}

Any thoughts?

resolve svelte/shared.js

it's possible for a third party component to try and import the wrong version of Svelte.
Changing this line should fix it:

+const relative = require('relative-require');

// later...

-if (!('shared' in options)) options.shared = options.format === 'es' && 'svelte/shared.js';
+if (!('shared' in options)) options.shared = options.format === 'es' && relative.resolve('svelte/shared.js', process.cwd());

hotReload does not like bound properties

When hotReload is enabled and component contains a bound property, it sadly throws TypeError: xxx._bind is not a function.

Simplest reproduction would be a new sapper-template, and adding e.g. bind:value to the <Layout component in routes/index.html:
<Layout bind:value page='home'>

Publish v1.1.0

I already updated the CHANGELOG and bumped the dependency (cdd1251).

Don't have the permissions to publish svelte-loader on NPM though.

add hot support

looks like right now when running webpack-dev-server with hot enabled and modifying a component in a svelte app the module that tries to hot reload is labelled as unacceptable and logs out that you should do a full reload to see the changes.

Postcss-preset-env && emit css

While using nested css properties of postcss-preset-env, the compiler throws error, although the setting is to emit css.

As far as I understand the problem, svelte-loader should allow the other loaders to handle the css if the emitCss is true. Otherwise it does not allow the other loaders to do their job and stops the compilation all together. I guess if implemented, this would also allow you to write SCSS, Less in the style element too inside svelte component.

Only workaround for now is to include separate css file for the svelte component and import it in the script tag of the component.

The error thrown when nested are used;

Module build failed (from ./node_modules/svelte-loader/index.js):
Error: ParseError: Identifier is expected (16:4)
14: ul.column {
15: flex-direction: column;
16: & li {
^
17: color: black;
18: }
at /home/emil/development/cv-to-pdf/node_modules/svelte-loader/index.js:180:12
@ ./src/App.svelte 15:0-47 22:18-24
@ ./src/index.js

Here is the webpack settings;

{
        test: /\.(html|svelte)$/,
        exclude: /node_modules/,
        use: {
          loader: "svelte-loader",
          options: {
            emitCss: true,
            hotReload: true
          }
        }
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: [{ loader: "style-loader", options: { sourceMap: true } }],
          use: [
            { loader: "css-loader", options: { sourceMap: true } },
            {
              loader: "postcss-loader",
              options: {
                sourceMap: true,
                ident: "postcss",
                plugins: loader => [
                  require("postcss-import")({}),
                  require("postcss-preset-env")(),
                  require("cssnano")()
                ]
              }
            }
          ]
        })
      }

watchRun issue with latest version

I updated svelte-loader to the latest version

{
    "svelte": "^2.5.0",
    "svelte-loader": "^2.9.0"
}

and now I'm getting this issue:

[Error running Gulp] Error: ./client/app/index.html
Module build failed: TypeError: Cannot read property 'watchRun' of undefined
    at new VirtualModulesPlugin (/Users/me/project1/node_modules/svelte-loader/lib/virtual.js:35:17)
    at Object.module.exports (/Users/me/project1/node_modules/svelte-loader/index.js:83:46)
 @ ./client/index.js 1:0-24

Edit: this seems to be an issue with the svelte-loader only. When I downgrade to v2.8.1 - everything works.

Module build failed: Error: ValidationError: Computed properties cannot use destructuring in function parameters

ERROR in ./packages/widgets/imageItem/index.html
Module build failed: Error: ValidationError: Computed properties cannot use destructuring in function parameters (28:19)
26:
27:     computed: {
28:       imageClass: ({ isShadow }) => {
                       ^
29:         let cls = `layload-img `;
30:
    at preprocess.then.catch.err (/Userscontent-list/node_modules/[email protected]@svelte-loader/index.js:135:12)
    at <anonymous>
 @ ./packages/widgets/imageItem/index.js 1:0-37
 @ ./example/components/imageItem/index.html
 @ ./example/pages/routes.js
 @ ./example/app.html
 @ ./example/index.js
 @ multi webpack-hot-middleware/client?reload=true ./example/index.js

Cannot set property '_observers' of undefined

I've installed the svelte-loader package and have added the following configuration:

     {
        test: /\.(html|svelte)$/,
        exclude: /node_modules/,
        use: {
          loader: 'svelte-loader',
          options: {
            emitCss: true,
            hotReload: true,
          },
        },
      },

When running webpack I get the following error:
Template execution failed: TypeError: Cannot set property '_observers' of undefined

Without the html test option, this works fine, but I'd like to use the .html extension in my project. Is there anything else I need to do to get it working?

Referenced images are not found during compile

The emitted css is put into a temp folder outside the path of the project, making it impossible to include images in the css.

webpack.config.js

      "rules": [
...
      {
        test: /\.html$/,
        use: {
          loader: 'svelte-loader',
          options: {
            emitCss: true,
          }
        }
      }

Projects.html

<style>
.logo {
  background: url(../images/logo.png) no-repeat center;
}
</style>

Gives a compile error:

ERROR in ./node_modules/css-loader!/var/folders/b5/j22nvd1n37bfj3nkpn_q8ld80000gp/T/svelte-pbcwuy.css
    Module not found: Error: Can't resolve '../images/logo.png' in '/var/folders/b5/j22nvd1n37bfj3nkpn_q8ld80000gp/T'
     @ ./node_modules/css-loader!/var/folders/b5/j22nvd1n37bfj3nkpn_q8ld80000gp/T/svelte-pbcwuy.css 7:2874-2903

Preprocess options should be on options.preprocess

I just realised that preprocess functions are being drawn directly from options:

options: {
  style: (...) => {...}
}

For consistency with other integrations, that should be like this instead:

options: {
  preprocess: {
    style: (...) => {...}
  }
}

We'll have to intercept options.style, options.script and options.markup and a) turn them into options.preprocess and b) print a big deprecation warning.

Using less for svelte component styles

The webpack buildchain for styles focuses on producing a common css style in the html head section. While it is possible with ExtractTextPlugin to extract the styles into separate css files, but still they go to link tags in the htmml head.

Svelte has a different approach, it attempts to make the css local to components. What seems to be needed is a way to process .less files with webpack (less-loader?) in such a way that it really produces css files which then would have to be included or embedded into the svelte component markup, so that svelte can make them local.

Not sure if this is something that should be solved by svelte-loader, but for the idea to use less in svelte-components, this is hopefully a more appropriate audience than less-loader.

Could this be solved by svelte-loader, i.e. could it pick up less files and add them to components?

Can't reexport the named export

Hi,

Not exactly sure if this is an issue with the loader or svelte.
I have a very basic webpack setup (like in the official template repo).
Whenever import anything from svelte, e.g.:

import {onMount} from 'svelte';

I get a bunch of errors:

ERROR in ./node_modules/svelte/index.mjs 1:0-10:20
Can't reexport the named export 'afterUpdate' from non EcmaScript module (only default export is available)
 @ ./src/App.html
 @ ./src/index.js

ERROR in ./node_modules/svelte/index.mjs 1:0-10:20
Can't reexport the named export 'beforeUpdate' from non EcmaScript module (only default export is available)
 @ ./src/App.html
 @ ./src/index.js

ERROR in ./node_modules/svelte/index.mjs 1:0-10:20
Can't reexport the named export 'createEventDispatcher' from non EcmaScript module (only default export is available)
 @ ./src/App.html
 @ ./src/index.js

ERROR in ./node_modules/svelte/index.mjs 1:0-10:20
Can't reexport the named export 'getContext' from non EcmaScript module (only default export is available)
 @ ./src/App.html
 @ ./src/index.js

ERROR in ./node_modules/svelte/index.mjs 1:0-10:20
Can't reexport the named export 'onDestroy' from non EcmaScript module (only default export is available)
 @ ./src/App.html
 @ ./src/index.js

ERROR in ./node_modules/svelte/index.mjs 1:0-10:20
Can't reexport the named export 'onMount' from non EcmaScript module (only default export is available)
 @ ./src/App.html
 @ ./src/index.js

ERROR in ./node_modules/svelte/index.mjs 1:0-10:20
Can't reexport the named export 'setContext' from non EcmaScript module (only default export is available)
 @ ./src/App.html
 @ ./src/index.js

ERROR in ./node_modules/svelte/index.mjs 1:0-10:20
Can't reexport the named export 'tick' from non EcmaScript module (only default export is available)
 @ ./src/App.html
 @ ./src/index.js

Use Vue.js source-map technique for Svelte source code

This issue relates to sveltejs/svelte#286, and having done some detective work, I think there is a simple solution.

Current Behaviour

When using Webpack 2 + svelte + svelte-loader + babel, everything is fine. Here's the relevant Webpack config that I'm using:

let htmlLoader = {
    test: /\.html?$/,
    use:['babel-loader', 'svelte-loader'],
    exclude: /index-template.html$/
  };
config.module.rules.push(htmlLoader);

However, when it comes to generating code coverage and instrumentation (using Karma and karma-coverage (which uses Istanbul)), I keep running into this error:

ERROR in ./src/modules/common/marketingPanel/marketingPanel.svlt
Module build failed: Error: /mydev/code/src/modules/common/marketingPanel/marketingPanel.svlt: don't know how to turn this value into a node
at Object.valueToNode (/mydev/code/node_modules/babel-types/lib/converters.js:337:9)
at Object.valueToNode (/mydev/code/node_modules/babel-types/lib/converters.js:332:46)
at Object.exit (/mydev/code/node_modules/istanbul-lib-instrument/dist/visitor.js:520:34)
at PluginPass.exit (/mydev/code/node_modules/babel-plugin-istanbul/lib/index.js:73:23)
at newFn (/mydev/code/node_modules/babel-traverse/lib/visitors.js:276:21)
at NodePath._call (/mydev/code/node_modules/babel-traverse/lib/path/context.js:76:18)
at NodePath.call (/mydev/code/node_modules/babel-traverse/lib/path/context.js:48:17)
at NodePath.visit (/mydev/code/node_modules/babel-traverse/lib/path/context.js:117:8)
at TraversalContext.visitQueue (/mydev/code/node_modules/babel-traverse/lib/context.js:150:16)
at TraversalContext.visitSingle (/mydev/code/node_modules/babel-traverse/lib/context.js:108:19)
at TraversalContext.visit (/mydev/code/node_modules/babel-traverse/lib/context.js:192:19)
at Function.traverse.node (/mydev/code/node_modules/babel-traverse/lib/index.js:114:17)
at traverse (/mydev/code/node_modules/babel-traverse/lib/index.js:79:12)
at File.transform (/mydev/code/node_modules/babel-core/lib/transformation/file/index.js:558:35)
at /mydev/code/node_modules/babel-core/lib/transformation/pipeline.js:50:19
at File.wrap (/mydev/code/node_modules/babel-core/lib/transformation/file/index.js:574:16)
at Pipeline.transform (/mydev/code/node_modules/babel-core/lib/transformation/pipeline.js:47:17)
at transpile (/mydev/code/node_modules/babel-loader/lib/index.js:38:20)
at Object.module.exports (/mydev/code/node_modules/babel-loader/lib/index.js:133:12)
@ ./src/modules/common/marketingPanel/unitTest/marketingPanel.spec.js 3:0-52
@ ./src/modules unitTest\/.*spec\.(js|jsx)$
@ ./config/testUnit/test.files.js
webpack: Failed to compile.

The root cause seems to be here: https://github.com/sveltejs/svelte-loader/blob/master/index.js#L30

try {
    let { code, map } = compile(source, options);
    // "map" is not a "plain object" according to Lodash, as it has toString() and toUrl() methods on the prototype
    this.callback(null, code, map);
  } 

Babel(-plugin-istanbul) is parsing the map object, which it expects is a "plain object" (according to Lodash' definition). In this case, map has a 2 prototype methods: toString() and toUrl().

When I replace the above code with the following code, the error disappears:

try {
    let { code, map } = compile(source, options);

     // Remove the toString() and toUrl() methods, which should mean isPlainObject() returns true.
+    let newMap = {
+      code: code.split(/(?:\r?\n)|\r/),  // For the HTML writer
+      file: map.file,
+      mappings: map.mappings,
+      names: map.names,
+      sources: map.sources,
+      sourcesContent: code,   // Change this to the compiled code, not the original code, for the HTML Writer
+      version: map.version
+    };

+    this.callback(null, code, newMap);
-    this.callback(null, code, map);
  }

There are two additional changes which are necessary to support Istanbul with HTML reports:

  1. The code property is an array of the lines of generated-by-svelte code. This property can be used within the karma.config.js file (see below) to cause Istanbul to correctly show code coverage for the generated code. Istanbul CANNOT use the original source code with HTML elements in it.
  2. The sourcesContent property is changed to be the generated-by-svelte code. Again, this is because Istanbul is expecting JS as the source code, not a mixture of HTML and JS.

Combined with the following karma-coverage config in karma.config.js, we now get accurate source maps for the generated code!

// karma.config.js
...
reporters: ['progress', 'junit', 'coverage', 'threshold'],

  coverageReporter: {
    dir: 'reports/coverage/',
    reporters: [
      { type: 'cobertura', subdir: 'cobertura' },
      { type: 'lcovonly', subdir: 'lcov' },
      { type: 'html', subdir: 'html' },
      { type: 'json', subdir: 'json' },
      { type: 'text' }
    ],
    // A custom report collector for Svelte HTML components, so that source maps display semi-correctly
    _onWriteReport: function(collector) {
      // Iterate over the keys of the collector.
      // If the collector key is a HTML file, it should have an inputSourceMap with a code property
      var store = collector.store;
      var keys = store.keys().filter(function(key) {
        return /\.html$/.test(key);
      });

      keys.forEach(function(key) {
        let coverage = store.getObject(key);

        if (coverage.inputSourceMap && coverage.inputSourceMap.code) {
          // Replace the existing key with one that has the code property
          coverage.code = coverage.inputSourceMap.code;
          store.set(key, JSON.stringify(coverage))
        }
      });
      
      return collector;
    }
  },
...

Svelte 3 HMR

I've seen HMR support is on its way: sveltejs/svelte#2377

But I couldn't wait to play with svelte-native, and no HMR is really a bummer there. Because the smallest change triggers a full relaunch of the app on the device, losing the page you were working on in the process...

So I hacked myself together a preliminary HMR for svelte3 & svelte-native.

It's more experiment than anything. It mainly only supports restoring state by public (exported) props, and it's not very stable.

But it already proved useful to me so I was thinking of sharing it, as a temporary solution for other impatient people. Maybe it could also be useful to work around HMR support for svelte-native since, as I have found, it presents its own challenges.

So I wanted to see if you had any thought to share on this. Like maybe how it goes with your projected timing, or anything ?

Also, I've got a question to ask. My changes also impacted the svelte-dev-helper project. For simpler logistics, I was thinking of merging svelte-dev-helper in my fork of svelte-loader. Is there a specific reason why it's not already the case? The two projects seem pretty tightly coupled to me, is there something I missed?

options.filename undefined in 2.13.1

ERROR in ./src/uis/control/App.svelte
Module build failed (from ./node_modules/svelte-loader/index.js):
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
    at assertPath (path.js:39:11)
    at basename (path.js:1294:5)
    at sanitize (/home/onip/workspace/pantobot3d/calibration-ui/node_modules/svelte-loader/index.js:57:9)
    at Object.module.exports (/home/onip/workspace/pantobot3d/calibration-ui/node_modules/svelte-loader/index.js:134:36)
$ npm ls svelte
[email protected] /home/onip/workspace/pantobot3d/calibration-ui
└── [email protected] 

the issue seems to have originated from commit f919ccf0c9b9d3d615269f54c33ff3f3086ef1d0

Build fails on windows

Related to #50
It now fails to build on windows.

Module not found: Error: Can't resolve 'C:UsersKhaledsome-foldernode_modulessvelte-loaderlibhot-api.js'

Always use `shared: true` and `format: 'es'`

There's no reason for shared: true to be configurable — there's no advantage in a webpack context to not sharing helpers.

I think the format should always be es — webpack can handle modules natively, right? (Not a webpack user, I could be wrong about this.) There's no reason for it to be anything else, is there?

More generally, rather than passing down each option in turn, it would probably make sense to pass through all the options, overriding the ones we need to.

Class based components

I prefer to use separate structure for html/css/js rather than single file. Are there any ways to deal with that using svelte-loader? Or another solutions for this problem?

Emit JS?

I'm currently making a svelte-webpack-template for a somewhat old webkit environment. With babel-preset-env, I'm trying to automatically polyfill my project's and svelte's generated code.

My first attempt was to call babel-loader after svelte-loader was done:

image

Unfortunately, it stopped working with the last updates of svelte-loader/svelte and now babel-loader tries to read the template file itself ( ¯\_(◕_◕)_/¯ ).

My next thought was probably a dumb question, but... would it make sense to "emit" the js generated by the svelte compiler?

(or maybe there's a better way to do this...)

throw Error `Unrecognized option 'onwarn' ` when loader 3.0.0

svelte/loader v3.0.0

There is 'TODO anything?' at index.js line 123.

{
  test: /\.svelte$/,
  exclude: /node_modules/,
  use: {
    loader: 'svelte-loader',
    options: {
      emitCss: true,
      onwarn,
      style: sass({}, {name: 'scss'}),
    },
  },
},

onwarn will be ignore.

Also, you forget to add onwarn to valid_options at svelte/compiler line 23800.

My english is so bad, I'm sorry. Do you understand me :)

Can't resolve 'svelte-loader/lib/hot-api'

Kind of an edge case, but if you're using a component that has been linked to your project, it won't be able to resolve hot-api. A plausible fix might be this:

+const resolved = require.resolve('./lib/hot-api');
+
function makeHot(id, code, hotOptions) {
	const options = JSON.stringify(hotOptions);
	const replacement = `

if (module.hot) {

-	const { configure, register, reload } = require('svelte-loader/lib/hot-api');
+	const { configure, register, reload } = require('${resolved}');

	module.hot.accept();

	if (!module.hot.data) {
		// initial load
		configure(${options});
		$2 = register(${id}, $2);
	} else {
		// hot update
		$2 = reload(${id}, $2);
	}
}


export default $2;
`;

hotReload: true prevents page navigation

I haven't looked into this at all yet, but it appears that hotReload: true is breaking page navigation in Sapper. My hunch is that it doesn't play nicely with components that have already been destroyed with component.destroy(). cc @ekhaled

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.