If you are not interested in manually setting up webpack, it is recommended to scaffold a project with [Vue CLI](https://github.com/vuejs/vue-cli) instead. Projects created by Vue CLI is pre-configured with most of the common development needs and works out of the box.
Follow this guide if the built-in configuration of Vue CLI does not suit your needs, or you'd rather create your own webpack config from scratch.
## Manual Configuration
Vue Loader's configuration is a bit different form other loaders. In addition to a rule that applies `vue-loader` to any files with extension `.vue`, make sure to add Vue Loader's plugin to your webpack config:
``` js
// webpack.config.js
const{VueLoaderPlugin}=require('vue-loader')
module.exports={
module:{
rules:[
// ... other rules
{
test:/\.vue$/,
loader:'vue-loader'
}
]
},
plugins:[
// make sure to include the plugin!
newVueLoaderPlugin()
]
}
```
**The plugin is required.** It is responsible for cloning any other rules you have defined and applying them to the corresponding language blocks in `.vue` files. For example, if you have a rule matching `/\.js$/`, it will be applied to `<script>` blocks in `.vue` files.
A more complete example webpack config will look like this:
By default, `vue-loader` automatically processes your style and template files with [css-loader](https://github.com/webpack/css-loader) and the Vue template compiler. In this compilation process, all asset URLs such as `<img src="...">`, `background: url(...)` and CSS `@import` are **resolved as module dependencies**.
When Vue Loader compiles the `<template>` blocks in SFCs, it also converts any encountered asset URLs into **webpack module requests**.
For example, `url(./image.png)` will be translated into `require('./image.png')`, and
src:require('../image.png')// this is now a module request
}
})
```
### Transform Rules
By default the following tag/attribute combinations are transformed, and can be configured using the [transformAssetUrls](../config.md#transformasseturls) option.
In addition, if you have configured to use [css-loader](https://github.com/webpack-contrib/css-loader) for the `<style>` blocks, asset URLs in your CSS will also be processed in a similar fashion.
## Transform Rules
Asset URL transforms adhere to the following rules:
- If the URL is an absolute path (e.g. `/images/foo.png`), it will be preserved as-is.
-(13.7.0+) If the URL starts with `@`, it's also interpreted as a module request. This is useful if your webpack config has an alias for `@`, which by default points to `/src` in any project created by `vue-cli`.
- If the URL starts with `@`, it's also interpreted as a module request. This is useful if your webpack config has an alias for `@`, which by default points to `/src` in any project created by `vue-cli`.
### Related Loaders
## Related Loaders
Because `.png` is not a JavaScript file, you will need to configure webpack to use [file-loader](https://github.com/webpack/file-loader) or [url-loader](https://github.com/webpack/url-loader) to handle them. The project scaffolded with `vue-cli` has also configured this for you.
Because extensions like `.png` are not JavaScript modules, you will need to configure webpack to use [file-loader](https://github.com/webpack/file-loader) or [url-loader](https://github.com/webpack/url-loader) to properly handle them. Projects created with Vue CLI has this pre-configured.
### Why
## Why
The benefits of all this are:
The benefits of asset URL transforms are:
1.`file-loader` allows you to designate where to copy and place the asset file, and how to name it using version hashes for better caching. Moreover, this also means **you can just place images next to your `*.vue` files and use relative paths based on the folder structure instead of worrying about deployment URLs**. With proper config, webpack will auto-rewrite the file paths into correct URLs in the bundled output.
[CSS Modules](https://github.com/css-modules/css-modules) is a popular system for modularizing and composing CSS. `vue-loader` provides first-class integration with CSS Modules as an alternative for simulated scoped CSS.
### Usage
## Usage
Just add the `module` attribute to your `<style>`:
First, CSS Modules must be enabled by passing `modules: true` to `css-loader`:
``` html
``` js
// webpack.config.js
{
module:{
rules:[
// ... other rules omitted
{
test:/\.css$/,
use:[
'vue-style-loader',
{
loader:'css-loader',
options:{
// enable CSS Modules
modules:true,
// customize generated class names
localIdentName:'[local]_[hash:base64:8]'
}
}
]
}
]
}
}
```
Then, add the `module` attribute to your `<style>`:
``` vue
<stylemodule>
.red{
color:red;
...
...
@@ -19,9 +45,9 @@ Just add the `module` attribute to your `<style>`:
</style>
```
This will turn on CSS Modules mode for `css-loader`, and the resulting class identifier object will be injected into the component as a computed property with the name `$style`. You can use it in your templates with a dynamic class binding:
The `module` attribute instructs Vue Loader to inject the CSS modules locals object into the component as a computed property with the name `$style`. You can then use it in your templates with a dynamic class binding:
```html
```vue
<template>
<p:class="$style.red">
This should be red
...
...
@@ -31,7 +57,7 @@ This will turn on CSS Modules mode for `css-loader`, and the resulting class ide
Since it's a computed property, it also works with the object/array syntax of `:class`:
```html
```vue
<template>
<div>
<p:class="{ [$style.red]: isRed }">
...
...
@@ -46,12 +72,12 @@ Since it's a computed property, it also works with the object/array syntax of `:
And you can also access it from JavaScript:
```html
```vue
<script>
exportdefault{
created(){
console.log(this.$style.red)
// -> "_1VyoJ-uZOjlOxP7jWUy19_0"
// -> "red_1VyoJ-uZ"
// an identifier generated based on filename and className.
}
}
...
...
@@ -60,47 +86,69 @@ export default {
Refer to the [CSS Modules spec](https://github.com/css-modules/css-modules) for mode details such as [global exceptions](https://github.com/css-modules/css-modules#exceptions) and [composition](https://github.com/css-modules/css-modules#composition).
### Custom Inject Name
You can have more than one `<style>` tags in a single `*.vue` component. To avoid injected styles to overwrite each other, you can customize the name of the injected computed property by giving the `module` attribute a value:
``` html
<style module="a">
/* identifiers injected as a */
</style>
<style module="b">
/* identifiers injected as b */
</style>
```
## Opt-in Usage
### Configuring `css-loader` Query
CSS Modules are processed via [css-loader](https://github.com/webpack/css-loader). With `<style module>`, the default query used for `css-loader` is:
If you only want to use CSS Modules in some of your Vue components, you can use a `oneOf` rule and check for the `module` string in resourceQuery:
``` js
// webpack.config.js -> module.rules
{
modules:true,
importLoaders:1,
localIdentName:'[hash:base64]'
test:/\.css$/,
oneOf:[
// this matches <style module>
{
resourceQuery:/module/,
use:[
'vue-style-loader',
{
loader:'css-loader',
options:{
modules:true,
localIdentName:'[local]_[hash:base64:5]'
}
}
]
},
// this matches plain <style> or <style scoped>
{
use:[
'vue-style-loader',
'css-loader'
]
}
]
}
```
You can use vue-loader's `cssModules` option to provide additional query options to `css-loader`:
## Using with Pre-Processors
CSS Modules can be used along with other pre-processors:
You can have more than one `<style>` tags in a single `*.vue` component. To avoid injected styles to overwrite each other, you can customize the name of the injected computed property by giving the `module` attribute a value:
You can define custom language blocks inside `*.vue` files. Loaders applied for a custom block are matched based on the `lang` attribute of the block, the block's tag name, and the rules in your webpack config.
You can define custom language blocks inside `*.vue` files. The content of a custom block will be processed by the loaders specified in the `loaders` object of `vue-loader` options and then required by the component module. The configuration is similar to what is described in [Advanced Loader Configuration](../configurations/advanced.md), except the matching uses the tag name instead of the `lang` attribute.
If a `lang` attribute is specified, the custom block will be matched as a file with the `lang` as its extension.
If a matching loader is found for a custom block, it will be processed; otherwise the custom block will simply be ignored. Additionally, if the found loader returns a function, that function will be called with the component of the `*.vue` file as a parameter.
## Single docs file example
Here's an example of extracting all `<docs>` custom blocks into a single docs file:
#### component.vue
``` html
<docs>
## This is an Example component.
</docs>
<template>
<h2class="red">{{msg}}</h2>
</template>
<script>
exportdefault{
data(){
return{
msg:'Hello from Component A!'
}
}
}
</script>
<style>
comp-ah2{
color:#f00;
}
</style>
```
#### webpack.config.js
You can also use `resourceQuery` to match a rule against a custom block with no `lang`. For example, to match against `<foo>` custom blocks:
If a matching rule is found for a custom block, it will be processed; otherwise the custom block will be silently ignored.
> Requires 11.3.0+
Additionally, if the custom block exports a function as the final result after being processed by all the matching loaders, that function will be called with the component of the `*.vue` file as a parameter.
Here's an example of injecting the `<docs>` custom blocks into the component so that it's available during runtime.
## Example
#### docs-loader.js
Here's an example of injecting the `<docs>` custom blocks into the component so that it's available during runtime.
In order for the custom block content to be injected, we'll need a custom loader:
In order for the custom block content to be injected, we'll write a custom loader:
With `vue-loader >= 13.3.0`, functional components defined as a Single-File Component in a `*.vue` file now enjoys proper template compilation, Scoped CSS and hot-reloading support.
Functional components defined as a Single-File Component in a `*.vue` file also receives proper template compilation, Scoped CSS and hot-reloading support.
To denote a template that should be compiled as a functional component, add the `functional` attribute to the template block. This also allows omitting the `functional` option in the `<script>` block.
Expressions in the template are evaluated in the [functional render context](https://vuejs.org/v2/guide/render-function.html#Functional-Components). This means props need to be accessed as `props.xxx` in the template:
```html
```vue
<templatefunctional>
<div>{{props.foo}}</div>
</template>
```
If you need to access properties defined globally on `Vue.prototype`, you can access them on `parent`:
You may have been wondering how do you lint your code inside `*.vue` files, since they are not JavaScript. We will assume you are using [ESLint](https://eslint.org/)(if you are not, you should!).
You will also need the official [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) which supports linting both the template and script parts of Vue files.
The official [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) supports linting both the template and script parts of Vue single file components.
Make sure to use the plugin's included config in your ESLint config:
Another option is using [eslint-loader](https://github.com/MoOx/eslint-loader) so that your `*.vue` files are automatically linted on save during development:
Any CSS output processed by `vue-loader` is piped through [PostCSS](https://github.com/postcss/postcss) for scoped CSS rewriting. You can also add custom PostCSS plugins to the process, for example [autoprefixer](https://github.com/postcss/autoprefixer) or [CSSNext](http://cssnext.io/).
## Using a Config File
`vue-loader` supports auto-loading the same PostCss config files supported by [`postcss-loader`](https://github.com/postcss/postcss-loader#usage):
-`postcss.config.js`
-`.postcssrc`
-`postcss` field in `package.json`
Using a config file allows you to share the same config between your normal CSS files processed by `postcss-loader` and the CSS inside `*.vue` files, and is recommended.
## Using with `postcss-loader`
Since `vue-loader` handles PostCSS on its styles internally, you only need to apply `postcss-loader` to standalone CSS files. There's no need to specify `lang="postcss"` on a style block if there is a PostCSS config file in your project.
Sometimes the user may want to use `lang="postcss"` only for syntax highlighting purposes. Starting in 13.6.0, if no loader has been explicitly configured for the following common PostCSS extensions (via `vue-loader`'s own `loaders` option), they will simply go through `vue-loader`'s default PostCSS transforms:
-`postcss`
-`pcss`
-`sugarss`
-`sss`
## Inline Options
Alternatively, you can specify PostCSS config specifically for `*.vue` files using the `postcss` option for `vue-loader`.
Example:
``` js
// webpack.config.js
module.exports={
// other options...
module:{
// `module.rules` is the same as `module.loaders` in 1.x
rules:[
{
test:/\.vue$/,
loader:'vue-loader',
// `vue-loader` options goes here
options:{
// ...
postcss:[require('postcss-cssnext')()]
}
}
]
}
}
```
In addition to providing an Array of plugins, the `postcss` option also accepts:
- A function that returns an array of plugins;
- An object that contains options to be passed to the PostCSS processor. This is useful when you are using PostCSS projects that relies on custom parser/stringifiers:
``` js
postcss:{
plugins:[...],// list of plugins
options:{
parser:'sugarss'// use sugarss parser
}
}
```
### Disabling Auto Config File Loading
In `13.6.0+`, auto PostCSS config file loading can be disabled by specifying `postcss.useConfigFile:false`:
``` js
postcss: {
useConfigFile: false,
plugins: [/* ... */],
options: {/* ... */}
}
```
This allows the PostCSS configuration inside `*.vue` files to be entirely controlled by the inline config.
In webpack, all pre-processors need to be applied with a corresponding loader. `vue-loader` allows you to use other webpack loaders to process a part of a Vue component. It will automatically infer the proper loaders to use from the `lang` attribute of a language block.
In webpack, all pre-processors need to be applied with a corresponding loader. `vue-loader` allows you to use other webpack loaders to process a part of a Vue component. It will automatically infer the proper loaders to use based on the `lang` attribute of a language block and the rules in your webpack config.
### CSS
## SASS
For example, let's compile our `<style>` tag with Sass:
For example, to compile our `<style>` tag with SASS/SCSS:
``` bash
npm install sass-loader node-sass --save-dev
npm install-D sass-loader node-sass
```
In your webpack config:
``` js
module.exports={
module:{
rules:[
// ...other rules omitted
// this will apply to both plain .scss files
// AND <style lang="scss"> blocks in vue files
{
test:/\.scss$/,
use:[
'vue-style-loader',
'css-loader',
'sass-loader'
]
}
]
},
// plugin omitted
}
```
Now in addition to being able to `import 'style.scss'`, we can use SCSS in Vue components as well:
``` html
<style lang="sass">
/* write sass here */
<style lang="scss">
/* write SCSS here */
</style>
```
Under the hood, the text content inside the `<style>` tag will be first compiled by `sass-loader` before being passed on for further processing.
Any content inside the block will be processed by webpack as if it's inside a `*.scss` file.
#### sass-loader caveat
### SASS vs SCSS
Contrary to what its name indicates, [*sass*-loader](https://github.com/jtangelder/sass-loader) parses *SCSS* syntax by default. If you actually want to use the indented *Sass* syntax, you have to configure vue-loader's options for sass-loader accordingly.
Note that `sass-loader` processes the non-indent-based `scss` syntax by default. In order to use the indent-based `sass` syntax, you need to pass options to the loader:
See the [Advanced Loader Configuration](./advanced.md) Section for further information about how to configure vue-loader.
### Sharing Global Variables
#### Loading a global settings file
`sass-loader` also supports a `data` option which allows you to share common variables among all processed files without having to explicit import them:
A common request is to be able to load a settings file in each component without the need to explicity import it each time, e.g. to use scss variables globally throughout all components. To accomplish this:
``` js
// webpack.config.js -> module.rules
{
test:/\.scss$/,
use:[
'vue-style-loader',
'css-loader',
{
loader:'sass-loader',
options:{
// you can also read from a file, e.g. `variables.scss`
It is recommended to only include variables, mixins, etc. in this file, to prevent duplicated css in your final, compiled files.
Configuration of PostCSS can be done via `postcss.config.js` or `postcss-loader` options. For details, consult [postcss-loader docs](https://github.com/postcss/postcss-loader).
### JavaScript
`postcss-loader` can also be applied in combination with other pre-processors mentioned above.
All JavaScript inside Vue components are processed by `babel-loader` by default. But you can of course change it:
## Babel
``` bash
npm install coffee-loader --save-dev
npm install-D babel-core babel-loader
```
``` html
<script lang="coffee">
#Writecoffeescript!
</script>
``` js
// webpack.config.js -> module.rules
{
test:/\.js?$/,
loader:'babel-loader'
}
```
### Templates
Configuration of Babel can be done via `.babelrc` or `babel-loader` options.
Processing templates is a little different, because most webpack template loaders such as `pug-loader` return a template function instead of a compiled HTML string. Instead of using `pug-loader`, we can just install the original `pug`:
## TypeScript
``` bash
npm install pug --save-dev
npm install-D typescript ts-loader
```
``` js
// webpack.config.js
module.exports={
resolve:{
// Add `.ts` as a resolvable extension.
extensions:['.ts','.js']
},
module:{
rules:[
// ...other rules omitted
{
test:/\.ts$/,
loader:'ts-loader',
options:{appendTsSuffixTo:[/\.vue$/]}
}
]
},
// ...plugin omitted
}
```
Configuration of TypeScipt can be done via `tsconfig.json`. Also see docs for [ts-loader](https://github.com/TypeStrong/ts-loader).
## Pug
Processing templates is a little different, because most webpack template loaders such as `pug-loader` return a template function instead of a compiled HTML string. Instead of using `pug-loader`, we need to use a loader that returns the raw HTML string instead, e.g. `pug-plain-loader`:
``` bash
npm install-D pug pug-plain-loader
```
``` js
// webpack.config.js -> module.rules
{
test:/\.pug$/,
loader:'pug-plain-loader'
}
```
Then you can write:
``` html
<templatelang="pug">
div
...
...
@@ -100,16 +226,22 @@ div
</template>
```
> **Important:** If you are using `vue-loader@<8.2.0`, you also need to install `template-html-loader`.
### Inline Loader Requests
You can use [webpack loader requests](https://webpack.github.io/docs/loaders.html#introduction) in the `lang` attribute:
If you also intend to use it to import `.pug` files as HTML strings in JavaScript, you will need to chain `raw-loader` after the preprocessing loader. Note however adding `raw-loader` would break the usage in Vue components, so you need to have two rules, one of them targeting Vue files using a `resourceQuery`, the other one (fallback) targeting JavaScript imports:
``` html
<style lang="sass?outputStyle=expanded">
/* use sass here with expanded output */
</style>
``` js
// webpack.config.js -> module.rules
{
test:/\.pug$/,
oneOf:[
// this applies to <template lang="pug"> in Vue components
{
resourceQuery:/^\?vue/,
use:['pug-plain-loader']
},
// this applies to pug imports inside JavaScript
{
use:['raw-loader','pug-plain-loader']
}
]
}
```
However, note this makes your Vue component webpack-specific and not compatible with Browserify and [vueify](https://github.com/vuejs/vueify). **If you intend to ship your Vue component as a reusable 3rd-party component, avoid using this syntax.**
You can include both scoped and non-scoped styles in the same component:
...
...
@@ -44,11 +42,11 @@ You can include both scoped and non-scoped styles in the same component:
</style>
```
### Child Component Root Elements
## Child Component Root Elements
With `scoped`, the parent component's styles will not leak into child components. However, a child component's root node will be affected by both the parent's scoped CSS and the child's scoped CSS. This is by design so that the parent can style the child root element for layout purposes.
### Deep Selectors
## Deep Selectors
If you want a selector in `scoped` styles to be "deep", i.e. affecting child components, you can use the `>>>` combinator:
...
...
@@ -66,11 +64,11 @@ The above will be compiled into:
Some pre-processors, such as Sass, may not be able to parse `>>>` properly. In those cases you can use the `/deep/` combinator instead - it's an alias for `>>>` and works exactly the same.
### Dynamically Generated Content
## Dynamically Generated Content
DOM content created with `v-html` are not affected by scoped styles, but you can still style them using deep selectors.
### Also Keep in Mind
## Also Keep in Mind
-**Scoped styles do not eliminate the need for classes**. Due to the way browsers render various CSS selectors, `p { color: red }` will be many times slower when scoped (i.e. when combined with an attribute selector). If you use classes or ids instead, such as in `.example { color: red }`, then you virtually eliminate that performance hit. [Here's a playground](https://stevesouders.com/efws/css-selectors/csscreate.php) where you can test the differences yourself.
-[@vue/cli](https://github.com/vuejs/vue-cli) offers pre-configured unit testing and e2e testing setups for you.
-[Vue CLI](https://github.com/vuejs/vue-cli) offers pre-configured unit testing and e2e testing setups.
- If you are interested in manually setting up unit tests for `*.vue` files, consult [the docs for `@vue/test-utils`](https://vue-test-utils.vuejs.org/en/).
- If you are interested in manually setting up unit tests for `*.vue` files, consult the docs for [@vue/test-utils](https://vue-test-utils.vuejs.org/en/), which covers setup with [mocha-webpack](https://vue-test-utils.vuejs.org/en/guides/testing-SFCs-with-mocha-webpack.html) or [Jest](https://vue-test-utils.vuejs.org/en/guides/testing-SFCs-with-jest.html).