详解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 相关文章推荐
js 创建快捷方式的代码(fso)
Nov 19 Javascript
深入理解JavaScript系列(4) 立即调用的函数表达式
Jan 15 Javascript
JavaScript插件化开发教程(六)
Feb 01 Javascript
JavaScript通过prototype给对象定义属性用法实例
Mar 23 Javascript
uploadify多文件上传参数设置技巧
Nov 16 Javascript
基于node实现websocket协议
Apr 25 Javascript
bootstrap输入框组代码分享
Jun 07 Javascript
js实现开启密码大写提示
Dec 21 Javascript
微信小程序 本地数据存储实例详解
Apr 13 Javascript
Angular.JS内置服务$http对数据库的增删改使用教程
May 07 Javascript
jQuery实现的简单对话框拖动功能示例
Jun 05 jQuery
vue的过滤器filter实例详解
Sep 17 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应用中使用XOR运算加密算法分享
2011/08/28 PHP
基于wordpress主题制作的具体实现步骤
2013/05/10 PHP
ThinkPHP控制器间实现相互调用的方法
2014/10/31 PHP
php检测apache mod_rewrite模块是否安装的方法
2015/03/14 PHP
PHPStorm 2020.1 调试 Nodejs的多种方法详解
2020/09/17 NodeJs
JavaScript 事件对象的实现
2009/07/13 Javascript
jQuery入门知识简介
2010/03/04 Javascript
侧栏跟随滚动的简单实现代码
2013/03/18 Javascript
Javascript算符的优先级介绍
2013/03/20 Javascript
JavaScript等比例缩放图片控制超出范围的图片
2013/08/06 Javascript
解析JavaScript面向对象概念中的Object类型与作用域
2016/05/10 Javascript
很酷的星级评分系统原生JS实现
2016/08/25 Javascript
使用InstantClick.js让页面提前加载200ms
2017/09/12 Javascript
使用JS实现图片轮播的实例(前后首尾相接)
2017/09/21 Javascript
vue 页面加载进度条组件实例
2018/02/05 Javascript
webpack组织模块打包Library的原理及实现
2018/03/10 Javascript
js实现前面自动补全位数的方法
2018/10/10 Javascript
vue使用v-if v-show页面闪烁,div闪现的解决方法
2018/10/12 Javascript
创建echart多个联动的示例代码
2018/11/23 Javascript
Js通过AES加密后PHP用Openssl解密的方法
2019/07/12 Javascript
微信小程序开发之map地图组件定位并手动修改位置偏差
2019/08/17 Javascript
jQuery实现判断滚动条滚动到document底部的方法分析
2019/08/27 jQuery
python查看微信好友是否删除自己
2016/12/19 Python
Python实现控制台中的进度条功能代码
2017/12/22 Python
Python音频操作工具PyAudio上手教程详解
2019/06/26 Python
python实现贪吃蛇游戏源码
2020/03/21 Python
python 使用raw socket进行TCP SYN扫描实例
2020/05/05 Python
详解Scrapy Redis入门实战
2020/11/18 Python
CSS3实现复选框动画特效示例代码
2016/09/27 HTML / CSS
马来西亚最好的婴儿商店:Motherhood
2017/09/14 全球购物
Linux文件系统类型
2012/09/16 面试题
团员个人的自我评价
2013/12/02 职场文书
运动会开幕式邀请函
2014/02/03 职场文书
会计毕业自我鉴定
2014/02/05 职场文书
商品陈列协议书
2014/09/29 职场文书
研究生毕业论文导师评语
2014/12/31 职场文书