最近在内部项目中做了一些基于 vue + webpack 的尝试,在小范围和同事们探讨之后,还是蛮多同学认可和喜欢的,所以通过 blog 分享给更多人。

首先,我会先简单介绍一下 vue 和 webpack:

(当然如果你已经比较熟悉它们的话前两个部分可以直接跳过)

介绍 vue

Vue.js 是一款极简的 mvvm 框架,如果让我用一个词来形容它,就是 “轻·巧” 。如果用一句话来描述它,它能够集众多优秀逐流的前端框架之大成,但同时保持简单易用。废话不多说,来看几个例子:

<script src="vue.js"></script><div id="demo">{{message}}<input v-model="message">
</div><script>var vm = new Vue({el: '#demo',data: {message: 'Hello Vue.js!'}})
</script>

首先,代码分两部分,一部分是 html,同时也是视图模板,里面包含一个值为 message的文本何一个相同值的输入框;另一部分是 script,它创建了一个 vm 对象,其中绑定的 dom 结点是 #demo,绑定的数据是 {message: 'Hello Vue.js'},最终页面的显示效果就是一段 Hello Vue.js 文本加一个含相同文字的输入框,更关键的是,由于数据是双向绑定的,所以我们修改文本框内文本的同时,第一段文本和被绑定的数据的 message 字段的值都会同步更新——而这底层的复杂逻辑,Vue.js 已经全部帮你做好了。

再多介绍一点

我们还可以加入更多的 directive,比如:

<script src="vue.js"></script><div id="demo2"><img title="{{name}}" alt="{{name}}" v-attr="src: url"><input v-model="name"><input v-model="url">
</div><script>var vm = new Vue({el: '#demo2',data: {name: 'taobao',url: 'https://www.taobao.com/favicon.ico'}})
</script>

这里的视图模板加入了一个 <img> 标签,同时我们看到了 2 个特性的值都写作了 {{name}}。这样的话,图片的 title 和 alt 特性值就都会被绑定为字符串 'taobao'

如果想绑定的特性是像 img[src] 这样的不能在 html 中随意初始化的 (可能默认会产生预期外的网络请求),没关系,有 v-attr="src: url" 这样的写法,把被绑定的数据里的 url 同步过来。

没有介绍到的功能还有很多,推荐大家来我(发起并)翻译的Vue.js 中文文档

web 组件化

最后要介绍 Vue.js 对于 web 组件化开发的思考和设计

如果我们要开发更大型的网页或 web 应用,web 组件化的思维是非常重要的,这也是今天整个前端社区长久不衰的话题。

Vue.js 设计了一个 *.vue 格式的文件,令每一个组件的样式、模板和脚本集合成了一整个文件, 每个文件就是一个组件,同时还包含了组件之间的依赖关系,麻雀虽小五脏俱全,整个组件从外观到结构到特性再到依赖关系都一览无余 :

并且支持预编译各种方言:

这样再大的系统、在复杂的界面,也可以用这样的方式庖丁解牛。当然这种组件的写法是需要编译工具才能最终在浏览器端工作的,下面会提到一个基于 webpack 的具体方案。

小结

从功能角度,template, directive, data-binding, components 各种实用功能都齐全,而 filter, computed var, var watcher, custom event 这样的高级功能也都洋溢着作者的巧思;从开发体验角度,这些设计几乎是完全自然的,没有刻意设计过或欠考虑的感觉,只有个别不得已的地方带了自己框架专属的 v- 前缀。从性能、体积角度评估,Vue.js 也非常有竞争力!

介绍 webpack

webpack 是另一个近期发现的好东西。它主要的用途是通过 CommonJS 的语法把所有浏览器端需要发布的静态资源做相应的准备,比如资源的合并和打包。

举个例子,现在有个脚本主文件 app.js 依赖了另一个脚本 module.js

// app.js
var module = require('./module.js')
... module.x ...// module.js
exports.x = ...

则通过 webpack app.js bundle.js 命令,可以把 app.js 和 module.js 打包在一起并保存到 bundle.js

同时 webpack 提供了强大的 loader 机制和 plugin 机制,loader 机制支持载入各种各样的静态资源,不只是 js 脚本、连 html, css, images 等各种资源都有相应的 loader 来做依赖管理和打包;而 plugin 则可以对整个 webpack 的流程进行一定的控制。

比如在安装并配置了 css-loader 和 style-loader 之后,就可以通过 require('./bootstrap.css') 这样的方式给网页载入一份样式表。非常方便。

webpack 背后的原理其实就是把所有的非 js 资源都转换成 js (如把一个 css 文件转换成“创建一个 style 标签并把它插入 document”的脚本、把图片转换成一个图片地址的 js 变量或 base64 编码等),然后用 CommonJS 的机制管理起来。一开始对于这种技术形态我个人还是不太喜欢的,不过随着不断的实践和体验,也逐渐习惯并认同了。

最后,对于之前提到的 Vue.js,作者也提供了一个叫做 vue-loader 的 npm 包,可以把 *.vue 文件转换成 webpack 包,和整个打包过程融合起来。所以有了 Vue.js、webpack 和 vue-loader,我们自然就可以把它们组合在一起试试看!

项目实践流程

回到正题。今天要分享的是,是基于上面两个东西:Vue.js 和 webpack,以及把它们串联起来的 vue-loader

Vue.js 的作者以及提供了一个基于它们三者的项目示例 (链接已失效)。而我们的例子会更贴近实际工作的场景,同时和团队之前总结出来的项目特点和项目流程相吻合。

目录结构设计

  • <components> 组件目录,一个组件一个 .vue 文件

    • a.vue
    • b.vue
  • <lib> 如果实在有不能算组件,但也不来自外部 (tnpm) 的代码,可以放在这里
    • foo.css
    • bar.js
  • <src> 主应用/页面相关文件
    • app.html 主 html
    • app.vue 主 vue
    • app.js 通常做的事情只是 var Vue = require('vue'); new Vue(require('./app.vue'))
  • <dist> (ignored)
  • <node_modules> (ignored)
  • gulpfile.js 设计项目打包/监听等任务
  • package.json 记录项目基本信息,包括模块依赖关系
  • README.md 项目基本介绍

打包

通过 gulpfile.js 我们可以设计整套基于 webpack 的打包/监听/调试的任务

在 gulp-webpack 包的官方文档里推荐的写法是这样的:

var gulp = require('gulp');
var webpack = require('gulp-webpack');
var named = require('vinyl-named');
gulp.task('default', function() {return gulp.src(['src/app.js', 'test/test.js']).pipe(named()).pipe(webpack()).pipe(gulp.dest('dist/'));
});

我们对这个文件稍加修改,首先加入 vue-loader

tnpm install vue-loader --save.pipe(webpack({module: {loaders: [{ test: /\.vue$/, loader: 'vue'}]}
}))

其次,把要打包的文件列表从 gulp.src(...) 中抽出来,方便将来维护,也有机会把这个信息共享到别的任务

var appList = ['main', 'sub1', 'sub2']gulp.task('default', function() {return gulp.src(mapFiles(appList, 'js'))...
})/*** @private*/
function mapFiles(list, extname) {return list.map(function (app) {return 'src/' + app + '.' + extname})
}

现在运行 gulp 命令,相应的文件应该就打包好并生成在了 dist 目录下。然后我们在 src/*.html 中加入对这些生成好的 js 文件的引入:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Main</title>
</head>
<body><div id="app"></div><script src="../dist/main.js"></script>
</body>
</html>

用浏览器打开 src/main.html 这时页面已经可以正常工作了

加入监听

监听更加简单,只要在刚才 webpack(opt) 的参数中加入 watch: true 就可以了。

.pipe(webpack({module: {loaders: [{ test: /\.vue$/, loader: 'vue'}]},watch: true
}))

当然最好把打包和监听设计成两个任务,分别起名为 bundle 和 watch

gulp.task('bundle', function() {return gulp.src(mapFiles(appList, 'js')).pipe(named()).pipe(webpack(getConfig())).pipe(gulp.dest('dist/'))
})gulp.task('watch', function() {return gulp.src(mapFiles(appList, 'js')).pipe(named()).pipe(webpack(getConfig({watch: true}))).pipe(gulp.dest('dist/'))
})/*** @private*/
function getConfig(opt) {var config = {module: {loaders: [{ test: /\.vue$/, loader: 'vue'}]}}if (!opt) {return config}for (var i in opt) {config[i] = opt}return config
}

现在你可以不必每次修改文件之后都运行 gulp bundle 才能看到最新的效果,每次改动之后直接刷新浏览器即可。

调试

打包好的代码已经不那么易读了,直接在这样的代码上调试还是不那么方便的。这个时候,webpack + vue 有另外一个现成的东西:source map 支持。为 webpack 加入这个配置字段 devtool: 'source-map'

var config = { module: { loaders: [ { test: /.vue$/, loader: 'vue'} ] }, devtool: 'source-map' }

再次运行 gulp bundle 或 gulp watch 试试看,是不是开发者工具里 debug 的时候,可以追踪断点到源代码了呢:)

完整的 javascript 代码如下:

var gulp = require('gulp')
var webpack = require('gulp-webpack')
var named = require('vinyl-named')var appList = ['main']gulp.task('default', ['bundle'], function() {console.log('done')
})gulp.task('bundle', function() {return gulp.src(mapFiles(appList, 'js')).pipe(named()).pipe(webpack(getConfig())).pipe(gulp.dest('dist/'))
})gulp.task('watch', function() {return gulp.src(mapFiles(appList, 'js')).pipe(named()).pipe(webpack(getConfig({watch: true}))).pipe(gulp.dest('dist/'))
})/*** @private*/
function getConfig(opt) {var config = {module: {loaders: [{ test: /\.vue$/, loader: 'vue'}]},devtool: 'source-map'}if (!opt) {return config}for (var i in opt) {config[i] = opt[i]}return config
}/*** @private*/
function mapFiles(list, extname) {return list.map(function (app) {return 'src/' + app + '.' + extname})
}

最后,杜拉拉不如紫罗兰

做出一个 vue + webpack 的 generator,把这样的项目体验分享给更多的人。目前我基于团队内部在使用的轻量级脚手架工具写了一份名叫 just-vue 的 generator,目前这个 generator 还在小范围试用当中,待比较成熟之后,再分享出来

总结

其实上面提到的 just-vue 脚手架已经远不止文章中介绍的东西了, 我们在业务落地的“最后一公里”做了更多的沉淀和积累,比如自动图片上传与画质处理、rem单位自动换算、服务端/客户端/数据埋点接口的梳理与整合、自动化 htmlone 打包与 awp 发布等等。它们为支持业务的开发者提供了更简单高效的工作体验。 篇幅有限,更多内容我也希望将来有机会再多分享出来。

最后再次希望大家如果有兴趣的话可以来玩一下,无线前端组内的同学我都愿意提供一对一入门指导:)

Just Vue!

from: http://jiongks.name/blog/just-vue/

Vue + webpack 项目实践相关推荐

  1. vue+webpack项目打包后背景图片加载不出来问题解决

    vue+webpack项目打包后背景图片加载不出来问题解决 参考文章: (1)vue+webpack项目打包后背景图片加载不出来问题解决 (2)https://www.cnblogs.com/mica ...

  2. 踩坑之旅:springboot+vue+webpack项目实战(一)

    2019独角兽企业重金招聘Python工程师标准>>> 网上关于springboot的小项目很多,node.js+vue的项目也很多,但是好像没有两者合一的项目,最近在想实践下将两者 ...

  3. vue+webpack项目中px2rem的例子

    引言: gitchat里有更详细的实战例子 Vue+Webpack 把 PX 转化成 REM 的实战例子 本文重点: 项目环境搭建此处省略,不再赘述,需要的请查阅相关资料. 本篇只介绍,如果在vue+ ...

  4. 搭建vue+webpack 项目

    首先非常感谢有关vue+webpack文档创建者,有的让我很迷茫,有的让我又惊又喜,因为根据自己的需要创建的方式也不一样,所以我就记录一种适合我开发的一种.再次感谢 1.安装vs code (根据自己 ...

  5. Vue + webpack 项目配置化、接口请求统一管理

    准备工作 需求由来: 当项目越来越大的时候提高项目运行编译速度.压缩代码体积.项目维护.bug修复......等等成为不得不考虑而且不得不做的问题.  又或者后面其他同事接手你的模块,或者改你的bug ...

  6. 拿到一个vue+webpack项目,该如何去看

    这也是我目前自己这么理解的,可能每个人看代码的过程也不一样,我这里也是拿到一个项目之后不知道如何开始,所以自己在慢慢摸索,然后记录下来,希望自己能不断超越自己.这里我不能把公司项目亮出来,所以...只 ...

  7. vue 虚拟服务器,vue+webpack项目中使用dev-server搭建虚拟服务器,请求json文件数据,实现先后台分离开发...

    在项目开发中,先后台分离,作了假数据,项目使用vue2.0重构,后台也推到重来了,为了避免耽误开发进程,我作了虚拟的数据请求,使用vue-cli脚手架搭建的项目文件中dev-server搭建虚拟api ...

  8. 重构ElementUI解决DatePicker日期选择组件修改父组件placement参数问题[Vue.js项目实践: 新冠自检系统]

    新冠疫情自我检测系统网页设计开发文档 Sylvan Ding 的第一个基于 Vue.js 的项目. 本项目所提供的信息,只供参考之用,不保证信息的准确性.有效性.及时性和完整性,更多内容请查看国家卫健 ...

  9. vue + iview 项目实践总结 【完】

    一直想把一大篇的总结写完.写好,感觉自己拖延太严重还总想写完美,然后好多笔记都死在编辑器里了,以后还按照一个小节一个小节的更新吧,小步快跑?,先发出来,以后再迭代吧. 最近我们参与开发了一个(年前了) ...

最新文章

  1. HBase的安装、写入和查询操作
  2. mysql 查看当前连接数 和 最大连接数
  3. 学习dubbo(二): 第1个例子
  4. 达梦数据库、oracle数据库如何判断指定表有没有建立索引?对应的表有没有索引查询方法
  5. threejs加载模型挤压变形_车用水阀套零件冷挤压成形数值模拟试验研究
  6. 剑指Offer 二维数组中的查找
  7. 在保护继承中基类的共有成员_C#初学者教程系列11:继承
  8. Linux升级glibc版本汉字乱码,Linux CentOS6升级glibc库过程
  9. JAVA xml转dom_如何在Java中将String转换为DOMSource?
  10. 9 FI配置-财务会计-维护会计年度变式
  11. ubuntu手动修改anaconda环境变量
  12. 基于JAVA+SpringMVC+Mybatis+MYSQL的校园二手市场系统
  13. shell下的常用语句
  14. oracle skipscan,查询条件包含组合索引所有键为啥执行计划走的是index skip scan???...
  15. 普通话测试-短文60篇文章,附带拼音(11-20篇)
  16. 计算机扫描服务开启,win7系统,电脑打印机右键中无扫描选项(WIA已启动)
  17. case when 多条件查询
  18. 图片太大上传不了怎么缩小?jpg图片压缩大小的方法
  19. python高级教程-2
  20. 读取手机内存和SD卡的空间大小

热门文章

  1. Advice for students of machine learning--转
  2. Understanding JVM Internals---不得不转载呀
  3. map以及类似指针iterator
  4. 4.4 开发模式下的测试:简化我们对链码的测试过程
  5. 专访 TensorFlow 贡献者唐源:掌握 Google 深度学习框架的正确姿势
  6. 江苏省高中计算机课程标准,教育部普通高中信息技术课程标准
  7. Java Review - 并发编程_ArrayBlockingQueue原理源码剖析
  8. 深入理解分布式技术 - 消息队列知识点回顾总结
  9. 从浏览器输入URL到最终看到页面, 这其中经历了哪些过程 ?
  10. 通过 SpringBoot 中使用 lombok 实现自动创建JavaBean的get/set方法、全参/无参构造方法、toString()、equals()、hashCode()