详解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中的Array数组对象详谈
Mar 03 Javascript
jquery实现将获取的颜色值转换为十六进制形式的方法
Dec 20 Javascript
轻松掌握JavaScript装饰者模式
Aug 27 Javascript
easyui form validate总是返回false的原因及解决方法
Nov 07 Javascript
总结js函数相关知识点
Feb 27 Javascript
JS获取月的第几周和年的第几周实例代码
Dec 05 Javascript
微信公众平台 发送模板消息(Java接口开发)
Apr 17 Javascript
vue实现移动端轻量日期组件不依赖第三方库的方法
Apr 28 Javascript
微信小程序引入Vant组件库过程解析
Aug 06 Javascript
vue使用微信扫一扫功能的实现代码
Apr 11 Javascript
Openlayers实现点闪烁扩散效果
Sep 24 Javascript
JS前端可扩展的低代码UI框架Sunmao使用详解
Jul 23 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
聊天室php&mysql(三)
2006/10/09 PHP
php中突破基于HTTP_REFERER的防盗链措施(stream_context_create)
2011/03/29 PHP
说说PHP的autoLoad自动加载机制
2012/09/27 PHP
php中调用其他系统http接口的方法说明
2014/02/28 PHP
php常用字符串处理函数实例分析
2014/11/22 PHP
PHP+MySQL实现的简单投票系统实例
2016/02/24 PHP
jquery不支持toggle()高(新)版本的问题解决
2016/09/24 PHP
PHP不使用递归的无限级分类简单实例
2016/11/05 PHP
laravel Model 执行事务的实现
2019/10/10 PHP
js文字滚动停顿效果代码
2008/06/28 Javascript
初识JQuery 实例一(first)
2011/03/16 Javascript
Js 冒泡事件阻止实现代码
2013/01/27 Javascript
js 阻止子元素响应父元素的onmouseout事件具体实现
2013/12/23 Javascript
手写的一个兼容各种浏览器的javascript getStyle函数(获取元素的样式)
2014/06/06 Javascript
JS动态添加Table的TR,TD实现方法
2015/01/28 Javascript
Javascript递归打印Document层次关系实例分析
2015/05/15 Javascript
JS触发服务器控件的单击事件(详解)
2016/08/06 Javascript
原生JS:Date对象全面解析
2016/09/06 Javascript
基于Javascript实现文件实时加载进度的方法
2016/10/12 Javascript
在vue项目中引入highcharts图表的方法
2019/01/21 Javascript
iview实现图片上传功能
2020/06/29 Javascript
浅谈五大Python Web框架
2017/03/20 Python
通过Python实现自动填写调查问卷
2017/09/06 Python
python difflib模块示例讲解
2017/09/13 Python
Python中max函数用于二维列表的实例
2018/04/03 Python
win10子系统python开发环境准备及kenlm和nltk的使用教程
2019/10/14 Python
Python实现密码薄文件读写操作
2019/12/16 Python
Python实现i人事自动打卡的示例代码
2020/01/09 Python
使用python从三个角度解决josephus问题的方法
2020/03/27 Python
Python configparser模块常用方法解析
2020/05/22 Python
HTML5超文本标记语言的实现方法
2020/09/24 HTML / CSS
印度手工编织服装和家居用品商店:Fabindi
2019/10/07 全球购物
《要下雨了》教学反思
2014/02/17 职场文书
入股协议书范本
2014/04/14 职场文书
家庭财产分割协议书范本
2014/11/24 职场文书
应聘教师求职信范文
2015/03/20 职场文书