Commit ca77b660 authored by Jinjiang's avatar Jinjiang

[docs][zh] init

parent 12043812
# Introduction
:::tip VERSION NOTE
This is the documentation for Vue Loader v15 and above. If you are upgrading from v14 or an earlier version, check out the [Migration Guide](../migrating.md). If you are using an older version, the old docs are [here](https://vue-loader-v14.vuejs.org).
:::
## What is Vue Loader?
`vue-loader` is a loader for [webpack](https://webpack.js.org/) that allows you to author Vue components in a format called [Single-File Components (SFCs)](./spec.md):
``` vue
<template>
<div class="example">{{ msg }}</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>
<style>
.example {
color: red;
}
</style>
```
There are many cool features provided by `vue-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 `.vue` file 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 and `vue-loader` gives you a modern, flexible and extremely powerful front-end workflow for authoring Vue.js applications.
# Getting Started
## Vue CLI
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 are pre-configured with most of the common development needs working 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!
new VueLoaderPlugin()
]
}
```
**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:
``` js
// webpack.config.js
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
// this will apply to both plain .js files
// AND <script> blocks in vue files
{
test: /\.js$/,
loader: 'babel-loader'
},
// this will apply to both plain .css files
// AND <style> blocks in vue files
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
}
]
},
plugins: [
// make sure to include the plugin for the magic
new VueLoaderPlugin()
]
}
```
Also see [Options Reference](../options.md) for all available loader options.
# Asset URL Handling
When Vue Loader compiles the `<template>` blocks in SFCs, it also converts any encountered asset URLs into **webpack module requests**.
For example, the following template snippet
``` vue
<img src="../image.png">
```
will be compiled into:
``` js
createElement('img', {
attrs: {
src: require('../image.png') // this is now a module request
}
})
```
By default the following tag/attribute combinations are transformed, and can be configured using the [transformAssetUrls](../options.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.
- If the URL starts with `.`, it's interpreted as a relative module request and resolved based on the folder structure on your file system.
- If the URL starts with `~`, anything after it is interpreted as a module request. This means you can even reference assets inside node modules:
``` html
<img src="~some-npm-package/foo.png">
```
- 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
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
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.
2. `url-loader` allows you to conditionally inline a file as base-64 data URL if they are smaller than a given threshold. This can reduce the amount of HTTP requests for trivial files. If the file is larger than the threshold, it automatically falls back to `file-loader`.
# CSS Modules
[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
First, CSS Modules must be enabled by passing `modules: true` to `css-loader`:
``` 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
<style module>
.red {
color: red;
}
.bold {
font-weight: bold;
}
</style>
```
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:
``` vue
<template>
<p :class="$style.red">
This should be red
</p>
</template>
```
Since it's a computed property, it also works with the object/array syntax of `:class`:
``` vue
<template>
<div>
<p :class="{ [$style.red]: isRed }">
Am I red?
</p>
<p :class="[$style.red, $style.bold]">
Red and bold
</p>
</div>
</template>
```
And you can also access it from JavaScript:
``` vue
<script>
export default {
created () {
console.log(this.$style.red)
// -> "red_1VyoJ-uZ"
// an identifier generated based on filename and className.
}
}
</script>
```
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).
## Opt-in Usage
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
{
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'
]
}
]
}
```
## Using with Pre-Processors
CSS Modules can be used along with other pre-processors:
``` js
// webpack.config.js -> module.rules
{
test: /\.scss$/,
use: [
'vue-style-loader',
{
loader: 'css-loader',
options: { modules: true }
},
'sass-loader'
]
}
```
## 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>
```
# Custom Blocks
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.
If a `lang` attribute is specified, the custom block will be matched as a file with the `lang` as its extension.
You can also use `resourceQuery` to match a rule against a custom block with no `lang`. For example, to match against `<foo>` custom blocks:
``` js
{
module: {
rules: [
{
resourceQuery: /blockType=foo/,
loader: 'loader-to-use'
}
]
}
}
```
If a matching rule is found for a custom block, it will be processed; otherwise the custom block will be silently ignored.
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.
## Example
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 write a custom loader:
``` js
module.exports = function (source, map) {
this.callback(
null,
`export default function (Component) {
Component.options.__docs = ${
JSON.stringify(source)
}
}`,
map
)
}
```
Now we'll configure webpack to use our custom loader for `<docs>` custom blocks.
``` js
// wepback.config.js
module.exports = {
module: {
rules: [
{
resourceQuery: /blockType=docs/,
loader: require.resolve('./docs-loader.js')
}
]
}
}
```
We are now able to access the `<docs>` block's content of imported components during runtime.
``` vue
<!-- ComponentB.vue -->
<template>
<div>Hello</div>
</template>
<docs>
This is the documentation for component B.
</docs>
```
``` vue
<!-- ComponentA.vue -->
<template>
<div>
<ComponentB/>
<p>{{ docs }}</p>
</div>
</template>
<script>
import ComponentB from './ComponentB.vue';
export default = {
components: { ComponentB },
data () {
return {
docs: ComponentB.__docs
}
}
}
</script>
```
# CSS Extraction
::: tip
Only apply CSS extraction for production so that you get CSS hot reload during development.
:::
## webpack 4
``` bash
npm install -D mini-css-extract-plugin
```
``` js
// webpack.config.js
var MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
// other options...
module: {
rules: [
// ...other rules omitted
{
test: /\.css$/,
use: [
process.env.NODE_ENV !== 'production'
? 'vue-style-loader'
: MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
// ...vue-loader plugin omitted
new MiniCssExtractPlugin({
filename: style.css
})
]
}
```
Also see [mini-css-extract-plugin docs](https://github.com/webpack-contrib/mini-css-extract-plugin).
## webpack 3
``` bash
npm install -D extract-text-webpack-plugin
```
``` js
// webpack.config.js
var ExtractTextPlugin = require("extract-text-webpack-plugin")
module.exports = {
// other options...
module: {
rules: [
// ...other rules omitted
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
use: 'css-loader',
fallback: 'vue-style-loader'
})
}
]
},
plugins: [
// ...vue-loader plugin omitted
new ExtractTextPlugin("style.css")
]
}
```
Also see [extract-text-webpack-plugin docs](https://github.com/webpack-contrib/extract-text-webpack-plugin).
# Functional Components
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:
``` vue
<template functional>
<div>{{ props.foo }}</div>
</template>
```
If you need to access properties defined globally on `Vue.prototype`, you can access them on `parent`:
``` vue
<template functional>
<div>{{ parent.$someProperty }}</div>
</template>
```
# Hot Reload
"Hot Reload" is not simply reloading the page when you edit a file. With hot reload enabled, when you edit a `*.vue` file, all instances of that component will be swapped in **without reloading the page**. It even preserves the current state of your app and these swapped components! This dramatically improves the development experience when you are tweaking the templates or styling of your components.
![hot-reload](http://blog.evanyou.me/images/vue-hot.gif)
## State Preservation Rules
- When editing the `<template>` of a component, instances of the edited component will re-render in place, preserving all current private state. This is possible because templates are compiled into new render functions that produce no side-effects.
- When editing the `<script>` part of a component, instances of the edited component will be destroyed and re-created in place. (State of the other components in the app are preserved) This is because `<script>` can include lifecycle hooks that may produce side-effects, so a "reload" instead of re-render is required to ensure consistent behavior. This also means you need to be careful about global side effects such as timers inside your components lifecycle hooks. Sometimes you may need to do a full-page reload if your component produces global side-effects.
- `<style>` hot reload operates on its own via `vue-style-loader`, so it doesn't affect application state.
## Usage
When scaffolding the project with `vue-cli`, Hot Reload is enabled out-of-the-box.
When manually setting up your project, hot-reload is enabled automatically when you serve your project with `webpack-dev-server --hot`.
Advanced users may want to check out [vue-hot-reload-api](https://github.com/vuejs/vue-hot-reload-api), which is used internally by `vue-loader`.
## Disabling Hot Reload
Hot Reload is always enabled except following situations:
* webpack `target` is `node` (SSR)
* webpack minifies the code
* `process.env.NODE_ENV === 'production'`
You may use `hotReload: false` option to disable the Hot Reload explicitly:
``` js
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
hotReload: false // disables Hot Reload
}
}
]
}
```
# Linting
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:
``` js
// .eslintrc.js
module.exports = {
extends: [
"plugin:vue/essential"
]
}
```
Then from the command line:
``` bash
eslint --ext js,vue MyComponent.vue
```
Another option is using [eslint-loader](https://github.com/MoOx/eslint-loader) so that your `*.vue` files are automatically linted on save during development:
``` bash
npm install -D eslint eslint-loader
```
Make sure it's applied as a pre-loader:
``` js
// webpack.config.js
module.exports = {
// ... other options
module: {
rules: [
{
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /node_modules/
}
]
}
}
```
---
sidebarDepth: 2
---
# Using Pre-Processors
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.
## SASS
For example, to compile our `<style>` tag with SASS/SCSS:
``` bash
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="scss">
/* write SCSS here */
</style>
```
Any content inside the block will be processed by webpack as if it's inside a `*.scss` file.
### SASS vs SCSS
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:
``` js
// webpack.config.js -> module.rules
{
test: /\.sass$/,
use: [
'vue-style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
indentedSyntax: true
}
}
]
}
```
### Sharing Global Variables
`sass-loader` also supports a `data` option which allows you to share common variables among all processed files without having to explicit import them:
``` 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`
data: `$color: red;`
}
}
]
}
```
## LESS
``` bash
npm install -D less less-loader
```
``` js
// webpack.config.js -> module.rules
{
test: /\.less$/,
use: [
'vue-style-loader',
'css-loader',
'less-loader'
]
}
```
## Stylus
``` bash
npm install -D stylus stylus-loader
```
``` js
// webpack.config.js -> module.rules
{
test: /\.styl(us)?$/,
use: [
'vue-style-loader',
'css-loader',
'stylus-loader'
]
}
```
## PostCSS
::: tip
Vue Loader v15 no longer applies PostCSS transforms by default. You will need to use PostCSS via `postcss-loader`.
:::
``` bash
npm install -D postcss-loader
```
``` js
// webpack.config.js -> module.rules
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: { importLoaders: 1 }
},
'postcss-loader'
]
}
```
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).
`postcss-loader` can also be applied in combination with other pre-processors mentioned above.
## Babel
``` bash
npm install -D babel-core babel-loader
```
``` js
// webpack.config.js -> module.rules
{
test: /\.js?$/,
loader: 'babel-loader'
}
```
Configuration of Babel can be done via `.babelrc` or `babel-loader` options.
## TypeScript
``` bash
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
<template lang="pug">
div
h1 Hello world!
</template>
```
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:
``` 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']
}
]
}
```
# Scoped CSS
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. It comes with some caveats, but doesn't require any polyfills. It is achieved by using PostCSS to transform the following:
``` html
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
```
Into the following:
``` html
<style>
.example[data-v-f3f3eg9] {
color: red;
}
</style>
<template>
<div class="example" data-v-f3f3eg9>hi</div>
</template>
```
## Mixing Local and Global Styles
You can include both scoped and non-scoped styles in the same component:
``` html
<style>
/* global styles */
</style>
<style scoped>
/* local styles */
</style>
```
## 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
If you want a selector in `scoped` styles to be "deep", i.e. affecting child components, you can use the `>>>` combinator:
``` html
<style scoped>
.a >>> .b { /* ... */ }
</style>
```
The above will be compiled into:
``` css
.a[data-v-f3f3eg9] .b { /* ... */ }
```
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
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
- **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.
- **Be careful with descendant selectors in recursive components!** For a CSS rule with the selector `.a .b`, if the element that matches `.a` contains a recursive child component, then all `.b` in that child component will be matched by the rule.
# Testing
- [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/), 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).
---
sidebar: auto
sidebarDepth: 2
---
# Migrating from v14
::: tip Heads Up
We are in the process of upgrading Vue CLI 3 beta to use webpack 4 + Vue Loader 15, so you might want to wait if you are planning to upgrade to Vue CLI 3.
:::
## Notable Breaking Changes
### A Plugin is Now Required
Vue Loader 15 now requires an accompanying webpack plugin to function properly:
``` js
// webpack.config.js
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
// ...
plugins: [
new VueLoaderPlugin()
]
}
```
### Loader Inference
Vue Loader 15 now uses a different strategy to infer loaders to use for language blocks.
Take `<style lang="less">` as an example: in v14 and below, it will attempt to load the block with `less-loader`, and implicitly chains `css-loader` and `vue-style-loader` after it, all using inline loader strings.
In v15, `<style lang="less">` will behave as if it's an actual `*.less` file being loaded. So, in order to process it, you need to provide an explicit rule in your main webpack config:
``` js
{
module: {
rules: [
// ...other rules
{
test: /\.less$/,
use: [
'vue-style-loader',
'css-loader',
'less-loader'
]
}
]
}
}
```
The benefit is that this same rule also applies to plain `*.less` imports from JavaScript, and you can configure options for these loaders anyway you want. In v14 and below, if you want to provide custom options to an inferred loader, you'd have to duplicate it under Vue Loader's own `loaders` option. In v15 it is no longer necessary.
v15 also allows using non-serializable options for loaders, which was not possible in previous versions.
### Template Preprocessing
v14 and below uses [consolidate](https://github.com/tj/consolidate.js/) to compile `<template lang="xxx">`. v15 now applies preprocessing for them using webpack loaders instead.
Note that some template loaders such as `pug-loader` exports a compiled templating function instead of plain HTML. In order to pass the correct content to Vue's template compiler, you must use a loader that outputs plain HTML instead. For example, to support `<template lang="pug">`, you can use [pug-plain-loader](https://github.com/yyx990803/pug-plain-loader):
``` js
{
module: {
rules: [
{
test: /\.pug$/,
loader: 'pug-plain-loader'
}
]
}
}
```
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:
``` 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']
}
]
}
]
}
}
```
### Style Injection
Client-side style injection now injects all styles upfront to ensure consistent behavior between development and extracted mode.
Note the injection order is still not guaranteed, so you should avoid writing CSS that relies on insertion order.
### PostCSS
Vue Loader no longer auto applies PostCSS transforms. To use PostCSS, configure `postcss-loader` the same way you would for normal CSS files.
### CSS Modules
CSS Modules now need to be explicitly configured via `css-loader` options. The `module` attribute on `<style>` tags is still needed for locals injection into the component.
The good news is that you can now configure `localIdentName` in one place:
``` js
{
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: 'vue-style-loader'
},
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[local]_[hash:base64:8]'
}
}
]
}
]
}
}
```
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
{
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'
]
}
]
}
```
## CSS Extraction
Works the same way as you'd configure it for normal CSS. Example usage with [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin):
``` js
{
module: {
rules: [
{
test: /\.vue$/,
use: 'vue-loader'
},
{
test: /\.css$/,
// or ExtractTextWebpackPlugin.extract(...)
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'output.css'
})
]
}
```
## SSR externals
In SSR, we typically use `webpack-node-externals` to exclude npm dependencies from the server build. If you need to import CSS from an npm dependency, the previous solution was using a whitelist like this:
``` js
// webpack config
externals: nodeExternals({
whitelist: /\.css$/
})
```
With v15, imports for `<style src="dep/foo.css">` now has resourceQuery strings appended at the end of the request, so you need to update the above to:
``` js
externals: nodeExternals({
whitelist: [/\.css$/, /\?vue&type=style/]
})
```
## Options Deprecation
The following options have been deprecated and should be configured using normal webpack module rules:
- `loader`
- `preLoaders`
- `postLoaders`
- `postcss`
- `cssSourceMap`
- `buble`
- `extractCSS`
- `template`
The following options have been deprecated and should be configured using the new `compilerOptions` option:
- `preserveWhitespace` (use `compilerOptions.preserveWhitespace`)
- `compilerModules` (use `compilerOptions.modules`)
- `compilerDirectives` (use `compilerOptions.directives`)
The following option has been renamed:
- `transformToRequire` (now renamed to `transformAssetUrls`)
The following option has been changed to resourceQuery:
- `shadowMode` (now use inline resource queries, e.g. `foo.vue?shadow`)
:::tip
For a complete list of new options, see [Options Reference](./options.md).
:::
---
sidebar: auto
---
# Options Reference
## transformAssetUrls
- type: `{ [tag: string]: string | Array<string> }`
- default:
``` js
{
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
```
During template compilation, the compiler can transform certain attributes, such as `src` URLs, into `require` calls, so that the target asset can be handled by webpack. For example, `<img src="./foo.png">` will attempt to locate the file `./foo.png` on your file system and include it as a dependency of your bundle.
## compiler
- Type: `VueTemplateCompiler`
- default: `require('vue-template-compiler')`
Override the default compiler used to compile `<template>` blocks in single file components.
## compilerOptions
- type: `Object`
- default: `{}`
Options for the template compiler. When using the default `vue-template-compiler`, you can use this option to add custom compiler directives, modules, or discard whitespaces between template tags with `{ preserveWhitespace: false }`.
See [`vue-template-compiler` options reference](https://github.com/vuejs/vue/tree/dev/packages/vue-template-compiler#options).
## transpileOptions
- type: `Object`
- default: `{}`
Configure ES2015+ to ES5 transpiling options for the generated render function code. The [transpiler](https://github.com/vuejs/vue-template-es2015-compiler) is a fork of [Buble](https://github.com/Rich-Harris/buble), so consult the available options [here](https://buble.surge.sh/guide/#using-the-javascript-api).
The template render functions compilation supports a special transform `stripWith` (enabled by default), which removes the `with` usage in generated render functions to make them strict-mode compliant. This is enabled by default.
## optimizeSSR
- type: `boolean`
- default: `true` when the webpack config has `target: 'node'` and `vue-template-compiler` is at version 2.4.0 or above.
Enable Vue 2.4 SSR compilation optimization that compiles part of the vdom trees returned by render functions into plain strings, which improves SSR performance. In some cases you might want to explicitly turn it off because the resulting render functions can only be used for SSR and cannot be used for client-side rendering or testing.
## hotReload
- type: `boolean`
- default: `true` in development mode, `false` in production mode or when the webpack config has `target: 'node'`.
- allowed value: `false` (`true` will not force Hot Reload neither in production mode nor when `target: 'node'`)
Whether to use webpack [Hot Module Replacement](https://webpack.js.org/concepts/hot-module-replacement/) to apply changes in the browser **without reloading the page**.
Use this option (value `false`) to disable the Hot Reload feature in development mode.
## productionMode
- type: `boolean`
- default: `process.env.NODE_ENV === 'production'`
Force production mode, which prohibits the loader from emitting code (e.g. hot-reload related code) that is development-only.
---
title: SFC Spec
sidebar: auto
---
# Vue Single-File Component (SFC) Spec
## Intro
A `*.vue` file is a custom file format that uses HTML-like syntax to describe a Vue component. Each `*.vue` file consists of three types of top-level language blocks: `<template>`, `<script>`, and `<style>`, and optionally additional custom blocks:
``` vue
<template>
<div class="example">{{ msg }}</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>
<style>
.example {
color: red;
}
</style>
<custom1>
This could be e.g. documentation for the component.
</custom1>
```
`vue-loader` will parse the file, extract each language block, pipe them through other loaders if necessary, and finally assemble them back into an ES Module whose default export is a Vue.js component options object.
`vue-loader` supports using non-default languages, such as CSS pre-processors and compile-to-HTML template languages, by specifying the `lang` attribute for a language block. For example, you can use Sass for the style of your component like this:
``` vue
<style lang="sass">
/* write Sass! */
</style>
```
More details can be found in [Using Pre-Processors](./pre-processors.md).
## Language Blocks
### Template
- Each `*.vue` file can contain at most one `<template>` block at a time.
- Contents will be extracted and passed on to `vue-template-compiler` and pre-compiled into JavaScript render functions, and finally injected into the exported component in the `<script>` section.
### Script
- Each `*.vue` file can contain at most one `<script>` block at a time.
- The script is executed as an ES Module.
- The **default export** should be a Vue.js [component options object](https://vuejs.org/v2/api/#Options-Data). Exporting an extended constructor created by `Vue.extend()` is also supported, but a plain object is preferred.
- Any webpack rules that match against `.js` files (or the extension specified by the `lang` attribute) will be applied to contents in the `<script>` block as well.
### Style
- Default match: `/\.css$/`.
- A single `*.vue` file can contain multiple `<style>` tags.
- A `<style>` tag can have `scoped` or `module` attributes (see [Scoped CSS](./scoped-css.md) and [CSS Modules](./css-modules.md)) to help encapsulate the styles to the current component. Multiple `<style>` tags with different encapsulation modes can be mixed in the same component.
- Any webpack rules that match against `.css` files (or the extension specified by the `lang` attribute) will be applied to contents in the `<style>` blocks as well.
### Custom Blocks
Additional custom blocks can be included in a `*.vue` file for any project specific needs, for example a `<docs>` block. `vue-loader` will use the tag name to look up which webpack loaders should be applied to the contents of the section. The webpack loaders should be specified in the `loaders` section of `vue-loader` options.
For mode details, see [Custom Blocks](./custom-blocks.md).
### Src Imports
If you prefer splitting up your `*.vue` components into multiple files, you can use the `src` attribute to import an external file for a language block:
``` vue
<template src="./template.html"></template>
<style src="./style.css"></style>
<script src="./script.js"></script>
```
Beware that `src` imports follow the same path resolution rules to webpack module requests, which means:
- Relative paths need to start with `./`
- You can import resources from npm dependencies:
``` vue
<!-- import a file from the installed "todomvc-app-css" npm package -->
<style src="todomvc-app-css/index.css">
```
`src` imports also work with custom blocks, e.g.:
``` vue
<unit-test src="./unit-test.js">
</unit-test>
```
## Syntax Highlighting / IDE Support
Currently there is syntax highlighting support for the following IDE/editors:
- [Sublime Text](https://github.com/vuejs/vue-syntax-highlight)
- [VS Code](https://marketplace.visualstudio.com/items?itemName=octref.vetur)
- [Atom](https://atom.io/packages/language-vue)
- [Vim](https://github.com/posva/vim-vue)
- [Emacs](https://github.com/AdamNiederer/vue-mode)
- [Brackets](https://github.com/pandao/brackets-vue)
- [JetBrains IDEs](https://plugins.jetbrains.com/plugin/8057) (WebStorm, PhpStorm, etc)
Contributions for other editors/IDEs are highly appreciated! If you are not using any pre-processors in Vue components, you can also get decent syntax highlighting by treating `*.vue` files as HTML in your editor.
## Comments
Inside each block you shall use the comment syntax of the language being used (HTML, CSS, JavaScript, Jade, etc). For top-level comments, use HTML comment syntax: `<!-- comment contents here -->`
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment