详解JS: reduce方法实现 webpack多文件入口


Posted in Javascript onFebruary 14, 2017

1. reduce 方法介绍

1.1 简单场景

reduce 函数的设计意图就是方便进行叠加运算:

var arr = [0, 1, 2, 3];

// reduce 实现累加
var total = arr.reduce(function (pre, cur){
 return pre + cur;
}, 0);

console.log(total);  // 6

上述代码中,reduce 方法有两个参数,第一个参数是一个 callback,用于进行计算的函数;第二个参数则是累加计算的初始值: 0

reduce 以 0 作为初始值,从数组第 0 项开始累加,上述代码的计算过程如下:

total = 0;    // => 0
total = 0 + 0;  // => 0
total = 0 + 1;  // => 1
total = 1 + 2;  // => 3
total = 3 + 3;  // => 6

若不设置初始值 0,则 reduce 以数组第 0 项作为初始值,从第 1 项开始累加,其计算过程如下:

total = 0;    // => 0
total = 0 + 1;  // => 1
total = 1 + 2;  // => 3
total = 3 + 3;  // => 6

可以看出,reduce 函数根据初始值 0,不断进行叠加,完成最简单的数组累加。

1.2 两种简单的运用场景

第一个 demo,使用 reduce 函数进行二维数组的拼接:

var arr = [ [0], [1, 2], [3, 4, 5] ];

// reduce 实现数组拼接
var result = arr.reduce(function (pre, cur){
 return pre.concat(cur);
}, []);

console.log(result);  // [0, 1, 2, 3, 4, 5]

第二个 demo,使用 reduce 函数构造 JSON 数组:

// 此例演示:将所有员工的姓名进行拆分
var staff = ['Bob Dell', 'Johon Jobs', 'Maria July'];

// reduce 构造 JSON 数组
var result = staff.reduce(function (arr, full_name){
 arr.push({
  first_name: full_name.split(' ')[0],
  last_name: full_name.split(' ')[1]
 });

 return arr;
}, []);

console.log(JSON.stringify(result));
// [{"first_name":"Bob","last_name":"Dell"},{"first_name":"Johon","last_name":"Jobs"},{"first_name":"Maria","last_name":"July"}]

灵活使用 reduce 函数,能为我们节省不少中间变量和代码。

2. 用于实现 webpack 多文件入口配置

webpack 配置项中entry参数用于配置入口文件路径,通常对于只打包一个目录下的文件,只需要遍历该目录,构造一个如下的对象传递给entry即可:

// 注:index.js 为每个页面的入口文件,所有页面均在 ./fe/pages/ 目录下
var entry = {
 index: './fe/pages/home/index.js',
 list: './fe/pages/list/index.js'
};

通常,我们使用 reduce 方法来遍历同一目录下的入口:

var fs = require('fs');
var path = require('path');
...

// 定义入口路径
var entryPath = './fe/pages';

// 遍历路径下多文件入口
var entris = fs.readdirSync(entryPath).reduce(function (o, filename) {
 !/\./.test(filename) &&
 (o[filename] = './' + path.join(entryPath, filename, 'index.js'));
 return o;
}, {});

// entry = {
//  index: './fe/pages/home/index.js',
//  list: './fe/pages/list/index.js'
// }

对于多页面应用的开发场景,也许会需要构造类似于下面这样的一个对象:

// 多个入口,页面、公共组件并不一定在同一个目录下
var entry = {
 index: './fe/pages/home/index.js',
 list: './fe/pages/list/index.js',
 header: './fe/components/header/index.js',
 footer: './fe/components/footer/index.js'
};

可以发现,我们要打包的页面、公共组件不一定在同一个目录下,这时候就需要对原先的方法进行扩展,见代码:

var fs = require('fs');
var path = require('path');
...

// 定义入口路径
var entryPath = ['./fe/pages', './fe/components'];

// 遍历路径下多文件入口
var mkEntriesMap = function (entryPath){
 if (typeof(entryPath) == 'string') {  // 若 entryPath 为字符串,则直接遍历此目录
  var path_map = fs.readdirSync(entryPath).map(function (filename){
   return filename + '::./' + path.join(entryPath, filename, 'index.js');
  });
 } else if (typeof(entryPath) == 'object') {  // 若 entryPath 为数组,则进行两级遍历
  var path_map = entryPath.map(function (entry){
   return fs.readdirSync(entry).map(function (filename){
    return filename + '::./' + path.join(entry, filename, 'index.js');
   });
  }).reduce(function (preArr, curArr){
   return preArr.concat(curArr);
  }, []);
 } else {
  throw 'Type of config.entryPath is not valid.';
  return;
 }

 return path_map.reduce(function (o, file_map){
  var file_name = file_map.split('::')[0];
  var file_path = file_map.split('::')[1];

  if (!/\./.test(file_name)) {
   o[file_name] = file_path;
  }

  return o;
 }, {});
};

// 构造对象
var entris = mkEntriesMap(entryPath);

// entry = {
//  index: './fe/pages/home/index.js',
//  list: './fe/pages/list/index.js',
//  header: './fe/components/header/index.js',
//  footer: './fe/components/footer/index.js'
// }

这样做的好处在于,只需配置一开始的entryPath就行了,同时支持单个或多个路径下的文件打包:

// entryPath 可以为一个字符串
var entryPath = './fe/pages';

// entryPath 也可以设为一个数组
var entryPath = ['./fe/pages', './fe/components'];

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript cookie解码函数(兼容ff)
Mar 17 Javascript
IE8 中使用加速器(Activities)
May 14 Javascript
深入探讨JavaScript String对象
Mar 09 Javascript
谈谈我对JavaScript中typeof和instanceof的深入理解
Dec 25 Javascript
JS控制伪元素的方法汇总
Apr 06 Javascript
jQuery实现简单的网页换肤效果示例
Sep 18 Javascript
微信小程序 ecshop地址三级联动实现实例代码
Feb 28 Javascript
node中的密码安全(加密)
Sep 17 Javascript
JavaScript面向对象中接口实现方法详解
Jul 24 Javascript
微信小程序制作扭蛋机代码实例
Sep 24 Javascript
JS实现扫码枪扫描二维码功能
Jan 03 Javascript
JavaScript实现简单的图片切换功能(实例代码)
Apr 10 Javascript
如何快速上手Vuex
Feb 14 #Javascript
BootStrap框架中的data-[ ]自定义属性理解(推荐)
Feb 14 #Javascript
Easyui Tree获取当前选择节点的所有顶级父节点
Feb 14 #Javascript
Vue组件开发初探
Feb 14 #Javascript
JavaScript Base64 作为文件上传的实例代码解析
Feb 14 #Javascript
JavaScript实现定时页面跳转功能示例
Feb 14 #Javascript
javaScript嗅探执行神器-sniffer.js
Feb 14 #Javascript
You might like
js实现的网页颜色代码表全集
2007/07/17 Javascript
TopList标签和JavaScript结合两例
2007/08/12 Javascript
jquery 单击li防止重复加载的实现代码
2010/12/24 Javascript
Javascript开发之三数组对象实例介绍
2012/11/12 Javascript
jquery插件开发之实现jquery手风琴功能分享
2014/03/10 Javascript
JavaScript阻止浏览器返回按钮的方法
2015/03/18 Javascript
javascript实现网站加入收藏功能
2015/12/16 Javascript
BootStrap selectpicker
2016/06/20 Javascript
利用Vue.js实现checkbox的全选反选效果
2017/01/18 Javascript
postman+json+springmvc测试批量添加实例
2018/03/31 Javascript
深入理解es6块级作用域的使用
2019/03/28 Javascript
jquery实现垂直无限轮播的方法分析
2019/07/16 jQuery
nuxt框架中对vuex进行模块化设置的实现方法
2019/09/06 Javascript
JS扁平化输出数组的2种方法解析
2019/09/17 Javascript
[01:08:56]DOTA2-DPC中国联赛 正赛 Magma vs LBZS BO3 第一场 2月7日
2021/03/11 DOTA
windows下安装python paramiko模块的代码
2013/02/10 Python
python连接池实现示例程序
2013/11/26 Python
跟老齐学Python之集合(set)
2014/09/24 Python
python操作mysql中文显示乱码的解决方法
2014/10/11 Python
在Python下尝试多线程编程
2015/04/28 Python
Python验证企业工商注册码
2015/10/25 Python
一个基于flask的web应用诞生 用户注册功能开发(5)
2017/04/11 Python
简单易懂的python环境安装教程
2017/07/13 Python
Python温度转换实例分析
2018/01/17 Python
Python从文件中读取数据的方法讲解
2019/02/14 Python
使用python将最新的测试报告以附件的形式发到指定邮箱
2019/09/20 Python
python使用yield压平嵌套字典的超简单方法
2019/11/02 Python
python 实现让字典的value 成为列表
2019/12/16 Python
python生成并处理uuid的实现方式
2020/03/03 Python
Flask处理Web表单的实现方法
2021/01/31 Python
纯CSS实现菜单、导航栏的3D翻转动画效果
2014/04/23 HTML / CSS
在校生钳工实习自我鉴定
2013/09/19 职场文书
怎么样写好简历中的自我评价
2013/10/25 职场文书
微观世界观后感
2015/06/10 职场文书
小学数学继续教育研修日志
2015/11/13 职场文书
HTML常用标签超详细整理
2022/03/19 HTML / CSS