学习 Vue 你需要知道的 webpack 知识(一)

 

学习使用 Vue 一年有余,业余时间也会在 SegmentFault 回答一些关于Vue 及其他前端问题,其中与 webpack 配置相关的问题较多,诚如 

尤雨溪

 大神在新手向:Vue 2.0 的建议学习顺序 - 知乎专栏中突出强调的,了解前端生态/工程化,学习 Webpack 相当重要(文中 webpack 一词出现 10 次,比 /Vue\s/ 还多 1 次,^_^)。

其实关于学习 webpack,尤大也提到"作为起步,理解它的『一切皆模块』的思想,并基本了解其常用配置选项和 loader 的概念/使用方法即可",而且,vue-loader 以及 vue-cli 所使用的 webpack 项目模板都提供了详尽的文档[1][2],然而正如这个问题所暴露出来的原因一样,有些人打开文档的姿势就是不对。

本文是对在 SegmentFault 回答的相关问题的分类总结(随时补充),全文以通过 vue-cli 命令 vue init webpack myProject,使用最新版本的 webpack 项目模板(以下简称“项目模板”)创建的项目(以下简称“项目”)为基础,通过该项目模板创建的项目具有开箱即用的特性,文中如涉及到 webpack 的配置以 webpack 2.0 的配置规范为准,需要注意和 1.0 的不兼容之处

 

1. 模块别名

Vue 有两种不同的构建,一种是 runtime-only 构建,另一种是 runtime + compiler 构建,具体差别见文档以及这篇文章。当使用 vue-cli 创建项目时,可以选择使用不同的构建。

在项目中,你还可以通过 webpack 的模块别名配置来指定使用哪种构建,webpack 配置中有一个 resolve 选项,其中的 alias 用来表示进行模块引入时的别名, 用于指定当打包时遇到引入某个模块时,引入文件的实际路径或文件名,可以简化引入操作的参数。

如果希望使用 runtime + compiler 构建,就需要如下图这样设置模块别名,其中 vue$ 表示必须精确匹配 vue,如果希望使用 runtime-only 构建,则不需要添加这个别名(留个问题,Why?)。

因此,如果在使用 vue-cli 时指定了 runtime-only 的构建,你可以通过修改 webpack 配置修改为 runtime + compiler 构建,这是你的“后悔药”。

这里另一个别名 @ 的作用是在你引入模块时,可以使用 @ 代替 /src 目录,避免书写麻烦又易错的相对路径。

2. 动态加载固定图片

webpack 在打包时,Vue 库、编写的 Vue 组件、JavaScript 模块及第三方 JavaScript 模块等代码会直接将模块打包,并按 webpack 的方式被 __webpack_require__ 调用,返回打包结果,以下对打包结果直接用“返回”表示,详情可参考这个 Code Slide

在单文件组件的 template 或 style 语言块或 css 文件中包含图片或字体文件时,webpack 会根据配置使用 url-loader 或者 file-loader 进行打包处理,大小在一定范围内的文件会返回该文件的 base64 dataurl(这是 url-loader 名称的由来),大小超限的文件,会将文件按配置改名、拷贝到对应目录之后,返回一个字符串表示文件的路径。

Vue 的核心是数据驱动的声明式渲染系统,我们有时候会有动态加载若干固定图片的需求,只需要设置或修改数据,即可达到多个图片列表渲染或切换变化的效果,那么这些动态的图片数据应该是什么样的呢?

考虑这样一些应用场景:制作一个产品列表,产品图片及描述文字放在 Vue 实例数据的一个数组中,并通过列表渲染的方式进行渲染;或者是使用 Vue 实例数据的一个图片数组通过列表渲染值绑定生成一个下拉选择框,根据用户选择显示不同的图片。对于前一应用场景,列表渲染方式比直接固定写在模板中具有更好的扩展性;对于后一应用场景,则无法简单地通过编写模板的方式实现。

我们会发现,如果 Vue 实例数据的数组中只保存图片文件路径,通过 webpack 打包并不会将图片拷贝到 dist 目标中,打开页面时,获取图片的请求也会出现 404 错误。

在 Vue 实例数据中仅仅使用图片路径不会使得 webpack 进行文件打包的操作,数组中的图片也必须作为模块引入,在其一切皆模块的思想下才会进行打包处理,因此上述的产品列表的数组数据应该写成这样:

var products = [{
  img: require('@/assets/products/1.png'),
  name: 'Product 1'
}, {
  img: require('@/assets/products/2.png'),
  name: 'Product 2'
}, {
  img: require('@/assets/products/3.png'),
  name: 'Product 3'
}, {
  img: require('@/assets/products/4.png'),
  name: 'Product 4'
}] 

然后将 products 声明为 Vue 实例数据的一部分。

以列表渲染图片为例,列表渲染中将 img 的 src 设置为 product.img 属性即可(假设列表渲染中的 v-for 指令表达式为 "product in products"),webpack 打包时会自动按配置进行打包,给各个product 的 img 返回一个 base64 dataurl,或者将文件改名存储,并给各 img 返回一个字符串表示改名后的文件路径。

 

我们知道在项目配置中设置文件改名是为了消除浏览器缓存对应用发布的负面影响,如果这些产品图片文件“万年不变”,项目模板中还提供了一个 /static 目录,可以将产品图片拷贝到 /static/img/products 目录下,那么,产品列表的数组数据就不需要使用 require 将这些图片作为模块来引入了,但需要将路径改写为 /static/img/products,具体写法如下:

var products = [{
  img: '/static/img/products/1.png',
  name: 'Product 1'
}, {
  img: '/static/img/products/2.png',
  name: 'Product 2'
}, {
  img: '/static/img/products/3.png',
  name: 'Product 3'
}, {
  img: '/static/img/products/4.png',
  name: 'Product 4'
}]

/src/assets 和 /static 目录的区别详见Vue webpack 项目模板官方文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值