本文主要说明的是这两款构建工具(coolie 和 webpack),是分别如何完成模块化构建的,以及它们之间的优缺点。

预备

首先准备以下文件和目录,基本是承接上文的。

- demo
|-- src
|   |-- body.png
|   |-- entry1.js
|   |-- entry2.js
|   |-- module1.js
|   |-- module2.js
|   |-- single1.css
|   `-- single2.css
|-- coolie.json
|-- index.html
`-- weboack.config.js

entry1.js 的内容为:

define(function(require){require('./module.js');require('./single1.css');require('./single2.css');
});

引用关系为

entry1.js => module1.js + single1.css + ( single2.css => body.png )

entry2.js 的内容为:

define(function(require){require('./module.js');require('./single1.css');
});

引用关系为,惟独缺少了 single2.css

entry1.js => module1.js + single1.css

其他文件内容都在前文说到。

webpack

webpack.config.js

修改 webpack.config.js 为(可能作者对 webpack 的使用和配置可能不当,若有错误欢迎指正):

var path = require("path");module.exports = {entry: {entry1: './src/entry1.js',entry2: './src/entry2.js'},output: {path: path.join(__dirname, '../out'), filename: '[name].js'},module: {loaders: [{ test: /\.css$/, loader: "style!css" }]}
};

loader 插件

需要先安装以下两个插件:

npm i -SD style-loader css-loader

构建

然后再执行:

➜  webpack
Hash: 55a90533e92c37e40c33
Version: webpack 1.9.11
Time: 441msAsset     Size  Chunks             Chunk Names
entry1.js  13.7 kB       0  [emitted]  entry1
entry2.js  13.5 kB       1  [emitted]  entry2[0] ./src/entry1.js 131 bytes {0} [built][0] ./src/entry2.js 94 bytes {1} [built][1] ./src/module.js 49 bytes {0} {1} [built][2] ./src ^\.\/.*$ 360 bytes {0} {1} [built] [5 warnings][3] ./src/body.png 0 bytes [built] [failed][4] ./src/single1.js 24 bytes {0} {1} [optional] [built][9] ./src/single2.js 24 bytes {0} {1} [optional] [built]+ 6 hidden modulesWARNING in ./src/entry2.js
Critical dependencies:
3:4-11 require function is used in a way in which dependencies cannot be statically extracted@ ./src/entry2.js 3:4-11WARNING in ./src/entry1.js
Critical dependencies:
3:4-11 require function is used in a way in which dependencies cannot be statically extracted
4:4-11 require function is used in a way in which dependencies cannot be statically extracted@ ./src/entry1.js 3:4-11 4:4-11WARNING in ./src ^\.\/.*$
Module not found: Error: a dependency to an entry point is not allowed@ ./src ^\.\/.*$WARNING in ./src ^\.\/.*$
Module not found: Error: a dependency to an entry point is not allowed@ ./src ^\.\/.*$WARNING in ./src ^\.\/.*$
Module not found: Error: a dependency to an entry point is not allowed@ ./src ^\.\/.*$WARNING in ./src ^\.\/.*$
Module not found: Error: a dependency to an entry point is not allowed@ ./src ^\.\/.*$WARNING in ./src/body.png
Module parse failed: /path/to/demo/src/body.png Line 1: Unexpected token ILLEGAL
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)@ ./src ^\.\/.*$

呵呵,无法正常处理 css 引用的图片。

结果

看下目标目录的 entry1.js

// 省略...// 注意点 1
var map = {"./module": 1,"./module.js": 1,"./single1": 4,"./single1.css": 5,"./single1.js": 4,"./single2": 9,"./single2.css": 10,"./single2.js": 9
};// 省略...// 注意点 2
if(!content.locals) {module.hot.accept("!!./../node_modules/css-loader/index.js!./single1.css", function() {var newContent = require("!!./../node_modules/css-loader/index.js!./single1.css");if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];update(newContent);});
}// 省略...

单从注意点 1 和 注意点 2 来看,就知道 webpack 构建的完全错误了。

coolie

修改的有点多,但值得,因为一旦配置完善,后续的配置都不会再变了。

coolie.json

{"js": {"src": ["./src/entry1.js", "./src/entry2.js"],"coolie-config.js": "./src/coolie-config.js","dest": "./src/"},"css": {"dest": "./src/","minify": {"compatibility": "ie7"}},"html": {"src": ["./*.html"],"minify": true},"resource": {"dest": "./src/","minify": true},"copy": [],"dest": {"dirname": "../dest/","host": ""}
}

相比较之前,主要修改了 JS 的配置,增加了srccoolie-config.js两个配置:
- src:需要构建的入口模块,通常我们将入口模块放在一个文件夹内,使用通配符即可。
- coolie-config.js:模块加载器的配置文件。

coolie.js

在 src 目录下新增 coolie.min.js,使用

coolie pull

下载即可。

➜  src  coolie pull╔═══════════════════════════════════════════════════════╗║          coolie.cli@0.20.11                           ║║          The front-end development builder.           ║╚═══════════════════════════════════════════════════════╝pull coolie.min.js => https://raw.githubusercontent.com/cloudcome/coolie/master/coolie.min.jspull coolie.min.js => /path/to/demo/src/coolie.min.js

coolie-config.js

在 src 目录下新增 coolie-config.js(模块加载器的配置文件):

coolie.config({base: "./"
}).use();

html 修改

将 index.html 修改为:

<!DOCTYPE html><!-- coolie -->
<link rel="stylesheet" type="text/css" href="./src/single1.css">
<link rel="stylesheet" type="text/css" href="./src/single2.css">
<!-- /coolie --><!-- coolie -->
<script src="./src/single1.js"></script>
<script src="./src/single2.js"></script>
<!-- /coolie --><script coolie src="./src/coolie.min.js" data-config="./coolie-config.js" data-main="entry1.js"></script>

主要新增了一个模块加载器,并添加了:
- coolie属性:标志这个script属于 coolie 的管辖范围。
- data-config属性:标志了模块加载的配置文件路径,相对于src属性。
- data-main属性:标志了模块入口文件路径,相对于coolie-config.js里的base(而base是相对于coolie-config.js本身)。

关于路径关系,详细看这里。

entry

为了方便的引入 css 文件,需要修改 entry1.js 为:

define(function(require){require('./module.js');require('./single1.css', 'css');require('./single2.css', 'css');
});

修改 entry2.js 为:

define(function(require){require('./module.js');require('./single1.css', 'css');
});

require 添加第二个参数,是不是觉得奇怪?coolie 支持的 require 语法为:

require(path, [type]);
  • path:模块的路径,相对于当前模块。
  • type:模块的类型,默认为js模块,还支持htmlcsstextjsonimage一共 6 种模块。

这种语法定义的原因:

  • 路径关系可以在 webstorm 里按 cmd + 单击直达模块,而如果加入了css!这种前缀就不可以了。
  • 清晰的路径,可以直接在 webstorm 里拖动模块层级,而不必手动修改模块的路径。
  • 独立的 type 非常清晰的标识了模块的类型。

构建

在 demo 目录下执行:

➜  coolie build╔═══════════════════════════════════════════════════════╗║          coolie.cli@0.20.11                           ║║          The front-end development builder.           ║╚═══════════════════════════════════════════════════════╝1/5 => copy files2/5 => build main√  => /path/to/demo/src/entry1.js√  => /path/to/demo/src/entry2.js3/5 => overwrite config√  => base: "./"√  => version: "{"entry1.js": "0ba981967e8b2712d6da6114ae90675c","entry2.js": "1c9621d551021410aa19acb2ecac94dc"}"√  => callbacks: 0√  => /path/to/dest/src/coolie-config.c58dd5aa2dacebd9a86c92b49b66a6ba.js4/5 => build html css√  => /path/to/dest/src/bdd8e022ce7470f06d7183daabac0b79.css√  => /path/to/dest/src/6c762d4e4b7d1e9504281bc12abd65b9.js√  => /path/to/dest/src/coolie.min.js√  => /path/to/demo/*.html5/5 => generator relationship map√  => /path/to/dest/relationship-map.jsonbuild success => copy 1 file(s),build 2 main file(s),build 2 js file(s),build 1 html file(s),build 2 css file(s),build 1 resource file(s),past 157 ms

构建的过程非常的清晰,说下构建结果:

  • 复制了一个文件,就是coolie.min.js文件,即模块加载器。
  • 构建两个入口文件,即entry1.jsentry2.js
  • 构建了两个 JS 文件,即single1.jssingle2.js
  • 构建了一个 HTML 文件,即index.html
  • 构建了两个 CSS 文件,即single1.csssingle2.css
  • 构建了一个资源文件,即body.png

结果

看下目标目录

.dest
|-- src
|   |-- 6c762d4e4b7d1e9504281bc12abd65b9.js
|   |-- a821bd973bf1114e6ed1d9170b6e84eb.png
|   |-- bdd8e022ce7470f06d7183daabac0b79.css
|   |-- coolie-config.c58dd5aa2dacebd9a86c92b49b66a6ba.js
|   |-- coolie.min.js
|   |-- entry1.0ba981967e8b2712d6da6114ae90675c.js
|   `-- entry2.1c9621d551021410aa19acb2ecac94dc.js
|-- index.html
`-- relationship-map.json

来看下 entry1.js(为了便于阅读,已省略了 base64 编码):

/*coolie@0.20.11*/
define("0",["1","2","3"],function(n){n("1");n("2");n("3")});
define("1",[],function(){console.log("module")});
define("2",[],function(y,d,r){r.exports="html{margin:0;padding:0}"});
define("3",[],function(y,d,r){r.exports="body{background:url(data:image/png;base64...)}"});

来看下 entry2.js:

/*coolie@0.20.11*/
define("0",["1","2"],function(n){n("1");n("2")});
define("1",[],function(){console.log("module")});
define("2",[],function(y,d,r){r.exports="html{margin:0;padding:0}"});

看下 index.html(为了便于阅读已折行和注释处理):

<!DOCTYPE html>
<!--1-->
<link rel="stylesheet" href="/src/bdd8e022ce7470f06d7183daabac0b79.css">
<!--2-->
<script src="/src/6c762d4e4b7d1e9504281bc12abd65b9.js"></script>
<!--3-->
<script src="/src/coolie.min.js" data-config="./coolie-config.c58dd5aa2dacebd9a86c92b49b66a6ba.js" data-main="entry1.js"></script>
<!--coolie@0.20.11-->

非常的清晰明了:

  1. CSS 文件的合并、压缩、版本管理。
  2. JS 文件的合并、压缩、版本管理。
  3. 模块文件的构建。

最后看看relationship-map.json

{"index.html": {"css": {"src/bdd8e022ce7470f06d7183daabac0b79.css": ["src/single1.css","src/single2.css"]},"js": {"src/6c762d4e4b7d1e9504281bc12abd65b9.js": ["src/single1.js","src/single2.js"]},"main": "src/entry1.js","deps": ["src/module.js","src/single1.css","src/single2.css"]}
}

与前文相比,多了maindeps

  • main:入口模块。
  • deps:入口模块的依赖模块。

总结

在模块构建上:

webpack

  • 优点

    • 自由定制。
  • 缺点
    • 需要安装各种插件,无法基本满足通用化需求。
    • 和 gulp、grunt 是没有本质区别的,都是自己实现一个 runner,然后来跑各种插件。
    • 出现了构建错误,依赖分析错误。
    • 无法正常构建 css 和 css 里引用的图片文件。
    • 需要丰富经验才能驾驭配置。

coolie

  • 优点

    • 构建完全正确
    • 非常优秀的版本管理。
    • 模块路径进行了压缩,将原有的./module1.js这种路径压缩成了1这种单个字符,极大减少了文件体积。
    • 支持 html/css/text/image/json 模块构建(部分未在本文涉及到)。
    • 支持 html/css 里引用的静态资源构建(本文未涉及)。
  • 缺点
    • 需要搭配订制的模块加载器。
    • 部分写法有些特殊。

综合,coolie 显而易见的完全胜出,得满分 40 分,webpack 得 1 分。


原文:http://frontenddev.org/article/coolie-pk-webpack-3-module-build.html

coolie PK webpack 之三:模块构建相关推荐

  1. webpack组织模块的原理 - 基础篇

    现在前端用Webpack打包JS和其它文件已经是主流了,加上Node的流行,使得前端的工程方式和后端越来越像.所有的东西都模块化,最后统一编译.Webpack因为版本的不断更新以及各种各样纷繁复杂的配 ...

  2. webpack联邦模块之webpack运行时

    webpack是如何打包ES模块的?webpack是如何构建自身的模块运行时的? __webpack_require__ 这是整个webpack运行时的核心. 该函数被用于根据模块Id从变量__web ...

  3. React+Webpack+Eslint+Babel构建React脚手架

    React+webpack+Eslint+Babel构建React脚手架 参考网上文章,说的不是很全,想自己写一篇来巩固知识点,脚手架源码参考阮一峰老师的Github 所用技术栈 React Babe ...

  4. webpack 5 模块联邦实现微前端疑难问题解决

    webpack 5 模块联邦实现微前端疑难问题解决 说明 webpack 5 新增 Module Federation(模块联邦)功能,他可以帮助将多个独立的构建组成一个应用程序,不同的构建可以独立的 ...

  5. linux su 模块未知,模块构建失败:的ReferenceError:[BABEL]未知的选项:base.stage

    我升级我的反应使用ncu /的WebPack应用并将其更新至babelify 7.2.0(因此巴贝尔至6.0.0).现在,我收到以下错误:模块构建失败:的ReferenceError:[BABEL]未 ...

  6. 深入理解Webpack核心模块Tapable钩子[异步版]

    接上一篇文章 深入理解Webpack核心模块WTApable钩子(同步版) tapable中三个注册方法 1 tap(同步) 2 tapAsync(cb) 3 tapPromise(注册的是Promi ...

  7. angular 模块构建_我如何在Angular 4和Magento上构建人力资源门户

    angular 模块构建 Sometimes trying a new technology mashup works wonders. Both Magento 2 + Angular 4 are ...

  8. angular 模块构建_通过构建全栈应用程序学习Angular 6

    angular 模块构建 Angular 6 is out! The new features include better performance, new powerful CLI additio ...

  9. angular 模块构建_如何通过11个简单的步骤从头开始构建Angular 8应用

    angular 模块构建 Angular is one of the three most popular frameworks for front-end development, alongsid ...

  10. 3项目里面全局用less变量 cli vue_Vue实战14——抽离全局less变量与Vuex持久化、多模块构建...

    上文中说到了利用Element-ui优化了导航栏,本节介绍抽离公共的less变量与利用Element-Ui实现登录注册页面.本项目git地址: https://gitee.com/vuejslearn ...

最新文章

  1. 关于“托管代码”和“非托管代码”
  2. 关于iOS7以后版本号企业公布问题
  3. python 笔记 pickle json
  4. 如何从单个服务器扩展到百万用户的系统?
  5. 如何选择适合你的企业数据管理类产品
  6. 关于Istio 1.1,你所不知道的细节
  7. 低代码开发,未来已来
  8. 10条思科文件管理命令帮你做到称职网管
  9. python 实现数据化大屏_基于Python实现交互式数据可视化的工具(用于Web)
  10. 颜色模型与颜色应用---标准基色和色度图
  11. 各大搜索引擎站点提交入口大全
  12. 机器学习识别图片的基本原理
  13. 蓝牙HC05主从设置连接说明
  14. 官方老爹之痛:为什么苹果能收到推送,而安卓不行?
  15. 通过路由器访问光猫(openwrt)
  16. 图像处理的一些相关知识(Related knowledge for IQA)
  17. 安卓基础学习 Day19|安卓高级控件------下拉列表
  18. 高德地图——关键字检索POI
  19. Qt属性动画仿真QPropertyAnimation的使用
  20. php redis都可以做什么,redis除了缓存还能做什么

热门文章

  1. 实验三 网际协议IP 实验报告
  2. BMVC2020 Best Paper: Delving Deeper into Anti-aliasing in ConvNets论文解读
  3. N卡怎么修改录屏文件保存位置
  4. CCD相机参数基本知识
  5. 如何只用电脑登录微信
  6. java freemarker导出word时添加或勾选复选框
  7. 计算机网卡实现的功能,网卡实现的主要功能是什么
  8. 行人重识别实验笔记3-JDAI fast-reid项目配置
  9. 验证码图片不显示解决问题
  10. 卡方检验的统计量推导_卡方检验的卡方检验法的基本原理和步骤