企业微信开发(二期)

在企业微信一期告一段落之后,今天终于抽出时间来开始把开年以来的二期项目好好的总结一下了。从开年来3月份开始到现在两个多月的时间,在以前的基础上针对项目做了一次换血更新,这次更新变动较大,还是有很多值得回味和记忆的东西。比如框架优化,新的组件设计,react的深入引用,jssdk的新功能集合以及nodejs的前端服务器与Jenkins的部署等等。这里我主要是想将之前遇到的一些问题和比较重要的知识点做一个总结回顾,同时也为今后在webapp的开发上多积累些经验,毕竟就算经常做的东西长时间不去回顾难免也有所遗忘。

框架优化

无论多么复杂的项目在框架上也得不停的进行优化,随着项目的发展优化工作也得不停的完善下去,优化框架是一项很考验能力的活,做起来虽然不像业务开发那么辛苦,但是对技术点的掌握和要求确实相当多的。

1、绝对路径
在项目构建初始我们无论是使用commonJS、requireJS、ES6等等模块化JS,我们都离不开对项目文件的引用

1
2
ES5: require('xxx')
ES6: import xxx from 'xxx'

最常见的引用就是使用相对路径,相对路径的文件引用是比较浅显易懂的,但是它在文件层级过多的时候引用就很容易出现错误,同时也使顶部引用文件显得很冗长,所以一般情况下我们都会考虑将项目的文件引用用绝对路径来替代,不仅便于我们快速开发,比如引用一些资源文件和一些层级结构较为复杂的文件,同时也让我们的代码看起来很清楚简洁。接下来主要介绍gulp和webpack这两种脚手架的绝对路径引用。

首先是gulp的绝对路径设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var gulp = require('gulp');
var path = require('path');
var pathmodify = require('pathmodify');
var bundleConfig = [{
entries: './app.js',
dest: '/javascripts',
outputName: 'bundle.js',
extensions: ['.js', '.json', '.hbs']
}]
var b = browserify(bundleConfig);
b.plugin(pathmodify, {
mods: [
pathmodify.mod.dir('src', path.join(__dirname, '../src'))
]
});

在gulp的browserify的打包过程中设置,因为gulp是采用的二进制管道流的打包方式,所以我们需要在后面继续执行bundle

1
2
3
4
5
6
7
8
9
10
11
12
13
var bundle = function() {
bundleLogger.start(bundleConfig.outputName);
return b
.bundle()
.on('error', handleErrors)
.pipe(source(bundleConfig.outputName))
.pipe(gulp.dest(bundleConfig.dest))
.on('end', reportFinished)
.pipe(browserSync.reload({
stream: true
}));
};

当然,我这里只是简要的进行了一些代码说明,很多地方还是需要我们自行去完善,所以上面主要也是介绍gulp中关于绝对路径的设置来仅供参考。在上面的代码编译完成之后,我们的打包文件中就可以用 src/ 的形式开始引用我们的绝对路径了。

其次是webpack的绝对路径设置:

1
2
3
4
5
6
7
8
9
10
var path = require('path');
module.exports = {
resolve: {
alias: {
'src': path.resolve('./app/src'),
'static': path.resolve('./app/static'),
'vendor': path.resolve('./app/vendor')
}
}
}

相对来说webpack的绝对路径设置比较简单,上面我们就简单的引入了项目文件,资源文件与插件的绝对路径,编译打包之后我们在项目里面就可以直接用 src/、 static/、 vendor/ 的方式进行文件绝对路径的引用。

2、多线程打包

在企业微信的开发过程中,最麻烦得还是属于调试,我们可以用chrome的devtool来做手机模拟器的调试,但是这样的调试仅是针对px像素显示屏,我们最终都得回到手机上进行调试,在手机上调试就需要我们将项目编译好然后打包,之后在手机上运行调试,在一些频繁的修改调试过程中,打包的频率也会很多,这个时候如果打包速度快的话就可以帮助我们节省大量的时间开销,在不引用线程池多线程打包的情况下我们每一次编译打包到手机显示的过程大概是2分钟左右,在任务繁重的开发过程中,每一次调试都需要等待两分钟,是非常消耗时间的,所以后面我们优化中引入的线程池进行多线程打包,这样我们每次调试过程时间就缩短的一半,频繁调试的过程中节省的时间就很客观了。

引用并启动线程池:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
const HappyPack = require('happypack');
const os = require('os')
const HappyThreadPool = HappyPack.ThreadPool({size:os.cpus().length});
//设置打包规则
rules: [
{
test: /.(jsx|js)$/,
use: {
loader: 'happypack/loader?id=jsx'
},
exclude: /node_modules/
},
{
test: /\.css$/,
use: {
loader: 'happypack/loader?id=css'
}
},
{
test: /\.less$/,
use: {
loader: 'happypack/loader?id=less'
}
}
]
//创建单线程对象
plugins:[
new HappyPack({
id: 'jsx',
threadPool: HappyThreadPool,
loaders: ['babel-loader?cacheDirectory']
}),
new HappyPack({
id: 'css',
threadPool: HappyThreadPool,
loaders: ['style-loader', 'css-loader', 'postcss-loader']
}),
new HappyPack({
id: 'less',
threadPool: HappyThreadPool,
loaders: [
'style-loader',
{
loader: "css-loader",
options: {
modules: true,
localIdentName: "[path][name]--[local]--[hash:base64:5]"
}
},
'postcss-loader',
'less-loader'
]
}),
]

在这些配置完成之后,我们在执行npm打包的过程中代码会自动区分为css线程、jsx线程、less线程。在同时进行多线程打包的过程中设置cacheDirectory缓存没有变动的打包内容,可以更加快速的进行打包,极大的节省了我们的开发时间。

组件设计

webapp类似于原生app,最常用的组件就属于列表组件,原生应用有平台提供的现成的封装组件,这类组件一般都能满足产品设计需求,但是webapp应用是没有这类完善的平台组件,所以需要我们自己去完善这些功能,接下来主要以UIListView这类列表组件的二次封装来进行组件的完善与设计,我们的项目是引入的antd-mobile的UI组件库,antd也给我们提供了一个基本的列表组件,所以我们只需要在这个列表组件上进行功能的完善。