webpack使用精通,致大家终将组件化的Web

致大家必将组件化的Web

2015/11/25 · HTML5 · 1
评论 ·
组件化

原稿出处:
AlloyTeam   

那篇小说将从两年前的叁回技术争议起来。冲突的聚焦正是下图的七个目录分层结构。作者说按模块划分好,他说你傻逼啊,当然是按能源划分。

皇家赌场手机版 1 《=》皇家赌场手机版 2

”按模块划分“目录结构,把当下模块下的全体逻辑和财富都放一块了,那对于两个人独立开发和保卫安全个人模块不是很可以吗?当然了,那争持的结果是自小编宝宝地改回主流的”按财富划分“的目录结构。因为,没有到位JS模块化和财富模块化,仅仅物理地点上的模块划分是没有意思的,只会增添创设的财力而已。

即便她说得好有道理小编无言以对,可是自个儿心不甘,等待他多年来端组件化成熟了,再来世界第一回大战!

方今日正是本人反复正义的光阴!只是那时候足够跟你撕逼的人不在。

模块化的不足

模块一般指能够独立拆分且通用的代码单元。由于JavaScript语言自身没有松手的模块机制(ES6有了!!),大家一般会选取CMD或ADM建立起模块机制。以往大多数有点大型一点的品种,都会利用requirejs或然seajs来兑现JS的模块化。两个人分工合作开发,其各自定义正视和暴光接口,维护成效模块间独立性,对于项指标支出效能和档次早先时期扩大和掩护,都是是有一点都不小的推抢功能。

但,麻烦大家不怎么略读一下上面的代码

JavaScript

require([
‘Tmpl!../tmpl/list.html’,’lib/qqapi’,’module/position’,’module/refresh’,’module/page’,’module/net’
], function(listTmpl, QQapi, Position, Refresh, Page, NET){ var foo =
”, bar = []; QQapi.report(); Position.getLocaiton(function(data){
//… }); var init = function(){ bind();
NET.get(‘/cgi-bin/xxx/xxx’,function(data){ renderA(data.banner);
renderB(data.list); }); }; var processData = function(){ }; var bind =
function(){ }; var renderA = function(){ }; var renderB =
function(data){ listTmpl.render(‘#listContent’,processData(data)); };
var refresh = function(){ Page.refresh(); }; // app start init(); });

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
require([
    ‘Tmpl!../tmpl/list.html’,’lib/qqapi’,’module/position’,’module/refresh’,’module/page’,’module/net’
], function(listTmpl, QQapi, Position, Refresh, Page, NET){
    var foo = ”,
        bar = [];
    QQapi.report();
    Position.getLocaiton(function(data){
        //…
    });
    var init = function(){
        bind();
        NET.get(‘/cgi-bin/xxx/xxx’,function(data){
            renderA(data.banner);
            renderB(data.list);
        });
    };
    var processData = function(){
    };
    var bind = function(){
    };
    var renderA = function(){
    };
    var renderB = function(data){
        listTmpl.render(‘#listContent’,processData(data));
    };
    var refresh = function(){
        Page.refresh();
    };
    // app start
    init();
});

地点是切实可行有个别页面包车型地铁主js,已经封装了像Position,NET,Refresh等功效模块,但页面包车型地铁主逻辑依然是”面向进度“的代码结构。所谓面向进度,是指依据页面包车型大巴渲染进程来编排代码结构。像:init
-> getData -> processData -> bindevent -> report -> xxx

方法之间线性跳转,你大约也能感受那样代码弊端。随着页面逻辑更是复杂,那条”进度线“也会愈来愈长,并且更为绕。加之贫乏专业约束,其余连串成员依据各自要求,在”进程线“加插各自逻辑,最后这些页面包车型大巴逻辑变得难以维护。

皇家赌场手机版 3

支付须求审慎,生怕影响“进度线”后面符合规律逻辑。并且每1次加插或改动都以bug泛滥,无不令产品有关人口无不提心吊胆。

 页面结构模块化

逸事上边的面向进程的难点,行行业内部也有诸多消除方案,而笔者辈协会也总括出一套成熟的解决方案:Abstractjs,页面结构模块化。大家能够把大家的页面想象为3个乐高机器人,要求区别零件组装,如下图,假诺页面划分为tabContainer,listContainer和imgsContainer多个模块。最终把这么些模块add到结尾的pageModel里面,最后使用rock方法让页面运维起来。

皇家赌场手机版 4
(原经过线示例图)

皇家赌场手机版 5
(页面结构化示例图)

上面是伪代码的完成

JavaScript

require([
‘Tmpl!../tmpl/list.html’,’Tmpl!../tmpl/imgs.html’,’lib/qqapi’,’module/refresh’,’module/page’
], function(listTmpl, imgsTmpl, QQapi, Refresh, Page ){ var
tabContainer = new RenderModel({ renderContainer: ‘#tabWrap’, data: {},
renderTmpl: “<li soda-repeat=’item in
data.tabs’>{{item}}</li>”, event: function(){ // tab’s event }
}); var listContainer = new ScrollModel({ scrollEl: $.os.ios ?
$(‘#Page’) : window, renderContainer: ‘#listWrap’, renderTmpl:
listTmpl, cgiName: ‘/cgi-bin/index-list?num=1’, processData:
function(data) { //… }, event: function(){ // listElement’s event },
error: function(data) { Page.show(‘数据重回分外[‘ + data.retcode +
‘]’); } }); var imgsContainer = new renderModel({ renderContainer:
‘#imgsWrap’, renderTmpl: listTmpl, cgiName: ‘/cgi-bin/getPics’,
processData: function(data) { //… }, event: function(){ //
imgsElement’s event }, complete: function(data) { QQapi.report(); } });
var page = new PageModel();
page.add([webpack使用精通,致大家终将组件化的Web。tabContainer,listContainer,imgsContainer]); page.rock(); });

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
require([
    ‘Tmpl!../tmpl/list.html’,’Tmpl!../tmpl/imgs.html’,’lib/qqapi’,’module/refresh’,’module/page’
], function(listTmpl, imgsTmpl, QQapi, Refresh, Page ){
 
    var tabContainer = new RenderModel({
        renderContainer: ‘#tabWrap’,
        data: {},
        renderTmpl: "<li soda-repeat=’item in data.tabs’>{{item}}</li>",
        event: function(){
            // tab’s event
        }
    });
 
    var listContainer = new ScrollModel({
        scrollEl: $.os.ios ? $(‘#Page’) : window,
        renderContainer: ‘#listWrap’,
        renderTmpl: listTmpl,
        cgiName: ‘/cgi-bin/index-list?num=1’,
        processData: function(data) {
            //…
        },
        event: function(){
            // listElement’s event
        },
        error: function(data) {
            Page.show(‘数据返回异常[‘ + data.retcode + ‘]’);
        }
    });
 
    var imgsContainer = new renderModel({
        renderContainer: ‘#imgsWrap’,
        renderTmpl: listTmpl,
        cgiName: ‘/cgi-bin/getPics’,
        processData: function(data) {
            //…
        },
        event: function(){
            // imgsElement’s event
        },
        complete: function(data) {
           QQapi.report();
        }
    });
 
    var page = new PageModel();
    page.add([tabContainer,listContainer,imgsContainer]);
    page.rock();
 
});

大家把那几个常用的伸手CGI,处理数量,事件绑定,上报,容错处理等一多重逻辑情势,以页面块为单位封装成一个Model模块。

如此那般的三个华而不实层Model,大家能够清晰地来看该页面块,请求的CGI是怎么着,绑定了怎么风浪,做了何等上报,出错怎么处理。新增的代码就相应放置在对应的模块上相应的事态方法(preload,process,event,complete…),杜绝了往年的无规则乱增代码的创作。并且,依照区别工作逻辑封装差异类别的Model,如列表滚动的ScrollModel,滑块作用的SliderModel等等,能够开始展览高度封装,集中优化。

现行依照Model的页面结构开发,已经包含一点”组件化“的寓意。每种Model都包涵各自的数额,模板,逻辑。已经算是贰个完好的机能单元。但相差真正的WebComponent照旧有一段距离,至少满足不断笔者的”理想目录结构“。

 WebComponents 标准

我们回看一下用到八个datapicker的jquery的插件,所须要的步奏:

  1. 引入插件js

  2. 引入插件所需的css(假使有)

  3. copy 组件的所需的html片段

  4. 累加代码触发组件运转

当下的“组件”基本上只好落得是有个别功效单元上的联谊。他的财富都以松散地分散在二种财富文件中,而且组件作用域暴光在全局意义域下,缺少内聚性很不难就会跟其他零件发生冲突,如最简易的css命名争辩。对于那种“组件”,还不如上边的页面结构模块化。

于是乎W3C按耐不住了,制定多少个WebComponents标准,为组件化的前途指点了明路。

下边以较为不难的法子介绍那份正经,力求大家能够急迅驾驭达成组件化的剧情。(对那有的询问的同班,能够跳过这一小节)

1. <template>模板能力

模板那东西浙高校家最纯熟不过了,二〇一八年见的较多的沙盘质量大战artTemplate,juicer,tmpl,underscoretemplate等等。而最近又有mustachejs无逻辑模板引擎等新入选手。但是大家有没有想过,这么基础的力量,原生HTML5是不扶助的(T_T)。

而明天WebComponent将要提供原生的模版能力

XHTML

<template id=”datapcikerTmpl”>
<div>作者是原生的模板</div> </template>

1
2
3
<template id="datapcikerTmpl">
<div>我是原生的模板</div>
</template>

template标签钦赐义了myTmpl的模板,须要使用的时候就要innerHTML= document.querySelector('#myTmpl').content;能够见见这一个原生的模版够原始,模板占位符等成效都未曾,对于动态数据渲染模板能力只好自力更新。

2. ShadowDom 封装组件独立的内部结构

ShadowDom能够知道为一份有单独成效域的html片段。那个html片段的CSS环境和主文书档案隔断的,各自笔者保护持内部的独立性。也多亏ShadowDom的单独性情,使得组件化成为了说不定。

JavaScript

var wrap = document.querySelector(‘#wrap’); var shadow =
wrap.createShadowRoot(); shadow.innerHTML = ‘<p>you can not see me
</p>’

1
2
3
var wrap = document.querySelector(‘#wrap’);
var shadow = wrap.createShadowRoot();
shadow.innerHTML = ‘<p>you can not see me </p>’

在切切实实dom节点上选用createShadowRoot方法即可生成其ShadowDom。就像是在整份Html的屋子里面,新建了贰个shadow的房间。房间外的人都不清楚房间内有怎么着,保持shadowDom的独立性。

3. 自定义原生标签

第二接触Angularjs的directive指令功能,设定好组件的逻辑后,多少个<Datepicker
/>就能引入整个组件。如此狂炫酷炸碉堡天的效用,实在令人弹冠相庆,跃地三尺。

JavaScript

var tmpl = document.querySelector(‘#datapickerTmpl’); var
datapickerProto = Object.create(HTMLElement.prototype); //
设置把大家模板内容大家的shadowDom datapickerProto.createdCallback =
function() { var root = this.createShadowRoot();
root.appendChild(document.importNode(tmpl.content, true)); }; var
datapicker = docuemnt.registerElement(‘datapicker’,{ prototype:
datapickerProto });

1
2
3
4
5
6
7
8
9
10
11
12
var tmpl = document.querySelector(‘#datapickerTmpl’);
var datapickerProto = Object.create(HTMLElement.prototype);
 
// 设置把我们模板内容我们的shadowDom
datapickerProto.createdCallback = function() {
    var root = this.createShadowRoot();
    root.appendChild(document.importNode(tmpl.content, true));
};
 
var datapicker = docuemnt.registerElement(‘datapicker’,{
    prototype: datapickerProto
});

Object.create格局持续HTMLElement.prototype,获得三个新的prototype。当解析器发现大家在文书档案中标记它将检查是还是不是3个名为createdCallback的章程。若是找到这几个情势它将及时运维它,所以大家把克隆模板的内容来创立的ShadowDom。

终极,registerElement的办法传递大家的prototype来注册自定义标签。

上面的代码初阶略显复杂了,把前边四个力量“模板”“shadowDom”结合,形成组件的中间逻辑。最终经过registerElement的格局注册组件。之后可以愉悦地<datapicker></datapicker>的选拔。

4. imports消除组件间的借助

XHTML

<link rel=”import” href=”datapciker.html”>

1
<link rel="import" href="datapciker.html">

其一类php最常用的html导入功用,HTML原生也能帮助了。

WebComponents标准内容大约到此地,是的,小编那里没有怎么Demo,也从没实践经验分享。由于webComponents新特征,基本三巳了高版本的Chrome扶助外,其余浏览器的支撑度甚少。尽管有polymer帮衬推动webcompoents的仓库储存在,可是polymer自身的供给版本也是老大高(IE10+)。所以今日的主演并不是她。

我们简要来回看一下WebCompoents的四局地机能:

1 .<template>定义组件的HTML模板能力

  1. Shadow Dom封装组件的内部结构,并且保持其独立性

  2. Custom Element 对外提供组件的标签,完毕自定义标签

  3. import化解组件结合和注重性加载

 组件化实践方案

法定的专业看完了,大家想想一下。一份真正成熟可信的组件化方案,供给拥有的力量。

“能源高内聚”—— 组件能源内部高内聚,组件能源由自个儿加载控制

“作用域独立”—— 内部结构密封,不与全局或任何零件发生震慑

“自定义标签”—— 定义组件的应用方法

“可相互结合”—— 组件正在有力的地点,组件间组装整合

“接口规范化”—— 组件接口有统一标准,恐怕是生命周期的田管

村办认为,模板能力是基础能力,跟是还是不是组件化没有强联系,所以并未提出一个大点。

既是是实施,现阶段WebComponent的支撑度还不成熟,不能够当做方案的手段。而除此以外一套以高品质虚拟Dom为切入点的组件框架React,在facebook的造势下,社区获取了大力发展。其余一名骨干Webpack,负责化解组件财富内聚,同时跟React十分切合形成互补。

所以【Webpack】+【React】将会是那套方案的核心技术。

不了然您今后是“又是react+webpack”感到失望皇家赌场手机版 6,照旧“太好了是react+webpack”不用再学2次新框架的开心皇家赌场手机版 7。无论怎样下边包车型大巴内容不会让你失望的。

一,组件生命周期

皇家赌场手机版 8

React天生就是强制性组件化的,所以可以从根性情上缓解面向进度代码所带来的劳累。React组件本人有生命周期方法,能够满意“接口规范化”能力点。并且跟“页面结构模块化”的所封装抽离的多少个点子能挨个对应。其它react的jsx自带模板作用,把html页面片直接写在render方法内,组件内聚性越发紧凑。

鉴于React编写的JSX是会先生成虚拟Dom的,要求时机才真正插入到Dom树。使用React必供给知道组件的生命周期,其生命周期多少个状态:

Mount: 插入Dom

Update: 更新Dom

Unmount: 拔出Dom

mount那单词翻译扩展,嵌入等。笔者倒是建议“插入”更好精通。插入!拔出!插入!拔出!默念3回,懂了没?别少看黄段子的能力,

皇家赌场手机版 9

组件状态就是: 插入-> 更新 ->拔出。

下一场每一个组件状态会有二种处理函数,一前一后,will函数和did函数。

componentWillMount()  准备插入前

componentDidlMount()  插入后

componentWillUpdate() 准备更新前

componentDidUpdate()  更新后

componentWillUnmount() 准备拔出前

因为拔出后为主都以贤者形态(笔者说的是组件),所以并未DidUnmount这一个措施。

除此以外React此外多个骨干:数据模型props和state,对应着也有自个状态方法

getInitialState()     获取开端化state。

getDefaultProps() 获取暗中认可props。对于那个并未父组件传递的props,通过该格局设置暗许的props

componentWillReceiveProps()  已插入的组件收到新的props时调用

还有一个独特别情报况的处理函数,用于优化处理

shouldComponentUpdate():判断组件是不是必要update调用

加上最重庆大学的render方法,React自个儿带的点子刚刚好11个。对于初学者的话是比较难以消化。但实质上getInitialStatecomponentDidMountrender多少个情景方法都能一呵而就大多数零件,不必惧怕。

归来组件化的宗旨。

2个页面结构模块化的零部件,能独立包装整个组件的进程线

皇家赌场手机版 10

作者们换算成React生命周期方法:

皇家赌场手机版 11

 

零件的情事方法流中,有两点须要特殊表达:

1,3次渲染:

鉴于React的虚构Dom天性,组件的render函数不需协调触发,依据props和state的更动自个通过差距算法,得出最优的渲染。

伸手CGI一般都以异步,所以毫无疑问带来贰次渲染。只是空数据渲染的时候,有大概会被React优化掉。当数码回来,通过setState,触发1遍render

 

2,componentWiillMount与componentDidMount的差别

和大部分React的科目小说不雷同,ajax请求笔者提议在威尔Mount的法子内实施,而不是组件开首化成功现在的DidMount。那样能在“空数据渲染”阶段此前请求数据,尽早地缩减三次渲染的光阴。

willMount只会执行二遍,分外适合做init的工作。

didMount也只会执行一次,并且那时候真实的Dom已经形成,分外适合事件绑定和complete类的逻辑。

 

 二,JSX非常难看,可是组件内聚的重要!

WebComponents的正经之一,要求模板能力。本是觉得是大家耳熟能详的模版能力,但React中的JSX那样的奇人依然令人议论纷繁。React还并未火起来的时候,大家就曾经在博客园上狠狠地吐槽了“JSX写的代码那TM的丑”。那其实只是Demo阶段JSX,等到实战的大型项目中的JSX,包涵多情状多数据多事件的时候,你会意识………….JSX写的代码照旧非常丑。

皇家赌场手机版 12
(固然用sublime-babel等插件高亮,逻辑和渲染耦合一起,阅读性如故略差)

为啥我们会以为丑?因为我们曾经经对“视图-样式-逻辑”分离的做法潜移默化。

依据维护性和可读性,甚至品质,大家都不建议直接在Dom上边绑定事件可能直接写style属性。我们会在JS写事件代理,在CSS上写上classname,html上的正是清晰的Dom结构。我们很好地掩护着MVC的设计格局,一切有惊无险。直到JSX把他们都夹杂在联合署名,所守护的技艺栈受到凌犯,难免有着抗拒。

 

唯独从组件化的目标来看,那种高内聚的做法未尝不可。

上边包车型客车代码,在此以前的“逻辑视图分离”情势,我们必要去找相应的js文件,相应的event函数体内,找到td-info的class所绑定的风云。

对待起JSX的惊人内聚,全数事件逻辑正是在自作者jsx文件内,绑定的就是自身的showInfo方法。组件化的风味能马上显示出来。

(注意:就算写法上我们好像是HTML的内联事件处理器,不过在React底层并从未实际赋值类似onClick属性,内层依旧选用类似事件代理的艺术,高效地维护着事件处理器)

再来看一段style的jsx。其实jsx没有对体制有硬性规定,大家完全可依据从前的定义class的逻辑。任何一段样式都应有用class来定义。在jsx你也截然能够那样做。不过由于组件的独立性,笔者提出部分唯有“三遍性”的体制直接选取style赋值更好。减弱冗余的class。

XHTML

<div className=”list” style={{background: “#ddd”}}> {list_html}
</div>

1
2
3
<div className="list" style={{background: "#ddd"}}>
   {list_html}
</div>

兴许JSX内部有负责繁琐的逻辑样式,可JSX的自定义标签能力,组件的黑盒性立马能体会出来,是或不是须臾间美好了不少。

JavaScript

render: function(){ return ( <div> <Menus
bannerNums={this.state.list.length}></Menus> <TableList
data={this.state.list}></TableList> </div> ); }

1
2
3
4
5
6
7
8
render: function(){
    return (
      <div>
         <Menus bannerNums={this.state.list.length}></Menus>
         <TableList data={this.state.list}></TableList>
      </div>
   );
}

虽说JSX本质上是为了虚拟Dom而准备的,但那种逻辑和视图中度合一对于组件化未尝不是一件善事。

 

上学完React这些组件化框架后,看看组件化能力点的形成景况

“能源高内聚”—— (33%)  html与js内聚

“成效域独立”—— (四分之二)  js的成效域独立

“自定义标签”—— (百分百)jsx

“可交互结合”—— (50%)  可组合,但缺少使得的加载格局

“接口规范化”—— (百分百)组件生命周期方法

 

Webpack 财富组件化

对于组件化的财富独立性,一般的模块加载工具和塑造流程视乎变得艰辛。组件化的构建筑工程程化,不再是后面大家周边的,css合二,js合三,而是体验在组件间的重视性于加载关系。webpack正好合乎供给点,一方面填补组件化能力点,另一方帮衬大家周到组件化的完好营造环境。

先是要阐喜宝(Beingmate)(Karicare)点是,webpack是二个模块加载打包工具,用于管理你的模块能源依赖打包难点。那跟大家熟习的requirejs模块加载工具,和grunt/gulp营造筑工程具的概念,多多少少有些出入又微微雷同。

皇家赌场手机版 13

首先webpak对于CommonJS与英特尔同时扶助,满足大家模块/组件的加载格局。

JavaScript

require(“module”); require(“../file.js”); exports.doStuff = function()
{}; module.exports = someValue;

1
2
3
4
require("module");
require("../file.js");
exports.doStuff = function() {};
module.exports = someValue;

JavaScript

define(“mymodule”, [“dep1”, “dep2”], function(d1, d2) { return
someExportedValue; });

1
2
3
define("mymodule", ["dep1", "dep2"], function(d1, d2) {
    return someExportedValue;
});

当然最强劲的,最卓越的,当然是模块打包作用。那多亏这一意义,补充了组件化能源注重,以及完整工程化的力量

根据webpack的布置意见,全部财富都以“模块”,webpack内部贯彻了一套能源加运载飞机制,能够把想css,图片等财富等有依靠关系的“模块”加载。那跟咱们使用requirejs那种只有处理js大大分化。而这套加运载飞机制,通过二个个loader来完毕。

 

JavaScript

// webpack.config.js module.exports = { entry: { entry: ‘./index.jsx’,
}, output: { path: __dirname, filename: ‘[name].min.js’ }, module:
{ loaders: [ {test: /\.css$/, loader: ‘style!css’ }, {test:
/\.(jsx|js)?$/, loader: ‘jsx?harmony’, exclude: /node_modules/},
{test: /\.(png|jpg|jpeg)$/, loader: ‘url-loader?limit=10240’} ] } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// webpack.config.js
module.exports = {
    entry: {
     entry: ‘./index.jsx’,
    },
    output: {
        path: __dirname,
        filename: ‘[name].min.js’
    },
    module: {
        loaders: [
            {test: /\.css$/, loader: ‘style!css’ },
            {test: /\.(jsx|js)?$/, loader: ‘jsx?harmony’, exclude: /node_modules/},
            {test: /\.(png|jpg|jpeg)$/, loader: ‘url-loader?limit=10240’}
        ]
    }
};

地点一份简单的webpack配置文件,留意loaders的布署,数组内1个object配置为一种模块能源的加载机制。test的正则为同盟文件规则,loader的为匹配到文件将由哪些加载器处理,七个电脑之间用相隔,处理顺序从右到左。

 

style!css,css文件通过css-loader(处理css),再到style-loader(inline到html)的加工处理流。

jsx文件通过jsx-loader编写翻译,‘?’开启加载参数,harmony帮衬ES6的语法。

图表财富通过url-loader加载器,配置参数limit,控制少于10KB的图纸将会base64化。

 财富文件怎么着被require?

JavaScript

// 加载组件本身css require(‘./slider.css’); // 加载组件重视的模块 var
Clip = require(‘./clipitem.js’); // 加载图片能源 var spinnerImg =
require(‘./loading.png’);

1
2
3
4
5
6
// 加载组件自身css
require(‘./slider.css’);
// 加载组件依赖的模块
var Clip = require(‘./clipitem.js’);
// 加载图片资源
var spinnerImg = require(‘./loading.png’);

在webpack的js文件中大家除了require我们符合规律的js文件,css和png等静态文件也足以被require进来。我们经过webpack命令,编写翻译之后,看看输出结果什么:

JavaScript

webpackJsonp([0], { /* 0 */ /***/ function(module, exports,
__webpack_require__) { // 加载组件自个儿css
__webpack_require__(1); // 加载组件重视的模块 var Clip =
__webpack_require__(5); // 加载图片能源 var spinnerImg =
__webpack_require__(6); /***/ }, /* 1 */ /***/
function(module, exports, __webpack_require__) { /***/ }, /* 2
*/ /***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
exports.push([module.id, “.slider-wrap{\r\n position: relative;\r\n
width: 100%;\r\n margin: 50px;\r\n background:
#fff;\r\n}\r\n\r\n.slider-wrap li{\r\n text-align:
center;\r\n line-height: 20px;\r\n}”, “”]); /***/ }, /* 3 */
/***/ function(module, exports) { /***/ }, /* 4 */ /***/
function(module, exports, __webpack_require__) { /***/ }, /* 5
*/ /***/ function(module, exports) { console.log(‘hello, here is
clipitem.js’) ; /***/ }, /* 6 */ /***/ function(module, exports)
{ module.exports = “data:image/png;base64,iVBORw0KGg……” /***/ }
]);

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
webpackJsonp([0], {
/* 0 */
/***/ function(module, exports, __webpack_require__) {
          // 加载组件自身css
          __webpack_require__(1);
          // 加载组件依赖的模块
          var Clip = __webpack_require__(5);
          // 加载图片资源
          var spinnerImg = __webpack_require__(6);
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
 
/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {
          exports = module.exports = __webpack_require__(3)();
          exports.push([module.id, ".slider-wrap{\r\n position: relative;\r\n width: 100%;\r\n margin: 50px;\r\n background: #fff;\r\n}\r\n\r\n.slider-wrap li{\r\n text-align: center;\r\n line-height: 20px;\r\n}", ""]);
 
/***/ },
/* 3 */
/***/ function(module, exports) {
 
/***/ },
 
/* 4 */
/***/ function(module, exports, __webpack_require__) {
/***/ },
 
/* 5 */
/***/ function(module, exports) {
          console.log(‘hello, here is clipitem.js’) ;
/***/ },
/* 6 */
/***/ function(module, exports) {
          module.exports = "data:image/png;base64,iVBORw0KGg……"
/***/ }
]);

webpack编写翻译之后,输出文件视乎乱糟糟的,但骨子里每四个财富都被封装在三个函数体内,并且以编号的花样标记(注释)。那几个模块,由webpack的__webpack_require__中间方法加载。入口文件为编号0的函数index.js,能够看出__webpack_require__加载别的编号的模块。

css文件在数码1,由于使用css-loader和style-loader,编号1-4都以拍卖css。个中编号2我们得以看我们的css的string体。最后会以内联的方法插入到html中。

图表文件在编号6,能够看出exports出base64化的图纸。

 组件一体输出

JavaScript

// 加载组件自身css require(‘./slider.css’); // 加载组件重视的模块 var
React = require(‘react’); var Clip = require(‘../ui/clipitem.jsx’); //
加载图片财富 var spinnerImg = require(‘./loading.png’); var Slider =
React.createClass({ getInitialState: function() { // … },
componentDidMount: function(){ // … }, render: function() { return (
<div> <Clip data={this.props.imgs} /> <img
className=”loading” src={spinnerImg} /> </div> ); } });
module.exports = Slider;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 加载组件自身css
require(‘./slider.css’);
// 加载组件依赖的模块
var React = require(‘react’);
var Clip = require(‘../ui/clipitem.jsx’);
// 加载图片资源
var spinnerImg = require(‘./loading.png’);
var Slider = React.createClass({
    getInitialState: function() {
        // …
    },
    componentDidMount: function(){
        // …
    },
    render: function() {
        return (
            <div>
               <Clip data={this.props.imgs} />
               <img className="loading" src={spinnerImg} />
            </div>
        );
    }
});
module.exports = Slider;

假诺说,react使到html和js合为一体。

那么丰富webpack,两者结合一起的话。js,css,png(base64),html
全数web能源都能合成八个JS文件。那便是那套方案的基本所在:组件独立一体化。假使要引用三个零件,仅仅require('./slider.js') 即可达成。

 

进入webpack的模块加载器之后,我们组件的加载难点,内聚难点也都事业有成地化解掉

“能源高内聚”—— (百分百) 全数能源得以一js出口

“可交互结合”—— (百分之百)  可构成可凭借加载

 

 CSS模块化实践

很兴奋,你能阅读到这边。近年来大家的组件完成度11分的高,能源内聚,易于组合,功效域独立互不污染。。。。等等皇家赌场手机版 14,视乎CSS模块的达成度有欠缺。

那么目前组件实现度来看,CSS功效域其实是全局性的,并非组件内部独立。下一步,大家要做得正是怎么让我们组件内部的CSS作用域独立。

那儿可能有人立刻跳出,大喊一句“德玛西亚!”,哦不,应该是“用sass啊傻逼!”。不过品种组件化之后,组件的内部封装已经很好了,个中间dom结构和css趋向简单,独立,甚至是千疮百孔的。LESS和SASS的一体式样式框架的宏图,他的嵌套,变量,include,函数等丰裕的功效对于全体大型项目标样式管理尤其实惠。但对此一个效益单一组件内部样式,视乎就变的略微顶牛。“不可能为了框架而框架,合适才是最好的”。视乎原生的css能力已经满意组件的体裁必要,唯独就是上边包车型地铁css效用域难点。

 

此地自身付诸思考的方案:
classname随便写,保持原生的章程。编写翻译阶段,依据组件在档次路线的唯一性,由【组件classname+组件唯一路径】打成md5,生成全局唯一性classname。正当小编要写一个loader达成本人的想法的时候,发现歪果仁已经早在先走一步了。。。。

此处具体方案参考笔者事先博客的译文:

以前大家谈谈过JS的模块。未来因此Webpack被加载的CSS能源叫做“CSS模块”?笔者以为如故有题指标。今后style-loader插件的落到实处精神上只是成立link[rel=stylesheet]webpack使用精通,致大家终将组件化的Web。要素插入到document中。那种作为和普通引入JS模块分外例外。引入另一个JS模块是调用它所提供的接口,但引入一个CSS却并不“调用”CSS。所以引入CSS本身对于JS程序来说并不设有“模块化”意义,纯粹只是表明了一种财富注重——即该零件所要完毕的功用还要求一些asset。

故此,那位歪果仁还扩展了“CSS模块化”的定义,除了下面的大家需求一些功能域外,还有许多效果,那里不详述。具体参考原来的书文 

十分赞的一点,便是cssmodules已经被css-loader收纳。所以大家不必要依靠额外的loader,基本的css-loader开启参数modules即可

JavaScript

//webpack.config.js … module: { loaders: [ {test: /\.css$/, loader:
‘style!css?modules&localIdentName=[local]__[name]_[hash:base64:5]’
}, ] } ….

1
2
3
4
5
6
7
8
//webpack.config.js
…  
    module: {
        loaders: [
            {test: /\.css$/, loader: ‘style!css?modules&localIdentName=[local]__[name]_[hash:base64:5]’ },
        ]  
    }
….

modules参数代表开启css-modules作用,loaclIdentName为设置我们编译后的css名字,为了便于debug,大家把classname(local)和零部件名字(name)输出。当然能够在最终输出的版本为了省去提交,仅仅使用hash值即可。别的在react中的用法大致如下。

JavaScript

var styles = require(‘./banner.css’); var Banner = new
React.createClass({ … render: function(){ return ( <div> <div
className={styles.classA}></div> </div> ) } });

1
2
3
4
5
6
7
8
9
10
11
var styles = require(‘./banner.css’);
var Banner = new React.createClass({
    …
    render: function(){
        return (
            <div>
                <div className={styles.classA}></div>
            </div>
        )
    }
});

终极那里关于出于对CSS一些合计,

至于css-modules的别的效用,作者并不打算利用。在内部分享【我们竭尽所能地让CSS变得复杂】中提及:

笔者们项目中多数的CSS都不会像boostrap这样供给变量来设置,身为一线开发者的大家大概能够感受到:设计师们改版UI,相对不是粗略的换个色或改个间距,而是面目全非的全新UI,那相对不是3个变量所能消除的”维护性“。

反而项目实战进程中,真正要缓解的是:在本子迭代进程中那几个淘汰掉的逾期CSS,多量地堆放在品种个中。大家像极了家中的欧巴酱不舍得丢掉没用的事物,因为那不过大家选用sass或less编写出具有中度的可维护性的,肯定有复用的一天。

这一个堆积的逾期CSS(or
sass)之间又有局地依赖,一部分逾期失效了,一部分又被新的体制复用了,导致没人敢动那个历史样式。结果现网项目迭代还带着大批量两年前没用的体裁文件。

组件化之后,css的布局同样被改造了。恐怕postcss才是你今后手上最符合的工具,而不在是sass。

 

到那里,我们算是把组件化最终八个难题也解决了。

“效用域独立”—— (百分之百) 就如shadowDom功效域独立

 

到此处,我们得以开一瓶82年的雪碧,好好庆祝一下。不是吧?

皇家赌场手机版 15

 

 组件化之路还在持续

webpack和react还有许多新相当关键的性情和效劳,介于本文仅仅围绕着组件化的为大旨,没有种种阐述。别的,配搭gulp/grunt补充webpack创设能力,webpack的codeSplitting,react的组件通讯问题,开发与生产条件布置等等,都以全部大型项目方案的所必须的,限于篇幅难点。能够等等笔者更新下篇,或大家可以自行查阅。

不过,不得不再安利一下react-hotloader神器。热加载的支付情势相对是下一代前端开发必备。严谨说,假定没有了热加载,作者会很泼辣地扬弃那套方案,即使那套方案再怎么完美,笔者都讨厌react须求5~6s的编写翻译时间。不过hotloader能够在本人不刷新页面包车型大巴情形下,动态修改代码,而且不单单是样式,连逻辑也是即时生效。

皇家赌场手机版 16

如上在form表单内。使用热加载,表单不须要再行填写,修改submit的逻辑立即见效。这样的支出功效真不是加强仅仅一个品位。必须安利一下。

 

兴许你意识,使用组件化方案以往,整个技术栈都被更新了一番。学习耗费也不少,并且能够预言到,基于组件化的前端还会众多不足的题材,例如性能优化方案供给重新考虑,甚至最基本的组件可复用性不肯定高。后边非常短一段时间,供给大家不断磨砺与优化,探求最优的前端组件化之道。

足足我们得以想像,不再担心本人写的代码跟某些什么人何人争辩,不再为找某段逻辑在三个文本和办法间持续,不再copy一片片逻辑然后改改。我们每一次编写都以可采纳,可组合,独立且内聚的机件。而各种页面将会由贰个个嵌套组合的零件,互相独立却相互功用。

 

对于这么的前端今后,有所期待,不是很好啊

由来,多谢您的开卷。

1 赞 6 收藏 1
评论

皇家赌场手机版 17

壹 、什么是webpack:webpack是一款模块加载兼打包工具,它能够将js、jsx、coffee、样式sass、less,图片等作为模块来使用和拍卖。
二 、优势:壹 、以commonJS的款型来书写脚本,对英特尔、CMD的协理也很完美,方便旧项指标迁徙。二 、能被模块化的不止是JS了。三 、能替代部分grunt/gulp的工作,例如打包,压缩混淆,图片转base64等。三 、扩充性强,插件机制完善,援救React热拔插(react-hot-loader)
叁 、安装和安排:
① 、安装:直接行使npm来进展安装
$ npm install webpack -g
将依靠写入package.json包
$ npm init
$ npm install webpack –save-dev
2、配置:
每种品种必须配备3个webpack.config.js,作用如同gulpfile.js/Gruntfile.js,二个安顿项,告诉webpack要做什么。
示例:
var webpack = require(‘webpack’);
var commonsPlugin = new
webpack.optimize.CommonsChunkPlugin(‘common.js’);
module.exports = {
//插件项
plugins: [commonsPlugin],
//页面入口文件配置
entry: {
index : ‘./src/js/page/index.js’
},
//入口文件输出配置
output: {
path: ‘dist/js/page’,
filename: ‘[name].js’
},
module: {
//加载器配置
loaders: [
{ test: /.css$/, loader: ‘style-loader!css-loader’ },
{ test: /.js$/, loader: ‘jsx-loader?harmony’ },
{ test: /.scss$/, loader: ‘style!css!sass?sourceMap’},
{ test: /.(png|jpg)$/, loader: ‘url-loader?limit=8192’}
]
},
//其余消除方案布置
resolve: {
root: ‘E:/github/flux-example/src’, //相对路线
extensions: [”, ‘.js’, ‘.json’, ‘.scss’],
alias: {
AppStore : ‘js/stores/AppStores.js’,
ActionType : ‘js/actions/ActionType.js’,
AppAction : ‘js/actions/AppAction.js’
}
}
};
(1)plugins是插件项,那里运用了3个CommonsChunkPlugin的插件,它用于提取两个输入文件的公物脚本有的,然后生成二个common.js来便宜多页面之间的复用。
(2)entry是页面包车型地铁入口文件配置,output是对应的出口项配置
{
entry: {
page1: “./page1”,
//帮忙数组方式,将加载数组中的全体模块,但以最终叁个模块作为出口
page2: [“./entry1”, “./entry2”]
},
output: {
path: “dist/js/page”,
filename: “[name].bundle.js”
}
}
该代码会生成一个page1.bundle.js和page2.bundle.js,并存放在./dist/js/page文件夹下。
(3)module.loaders,告知webpack每种文件都亟待如何加载器来处理
module: {
//加载器配置
loaders: [
//.css 文件使用 style-loader 和 css-loader 来处理
{ test: /.css$/, loader: ‘style-loader!css-loader’ },
//.js 文件使用 jsx-loader 来编写翻译处理
{ test: /.js$/, loader: ‘jsx-loader?harmony’ },
//.scss 文件使用 style-loader、css-loader 和 sass-loader 来编写翻译处理
{ test: /.scss$/, loader: ‘style!css!sass?sourceMap’},
//图片文件使用 url-loader 来拍卖,小于8kb的直白转为base64
{ test: /.(png|jpg)$/, loader: ‘url-loader?limit=8192’}
]
}
-loader能够不写,八个loader之间用“!”连接起来。全体的加载器都须求通过npm来加载。
譬如说最终七个url-loader,它会将样式中引用到的图形转为模块来处理。使用前开展设置:
$ npm install url-loader -save-dev
安顿消息的参数:“?limit=8192”表示将享有小于8kb的图片都转为base64方式(超越8kb的才使用url-loader来映射到文件,不然转为data
url情势)
(4)resolve配置,
resolve: {
//查找module的话从此处初叶查找
root: ‘E:/github/flux-example/src’, //绝对路线
//自动扩充文件后缀名,意味着大家require模块能够不难不写后缀名
extensions: [”, ‘.js’, ‘.json’, ‘.scss’],
//模块别称定义,方便后续直接引用别称,无须多写长长的地址
alias: {
AppStore : ‘js/stores/AppStores.js’,//后续直接 require(‘AppStore’)
即可
ActionType : ‘js/actions/ActionType.js’,
AppAction : ‘js/actions/AppAction.js’
}
}
肆 、运营webpack,直接实施:
$ webpack –display-error-details
末端的参数
“-display-error-details”推荐加上,方便出错开上下班时间能了然到更详尽的消息。别的主要参数:
$ webpack –config XXX.js
//使用另一份配置文件(比如webpack.config2.js)来打包
$ webpack –watch //监听变动并活动打包
$ webpack -p //压缩混淆脚本,这一个可怜尤其首要!
$ webpack -d //生成map映射文件,告知哪些模块被最后包装到哪个地方了
-p是很要紧的参数,曾经一个未压缩的 700kb 的文书,压缩后一贯降到
180kb(首若是样式那块一句就占据一行脚本,导致未压缩脚本变得十分大)。
五 、模块引入:
一 、在HTML页面引入:引入webpack最后生成的台本即可:
<!DOCTYPE html>
<html>
<head lang=”en”>
<meta charset=”UTF-8″>
<title>demo</title>
</head>
<body>
<script src=”dist/js/page/common.js”></script>
<script src=”dist/js/page/index.js”></script>
</body>
</html>
能够见到大家连样式都并非引入,究竟脚本执行时会动态生成style并标签打到head里。
② 、JS引入:各脚本模块可以行使common.js来书写,并能够直接引入未经编写翻译的模块,比如:jsx,coffee,sass,只要在webpack.config.js中布置好了相应的加载器就行。
编写翻译页面包车型客车入口文件:
require(‘../../css/reset.scss’); //加载早先化样式
require(‘../../css/allComponent.scss’); //加载组件样式
var React = require(‘react’);
var AppWrap = require(‘../component/AppWrap’); //加载组件
var createRedux = require(‘redux’).createRedux;
var Provider = require(‘redux/react’).Provider;
var stores = require(‘AppStore’);
var redux = createRedux(stores);
var App = React.createClass({
render: function() {
return (
<Provider redux={redux}>
{function() { return <AppWrap />; }}
</Provider>
);
}
});
React.render(
<App />, document.body
);

*安装

webpack 介绍

其他:
1、shimming :
在 英特尔/CMD
中,大家必要对不符合规范的模块(比如有的一直回到全局变量的插件)进行shim 处理,那时候大家需求使用 exports-loader 来帮助:
{ test: require.resolve(“./src/js/tool/swipe.js”), loader:
“exports?swipe”}
后来在剧本中须要引用该模块的时候,这么简单地来接纳就足以了:
require(‘./tool/swipe.js’);
swipe();
贰 、自定义公共模块提取:
在篇章开首我们应用了 CommonsChunkPlugin
插件来提取八个页面之间的公家模块,并将该模块打包为 common.js 。
但有时候大家期望能特别特性化一些,大家能够这么布置:
var CommonsChunkPlugin =
require(“webpack/lib/optimize/CommonsChunkPlugin”);
module.exports = {
entry: {
p1: “./page1”,
p2: “./page2”,
p3: “./page3”,
ap1: “./admin/page1”,
ap2: “./admin/page2”
},
output: {
filename: “[name].js”
},
plugins: [
new CommonsChunkPlugin(“admin-commons.js”, [“ap1”, “ap2”]),
new CommonsChunkPlugin(“commons.js”, [“p1”, “p2”,
“admin-commons.js”])
]
};
// <script>s required:
// page1.html: commons.js, p1.js
// page2.html: commons.js, p2.js
// page3.html: p3.js
// admin-page1.html: commons.js, admin-commons.js, ap1.js
// admin-page2.html: commons.js, admin-commons.js, ap2.js
三 、独立包装样式:
偶尔或许希望项指标体制能不用被打包到脚本中,而是独立出来作为.css,然后在页面中以标签引入。那时候我们需求extract-text-webpack-plugin 来资助:
var webpack = require(‘webpack’);
var commonsPlugin = new
webpack.optimize.CommonsChunkPlugin(‘common.js’);
var ExtractTextPlugin = require(“extract-text-webpack-plugin”);
module.exports = {
plugins: [commonsPlugin, new ExtractTextPlugin(“[name].css”)],
entry: {
//…省略别的配置
最终 webpack 执行后会乖乖地把体制文件提取出来:
四 、使用CDN远程文件:
突发性大家希望有个别模块走CDN并以<script>的格局挂载到页面上来加载,但又愿意能在
webpack 的模块中运用上。
那时候大家能够在陈设文件里选取 externals 属性来增援:
{
externals: {
// require(“jquery”) 是引用自外部模块的
// 对应全局变量 jQuery
“jquery”: “jQuery”
}
}
需求留意的是,得保障 CDN 文件必须在 webpack 打包文件引入在此之前先引入。
大家倒也足以利用 script.js 在剧本中来加载大家的模块:
var $script = require(“scriptjs”);
$script(“//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js”,
function() {
$(‘body’).html(‘It works!’)
});
5、与grunt/gulp相结合:
gulp.task(“webpack”, function(callback) {
// run webpack
webpack({
// configuration
}, function(err, stats) {
if(err) throw new gutil.PluginError(“webpack”, err);
gutil.log(“[webpack]”, stats.toString({
// output options
}));
callback();
});
});
自然我们只必要把陈设写到 webpack({ … }) 中去即可,无须再写
webpack.config.js 了。

跻身到您的种类将webpack安装到项目标依靠中,那样就能够运用项目本地版本的webpack
npm install webpack@1.12.x–save-dev(那种格式是安装钦定版本)

webpack 是什么

npm install webpack –save-dev

缘何引入新的卷入工具

npm i webpack-dev-server –save

webpack 核激情想

npm install react –save

webpack 安装

npm install babel-loader babel-core babel-preset-es2015
babel-preset-react –save-dev

webpack 使用

npm i react-dom –save

一声令下行调用

*目录

配备文件

index.html
js / 你的js文件
dist / 你打包的文件(也正是您JS目录下的文书打包后的文书)
手动打包方法

webpack 配置参数

手动打包: webpack 源文件路径 打包路径(webpack ./entry.js
./bundle.js)//那里是尚未配置webpack.config.js
$ webpack –watch //监听变动并自动打包 监视webpack.config.js 的变更$
webpack -p //压缩混淆脚本,那些相当足够重庆大学!

entry 和 output

*注意事项

单一入口

页面要引入打包后的途径的JS文件

两个入口

*loader理解

多少个包装指标

是模块和能源的转换器,它自己是1个函数,接受源文件作为参数,重返转换的结果。那样,大家就可以通过
require 来加载任何项目标模块或文件,比如CoffeeScriptJSX
LESS图片

webpack 支持 Jsx 和 Es6

*露马网络模特块

webpack loaders

module.exports = “It works from content.js.”;//nodejs中的暴露格局

loader 定义

export default Girls;//ES6

loader 功能

*引入模块

loader 配置

import MyModule from ‘./modules/MyModule.js’;//es6

使用 loader

var MyModule = require(‘./MyModule.js’);//commonjs

webpack 开发条件与生产条件

webpack require 一切
require(“./content.js”); // 添加content.js

webpack 分割 vendor 代码和行使工作代码

*加载CSS

webpack develop server

安装css-loader : npm install css-loader style-loader
require(“style!css!
../css/main.css”)//加载CSS style!css!是宣称这几个模块是CSS
style!css!能够不写 在loaders里面配备音讯即可

安装 webpack-dev-server

import “../css/main.css”;//ES6引入格局

启动 webpack-dev-server

*配备文件

代码监察和控制

webpack.config.js 以下是宗旨配置
单个入口文件
var path = require(‘path’);

自行刷新

module.exports = {

热加载 (hot module replacement)

entry: "./js/entry.js",

output: {

在 webpack.config.js 中配置 webpack develop server

path: ‘./dist’,

2.2.1 webpack 介绍

    publicPath: './dist/',

    filename: "bundle.js"

},

module: {

    loaders: [

        { test: /\.css$/, loader: "style!css" }

    ]

}

webpack 是什么

};

webpack is a module bundler. webpack takes modules with dependencies and
generates static assets representing those modules

四个入口文件

webpack
是三个模块打包工具,输入为带有依赖关系的模块集,输出为包装合并的前端静态财富。在上一节的前端工程化中,已经介绍过,webpack
是同时援救 英特尔 和 CommonJs 的模块定义情势,不仅如此,webpack
能够将别的前端能源视为模块,如 css,图片,文本。

var path = require(‘path’);

怎么要引入新的卷入工具

module.exports = {

在 webpack 出现此前,已经有了一些封装工具,如 Browserify,
那怎么不优化那个工具,而是重复造轮子?

entry: {

    page1:["./js/entry.js","./js/double.js"]

},

output: {

webpack 从前的包裹工具工具功能单一,只可以形成一定的天职,但是 web
前端工程是犬牙相制的,贰个 webapp 对于工作代码的供给也许有:

path: ‘./dist’,

代码能够分块,完成按需加载

    publicPath: './dist/',

    filename: "bundle.js"

},

module: {

    loaders: [

        { test: /\.css$/, loader: "style!css" }

    ]

}

首屏加载时间要尽量收缩

};

亟需集成一些第②方库

加载器配置

对于模块打包工具,单一的支撑 CommonJs
的打包在大型项目中是不够用的,为了满意一个大型项指标前端须要,那么3个打包工具应该包罗部分那个效应:

此处要求在output模块里面安装publicPath不然CSS背景图片等出口不寻常

支撑八个 bundler 输出 -> 解决代码分块难点

module: { //加载器配置 loaders: [ { test: /.css$/, loader:
‘style-loader!css-loader’ }, { test: /.js$/, loader:
‘jsx-loader?harmony’ }, { test: /.scss$/, loader:
‘style!css!sass?sourceMap’}, { test: /.(png|jpg)$/, loader:
‘url-loader?limit=8192’} ] },

异步加载 -> 按需加载,优化首屏加载时间

entry: {
page1: “./page1”,//单个文件形式援助数组格局,将加载数组中的全体模块,但以最后二个模块作为出口
page2: [“./entry1”, “./entry2”]
},//数组格局 借使利用上边你的写法 不能够用上边包车型地铁那种
output: {
path: “dist/js/page”,
filename: “[name].bundle.js”
}

可定制化 -> 能够融合为一第2方库,能够定制化打包过程

*爆出模块使用案例

任何能源也得以定义为模块

var index={//那是添加content.js
main:function(){
var html=”1111111″;
return html;
}
}
module.exports=index;

webpack 的面世正式为理解决那些题材,在 webpack 中,提供了一晃那一个效应:

//那是在另一个文件
var index=require(“./content.js”); // 添加content.js

代码分块: webpack
有三种档次的模块注重,一种是同台的,一种是异步的。在包装的长河中得以将代码输出为代码块(chunk),代码块能够完成按需加载。
异步加载的代码块通过分割点(spliting point)来显明。

document.getElementById(“box”).innerHTML=index.main();

Loaders: Webpack 本人只会处理
Javascript,为了落到实处将其余能源也定义为模块,并转账为 Javascript,
Webpack 定义 loaders , 区别的 loader 能够将相应的能源转化为 Javascript
模块。

*npm install –save 与 npm install –save-dev 的区别

智能的模块解析: webpack
能够很简单将第2方库转化为模块集成到项目代码中,模块的借助能够用表明式的方法(那在任何包裹工具中是尚未辅助的),那种模块正视叫做动态模块依赖。

二个位于package.json 的dependencies , 四个坐落devDependencies里面

插件系统: webpack
的可定制化在于其插件系统,其本身的洋洋成效也是通过插件的办法贯彻,插件系统形成了
webpack 的生态,是的能够动用过多开源的第1方插件。

扩展:

webpack 核心理想

在package.json 设置它的scripts npm run build===webpack(那里是运作打包)

webpack 的多少个主导:

{ “scripts”: { “build”: “webpack”, “dev”: “webpack-dev-server –devtool
eval –progress –colors –hot –content-base build” }}

万物皆模块:在 webpack 的世界中,除了
Javascript,其余任何能源都足以看成模块的法门引用

webpack-dev-server 自动监听(此时还不可能自行刷新浏览器)ctrl+C退出服务

按需加载: webapp
的优化关键在于代码体量,当使用体量增大,完成代码的按需加载是刚需,那也是
webpack 现身的根本原因

npm i webpack-dev-server –save
npm run dev
在http://localhost:8080监听文件修改
“dev”: “webpack-dev-server –devtool eval –progress –colors –hot
–content-base build”

可定制化:
任何2个工具都不容许消除全体标题,提供化解方案才是最可行的,webpack
基于可定制化的看法塑造,通过插件系统,配置文件,能够兑现大型项目标定制必要。

webpack-dev-server

2.2.2 安装配备

  • 在 localhost:8080 建立三个 Web 服务器
    –devtool eval
  • 为你的代码成立源地址。当有其它报错的时候能够让你尤其规范地稳定到文件和行号
    –progress
  • 体现合并代码进程
    –colors
  • Yay,命令行中展现颜色!
    –content-base build
  • 针对设置的出口目录

第一步:Node.js

设若急需浏览器自动刷新你须要在配备中追加贰个入口点。
webpack.config.js
**entry: [ ‘webpack/hot/dev-server’,
‘webpack-dev-server/client?http://localhost:8080’,
path.resolve(__dirname, ‘app/main.js’) ],

webpack 是 Node 实现,首先必要到 Node.js 下载安装最新版本的 Node.js

**

第二步:webpack-cli

Node.js 安装好今后,打开命令行终端,通过 npm 命令安装:

// -g 参数表示全局安装
$ npm install webpack -g
其三步:新建空前端项目

为了选择 webpack,先新建三个破天荒端项目,创立贰个索引,目录结构如下:

.
├── index.html // 入口 HTML
├── dist // dist 目录放置编写翻译过后的文本文件
└── src // src 目录放置源文件
└── index.js // 入口 js
其中 html 内容:

<!DOCTYPE html>
<html>
<head>
<meta charset=”UTF-8″>
<title>Hello React!</title>
</head>
<body>
<div id=”AppRoot”></div>
<script src=”dist/index.js”></script>
</body>
</html>
index.js 内容为:

alert(‘hello world webpack’);
第6步:在品种中设置 webpack

// 开端化 package.json, 依据提醒填写 package.json 的有关音讯
$ npm init

// 下载 webpack 依赖
// –save-dev 代表将借助添加到 package.json 中的 ‘devDependencies’
对象中
$ npm install webpack –save-dev

  • 第五步:Develop Server 工具 (可选)

dev server 能够完成1个依据 node + express 的前端 server

$ npm install webpack-dev-server –save-dev
2.2.3 webpack 使用

命令行调用

在事先创立的目录下实施:

$ webpack src/index.js dist/index.js
履行成功现在会并发如下信息:

Hash: 9a8e7e83864a07c0842f
Version: webpack 1.13.1
Time: 37ms
Asset Size Chunks Chunk Names
index.js 1.42 kB 0 [emitted] main
[0] ./src/index.js 29 bytes {0} [built]
能够查看 dist/index.js 的编写翻译结果:

/******/ (function(modules) { // webpackBootstrap
// ………. UMD 定义内容
/******/ })
/************************************************************************/
/******/ ([
/* 0 /
/
**/ function(module, exports) {
// index.js 的内容被打包进去
alert(‘hello world webpack’);

/***/ }
/******/ ]);
在浏览器中开辟 index.html :

配备文件

以命令执行的不二法门亟待填写不长的参数,所以 webpack
提供了经过安排的格局履行,在品种目录下创办 webpack.config.js 如下:

var webpack = require(‘webpack’)
module.exports = {
entry: ‘./src/index.js’,
output: {
path: ‘./dist/’,
filename: ‘index.js’
}
}
执行:

$ webpack
会和经过命令执行有同等的输出

2.2.4 webpack 配置

entry 和 output

webpack 的配备中关键的几个布局 key 是,entry 和 output。

{
entry: [String | Array | Object], // 入口模块
output: {
path: String, // 输出路径
filename: String // 输有名称或称谓 pattern
publicPath: String // 钦定静态能源的地点
… // 其余布置
}
}
单纯入口

假若唯有一个输入文件,能够有如下二种配备情势

// 第一种 String
{
entry: ‘./src/index.js’,
output: {
path: ‘./dist/’,
filename: ‘index.js’
}
}

// 第二种 Array
{
entry: [‘./src/index.js’],
output: {
path: ‘./dist/’,
filename: ‘index.js’
}
}

// 第三种 Object
{
entry: {
index: ‘./src/index.js’,
},
output: {
path: ‘./dist/’,
filename: ‘index.js’
}
}
两个入口文件

当存在四个入口时 ,能够行使 Array 的法门,比如借助第贰方库 bootstrap
,最后 bootstrap 会被追加到打包好的 index.js 中,数组中的最终一个会被
export。

{
entry: [‘./src/index.js’, ‘./vendor/bootstrap.min.js’],
output: {
path: ‘./dist’,
filename: “index.js”
}
}
最终的输出结果如:

/******/ ([
/* 0 /
/
**/ function(module, exports, webpack_require) {

__webpack_require__(1);

// export 最后一个
module.exports = __webpack_require__(2);

// },
/
1 /
/
/ function(module, exports) {

alert('hello world webpack');

// },
/
2 /
/
/ function(module, exports) {
// bootstrap 的内容被追加到模块中
console.log(‘bootstrap file’);

/***/ }
/******/ ])
几个包装目的

地点的事例中都以包装出贰个 index.js
文件,若是项目有多少个页面,那么须要打包出八个公文,webpack
能够用对象的方法陈设八个包裹文件

{
entry: {
index: ‘./src/index.js’,
a: ‘./src/a.js’
},
output: {
path: ‘./dist/’,
filename: ‘[name].js’
}
}
终极会卷入出:

.
├── a.js
└── index.js
文件名称 pattern

[name] entry 对应的名称

[hash] webpack 命令执行结果呈现的 Hash 值

[chunkhash] chunk 的 hash

为了让编写翻译的结果名称是唯一的,可以利用 hash 。

2.2.5 webpack 支持 Jsx

到现在大家曾经得以动用 webpack 来打包基于 CommonJs 的 Javascript
模块了,但是还没办法解析 JSX 语法和 Es6 语法。上边大家将动用 Babel 让
webpack 能够分析 Es6 和 Babel

先是步:npm install 重视模块

// babel 相关的模块
$ npm install babel-loader babel-preset-es2015 babel-preset-stage-0
babel-preset-react babel-polyfill –save-dev

// react 相关的模块
$ npm install react react-dom –save
第二步:webpack.config.js 中添加 babel loader 配置

{
entry: {
index: ‘./src/index.js’,
a: ‘./src/a.js’
},
output: {
path: ‘./dist/’,
filename: ‘[name].js’
},
module: {
loaders: [{
test: /.js$/,
exclude: /node_modules/,
loader: ‘babel’,
query: {
presets: [‘es2015’, ‘stage-0’, ‘react’]
}
}]
}
}
第三步: 修改 index.js 为 React 的语法

src/index.js 内容改为:

Es6 的学问在后面包车型客车章节中等教育授,最近大家一时以 Es5
的形式来写,可是配置已经支撑了 Es6 的编写翻译,熟谙 Es6 的读者也得以直接写
Es6

// 通过 require 的主意依赖 React,ReactDOM
var React = require(‘react’);
var ReactDOM = require(‘react-dom’);

var Hello = React.createClass({
render: function render() {
return <div>Hello {this.props.name}</div>;
}
});

ReactDOM.render(
<Hello name=”World” />,
document.getElementById(‘AppRoot’)
);
第四步:运行 webpack

$ webpack
实施结果:

Hash: ae2a037c191c18195b6a
Version: webpack 1.13.1
Time: 1016ms
Asset Size Chunks Chunk Names
a.js 1.42 kB 0 [emitted] a
index.js 700 kB 1 [emitted] index

  • 169 hidden modules
    浏览器中打开 index.html 会呈现 Hello World

2.2.6 webpack loaders

在配置 JSX 的进度中,使用到了 loader, 前边已经介绍过 webpack
的为主职能包罗 loader,通过 loader 能够将随机财富转化为 javascript
模块。

loader 定义

Loaders are transformations that are applied on a resource file of your
app.
(Loaders 是采取中源码文件的编写翻译转换器)

也等于说在 webpack 中,通过 loader 能够完成 JSX 、Es六 、CoffeeScript
等的变换

loader 功能
loader 管道:在一如既往种档次的源文件上,能够而且举办八个 loader , loader
的实践措施得以接近管道的措施,管道进行的措施是从右到左的艺术loader
能够支撑同步和异步
loader 能够接收安顿参数

loader 能够透过正则表明式也许文件后缀内定特定项指标源文件

插件能够提需求 loader 更加多效益

loader 除了做文件转换以外,仍是能够创制额外的文件

loader 配置

增加产量 loader 能够在 webpack.config.js 的 module.loaders 数组中新增二个loader 配置。

1个 loader 的布局为:

{
// 通过扩大名称和正则表明式来配独能源文件
test: String ,
// 匹配到的财富会应用 loader, loader 能够为 string 也得以为数组
loader: String | Array
}
感慨号和数组能够定义 loader 管道:

{
module: {
loaders: [
{ test: /.jade$/, loader: “jade” },
// => .jade 文件应用 “jade” loader

        { test: /\.css$/, loader: "style!css" },
        { test: /\.css$/, loaders: ["style", "css"] },
        // => .css 文件应用  "style" 和 "css" loader  
    ]
}

}
loader 能够配备参数

{
module: {
loaders: [
// => url-loader 配置 mimetype=image/png 参数
{
test: /.png$/,
loader: “url-loader?mimetype=image/png”
}, {
test: /.png$/,
loader: “url-loader”,
query: { mimetype: “image/png” }
}

    ]
}

}
使用 loader

第一步: 安装

loader 和 webpack 一样都以 Node.js 完毕,发表到 npm 个中,需求采取loader 的时候,只须求

$ npm install xx-loader –save-dev

// eg css loader
$ npm install css-loader style-loader –save-dev
第③步:修改配置

{
entry: {
index: ‘./src/index.js’,
a: ‘./src/a.js’
},
output: {
path: ‘./dist/’,
filename: ‘[name].js’
},
module: {
loaders: [{
test: /.js$/,
exclude: /node_modules/,
loader: ‘babel’,
query: {
presets: [‘es2015’, ‘stage-0’, ‘react’]
}
}, {
test: /.css$/,
loader: “style-loader!css-loader”
}]
}
}
第三步:使用

前边大家早就采纳过 jsx loader 了, loader 的选择格局有各个

在配备文件中配置

展现的通过 require 调用

指令行调用

展现的调用 require 会扩充模块的耦合度,应尽量防止这种艺术

以 css-loader 为例子,在类型 src 上边创造叁个 css

src/style.css

body {
background: red;
color: white;
}
修改 webpack 配置 entry 添加

entry: {
index: [‘./src/index.js’, ‘./src/style.css’]
}
施行 webpack 命令然后打开 index.html 会看到页面背景被改为深灰蓝。

最终的编写翻译结果为:

….
function(module, exports, webpack_require) {
exports = module.exports = webpack_require(171)();
exports.push([module.id, “\nbody {\n background: red;\n color:
white;\n}\n”, “”]);
}
….
能够看看 css 被转载为了 javascript, 在页面中不用调用 <link
rel=”stylesheet” href=””> 的主意, 而是使用 inline
的<style>…..</style>

其余一种格局是一向 require, 修改 src/index.js:

var css = require(“css!./style.css”);
编写翻译结果同样。

2.2.7 webpack 开发条件与生产条件

前端开发环境一般分为两种,开发条件和扭转环境,在支付条件中,大概大家须求日志输出,sourcemap
,错误报告等效果,在阪上走丸环境中,需求做代码压缩,hash
值生成。三种环境在其他的一些布局上也大概不一致。

据此为了分化,大家能够创设四个文本:

webpack.config.js // 开发条件

webpack.config.prod.js // 生产条件

生产条件 build 用如下命令:

$ webpack –config webpack.config.prod.js
在本章深入 webpack 小节中会更加多的介绍生产环境中的优化

2.2.8 webpack 插件

webpack 提供插件机制,能够对每回 build 的结果开始展览处理。配置 plugin
的方法为在 webpack.config.js 中拉长:

{
plugins: [
new BellOnBundlerErrorPlugin()
]
}
plugin 也是1个 npm 模块,安装三个 plugin :

$ npm install bell-on-bundler-error-plugin –save-dev
2.2.9 webpack 分割 vendor 代码和利用工作代码

在上头的 jsx 配置中,大家将 React 和 ReactDOM
一起打包进了项目代码。为了促成业务代码和第叁方代码的分手,大家能够应用
CommonsChunkPlugin 插件.

修改 webpack.config.js

{
entry: {
index: ‘./src/index.js’,
a: ‘./src/a.js’,
// 第③方包
vendor: [
‘react’,
‘react-dom’
]
},
output: {
path: ‘./dist/’,
filename: ‘[name].js’
},
module: {
loaders: [{
test: /.js$/,
exclude: /node_modules/,
loader: ‘babel’,
query: {
presets: [‘es2015’, ‘stage-0’, ‘react’]
}
}, {
test: /.css$/,
loader: “style-loader!css-loader”
}]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin(/* chunkName= /”vendor”, /
filename= */”vendor.bundle.js”)
]
}
执行 webpack 命令,输出日志:

Hash: f1256dc00b9d4bde8f7f
Version: webpack 1.13.1
Time: 1459ms
Asset Size Chunks Chunk Names
a.js 109 bytes 0 [emitted] a
index.js 10.9 kB 1 [emitted] index
vendor.bundle.js 702 kB 2 [emitted] vendor
[0] multi vendor 40 bytes {2} [built]
[0] multi index 40 bytes {1} [built]

  • 173 hidden modules
    index.js 容积变小了,多出了 vendor.bundle.js

2.2.10 webpack develop server

在前端开发的经过中,平常必要运行一个服务器,把开发打包好的前端代码放在服务器上,通过访问服务器访问并测试(因为可以稍微情形要求ajax 请求)。 webpack 提供了2个基于 node.js Express 的服务器 –
webpack-dev-server
来增派我们简化服务器的搭建,并提供服务器财富访问的有的简单易行布署。

安装 webpack-dev-server

$ npm install webpack-dev-server -g
启动 webpack-dev-server

$ webpack-dev-server –content-base ./
–content-base ./ 参数表示将当前目录作为 server 根目录。
命令运营过后,会在 8080 端口运转二个 http
服务,通过拜访http://localhost:8080/index.html
能够访问 index.html 内容。

只要访问提醒报错:

Uncaught ReferenceError: webpackJsonp is not defined
由来是 html 中尚无引用 vendor.bundle.js, 修改 html :

<script src=”dist/vendor.bundle.js”></script>
<script src=”dist/index.js”></script>
修改 index.html 过后可以见到科学结果

皇家赌场手机版,代码监察和控制

webpack-dev-server 除了提供 server 服务以外,
还会监察和控制源文件的修改,若是源文件改变了,会调用 webpack 重新包装

修改 style.css 中的内容为:

body {
background: whitesmoke;
color: #333;
font-size: 100px;
}
能够见到输出以下日志:

[168] ./~/react/lib/renderSubtreeIntoContainer.js 466 bytes {2}
[built]
webpack: bundle is now VALID.
webpack: bundle is now INVALID.
Hash: cc7d7720b1a0fcbef972
Version: webpack 1.13.0
Time: 76ms
chunk {0} a.js (a) 32 bytes {2}

  • 1 hidden modules
    chunk {1} index.js (index) 10.3 kB {2}
    [170] ./~/css-loader!./src/style.css 230 bytes {1} [built]
  • 5 hidden modules
    chunk {2} vendor.bundle.js (vendor) 665 kB
  • 168 hidden modules
    webpack: bundle is now VALID.
    那些时候证实代码已经修改了,但是那些时候刷新浏览器过后,背景是不曾改观的,原因是
    webpack-dev-server 的打包结果是位于内部存款和储蓄器的,查看 dist/index.js
    的剧情实在是尚未变动的,那如何访问内部存款和储蓄器中的打包内容呢?

修改 webpack.config.js 的 output.publicPath:

output: {
path: ‘./dist/’,
filename: ‘[name].js’,
publicPath: ‘/dist’
// webpack-dev-server 运行目录是 /, /dist
目录是包装的目的目录相对于运维目录的路子
},
双重启航

$ ctrl + c 结束进度
$ webpack-dev-server
修改 style.css 再刷新页面,修改的内容会呈现出去。

活动刷新

地点的配备已经能到位自动监察和控制代码,每一回修改完代码,刷新浏览器就足以看出最新结果,可是webpack-dev-server 还提供了机关刷新成效,有二种形式。

Iframe 模式

修改访问的门径:
http://localhost:8080/index.html
->
http://localhost:8080/webpack-dev-server/index.html
。那几个时候每便修改代码,打包完结以往都会活动刷新页面。

不供给万分布置,只用修改路径

运用被置于了一个 iframe 内部,页面顶部能够显得打包进程消息

因为 iframe 的关联,借使选拔有四个页面,不大概看出眼下利用的 url 消息

inline 模式

开发银行 webpack-dev-server 的时候添加 –inline 参数

急需添加 –inline 配置参数

从未顶部音讯提示条,提醒音讯在控制埃德蒙顿突显

热加载 (hot module replacement)

webpack-dev-server
还提供了模块热加载的艺术,在不刷新浏览器的标准下,应用新型的代码更新,运维webpack-dev-server 的时候添加 –inline –hot 参数就能够感受。

$ webpack-dev-server –inline –hot
修改代码在浏览器控制西安会看到如此的日志输出:

[HMR] Waiting for update signal from WDS…
vendor.bundle.js:670 [WDS] Hot Module Replacement enabled.
2vendor.bundle.js:673 [WDS] App updated. Recompiling…
vendor.bundle.js:738 [WDS] App hot update…
vendor.bundle.js:8152 [HMR] Checking for updates on the server…
vendor.bundle.js:8186 [HMR] Updated modules:
vendor.bundle.js:8188 [HMR] – 245
vendor.bundle.js:8138 [HMR] App is up to date.
在 webpack.config.js 中配置 webpack develop server

修改 webpack.config.js 添加:

plugins: [
new webpack.optimize.CommonsChunkPlugin(
/* chunkName= /”vendor”,
/
filename= */”vendor.bundle.js”, Infinity),
// 须要手动添加 HotModuleReplacementPlugin , 命令行的艺术会活动抬高
new webpack.HotModuleReplacementPlugin()
],
devServer: {
hot: true,
inline: true
}
不加参数直接实施 webpack-dev-server

$ webpack-dev-server
webpack-dev-server 还提供了别的的部分效率, 如:

配置 proxy

访问 node.js API

和水保的 node 服务集成

依照这么些功能能够完结广大自定义的配备。

Leave a Comment.