您的位置:首页 > Web前端 > Webpack

WebPack系列教程(二):动机

2016-03-09 08:55 375 查看
当今的网站已经发展为web app:

越来越多的js脚本放入页面;

在现代浏览器中,我们能做越来越的事情;

如今很少有网站会采用整页面重载,因而页面的代码越来越多;

最终导致大量的代码放入客户端中了。

庞大的前端代码库需要重新组织。模块系统提供了这样的能力来帮助你拆分代码库到各个模块中。

目录

Module system styles

<script>
标签(无模块化)

CommonJs: (同步加载)

AMD: (异步加载)

ES6 模块系统

公正的解决方案

传输

分块传输

为什么仅仅是Javascript

静态分析

策略

Module system styles

如今有很多标准来定义依赖(dependencies)和导出(export)的值:

<script>
标签(无模块化)

CommonJs: (同步加载)

AMD: (异步加载)

ES6 模块系统

更多…

<script>
标签(无模块化)

下面是未使用模块系统来加载使用已经模块化了的代码库

<script src="module1.js"></script>
<script src="module2.js"></script>
<script src="libraryA.js"></script>
<script src="module3.js"></script>


这种方式会把加载的模块对象添加到全局对象上,如window对象。模块能通过window对象访问到其所依赖的各模块对象。

存在的问题

全局对象命名冲突;

加载顺序非常重要;

开发人员不得不解决模块/库之间的依赖;

在大型项目中,如此多的引入脚本是相当费时和难以维护的;

这种方式使用同步require方法加载依赖并返回对外的接口。一个模块能通过给exports对象添加属性或者给module.exports设置值来指定开放哪些接口。

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


CommonJs多用于服务端NodeJs

支持者

服务端模块能复用;

npm中已经有很多模块使用该方式;

非常简单和容易使用;

反对者

阻塞式的加载不适用于网络环境,网络请求通常都是异步的;

无法并行请求多个模块;

基于该方式实现的库

node.js - server-side

browserify

modules-webmake - compile to one bundle

wreq - client-side

AMD: (异步加载)

异步模块定义Asynchronous Module Definition

对于浏览器端的模块系统使用同步加载的方式会存在问题,因而引入了异步加载的方式。

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


支持者

适合网络环境的异步请求方式;

多模块的并行加载;

反对者

编码开销:更难以读和编写;

看起来像某种变通方案;

基于该方式实现的库

require.js - client-side

curl - client-side

阅读更多关于CommonJs and AMD.

ES6模块系统

EcmaScript6添加了一些语言结构到javascript当中,使之形成了另一套模块系统。

import "jquery";
export function doStuff() {}
module "localModule" {}


支持者

静态分析很容易;

成为ES标准:不会过时;

反对者

本地浏览器支持尚需时日;

使用这种方式的模块太少;

公正的解决方案

允许开发者自己选择使用哪种模块系统;兼容现有的代码;添加自定义模块更加容易;

传输

模块代码需要在客户端执行,因此它们必须要从服务端传输到浏览器中。

有两种传输模块的极端方式:

一个请求一个模块;

一个请求所有模块;

两种方式都使用很广,但都不是最佳方案:

一个请求一个模块;

支持者:只传输必须加载的模块;

反对者:很多的请求意味着更多的开销;

反对者:因为延迟加载,导致应用程序启动变慢;

一个请求所有模块;

支持者:更少的请求开销,更少的延迟;

反对者:会加载不需要(多余)的模块;

分块传输

一种更灵活的传输方式可能会更好。在很多案例中对于上述两种极端情形进行折中会更合适。

当编译所有模块时:可以将多个模块组成模块集分别放入多个更小的打包分块的文件中。

我们会得到大量更小的请求。大模块集不会在初始化时就加载,只有当需要时才会去加载它们。初次加载不会请求项目所有的代码库。

代码分割的“拆分点 ”取决于开发者,并且是可选的。

编写大代码库成为可能。

注:该思想来源于Google’s GWT

阅读更多关于代码拆分

为什么仅仅是Javascript

为什么一个模块系统只能帮助开发者处理Javascript。要知道前端代码中存在很多需要被处理的其他静态资源:

样式表

图片

网络字体

html模板

等等…

同时还有:

coffeescript → javascript

elm → javascript

less/sass stylesheets→ css stylesheets

jade templates → javascript which generates html

i18n files → something

等等…

这些都应该同样可以简单使用:

require("./style.css");


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


阅读更多关于Using LoadersLoaders

静态分析

当编译所有模块时,静态分析试图查找所有的依赖。

通常静态分析只能通过简单没有表达式的字符串进行查找,但是像
require("./template/" + templateName + ".jade")
是一种很常见的结构。

很多库使用不同的风格,有些事非常怪异的…

策略

一个聪明的解析器需要能够保证大量已经存在的代码可以运行。如果开发人员使用了一些怪异的方式编写,解析器要能找到最兼容的解决方案。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: