Skip to content

vuejs/vue-loader

Repository files navigation

vue-loaderci

webpack loader for Vue Single-File Components

v17.2.1+ Only Options

  • experimentalInlineMatchResource: boolean:enableInline matchResourcefor rule matching for vue-loader.

v16+ Only Options

  • reactivityTransform: boolean:enableVue Reactivity Transform(SFCs only).

  • refSugar: boolean:removed.usereactivityTransforminstead.

  • customElement: boolean | RegExp:enable custom elements mode. An SFC loaded in custom elements mode inlines its<style>tags as strings under the component'sstylesoption. When used withdefineCustomElementfrom Vue core, the styles will be injected into the custom element's shadow root.

    • Default is/\.ce\.vue$/
    • Setting totruewill process all.vuefiles in custom element mode.
  • enableTsInTemplate: boolean(16.8+): allow TS expressions in templates when<script>haslang= "ts".Defaults totrue.

    • When used withts-loader,due tots-loader's cache invalidation behavior, it sometimes prevents the template from being hot-reloaded in isolation, causing the component to reload despite only the template being edited. If this is annoying, you can set this option tofalse(and avoid using TS expressions in templates).

    • Alternatively, leave this option on (by default) and useesbuild-loaderto transpile TS instead, which doesn't suffer from this problem (it's also a lot faster). However, do note you will need to rely on TS type checking from other sources (e.g. IDE orvue-tsc).

What is Vue Loader?

vue-loaderis a loader forwebpackthat allows you to author Vue components in a format calledSingle-File Components (SFCs):

<template>
<divclass="example">{{ msg }}</div>
</template>

<script>
exportdefault{
data() {
return{
msg:'Hello world!',
}
},
}
</script>

<style>
.example{
color:red;
}
</style>

There are many cool features provided byvue-loader:

  • Allows using other webpack loaders for each part of a Vue component, for example Sass for<style>and Pug for<template>;
  • Allows custom blocks in a.vuefile that can have custom loader chains applied to them;
  • Treat static assets referenced in<style>and<template>as module dependencies and handle them with webpack loaders;
  • Simulate scoped CSS for each component;
  • State-preserving hot-reloading during development.

In a nutshell, the combination of webpack andvue-loadergives you a modern, flexible and extremely powerful front-end workflow for authoring Vue.js applications.

How It Works

The following section is for maintainers and contributors who are interested in the internal implementation details ofvue-loader,and isnotrequired knowledge for end users.

vue-loaderis not a simple source transform loader. It handles each language blocks inside an SFC with its own dedicated loader chain (you can think of each block as a "virtual module" ), and finally assembles the blocks together into the final module. Here's a brief overview of how the whole thing works:

  1. vue-loaderparses the SFC source code into anSFC Descriptorusing@vue/compiler-sfc.It then generates an import for each language block so the actual returned module code looks like this:

    // code returned from the main loader for 'source.vue'
    
    // import the <template> block
    importrenderfrom'source.vue?vue&type=template'
    // import the <script> block
    importscriptfrom'source.vue?vue&type=script'
    export*from'source.vue?vue&type=script'
    // import <style> blocks
    import'source.vue?vue&type=style&index=1'
    
    script.render=render
    exportdefaultscript

    Notice how the code is importingsource.vueitself, but with different request queries for each block.

  2. We want the content inscriptblock to be treated like.jsfiles (and if it's<script lang= "ts" >,we want to to be treated like.tsfiles). Same for other language blocks. So we want webpack to apply any configured module rules that matches.jsalso to requests that look likesource.vue?vue&type=script.This is whatVueLoaderPlugin(src/plugins.ts) does: for each module rule in the webpack config, it creates a modified clone that targets corresponding Vue language block requests.

    Suppose we have configuredbabel-loaderfor all*.jsfiles. That rule will be cloned and applied to Vue SFC<script>blocks as well. Internally to webpack, a request like

    importscriptfrom'source.vue?vue&type=script'

    Will expand to:

    importscriptfrom'babel-loader!vue-loader!source.vue?vue&type=script'

    Notice thevue-loaderis also matched becausevue-loaderare applied to.vuefiles.

    Similarly, if you have configuredstyle-loader+css-loader+sass-loaderfor*.scssfiles:

    <stylescopedlang= "scss">

    Will be returned byvue-loaderas:

    import'source.vue?vue&type=style&index=1&scoped&lang=scss'

    And webpack will expand it to:

    import'style-loader!css-loader!sass-loader!vue-loader!source.vue?vue&type=style&index=1&scoped&lang=scss'
  3. When processing the expanded requests, the mainvue-loaderwill get invoked again. This time though, the loader notices that the request has queries and is targeting a specific block only. So it selects (src/select.ts) the inner content of the target block and passes it on to the loaders matched after it.

  4. For the<script>block, this is pretty much it. For<template>and<style>blocks though, a few extra tasks need to be performed:

    • We need to compile the template using the Vue template compiler;
    • We need to post-process the CSS in<style scoped>blocks,aftercss-loaderbutbeforestyle-loader.

    Technically, these are additional loaders (src/templateLoader.tsandsrc/stylePostLoader.ts) that need to be injected into the expanded loader chain. It would be very complicated if the end users have to configure this themselves, soVueLoaderPluginalso injects a globalPitching Loader(src/pitcher.ts) that intercepts Vue<template>and<style>requests and injects the necessary loaders. The final requests look like the following:

    // <template lang= "pug" >
    import'vue-loader/template-loader!pug-loader!source.vue?vue&type=template'
    
    // <style scoped lang= "scss" >
    import'style-loader!vue-loader/style-post-loader!css-loader!sass-loader!vue-loader!source.vue?vue&type=style&index=1&scoped&lang=scss'