致我们终将组件化的Web,webpack使用理解
分类:澳门新萄京最大平台

致大家必然组件化的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

支付须求严慎,生怕影响“进度线”前面平常逻辑。况且每回加插或涂改都以bug泛滥,无不令产品有关人士一律惶惶不安。

 页面结构模块化

依靠上边的面向进度的难点,行行业内部也可以有为数不菲建设方案,而大家团队也总括出一套成熟的缓和方案:Abstractjs,页面结构模块化。大家得以把大家的页面想象为三个乐高机器人,必要不一致零件组装,如下图,假如页面划分为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([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。当解析器发掘大家在文书档案中标志它将检查是不是多少个名字为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标准内容大致到此地,是的,笔者那边未有啥德姆o,也从不试行经验分享。由于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”不用再学二遍新框架的心潮澎湃澳门新萄京 7。无论怎么样下边包车型地铁原委不会让你失望的。

一,组件生命周期

澳门新萄京 8

React天生便是强制性组件化的,所以能够从根性格上消除面向进度代码所带动的辛勤。React组件自个儿有生命周期方法,能够满意“接口标准化”能力点。何况跟“页面结构模块化”的所封装抽离的多少个点子能挨个对应。其它react的jsx自带模板效率,把html页面片直接写在render方法内,组件内聚性越发严俊。

出于React编写的JSX是会先生成设想Dom的,供给时机才真正插入到Dom树。使用React必得求精晓组件的生命周期,其生命周期八个情状:

Mount: 插入Dom

Update: 更新Dom

Unmount: 拔出Dom

mount那单词翻译扩展,嵌入等。作者倒是提出“插入”更好掌握。插入!拔出!插入!拔出!默念二遍,懂了没?别少看黄段子的技能,

澳门新萄京 9

零件状态正是: 插入-> 更新 ->拔出。

接下来每一种组件状态会有三种管理函数,一前一后,will函数和did函数。

componentWillMount()  绸缪插入前

componentDidlMount()  插入后

componentWillUpdate() 筹划更新前

componentDidUpdate()  更新后

componentWillUnmount() 希图拔出前

因为拔出后为主都以贤者形态(作者说的是组件),所以并未有DidUnmount那个法子。

除此以外React别的一个为主:数据模型props和state,对应着也可能有自个状态方法

getInitialState()     获取初步化state。

getDefaultProps() 获取暗许props。对于那个未有父组件传递的props,通过该办法设置私下认可的props

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

再有三个优秀景况的管理函数,用于优化管理

shouldComponentUpdate():判别组件是或不是须求update调用

增添最重大的render方法,React自己带的不二等秘书籍刚刚好拾一个。对于初学者的话是相比较为难消食。但骨子里getInitialStatecomponentDidMountrender两个景况方法都能成功超过八分之四组件,不必惧怕。

回来组件化的核心。

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

澳门新萄京 10

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

澳门新萄京 11

 

组件的境况方法流中,有两点必要极其表明:

1,一回渲染:

是因为React的虚构Dom天性,组件的render函数不需和睦触发,依据props和state的更改自个通过差别算法,得出最优的渲染。

恳请CGI平时都以异步,所以自然带来三回渲染。只是空数据渲染的时候,有希望会被React优化掉。当数码回来,通过setState,触发一回render

 

2,componentWiillMount与componentDidMount的差别

和大大多React的科目作品差别等,ajax要求作者提议在WillMount的办法内实行,实际不是组件初阶化成功以往的DidMount。那样能在“空数据渲染”阶段此前必要数据,尽早地回降贰次渲染的年华。

willMount只会进行三遍,特别相符做init的职业。

didMount也只会实践三回,何况那时候真实的Dom已经变成,非常相符事件绑定和complete类的逻辑。

 

 二,JSX极难看,然而组件内聚的重要!

WebComponents的正式之一,要求模板能力。本是感到是大家耳濡目染的模板本领,但React中的JSX那样的怪物照旧令人商讨纷繁。React还尚未火起来的时候,大家就已经在搜狐上尖锐地嘲弄了“JSX写的代码这TM的丑”。那实际只是德姆o阶段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

“可相互结合”—— (四分之二)  可结合,但缺乏可行的加载格局

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

 

Webpack 资源组件化

对于组件化的财富独立性,日常的模块加载工具和创设流程视乎变得劳顿。组件化的创设筑工程程化,不再是事先大家广大的,css合二,js合三,而是体验在组件间的借助于加载关系。webpack正好合乎必要点,一方面填补组件化本事点,另一方帮助大家周到组件化的一体化创设情形。

首先要阐惠氏(Nutrilon)点是,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的布署,数组内二个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{rn position: relative;rn width: 100%;rn margin: 50px;rn background: #fff;rn}rnrn.slider-wrap li{rn text-align: center;rn line-height: 20px;rn}", ""]); /***/ }, /* 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{rn position: relative;rn width: 100%;rn margin: 50px;rn background: #fff;rn}rnrn.slider-wrap li{rn text-align: center;rn line-height: 20px;rn}", ""]);
 
/***/ },
/* 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模块化施行

很乐意,你能翻阅到此处。近来我们的机件完结度非常的高,财富内聚,易于组合,成效域独立互不污染。。。。等等澳门新萄京 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]要素插入到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,那纯属不是八个变量所能解决的”维护性“。

反倒项目实战进度中,真正要化解的是:在本子迭代进度中那多少个淘汰掉的晚点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,图片等作为模块来接纳和管理。
二、优势:1、以commonJS的花样来书写脚本,对英特尔、CMD的帮助也很周密,方便旧项目标动员搬迁。2、能被模块化的不断是JS了。3、能代表部分grunt/gulp的劳作,比方打包,压缩混淆,图片转base64等。3、扩大性强,插件机制周详,帮衬React热拔插(react-hot-loader)
三、安装和布局:
1、安装:直接动用npm来实行设置
$ npm install webpack -g
将凭仗写入package.json包
$ npm init
$ npm install webpack --save-dev
2、配置:
每一种品种必得配备三个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是插件项,这里运用了二个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(重若是体制这块一句就攻下一行脚本,导致未压缩脚本变得比不小)。
五、模块引进:
1、在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里。
2、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 介绍

Webpack 中文指南

Webpack是当下最畅销的前端财富模块化管理和打包工具。它能够将广大松懈的模块依照依赖和准则打包成契合生产遭逢安顿的前端财富。还足以将按需加载的模块实行代码分隔,等到实际要求的时候再异步加载。通过loader的调换,任何款式的能源都得以视作模块,比如CommonJs 模块、 英特尔 模块、 ES6 模块、CSS、图片、 JSON、Coffeescript、 LESS 等。

其他:
1、shimming :
在 英特尔/CMD 中,大家需求对不切合标准的模块(譬喻部分直接重临全局变量的插件)进行shim 管理,那时候我们须要动用 exports-loader 来提携:
{ test: require.resolve(“./src/js/tool/swipe.js”), loader: “exports?swipe”}
日后在剧本中供给征引该模块的时候,这么简单地来行使就能够了:
require(‘./tool/swipe.js’);
swipe();
2、自定义公共模块提取:
在篇章起始我们运用了 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
3、独立包装样式:
突发性或者希望项目标体裁能不用被打包到脚本中,而是独立出来作为.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 推行后会乖乖地把体制文件提抽取来:
4、使用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 是什么

现状

文本只可以依据的书写顺序进行加载

开拓职员必得主观消除模块和代码库的信任性关系

在大型项目中各类财富难以管理,短时间积存的难题形成代码库混乱不堪

CommonJS

劳务器端的 Node.js 遵从CommonJS规范,该标准的核心情想是允许模块通过require方法来共同加载所要依赖的其余模块,然后通过exports或module.exports来导出要求暴露的接口。

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

优点:

劳动器端模块便于重用

NPM中一度有接近20万个能够应用模块包

简单的说并轻易选取

缺点:

一齐的模块加载方式不合乎在浏览器遭遇中,同步意味着阻塞加载,浏览器财富是异步加载的

不可能非阻塞的互动加载多少个模块

npm install webpack --save-dev

干什么引进新的卷入工具

AMD

Asynchronous Module Definition标准其实唯有一个首要接口define(id?, dependencies?, factory),它要在宣称模块的时候内定全部的信任dependencies,并且还要作为形参传到factory中,对于依据的模块提前实行,信赖前置。

define("module", ["dep1","dep2"],function(d1, d2){returnsomeExportedValue;});require(["module","../file"],function(module, file){/* ... */});

优点:

切合在浏览器情形中异步加载模块

能够互相加载四个模块

缺点:

增长了开辟花费,代码的读书和书写相比较辛劳,模块定义情势的语义不顺手

不符合通用的模块化思维方法,是一种迁就的兑现

npm i webpack-dev-server --save

webpack 宗旨绪想

CMD

Common Module Definition正规和 英特尔 很相像,尽量保险轻易,并与 CommonJS 和 Node.js 的 Modules 规范保证了极大的宽容性。

define(function(require, exports, module){var$ =require('jquery');varSpinning =require('./spinning');  exports.doSomething = ...module.exports = ...})

优点:

依傍就近,延迟试行

可以很轻易在 Node.js 中运作

缺点:

信任 SPM 打包,模块的加载逻辑偏重

npm install react --save

webpack 安装

UMD

Universal Module Definition正式类似于兼容CommonJS 和 AMD 的语法糖,是模块定义的跨平台建设方案。

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

webpack 使用

ES6 模块

EcmaScript6 规范扩张了 JavaScript 语言层面包车型地铁模块种类定义。ES6 模块的统一希图思想,是尽也许的静态化,使得编写翻译时就能够明确模块的重视性关系,以及输入和输出的变量。CommonJS 和 速龙 模块,都只好在运作时规定那么些事物。

import"jquery";exportfunctiondoStuff(){}module"localModule"{}

优点:

轻松开展静态分析

面向现在的 EcmaScript 规范

缺点:

原生浏览器端还并未有落到实处该专门的学问

斩新的命令字,新版的 Node.js才支撑

npm i react-dom --save

命令行调用

意在的模块系统

能够包容多样模块风格,尽量能够动用已有个别代码,不独有只是 JavaScript 模块化,还应该有 CSS、图片、字体等能源也要求模块化。

前面一个模块加载

前端模块要在顾客端中推行,所以他们须求增量加载到浏览器中。

模块的加载和传导,大家率先能想到三种极端的情势,一种是每一个模块文件都独立央求,另一种是把全体模块打包成多个文书然后只央浼三遍。总之,每种模块都提倡单独的央浼变成了恳求次数过多,导致应用运营速度慢;三次呼吁加载全体模块导致流量浪费、伊始化进程慢。这三种办法都不是好的缓和方案,它们过于简单凶横。

分块传输,按需举办懒加载,在其实用到一点模块的时候再增量更新,才是较为合理的模块加载方案。

要达成模块的按需加载,就供给三个对全部代码库中的模块实行静态解析、编写翻译打包的历程。

具备财富都以模块

在上头的深入分析进度中,大家提到的模块仅仅是指JavaScript模块文件。然则,在前端开采进程中还提到到样式、图片、字体、HTML 模板等等众多的财富。这几个财富还恐怕会以各样方言的花样存在,比如coffeescript、 less、 sass、众多的模板库、多语言种类(i18n)等等。

一旦他们都足以看做模块,而且都能够透过require的措施来加载,将牵动高贵的开支体验,譬喻:

require("./style.css");require("./style.less");require("./template.jade");require("./image.png");

那么怎么着完毕让require能加载各个能源呢?

静态深入分析

在编译的时候,要对全数代码进行静态解析,分析出各种模块的类型和它们依赖关系,然后将差别档期的顺序的模块提交给适配的加载器来拍卖。举例二个用 LESS 写的样式模块,能够先用 LESS 加载器将它转成三个CSS 模块,在经过 CSS 模块把她插入到页面包车型客车价签中施行。Webpack 正是在如此的须要中冒出。

同临时间,为了能应用已经存在的各类框架、库和已经写好的文书,大家还索要一个模块加载的卓越计谋,来制止重写全体的模块。

*目录

布局文件

什么是 Webpack

Webpack 是四个模块打包器。它将依赖模块的注重性关系张开静态分析,然后将那几个模块遵照内定的平整变化对应的静态能源。

澳门新萄京 18

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

webpack 配置参数

何以重复造轮子

市道辰月经存在的模块管理和打包工具并不切合大型的类别,极其单页面 Web 应用程序。最迫不如待的缘故是怎样在三个广阔的代码库中,维护各样模块能源的剪切和寄放,维护它们之间的借助关系,况且无缝的将它们构成到一块生成相符浏览器端诉求加载的静态财富。

手动打包: webpack 源文件路线 打包路线(webpack ./entry.js ./bundle.js)//这里是一贯不配备webpack.config.js
$ webpack --watch //监听变动并自动打包 监视webpack.config.js 的转移$ webpack -p //压缩混淆脚本,这么些丰富可怜关键!

entry 和 output

那个已有的模块化工具并无法很好的成功如下的目的:

将借助树拆分成按需加载的块

开始化加载的耗费时间尽量少

各样静态财富都能够充任模块

将第三方库整合成模块的本事

能够自定义打包逻辑的本领

顺应大品种,无论是单页照旧多页的 Web 应用

*注意事项

单一入口

Webpack 的特点

Webpack 和其余模块化学工业具有哪些分别呢?

代码拆分

Webpack 有二种集人体模型块重视的章程,同步和异步。异步注重作为分割点,变成多少个新的块。在优化了信任树后,每一个异步区块都充任三个文本被包裹。

Loader

Webpack 自己只可以管理原生的 JavaScript 模块,可是 loader 转换器可以将各系列型的财富转变到 JavaScript 模块。那样,任何财富都得以变成 Webpack 能够拍卖的模块。

智能分析

Webpack 有三个智能深入分析器,差不离能够拍卖其余第三方库,无论它们的模块情势是 CommonJS、 英特尔 照旧普通的 JS 文件。乃至在加载依赖的时候,允许行使动态表明式require("./templates/" name ".jade")。

插件系统

Webpack 还也许有一个成效丰盛的插件系统。大非常多内容成效都以依照这么些插件系统运转的,还足以付出和行使开源的 Webpack 插件,来满足多姿多彩的急需。

迅猛运营

Webpack 使用异步 I/O 和多样缓存提升运转功用,那使得 Webpack 能够以令人出乎意料的快慢高速增量编译。

页面要引进打包后的路线的JS文件

多少个输入

安装

先是要设置Node.js, Node.js 自带了软件包处理器 npm,Webpack 须要 Node.js v0.6 以上帮衬,建议利用最新版 Node.js。

用 npm 安装 Webpack:

$ npm install webpack -g

那时 Webpack 已经设置到了大局情形下,能够通过命令行webpack -h试试。

常常大家会将 Webpack 安装到项指标借助中,那样就能够运用项目当地版本的 Webpack。

# 步向项目目录# 鲜明已经有 package.json,未有就经过 npm init 成立# 安装 webpack 依赖

$ npm install webpack --save-dev

Webpack 近来有七个主版本,三个是在 master 主干的牢固版,三个是在 webpack-2 分支的测验版,测验版具备一点实验性意义况且和牢固版不相配,在业内项目中应当利用稳固版。

# 查看 webpack 版本消息

$ npm info webpack

# 安装钦定版本的 webpack

$ npm install webpack@1.12.x --save-dev

如若要求利用 Webpack 开拓工具,要独立安装:

$ npm install webpack-dev-server --save-dev

*loader理解

七个包装目的

使用

首先成立二个静态页面 index.html 和贰个 JS 入口文件 entry.js:

// entry.js

document.write('It works.')

接下来编写翻译 entry.js 并打包到 bundle.js:

$ webpack entry.js bundle.js

打包进度会显得日志:

Hash: e964f90ec65eb2c29bb9

Version: webpack 1.12.2

Time: 54ms

Asset    Size  Chunks            Chunk Names

bundle.js  1.42 kB      0  [emitted]  main

[0] ./entry.js 27 bytes {0} [built]

用浏览器张开index.html将拜访到It works.。

接下去加多一个模块module.js并修改入口entry.js:

// module.js

module.exports ='It works from module.js.'

// entry.js

document.write('It works.')

document.write(require('./module.js'))// 加多模块

重新打包webpack entry.js bundle.js后刷新页面看见变化It works.It works from module.js.

Hash: 279c7601d5d08396e751

Version: webpack 1.12.2

Time: 63ms

Asset    Size  Chunks            Chunk Names

bundle.js  1.57 kB      0  [emitted]  main

[0] ./entry.js 66 bytes {0} [built]

[1] ./module.js 43 bytes {0} [built]

Webpack 会剖判入口文件,分析包括正视关系的逐个文件。那一个文件(模块)都打包到 bundle.js 。Webpack 会给种种模块分配多个独一的 id 并透过那几个 id 索引和做客模块。在页面运转时,会先施行 entry.js 中的代码,其余模块会在运维require的时候再推行。

是模块和能源的调换器,它本身是一个函数,接受源文件作为参数,重回转换的结果。这样,大家就能够通过 require 来加载任何项目标模块或文件,举例CoffeeScriptJSXLESS图片

webpack 支持 Jsx 和 Es6

Loader

Webpack 本人只好管理 JavaScript 模块,要是要管理任何品种的文件,就需求利用 loader 进行调换。

Loader 能够了然为是模块和能源的转换器,它自己是二个函数,接受源文件作为参数,重临转变的结果。那样,大家就能够经过require来加载任何项指标模块或文件,比如CoffeeScript、 JSX、 LESS 或图表。

先来看看 loader 有哪些特色?

Loader 能够经过管道格局链式调用,每种 loader 能够把财富转变来跋扈格式并传递给下三个 loader ,但是最后四个 loader 必需回到 JavaScript。

Loader 能够一并或异步推行。

Loader 运维在 node.js 碰到中,所以能够做别的恐怕的事情。

Loader 还可以参数,以此来传递配置项给 loader。

Loader 能够经过文件扩大名(或正则表明式)绑定给分裂类其他公文。

Loader 能够因此npm公布和装置。

除开通过package.json的main钦定,平日的模块也得以导出三个 loader 来利用。

Loader 能够访问安排。

插件能够让 loader 具有越多特点。

Loader 能够分发出附加的大肆文件。

Loader 本人也是运作在 node.js 遭遇中的 JavaScript 模块,它常常会回来三个函数。大许多情形下,大家透过 npm 来治本 loader,然而你也能够在类型中和睦写 loader 模块。

安分守己常规,而非必需,loader 日常以xxx-loader的格局命名,xxx代表了这几个loader 要做的转变职能,比如json-loader。

在援引 loader 的时候能够应用人名json-loader,也许使用短名json。这些命名规则和查找优先级依次在 webpack 的resolveLoader.moduleTemplatesapi 中定义。

Default: ["*-webpack-loader", "*-web-loader", "*-loader", "*"]

Loader 能够在require()援引模块的时候拉长,也得以在 webpack 全局配置中张开绑定,还足以透过命令行的不二等秘书籍选拔。

接上一节的例子,我们要在页面中引进二个 CSS 文件 style.css,首页将 style.css 也当做是三个模块,然后用css-loader来读取它,再用style-loader把它插入到页面中。

/* style.css */

body{background:yellow; }

修改 entry.js:

require("!style-loader!css-loader!./style.css")// 载入 style.css

document.write('It works.')

document.write(require('./module.js'))

安装 loader:

npm install css-loader style-loader

再也编译打包,刷新页面,就能够看看白色的页面背景了。

若是老是requireCSS 文件的时候都要写 loader 前缀,是一件很麻烦的职业。大家得以依靠模块类型(扩大名)来机关绑定须要的 loader。

将 entry.js 中的require("!style!css!./style.css")修改为require("./style.css"),然后实践:

$ webpack entry.js bundle.js --module-bind'css=style-loader!css-loader'# 有个别条件下只怕须要动用双引号$ webpack entry.js bundle.js --module-bind"css=style-loader!css-loader"

显而易见,这三种选取 loader 的方法,效果是一律的。

*爆出模块

webpack loaders

配备文件

Webpack 在试行的时候,除了在命令行传入参数,还足以由此点名的布局文件来实践。暗中认可景况下,会招来当前目录的webpack.config.js文件,这么些文件是一个node.js 模块,重回贰个 json 格式的安顿消息目的,或许通过--config选项来钦点布置文件。

接轨大家的案例,在根目录成立package.json来增加 webpack 特需的注重:

{

     "name":"webpack-example",

     "version":"1.0.0",

     "description":"A simple webpack example.",

    "main":"bundle.js",

     "scripts": {"test":"echo "Error: no test specified" && exit 1"},

     "keywords": ["webpack"],

     "author":"zhaoda",

     "license":"MIT",

     "devDependencies": {

           "css-loader":"^0.21.0",

           "style-loader":"^0.13.0",

           "webpack":"^1.12.2"

     }

}

# 若无写入权限,请尝试如下代码退换权限

chflags -R nouchg .

sudo chmod775package.json

别忘了运转npm install。

下一场成立七个配置文件webpack.config.js:

var webpack =require('webpack')

module.exports = { 

     entry:'./entry.js',  

     output: {   path: __dirname,    filename:'bundle.js'},

     module: {    loaders: [      {test:/.css$/, loader:'style-loader!css-loader'}    ]  }

}

何况简化entry.js中的style.css加载格局:

require('./style.css')

末段运转webpack,能够见见 webpack 通过配备文件实行的结果和上一章节通过命令行webpack entry.js bundle.js --module-bind 'css=style-loader!css-loader'施行的结果是同一的。

module.exports = "It works from content.js.";//nodejs中的揭示格局

loader 定义

插件

插件能够产生越来越多 loader 不能够成就的功力。

插件的选用相似是在 webpack 的配备音讯plugins选项中钦定。

Webpack 自己内置了某个常用的插件,还足以因此 npm 安装第三方插件。

接下去,大家使用三个最简便易行的BannerPlugin内置插件来举办插件的布署和平运动转,那几个插件的意义是给输出的文书底部增添注释新闻。

修改webpack.config.js,添加plugins:

var webpack =require('webpack')

module.exports = {  

     entry:'./entry.js',  

     output: {    path: __dirname,    filename:'bundle.js'},

     module: {    loaders: [      {test:/.css$/, loader:'style-loader!css-loader'}    ]  },  

     plugins: [newwebpack.BannerPlugin('This file is created by zhaoda')  ]

}

下一场运维webpack,展开bundle.js,能够看见文件尾部现身了小编们钦赐的批注音讯:

/*! This file is created by zhaoda *//******/(function(modules){// webpackBootstrap/******/// The module cache/******/varinstalledModules = {};// 前边代码省略

export default Girls;//ES6

loader 功能

支出情况

当项目日益变大,webpack 的编写翻译时间会变长,能够因而参数让编写翻译的出口内容包蕴进程和颜料。

$ webpack --progress --colors

若果不想每便修改模块后都再也编译,那么能够运转监听形式。开启监听形式后,没有转换的模块会在编写翻译后缓存到内部存款和储蓄器中,而不会每一趟都被重复编译,所以监听形式的欧洲经济共同体进程是全速的。

$ webpack --progress --colors --watch

本来,使用webpack-dev-server开拓服务是三个越来越好的选料。它就要localhost:8080 运营多少个 express 静态财富 web 服务器,何况会以监听格局自动运维webpack,在浏览器展开http://localhost:8080/或http://localhost:8080/webpack-dev-server/能够浏览项目中的页面和编译后的财富输出,并且经过一个socket.io 服务实时监听它们的生成并自动刷新页面。

# 安装

$ npm install webpack-dev-server -g

# 运行

$ webpack-dev-server --progress --colors

*引进模块

loader 配置

故障管理

Webpack 的布局比较复杂,很容出现错误,上边是局地惯常的故障处理花招。

诚如意况下,webpack 若是出标题,会打字与印刷一些差不离的错误音信,例如模块未有找到。我们还足以因此参数--display-error-details来打印错误详细情形。

$ webpack --display-error-details

Hash: a40fbc6d852c51fceadbVersion: webpack1.12.2Time:586ms    Asset    Size  Chunks            Chunk Namesbundle.js12.1kB0[emitted]  main  [0] ./entry.js153bytes {0} [built] [1error]  [5] ./module.js43bytes {0} [built]    4hidden modulesERRORin./entry.jsModule not found: Error: Cannot resolve'file'or'directory'./badpathmodulein/Users/zhaoda/data/projects/webpack-handbook/examplesresolve file  /Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule doesn't exist

/Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule.webpack.js doesn't exist  /Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule.js doesn't exist

/Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule.web.js doesn't exist  /Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule.json doesn't exist

resolve directory

/Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule doesn't exist (directory default file)  /Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule/package.json doesn't exist (directory description file)

[/Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule]

[/Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule.webpack.js]

[/Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule.js]

[/Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule.web.js]

[/Users/zhaoda/data/projects/webpack-handbook/examples/badpathmodule.json]

@ ./entry.js 3:0-26

Webpack 的陈设提供了resolve和resolveLoader参数来设置模块深入分析的拍卖细节,resolve用来布局应用层的模块(要被打包的模块)分析,resolveLoader用来安插loader模块的分析。

当引进通过 npm 安装的 node.js 模块时,可能出现找不到依据的失实。Node.js 模块的依附剖析算法非常粗大略,是经过翻看模块的每一层父目录中的node_modules文件夹来询问正视的。当出现Node.js 模块重视查找未果的时候,能够尝尝设置resolve.fallback和resolveLoader.fallback来化解难点。

module.exports = {  

             resolve: { fallback: path.join(__dirname,"node_modules") }, 

             resolveLoader: { fallback: path.join(__dirname,"node_modules") }

澳门新萄京,};

Webpack 中关系路线配置最棒应用相对路线,提出通过path.resolve(__dirname, "app/folder")或path.join(__dirname, "app", "folder")的措施来安顿,乃十分 Windows 境况。

import MyModule from './modules/MyModule.js';//es6

使用 loader

CommonJS 规范

CommonJS 是以在浏览器景况之外创设 JavaScript 生态系统为目的而发出的品种,举个例子在服务器和桌面情形中。

其一项目最早始是由 Mozilla 的程序猿 凯文 Dangoor 在二零零六年10月创办的,那时候的名字是 ServerJS。

笔者在此地描述的并非一个技能难题,而是一件首要的作业,让大家走到联合来做决定,迈出第一步,来确立三个更加大更酷的事物。 —— 凯文 Dangoor'sWhat Server Side JavaScript needs

二零零六年八月,这一个类型改名叫 CommonJS,以呈现其 API 的越来越宽广实用性。CommonJS 是一套规范,它的创办和把关是开放的。那些专门的学问已经有这么些版本和现实贯彻。CommonJS 实际不是属于 ECMAScript TC39 小组的行事,但 TC39 中的一些分子加入 CommonJS 的制订。2013年一月,Node.js 的包管理器 NPM 的撰稿人 Isaac Z. Schlueter 说CommonJS 已经不符合时机,Node.js 的木本开荒者现已甩掉了该专门的工作。

CommonJS 标准是为着化解 JavaScript 的成效域难点而定义的模块方式,能够使种种模块它自己的命名空间中实施。该职业的主要性内容是,模块必需经过module.exports导出对外的变量或接口,通过require()来导入其余模块的输出到当前模块效用域中。

八个直观的事例:

// moduleA.jsmodule.exports =function(value){returnvalue *2;}

// moduleB.jsvarmultiplyBy2 =require('./moduleA');varresult = multiplyBy2(4);

CommonJS 是联合加载模块,但实际也可以有浏览器端的达成,其规律是现将全数模块都定义好并经过id索引,那样就可以低价的在浏览器情况中剖判了,能够参见require1k和tiny-browser-require的源码来领会其剖析(resolve)的经过。

var MyModule = require('./MyModule.js');//commonjs

webpack 开采条件与生育遇到

AMD 规范

英特尔(异步模块定义)是为浏览器景况设计的,因为 CommonJS 模块系统是一只加载的,当前浏览器情状还不曾早为之所好同步加载模块的尺度。

英特尔 定义了一套 JavaScript 模块正视异步加载标准,来减轻协同加载的主题素材。

模块通过define函数定义在闭包中,格式如下:

define(id?:String, dependencies?:String[], factory:Function|Object);

id是模块的名字,它是可选的参数。

dependencies钦赐了所要依赖的模块列表,它是叁个数组,也是可选的参数,每种正视的模块的出口将用作参数叁回传入factory中。若无一点点名dependencies,那么它的默许值是["require", "exports", "module"]。

define(function(require, exports, module){})

factory是最终三个参数,它包裹了模块的现实贯彻,它是叁个函数或许目的。假诺是函数,那么它的重返值正是模块的出口接口或值。

有个别用例:

概念多个名叫myModule的模块,它正视jQuery模块:

define('myModule', ['jquery'],function($){// $ 是 jquery 模块的输出$('body').text('hello world');});// 使用define(['myModule'],function(myModule){});

专一:在 webpack 中,模块名独有部分功用域,在 Require.js 中模块名是全局成效域,能够在全局援引。

概念两个从未id值的匿超模块,平常作为利用的起步函数:

define(['jquery'],function($){    $('body').text('hello world');});

依傍几个模块的概念:

define(['jquery','./math.js'],function($, math){// $ 和 math 三遍传入 factory$('body').text('hello world');});

模块输出:

define(['jquery'],function($){varHelloWorldize =function(selector){       

 $(selector).text('hello world');    };// HelloWorldize 是该模块输出的对外接口returnHelloWorldize;});

在模块定义内部引用信任:

define(function(require){var$ =require('jquery');    $('body').text('hello world');});

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 的打包在大型项目中是远远不够用的,为了满足八个大型项指标前端要求,那么贰个装进工具应该包罗部分那些成效:

此处须要在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"
}

可定制化 -> 能够融为一体第三方库,能够定制化打包进度

*爆出模块使用案例

别的能源也足以定义为模块

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 能够很轻易将第三方库转化为模块集成到品种代码中,模块的正视性能够用表明式的不二法门(那在其余包裹工具中是从未匡助的),这种模块信任叫做动态模块重视。

两个位于package.json 的dependencies , 三个位于devDependencies里面

插件系统: webpack 的可定制化在于其插件系统,其自个儿的不在少数意义也是透过插件的格局完结,插件系统变成了 webpack 的生态,是的能够使用过多开源的第三方插件。

扩展:

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"

可定制化: 任何贰个工具都不容许消除全体标题,提供实施方案才是最可行的,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');
第四步:在档案的次序中设置 webpack

// 初步化 package.json, 依据提示填写 package.json 的相关音讯
$ npm init

// 下载 webpack 依赖
// --save-dev 代表将凭仗增加到 package.json 中的 'devDependencies' 对象中
$ npm install webpack --save-dev

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

dev server 能够完结二个依据 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 定义内容
/******/ })
/************************************************************************/
/******/ ([
/*致我们终将组件化的Web,webpack使用理解。 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 、Es6、CoffeeScript 等的转移

loader 功能
loader 管道:在同等种档案的次序的源文件上,能够同期实施多个 loader , loader 的施行措施得以周围管道的格局,管道实施的方法是从右到左的方法loader 能够协助同步和异步
loader 能够收起安插参数

loader 可以通过正则表明式大概文件后缀钦命特定项目标源文件

插件能够提要求 loader 越多效果与利益

loader 除了做文件转变以外,还是可以够创立额外的公文

loader 配置

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

三个 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  
    ]
}

}
致我们终将组件化的Web,webpack使用理解。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 也是二个 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 提供了二个基于 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 服务集成

基于那一个效用能够兑现无数自定义的配备。

本文由澳门新萄京发布于澳门新萄京最大平台,转载请注明出处:致我们终将组件化的Web,webpack使用理解

上一篇:微服务架构下的统一身份认证和授权,登录工程 下一篇:没有了
猜你喜欢
热门排行
精彩图文