What is vue-loader?
vue-loader is a loader for webpack that allows you to author Vue components in a format called Single-File Components (SFCs). It provides the ability to transform and load .vue files directly into webpack. It handles the parsing of .vue files, which can contain template, script, and style elements, and it applies other webpack loaders to the respective parts, such as babel-loader for the script section and css-loader for the style section.
What are vue-loader's main functionalities?
Parsing Single-File Components
vue-loader parses .vue files, extracting the script, template, and style sections. This code snippet shows how to configure webpack to use vue-loader for .vue files.
module.exports = {
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
new VueLoaderPlugin()
]
}
Scoped CSS
vue-loader enables scoped CSS for Vue components, ensuring styles only apply to the current component. The code sample shows a scoped style block within a .vue file.
<style scoped>
p[data-v-f3f3eg9] {
color: red;
}
</style>
Hot Module Replacement
vue-loader supports Hot Module Replacement (HMR) for Vue components, allowing components to be updated in real-time without a full page reload. The code sample demonstrates how to set up HMR for a Vue component.
if (module.hot) {
module.hot.accept('./components/MyComponent.vue', function () {
// Any required update logic...
})
}
Pre-Processors
vue-loader allows the use of pre-processors like SCSS, LESS, and Stylus within the style section of a .vue file. The code sample shows how to use SCSS within a Vue component.
<style lang="scss">
$color: red;
.style-class {
color: $color;
}
</style>
Asset URL Handling
vue-loader can transform asset URLs found in a Vue component's template into webpack module requests. The code sample demonstrates how to require an image asset in a .vue file's template.
<template>
<img :src="require('./assets/logo.png')">
</template>
Other packages similar to vue-loader
react-hot-loader
react-hot-loader is similar to vue-loader in that it provides hot module replacement for React components. However, it is specific to React and does not handle single-file components like vue-loader does for Vue.
angular2-template-loader
angular2-template-loader is a loader for webpack that inlines HTML and CSS into Angular components. It is similar to vue-loader in that it processes component templates and styles, but it is designed for Angular rather than Vue.
svelte-loader
svelte-loader is a webpack loader for Svelte components, which are single-file components similar to Vue's SFCs. It compiles Svelte components into JavaScript modules, much like vue-loader does for Vue components.
vue-loader
Vue.js component loader for Webpack, using Webpack loaders for the parts.
It allows you to write your components in this format:
// app.vue
<style>
.red {
color: #f00;
}
</style>
<template>
<h1 class="red">{{msg}}</h1>
</template>
<script>
module.exports = {
data: function () {
return {
msg: 'Hello world!'
}
}
}
</script>
Table of Contents
Basic Usage
Config Webpack:
module.exports = {
entry: './main.js',
output: {
filename: 'build.js'
},
module: {
loaders: [
{ test: /\.vue$/, loader: 'vue' },
]
}
}
And this is all you need to do in your main entry file:
var Vue = require('vue')
var appOptions = require('./app.vue')
var app = new Vue(appOptions).$mount('#app')
Pre-Processors
vue-loader
allows you to use other Webpack loaders to pre-process the different parts inside your *.vue
components. Just specify the loader to use with the lang
attribute (you also need to install the loader, obviously):
<style lang="stylus">
</style>
You can also include Webpack loader queries in the lang
attribute:
<style lang="sass?outputStyle=expanded">
</style>
Template Pre-Processors
For template pre-processors, you should install template-html-loader
plus the raw templating engine. For example to use jade
, you will need to install both template-html-loader
and jade
instead of jade-loader
.
Style Imports
If you want, you can separate your styles into a separate file and import it using the src
attribute:
<style src="./style.css"></style>
Beware that src
imports follow similar rules to require()
calls, which means for relative paths you need to start with ./
, and you can import resources from node modules: <style src="todomvc-app-css/index.css">
.
Asset URL Handling
By default, vue-loader
automatically processes your style and template files with css-loader
and vue-html-loader
- this means that all asset URLs such as <img src="...">
, background: url(...)
and CSS @import
are resolved as module dependencies.
For example, url(image.png)
will be translated into require('./image.png')
. Because .png
is not JavaScript, you will need to configure Webpack to use file-loader or url-loader to handle them. This may feel cumbersome, but it gives you some very powerful benefits in managing your static assets this way:
-
file-loader
allows you to customize where to copy and place the asset file (by specifying publicPath
in your Webpack config), and how they should be named with version hashes.
-
url-loader
allows you to conditionally load a file as a inline Data URL if they are smaller than a given threshold.
For more details, see the respective documentations for vue-html-loader and css-loader.
Scoped Styles
Experimental
When a <style>
tag has the scoped
attribute, its CSS will apply to elements of the current component only. This is similar to the style encapsulation found in Shadow DOM, but doesn't require any polyfills. It is achieved by transforming the following:
<style>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
Into the following:
<style>
.example[_v-1] {
color: red;
}
</style>
<template>
<div class="example" _v-1>hi</div>
</template>
Notes
-
You can include both scoped and non-scoped styles in the same component.
-
A child component's root node will be affected by both the parent's scoped CSS and the child's scoped CSS.
-
Partials are not affected by scoped styles.
Hot Reload
Experimental
When using webpack-dev-server
in hot mode, vue-loader
enables hot component reloading for Vue.js 1.0.0+. An example config:
module.exports = {
entry: ['webpack/hot/dev-server', './src/main.js'],
output: {
publicPath: '/static/',
filename: 'build.js'
},
module: {
loaders: [
{ test: /\.vue$/, loader: 'vue' },
]
},
devtool: '#source-map'
}
In index.html
, include the bundle:
<script src="/static/build.js"></script>
Then, run the dev server with:
webpack-dev-server --hot --config build/webpack.dev.config.js
Finally, visit http://localhost:8080/webpack-dev-server/
to see the app with hot reloading.
For a complete example with hot reloading in action, see vue-hackernews.
Advanced Loader configuration
By default, vue-loader
will try to use the loader with the same name as
the lang
attribute, but you can configure which loader should be used.
Example: Using ES6 with Babel
To apply Babel transforms to all your JavaScript, use this Webpack config:
var vue = require('vue-loader')
module.exports = {
module: {
loaders: [
{
test: /\.vue$/,
loader: vue.withLoaders({
js: 'babel?optional[]=runtime'
})
}
]
},
devtool: 'source-map'
}
Some explanantions:
-
Here js
is the default language for <script>
blocks.
-
The ?optional[]=runtime
query string passed to the loader. This instructs Babel to use helper functions from the babel-runtime
NPM package instead of injecting the helpers into every single file. You'll want this most of the time.
To extract out the generated css into a separate file,
use this Webpack config:
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var vue = require("vue-loader");
module.exports = {
module: {
loaders: [
{
test: /\.vue$/, loader: vue.withLoaders({
css: ExtractTextPlugin.extract("css"),
stylus: ExtractTextPlugin.extract("css!stylus")
})
},
]
},
plugins: [
new ExtractTextPlugin("[name].css")
]
}
Example Project
For a simple setup example, see vue-loader-example.
For an actual project with dev setup with hot reloading and production setup with minification, see vue-hackernews.