nodejs, vue, webpack 项目实践
vue 及 webpack,均不需要与nodejs一期使用,他们都可以单独使用到任何语言的框架中。
http://jiongks.name/blog/just-vue/
https://cn.vuejs.org/v2/guide/ vue 官网,超好资料教程
最近在内部项目中做了一些基于 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
主 htmlapp.vue
主 vueapp.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!
nodejs, vue, webpack 项目实践的更多相关文章
- Vue + webpack 项目实践
Vue.js 是一款极简的 mvvm 框架,如果让我用一个词来形容它,就是 “轻·巧” .如果用一句话来描述它,它能够集众多优秀逐流的前端框架之大成,但同时保持简单易用.废话不多说,来看几个例子: & ...
- (转)windows环境vue+webpack项目搭建
首先,vue.js是一种前端框架,一般利用vue创建项目是要搭配webpack项目构建工具的,而webpack在执行打包压缩的时候是依赖node.js的环境的,所以,要进行vue项目的开发,我们首先要 ...
- 从零开始搭建Electron+Vue+Webpack项目框架,一套代码,同时构建客户端、web端(一)
摘要:随着前端技术的飞速发展,越来越多的技术领域开始被前端工程师踏足.从NodeJs问世至今,各种前端工具脚手架.服务端框架层出不穷,“全栈工程师”对于前端开发者来说,再也不只是说说而已.在NodeJ ...
- vue+webpack项目环境搭建
首先安装node.js 下载地址:https://nodejs.org/en/download/ 看下是否成功安装 node -v 安装webpack,命令行npm install webpack - ...
- 从零开始:一个正式的vue+webpack项目的目录结构是怎么形成的
如何从零开始一个vue+webpack前端工程工作流的搭建,首先我们先从项目的目录结构入手.一个持续可发展,不断加入新功能,方便后期维护的目录结构究竟是长什么样子的?接下来闰土大叔带你们一起手摸手学起 ...
- vue+webpack项目打包后背景图片加载不出来问题解决
在做VUE +的WebPack脚手架项目打包完成后,在IIS服务器上运行发现项目中的背景图片加载不出来检查项目代码发现是因为CSS文件中,背景图片引用的路径问题;后来通过修改配置文件,问题终于解决了, ...
- Node + Express + vue2.0 + Webpack项目实践
技术 Express.Vue.Vue-Router.Vue-Resource.Webpack Vue vue 的组件化思想和 React 很像,一个 vue 组件将 html.css 和 js 都写在 ...
- Vue+webpack项目中,运行报错Cannot find module 'chalk'的处理
刚开始用vue + webpack新建项目,在github上下载了一个示例,输入npm init >>>npm run dev 后报错 Cannot find module 'cha ...
- #单元测试#以karma+mocha+chai 为测试框架的Vue webpack项目(一)
目标: 为已有的vue项目搭建 karma+mocha+chai 测试框架 编写组件测试脚本 测试运行通过 抽出共通 一.初始化项目 新建项目文件夹并克隆要测试的已有项目 webAdmin-web 转 ...
随机推荐
- linux命令学习(3):ls命令
ls命令是linux下最常用的命令.ls命令就是list的缩写,缺省下ls用来打印出当前目录的清单.如果ls指定其他目录,那么就会显示指定 目录里的文件及文件夹清单. 通过ls 命令不仅可以查看lin ...
- 修改testtools框架,将测试结果显示用例注释名字
在之前介绍的测试框架testtool中,发现测试结果中显示的都是测试用例的函数名,并没有将注释显示出来 这很不符合国人使用阿,没办法,自己动手来改改吧 首先,testtools是继承unittest的 ...
- Git版本控制工具的简单使用
1.下载gitd客户端,注册github账号. 2.本地生成公钥和私钥,并将公钥粘贴到github上,测试连接. 3.先pull,从远程服务器中下载项目文件,然后再pushi,提交至服务器. 4. g ...
- html学习_表格、表单
表格(table):是用来处理表格式数据的,不是用来布局的. table > tr(行标签)> td(单元格标签) 1.表格注意事项: tr只能放置td标签,td里面可以放置任意元素. ...
- export,import ,export default区别
export,import ,export default区别 一.export,import ,export default ES6模块主要有两个功能:export和import export用于对 ...
- Docker容器与容器云之Docker单机集群部署案例
准备工作: CentOS 7安装docker: #yum -y install docker 1.获取节点所需镜像 --主机执行 #docker pull django #docker pull ha ...
- 如果是多个 c 代码的源码文件,编译方法如下: $ gcc test1.c test2.c -o main.out $ ./main.out test1.c 与 test2.c 是两个源代码文件。
如果是多个 c 代码的源码文件,编译方法如下: $ gcc test1.c test2.c -o main.out $ ./main.out test1.c 与 test2.c 是两个源代码文件.
- redis分页获取数据
php代码: 采用哈希类型存储数据,有序集合存储分页数据,进行倒序与正序的排序. $getGoodsInfo = M('goods_test')->select(); for($i=0;$i&l ...
- 内部排序->插入排序->希尔排序
文字描述 希尔排序又称缩小增量排序,也属于插入排序类,但在时间效率上较之前的插入排序有较大的改进. 从之前的直接插入排序的分析得知,时间复杂度为n*n, 有如下两个特点: (1)如果待排序记录本身就是 ...
- LeetCode 922 Sort Array By Parity II 解题报告
题目要求 Given an array A of non-negative integers, half of the integers in A are odd, and half of the i ...