本文深入解析 Vue-loader 与 Webpack 的协同工作机制,详细阐述 .vue 文件的模板、脚本及样式块的处理流程。重点介绍 Scoped CSS 的实现原理与性能优化、PostCSS 插件集成方法,以及 ES2015 语法转译和开发环境热加载的配置技巧,帮助开发者构建高效的前端工程化工作流。
Vue-loader 与 Webpack 核心概念
Vue-loader 定义解析
vue-loader 作为加载器,可将指定格式的 Vue 组件转换为 JavaScript 模块。

vue-loader 提供多项高级特性:
- 默认启用 ES2015 支持;
- 允许在 Vue 组件内部使用其他 Webpack 加载器,例如 <style> 使用 SASS,<template> 使用 Jade。
- 将 <style> 和 <template> 中引用的静态资源视为模块依赖,并通过 Webpack 加载器进行处理。
- 为每个组件模拟作用域 CSS。
- 开发阶段支持组件热加载功能。
总结而言,webpack 与 vue-loader 的组合提供了一种更先进、灵巧且强大的前端开发模式。
Webpack 定义解析
若熟悉 Webpack 可跳过,新手请参考以下简介:
Webpack 是一种模块打包工具。它将文件视为模块,分析依赖关系,并打包为静态资源。

基本示例:处理一堆 CommonJS 引用,这些引用无法直接在浏览器运行,需捆绑为 <script> 标签内的单一文件。Webpack 依据 require() 调用的依赖关系实现此功能。
通过 "loaders",Webpack 可按需打包输出。例如:
- 将 ES2015、CoffeeScript 或 TypeScript 模块编译为 ES5 CommonJS 模块;
- 在编译前通过 linter 校验源代码。
- 将 Jade 模板编译为 HTML 并内联 JavaScript 字符串。
- 将 SASS 文件编译为 CSS,插入 <style> 标签,再转译为 JavaScript 代码段。
- 处理 HTML 或 CSS 中引用的图片文件,根据配置路径移动并按 MD5 hash 命名。
- 掌握 Webpack 可显著提升前端开发效率。尽管配置稍显复杂,但本指南旨在扫除使用 Webpack + Vue + vue-loader 的大部分障碍。
Vue 组件规范与语言块处理
Vue 组件规格说明
*.vue 文件采用 HTML-like 语法编写。每个 *.vue 文件包含 <template>、<script> 和 <style> 三部分:
<template>
<div class="example">{{ msg }}</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>
<style>
.example {
color: red;
}
</style>
vue-loader 解析文件,提取各语言块并通过相应 loaders 处理,最终组装为 CommonJS 模块,其 module.exports 为 Vue.js 组件对象。
vue-loader 默认不使用语言编译器。如需 CSS 预编译或 HTML 模板编译等功能,需设置 lang 属性。例如在组件样式中使用 SASS:
<style lang="sass">
/* 编写 SASS! */
</style>
更多细节请参阅 [使用预编译器]。
语言块详解
<template> 块
- 默认语言:html。
- 每个 *.vue 文件几乎都包含一个 <template> 块。
- <template> 内的内容字符串被提取,用于编译进 Vue 组件的 template 选项。
<script> 块
- 默认语言:js(默认通过 Babel 支持 ES2015)。
- 每个 *.vue 文件几乎都包含一个 <script> 块。
- 脚本在 CommonJS 环境中执行(类似通过 Webpack 捆绑的正常 .js 模块)。可 require() 其他依赖项。因默认支持 ES2015,也可使用 import 和 export 语法。
- 该脚本必须导出一个 Vue.js 组件选项对象,也支持导出使用 Vue.extend() 创建的扩展构造函数,但优先导出普通对象。
<style> 块
- 默认语言:css。
- 每个 *.vue 文件支持多个 <style> 标签。
- 默认情况下,通过 style-loader 将内容提取并加载到文档 <head> 内的 <style> 标签中。也可通过配置 Webpack 将组件内所有样式提取到单一 CSS 文件。
Src Imports 导入机制
若希望将 *.vue 组件拆分为多个文件,可使用 src 属性导入外部文件,代码如下:
<template src="./template.html"></template>
<style src="./style.css"></style>
<script src="./script.js"></script>
需注意 src 导入遵循与 CommonJS require() 调用相同的路径解析规则,即需使用以 ./ 开头的相对路径。也可直接从已安装的 NPM 包内导入资源,例如:
<!-- 从已安装的 "todomvc-app-css" NPM 包内导入文件 -->
<style src="todomvc-app-css/index.css">
项目设置与语法高亮
语法高亮显示配置
开发首要任务可能是实现 *.vue 组件的高亮显示。目前,Sublime Text、Atom、Vim、Visual Studio Code、Brackets 及 JetBrains 产品(WebStorm、PhpStorm 等)均提供支持语法高亮的插件。若未使用预编译器,编辑器将 *.vue 文件视为普通 HTML 文件。
注释处理规范
在各代码块内注释时,需使用对应语言的注释语法(HTML、CSS、JavaScript、Jade 等)。文件顶部注释使用 HTML 注释语法:<!— 在这里写注释的内容 --> 。
项目设置指南
语法高亮配置
开发首要任务可能是实现 *.vue 组件的高亮显示。目前,Sublime Text、Atom、Vim、Visual Studio Code、Brackets 及 JetBrains 产品(WebStorm、PhpStorm 等)均提供支持语法高亮的插件。若未使用预编译器,编辑器将 *.vue 文件视为普通 HTML 文件。
使用 vue-cli 工具
推荐使用脚手架工具创建项目,结合 vue-loader 和 vue-cli,命令行如下:
npm install -g vue-cli
vue init webpack-simple hello-vue
cd hello-vue
npm install
npm run dev # 一切就绪!
ES2015 支持与组件引用
ES2015 支持配置
当 vue-loader 检测到项目中存在 babel-loader 或 buble-loader 时,将使用它们处理所有 *.vue 文件的 <script> 部分,从而在 Vue 组件中使用 ES2015。若不熟悉该语言,建议学习:
- Babel - Learn ES2015
- ES6 Features
- Exploring ES6 (book)
引用其他 Vue 组件的典型模式如下:
<script>
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'
export default {
components: {
ComponentA,
ComponentB
}
}
</script>
此处使用 ES2015 精简语法定义子组件。{ ComponentA } 指代 { ComponentA: ComponentA }。Vue 自动将其转为 component-a,故可在模板中引入组件 <component-a> 。
转译正常 .js 文件方法
因 vue-loader 仅处理 *.vue 文件,需在配置文件中告知 Webpack 使用 babel-loader 或 buble-loader。此步骤可通过项目脚手架工具 vue-cli 完成。
使用 .babelrc 文件配置 Babel
.babelrc 用于控制 babel-loader,推荐以此方式配置 Babel 预设插件。
Scoped CSS 与 PostCSS 配置
Scoped CSS 作用域样式
当 <style> 标签包含 scoped 属性时,其 CSS 仅作用于当前组件,类似样式被封装在 Shadow DOM 内。此功能由 PostCSS 转译实现。如下:
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
转换结果示例:
<style>
.example[_v-f3f3eg9] {
color: red;
}
</style>
<template>
<div class="example" _v-f3f3eg9>hi</div>
</template>
注意事项
在同一组件内,可同时使用有作用域和无作用域的样式:
<style>
/* global styles */
</style>
<style scoped>
/* local styles */
</style>
- 父组件的有作用域 CSS 和子组件的有作用域 CSS 将共同影响子组件。
- 有作用域的样式对其他部分无影响。
- 有作用域限定的样式不排除类的需要。由于浏览器渲染方式支持多种不同的 CSS 选择器,加了作用域的 p { color: red } 会慢好多倍 (即,和属性选择器组合时候的时候)。如果使用类或者 id 选择器,比如 .example { color: red } ,就能消除性能损失。这里有个练习场 ,你可以比较测试下其中的差异。
- 在递归组件中小心后代选择器! 对于 CSS 规则的选择器 .a .b,如果匹配 .a 的元素内包含一个递归子组件,那么子组件中所有包含 .b 的元素都会被匹配到。
PostCSS 插件配置
任何通过 vue-loader 处理过的 CSS 都再用 PostCSS 重写有作用域限制的 CSS 部分。也可添加自定义的 PostCSS 插件处理,例如, autoprefixer 或 CSSNext。
在 Webpack 1.x 中的用法如下:
// webpack.config.js
module.exports = {
// 其他配置...
vue: {
// 使用用户自定义的 postcss 插件
postcss: [require('postcss-cssnext')()]
}
}
Webpack 2.x 中的用法:
// webpack.config.js
module.exports = {
// 其他配置...
plugins: [
new webpack.LoaderOptionsPlugin({
vue: {
// 使用用户自定义插件
postcss: [require('postcss-cssnext')()]
}
})
]
}
除了接受插件的数组,postcss 选项也接受:
- 返回值是插件数组的方法;
- 包含被传递到 PostCSS 处理器选项的对象。当你的项目依赖于自定义解析器或编译器的时候,这就会很有用。
postcss: {
plugins: [...], // list of plugins
options: {
parser: sugarss // use sugarss parser
}
}
开发环境热加载机制
热加载功能说明
“热加载” 不只是当你修改了文件简单地重新加载下页面。当启用了热加载功能,编写完 *.vue 文件后,组件的所有的实例对象被替换,而页面并没有重新加载。仍然保持应用原有的状态。这在你调整模板或修改组件样式的时候,大大改善了开发体验。
当使用项目的脚手架工具 vue-cli ,热加载自动启用。
总结陈词
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对本站的支持。