众所周知,Callback-Hell(回调地狱)是传统 JS 语法上的历史问题。但毕竟称手的工具是开发效率的源泉,因此笔者对当前版本的微信小程序 API 做了简单的封装——weapp。
	同时,微信小程序框架本身专注于交互和 UI 的实现,并未提供内置的状态管理。如果众多的异步操作都直接在 App 或 Page 中一一实现,相信开发起来会很困难,而且不易于测试。
因此,我又因此针对微信小程序实现了一个基于 Redux 方案的状态管理模块,用以方便的在小程序中实现应用状态管理 redux-weapp。
特别地,微信小程序构建(编译)时不支持从 App scope 之外 require 文件,npm 在此就不好用了。
所以,我们需要实时 build 依赖到应用本地,在微信小程序中引用本地的 modules。
对于这种构建场景,我认为 webpack 算是最方便的方案。
从官方文档,了解微信小程序是什么;
了解 Redux 应用状态管理方案,同时它也是 Flux 架构的具体实现;
了解 JavaScript 打包工具 webpack;
了解 ES6/7 代码转译(transcompile)工具 Babel。原理是借助语法分析工具,将代码解析成抽象语法树后「重写」成最终的代码;
类似 Jest、Mocha 等 JavaScript 测试工具,可以根据需要选择。
开发者工具是用 NW.js 模拟的环境,在微信中,则是 JavascriptCore 环境。
不过不用担心, 只是两个不同的 VM,本质是一样的。
NW.js 可能存在一些小 bug,写代码的时候注意一下就好。
| 
					1 
					2 | mkdirmyappcd myappnpm init | 
由于除了小程序运行时需要的模块,还有构建所需要的模块。
看起来会比较多,不过不用担心,大多数都是声明性的,不需要你直接调用。
为了方便经验少些的同学理解,我将这些依赖分步安装。
首先是代码转译工具 Babel:
| 
					1 | npm install--save-dev babel-cli babel-core babel-loader babel-plugin-add-module-exports babel-polyfill babel-preset-es2015 babel-preset-stage-0 | 
有了上面这些模块,就可以在构建时,将 ES6/7 的代码转译为 ES5 的代码了(其实解释器都只认 ES5)。
接下来,我们安装打包工具 webpack:
| 
					1 | npm installwebpack --save-dev | 
我们只需要对代码进行打包,不需要 dev server 和 hot module replace 功能。
因此,我们只需要安装 webpack module 本身即可,无需安装其他扩展和插件。
接下来,我们来安装 Redux:
| 
					1 | npm installredux redux-thunk --save-dev | 
	需要注意的是,由于在实际应用中,我们经常会需要异步调用 API 服务器的接口,因此我们还需要 redux-thunk这个模块,来处理异步行为。
然后安装开发小程序的辅助模块:
| 
					1 | npm installxixilive/weappxixilive/redux-weapp--save-dev | 
其中,weapp 模块是对微信小程序 API 的 wrapper,提供了更易于使用的 API,redux-weapp 是基于 Redux 对微信小程序进行状态管理。
| 
					1 
					2 
					3 
					4 
					5 
					6 
					7 
					8 
					9 
					10 
					11 
					12 
					13 
					14 
					15 | myapp |- es6                # 源代码   |- myapp.js         # 在app.js文件中require此文件 |- lib                # 存放编译之后的js文件 |- pages              # 小程序页面定义   |- projects     |- projects.js     |- projects.json     |- projects.wxml     |- projects.wxss   ... |- app.js             # 小程序入口文件 |- app.json |- app.wxss |- webpack.config.js  # webpack配置文件 | 
	首先得写 webpack.config.js, 这个是必须的。
由于这个构建是为了本地化微信小程序的依赖,因此我们只处理 JS 文件。若需要打包其他资源,请读者自行研究。
而且,值得注意的是,微信小程序包有 1 MB 的上限。
| 
					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 | //webpack.config.jsvar path =require('path'), webpack =require('webpack')var jsLoader ={  test: /\.js$/, //你也可以用.es6做文件扩展名, 然后在这里定义相应的pattern  loader: 'babel',  query: {    //代码转译预设, 并不包含ES新特性的polyfill, polyfill需要在具体代码中显示require    presets: ["es2015", "stage-0"]  },  //指定转译es6目录下的代码  include: path.join(dirname, 'es6'),  //指定不转译node_modules下的代码  exclude: path.join(dirname, 'node_modules')}module.exports ={  //sourcemap 选项, 建议开发时包含sourcemap, production版本时去掉(节能减排)  devtool: null,  //指定es6目录为context目录, 这样在下面的entry, output部分就可以少些几个`../`了  context: path.join(dirname, 'es6'),  //定义要打包的文件  //比如: `{entry: {out: ['./x', './y','./z']}}` 的意思是: 将x,y,z等这些文件打包成一个文件,取名为: out  //具体请参看webpack文档  entry: {    myapp: './myapp'  },  output: {    //将打包后的文件输出到lib目录    path: path.join(dirname, 'lib'),    //将打包后的文件命名为 myapp, `[name]`可以理解为模板变量    filename: '[name].js',    //module规范为 `umd`, 兼容commonjs和amd, 具体请参看webpack文档    libraryTarget: 'umd'  },  module: {    loaders: [jsLoader]  },  resolve: {    extensions: ['', '.js'],    //将es6目录指定为加载目录, 这样在require/import时就会自动在这个目录下resolve文件(可以省去不少../)    modulesDirectories: ['es6', 'node_modules']  },  plugins: [    new webpack.NoErrorsPlugin(),    //通常会需要区分dev和production, 建议定义这个变量    //编译后会在global中定义`process.env`这个Objectnew webpack.DefinePlugin({      'process.env': {        'NODE_ENV': JSON.stringify('development')      }    })  ]} | 
	首先是代码测试命令 test。
由于我喜欢用 Jest,所以这里也用 Jest 做范例。
| 
					1 
					2 
					3 
					4 
					5 
					6 
					7 
					8 
					9 | // package.json"scripts": {  "pretest": "eslint es6", //推荐进行静态检查  "test": "jest",  ...},...,// jest允许在package.json中定义配置"jest": {  "automock": false,  "bail": true,  "transform": {    ".js": "/node_modules/babel-jest" //用babel转译  },  "testPathDirs": [    "/tests/"  ],  "testRegex": ".test.js$",  "unmockedModulePathPatterns": [    "/node_modules/"  ],  "testPathIgnorePatterns": [    "/node_modules/"  ]} | 
	接下来,就是激动人心的 build 命令。成败在此一举