WebPack系列教程(二):动机
2016-03-09 08:55
375 查看
当今的网站已经发展为web app:
越来越多的js脚本放入页面;
在现代浏览器中,我们能做越来越的事情;
如今很少有网站会采用整页面重载,因而页面的代码越来越多;
最终导致大量的代码放入客户端中了。
庞大的前端代码库需要重新组织。模块系统提供了这样的能力来帮助你拆分代码库到各个模块中。
目录
Module system styles
CommonJs: (同步加载)
AMD: (异步加载)
ES6 模块系统
公正的解决方案
传输
分块传输
为什么仅仅是Javascript
静态分析
策略
CommonJs: (同步加载)
AMD: (异步加载)
ES6 模块系统
更多…
下面是未使用模块系统来加载使用已经模块化了的代码库
这种方式会把加载的模块对象添加到全局对象上,如window对象。模块能通过window对象访问到其所依赖的各模块对象。
存在的问题
全局对象命名冲突;
加载顺序非常重要;
开发人员不得不解决模块/库之间的依赖;
在大型项目中,如此多的引入脚本是相当费时和难以维护的;
这种方式使用同步require方法加载依赖并返回对外的接口。一个模块能通过给exports对象添加属性或者给module.exports设置值来指定开放哪些接口。
CommonJs多用于服务端NodeJs
支持者
服务端模块能复用;
npm中已经有很多模块使用该方式;
非常简单和容易使用;
反对者
阻塞式的加载不适用于网络环境,网络请求通常都是异步的;
无法并行请求多个模块;
基于该方式实现的库
node.js - server-side
browserify
modules-webmake - compile to one bundle
wreq - client-side
对于浏览器端的模块系统使用同步加载的方式会存在问题,因而引入了异步加载的方式。
支持者
适合网络环境的异步请求方式;
多模块的并行加载;
反对者
编码开销:更难以读和编写;
看起来像某种变通方案;
基于该方式实现的库
require.js - client-side
curl - client-side
阅读更多关于CommonJs and AMD.
支持者
静态分析很容易;
成为ES标准:不会过时;
反对者
本地浏览器支持尚需时日;
使用这种方式的模块太少;
有两种传输模块的极端方式:
一个请求一个模块;
一个请求所有模块;
两种方式都使用很广,但都不是最佳方案:
一个请求一个模块;
支持者:只传输必须加载的模块;
反对者:很多的请求意味着更多的开销;
反对者:因为延迟加载,导致应用程序启动变慢;
一个请求所有模块;
支持者:更少的请求开销,更少的延迟;
反对者:会加载不需要(多余)的模块;
当编译所有模块时:可以将多个模块组成模块集分别放入多个更小的打包分块的文件中。
我们会得到大量更小的请求。大模块集不会在初始化时就加载,只有当需要时才会去加载它们。初次加载不会请求项目所有的代码库。
代码分割的“拆分点 ”取决于开发者,并且是可选的。
编写大代码库成为可能。
注:该思想来源于Google’s GWT
阅读更多关于代码拆分
样式表
图片
网络字体
html模板
等等…
同时还有:
coffeescript → javascript
elm → javascript
less/sass stylesheets→ css stylesheets
jade templates → javascript which generates html
i18n files → something
等等…
这些都应该同样可以简单使用:
阅读更多关于Using Loaders和Loaders
通常静态分析只能通过简单没有表达式的字符串进行查找,但是像
很多库使用不同的风格,有些事非常怪异的…
越来越多的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 Loaders和Loaders
静态分析
当编译所有模块时,静态分析试图查找所有的依赖。通常静态分析只能通过简单没有表达式的字符串进行查找,但是像
require("./template/" + templateName + ".jade")是一种很常见的结构。
很多库使用不同的风格,有些事非常怪异的…
策略
一个聪明的解析器需要能够保证大量已经存在的代码可以运行。如果开发人员使用了一些怪异的方式编写,解析器要能找到最兼容的解决方案。相关文章推荐
- WebPack系列教程(一):目录
- webpack使用笔记
- Webpack your bags(中文翻译)
- Webpack 学习笔记
- webpack初识!
- 一小时包教会 —— webpack 入门指南
- Webpack 新手入门
- Karma 4 - Karma 集成 Webpack 进行单元测试
- webpack备忘录
- webpack的问题;
- Webpack的安装、配置与执行
- webpack
- webpack入门(七) API in LOADERS
- 基于webpack的模块化构建
- webpack入门(六) API in modules
- webpack入门(五)webpack CLI
- webpack入门(四)webpack的api 2 module
- Webpack
- webpack 发布配置
- webpack入门(三)webpack的api