1下载

使用 coolie demo 命令下载本 demo。

  1. coolie demo 9

2异步模块

异步模块与同步模块相反,指的是模块是在运行时才去异步加载然后再运行。

  1. setTimeout(function(){
  2. // 异步模块`async.js`在 1000ms 后加载,然后再运行
  3. require.async('async.js', function(exports){
  4. // 模块加载完成后,返回模块的导出
  5. // exports
  6. })
  7. }, 1000);

异步模块常用于单页面应用,如:

  1. window.on('hashchange', function(eve){
  2. if (location.hash === '#a') {
  3. require.async('pages/a.js');
  4. } else if (location.hash === '#b') {
  5. require.async('pages/b.js');
  6. } else {
  7. require.async('pages/404.js');
  8. }
  9. });

如上,监听hashchange事件,然后根据不同的 hash 载入不同的页面。

3demo

本 demo 就是通过监听 hash 来载入不同的 page,是异步模块的一个典型使用场景。

3.1初始化目录结构

新建一个空目录 coolie-demo9:

  1. .
  2. └── webroot-dev
  3. 1 directory, 0 files

3.2初始化文件

3.2.1index.js

新建一个入口模块index.js

  1. var onhashchange = function (eve) {
  2. if (location.hash === '#a') {
  3. require.async('pages/a.js', function (page) {
  4. page();
  5. });
  6. } else if (location.hash === '#b') {
  7. require.async('pages/b.js', function (page) {
  8. page();
  9. });
  10. } else {
  11. require.async('pages/404.js', function (page) {
  12. page();
  13. });
  14. }
  15. };
  16. window.onhashchange = onhashchange;
  17. setTimeout(onhashchange, 0);

然后新建一个 pages 目录,分别放置这些页面片段。

pages/a.js:

  1. module.exports = function () {
  2. document.getElementById('demo').innerHTML = 'page a ' + Date.now();
  3. };

pages/b.js:

  1. module.exports = function () {
  2. document.getElementById('demo').innerHTML = 'page b ' + Date.now();
  3. };

pages/404.js:

  1. module.exports = function () {
  2. document.getElementById('demo').innerHTML = 'page 404 ' + Date.now();
  3. };
  • webroot-dev 目录下,新建package.json
  • webroot-dev 目录下,下载模块加载器npm install —save coolie.js
  • 初始化模块加载器配置文件coolie init -j
  • 修改coolie-config.jsmainModulesDir: "/" 配置,使其指向了根目录。
    省略了以上步骤的详细操作方式,详细参考 demo1

最后写index.html

  1. <!doctype html>
  2. <meta charset="utf-8">
  3. <style>
  4. #demo {
  5. border: 1px solid #ccc;
  6. padding: 10px;
  7. font-size: 20px;
  8. }
  9. </style>
  10. <div id="demo"></div>
  11. <p><a href="#a">pages/a</a></p>
  12. <p><a href="#b">pages/b</a></p>
  13. <p><a href="#c">pages/c</a></p>
  14. <p><a href="#d">pages/d</a></p>
  15. <script coolie
  16. src="/node_modules/coolie.js/coolie.js"
  17. data-config="/coolie-config.js"
  18. data-main="index.js"></script>

html 里分别加上了 4 个链接,来分别监听 hash 变化来异步载入不同的模块。

3.3前端构建前运行

webroot-dev目录下,使用构建异步模块(demo9) - 图1sts启动。

构建异步模块(demo9) - 图2

从上面的 gif 动画中可以清楚的看到:

  • 页面载入的时候,匹配的 hash 是 404 页面,此时载入了主模块和异步的 404 模块
  • 当点击pages/a的时候,匹配的 hash 是 a 页面,此时载入了异步的 a 模块
  • 当点击pages/b的时候,匹配的 hash 是 a 页面,此时载入了异步的 b 模块
  • 当点击pages/c的时候,匹配的 hash 是 404 页面,此时并未重复载入 404 模块,而是直接执行了已经加载完成的 404 模块
  • 当点击pages/d的时候,与上条相同

3.4前端构建配置

前端构建也不复杂,使用命令初始化前端构建配置文件(coolie.config.js

修改配置文件为:

  1. /**
  2. * ======================================================
  3. * coolie-cli 配置文件 `coolie.config.js`
  4. * 使用 `coolie init -c` 生成 `coolie.config.js` 文件模板
  5. * 当前配置文件所在的目录为构建的根目录
  6. *
  7. * @link http://coolie.ydr.me/guide/coolie.config.js/
  8. * @author ydr.me
  9. * @version 1.6.5
  10. * @create 2016-01-26 21:42:33
  11. * =======================================================
  12. */
  13. 'use strict';
  14. module.exports = function (coolie) {
  15. // coolie 配置
  16. coolie.config({
  17. // 是否在构建之前清空目标目录
  18. clean: true,
  19. // 目标配置
  20. dest: {
  21. // 目标目录,相对于当前文件
  22. dirname: '../webroot-pro/',
  23. // 目标根域
  24. host: '',
  25. // 版本号长度
  26. versionLength: 32
  27. },
  28. // js 构建
  29. js: {
  30. // 入口模块,相对于当前文件
  31. main: [
  32. // 支持 glob 语法
  33. //【1】
  34. 'index.js'
  35. ],
  36. // coolie-config.js 路径,相对于当前文件
  37. //【2】
  38. 'coolie-config.js': 'coolie-config.js',
  39. // js 文件保存目录,相对于 dest.dirname
  40. dest: './static/js/',
  41. // 分块配置
  42. chunk: []
  43. },
  44. // html 构建
  45. html: {
  46. // html 文件,相对于当前文件
  47. src: [
  48. // 支持 glob 语法
  49. //【3】
  50. 'index.html'
  51. ],
  52. // 是否压缩
  53. minify: true
  54. },
  55. // css 构建
  56. css: {
  57. // css 文件保存目录,相对于 dest.dirname
  58. dest: './static/css/',
  59. // css 压缩配置
  60. minify: {
  61. compatibility: 'ie7'
  62. }
  63. },
  64. // 资源
  65. resource: {
  66. // 资源保存目录,相对于 dest.dirname
  67. dest: './static/res/',
  68. // 是否压缩
  69. minify: true
  70. },
  71. // 原样复制文件,相对于当前文件
  72. copy: [
  73. // 支持 glob 语法
  74. //【4】
  75. //'./favicon.ico',
  76. //'./robots.txt'
  77. ]
  78. });
  79. // 使用 coolie 中间件
  80. // coolie.use(require('coolie-*'));
  81. // 自定义 coolie 中间件
  82. //coolie.use(function (options) {
  83. // // do sth.
  84. // return options;
  85. //});
  86. };
  • 【1】:修改了入口模块路径为index.js
  • 【2】:修改了模块加载器配置文件路径为coolie-config.js
  • 【3】:修改了 html 路径为index.html
  • 【4】:去除了需要复制的文件路径

3.5前端构建

在 webroot-dev 目录下,执行:

  1. coolie build
  2. ┌──────────────────────────────┐
  3. coolie@2.0.0
  4. 前端工程化构建工具
  5. 官网:https://coolie.ydr.me/ │
  6. └──────────────────────────────┘
  7. step 1/6 >> parse coolie-cli profile
  8. coolie config >> /coolie-demo9/webroot-dev/coolie.config.js
  9. src dirname >> /coolie-demo9/webroot-dev
  10. dest dirname >> /coolie-demo9/webroot-pro/
  11. step 2/6 >> copy files
  12. copy files >> no files are copied
  13. step 3/6 >> build main modules
  14. parse module >> 4 modules parsed
  15. build main >> will build 4 main modules
  16. 1/4 >> /index.js
  17. 2/4 >> /pages/a.js
  18. 3/4 >> /pages/b.js
  19. 4/4 >> /pages/404.js
  20. step 4/6 >> generate coolie.js profile
  21. coolie-config.js >> mainModulesDir: "/static/js/main/"
  22. coolie-config.js >> asyncModulesDir: "../async/"
  23. coolie-config.js >> chunkModulesDir: "../chunk/"
  24. coolie-config.js >> callbacks: 0
  25. coolie-config.js >> ../webroot-pro/static/js/6d22eee322fab66f0f6a574a74d2dba6.js
  26. step 5/6 >> build htmls
  27. 1/1 >> /index.html
  28. step 6/6 >> generate coolie map
  29. coolie map >> ../webroot-pro/coolie-map.json
  30. build success >> elapsed 543ms, at 2016-05-28 22:26:52.578

从实时打印的构建日志来看:

  • 构建的入口模块不止index.js,还有pages/a.jspages/b.jspages/404.js
  • 构建之后的版本信息,多了async/1.jsasync/2.jsasync/3.js
    从目录结构也可以看出,原来的pages目录已经不存在了,并且多了一个async目录。

3.6前端构建后运行

切换到 webroot-pro 目录,使用构建异步模块(demo9) - 图3sts执行:

构建异步模块(demo9) - 图4

表现的情况与构建之前是一致的,唯一不同的时候控制台打印的日志要少很多。

3.7分析构建结果

3.7.1coolie-map

首先分析下coolie-map.json深度解析点这里):

  1. {
  2. "/index.html": {
  3. "main": [
  4. {
  5. "src": "../webroot-dev/index.js",
  6. "dest": "/static/js/main/71b6a58839bc79bd924418ad47923722.js",
  7. "deps": []
  8. }
  9. ],
  10. "js": [
  11. {
  12. "dest": "/static/js/0996319be2c4f9517575b54dcc4af897.js",
  13. "deps": [
  14. "../webroot-dev/node_modules/coolie.js/coolie.js"
  15. ]
  16. }
  17. ],
  18. "css": [],
  19. "res": []
  20. }
  21. }

可见的是,内容比之前的 demo 要多,最主要的是 async 里有一个数组,数组里展示是异步模块的信息。

3.7.2入口模块

接下来,看看入口模块(71b6a58839bc79bd924418ad47923722.js,已格式化):

  1. /*coolie built*/
  2. define("0", [], function (n, o, a) {
  3. var c = function (o) {
  4. "#a" === location.hash ? n.async("4", function (n) {
  5. n()
  6. }) : "#b" === location.hash ? n.async("5", function (n) {
  7. n()
  8. }) : n.async("6", function (n) {
  9. n()
  10. })
  11. };
  12. window.onhashchange = c;
  13. setTimeout(c, 0)
  14. });

3.7.3异步模块

简单的看了下,入口模块竟然只有一个模块,三个异步没有被打包进来(这也是异步模块的特点)。

  1. function(require, exports, module)
  2. function(n, o, a)

上下一一对比,异步模块载入的方法应该是n.async(),通过搜索可以找到:

  1. n.async("1",function(
  2. n.async("2",function(
  3. n.async("3",function(

构建前后的一一对比,路径与 ID 的对应关系为:

  1. pages/a.js => 4
  2. pages/b.js => 5
  3. pages/404.js => 6

不止是同步模块的路径会被压缩,连异步模块的路径也会被压缩。

3.7.4index.html

接下来去看看index.html(已格式化):

  1. <!doctype html>
  2. <meta charset="utf-8">
  3. <style>#demo {
  4. border: 1px solid #ccc;
  5. padding: 10px;
  6. font-size: 20px
  7. }</style>
  8. <div id="demo"></div> <p><a href="#a">pages/a</a></p><p><a href="#b">pages/b</a></p><p><a href="#c">pages/c</a></p><p><a
  9. href="#d">pages/d</a></p>
  10. <script src="/static/js/0996319be2c4f9517575b54dcc4af897.js"
  11. data-config="/static/js/6d22eee322fab66f0f6a574a74d2dba6.js"
  12. data-main="71b6a58839bc79bd924418ad47923722.js"></script>
  13. <!--coolie built-->

3.7.5coolie-config.js

data-config属性可知,构建之后的配置文件为6d22eee322fab66f0f6a574a74d2dba6.js(已格式化):

  1. /*coolie built*/
  2. coolie.config({
  3. debug: !1,
  4. mode: "AMD",
  5. asyncModulesMap: {
  6. 4: "6039b8b176c5b79d8689eadc6cfa0840",
  7. 5: "546a0fa8aecd9ddee215f899080ce728",
  8. 6: "4e06aa7b5770cf4cc779c5976a269e91"
  9. },
  10. chunkModulesMap: {},
  11. built: "coolie@2.0.0",
  12. mainModulesDir: "/static/js/main/",
  13. asyncModulesDir: "../async/",
  14. chunkModulesDir: "../chunk/",
  15. global: {}
  16. }).use();

从文件内容可见,asyncModulesMap属性下多了 3 个属性值:

  1. asyncModulesMap: {
  2. 4: "6039b8b176c5b79d8689eadc6cfa0840",
  3. 5: "546a0fa8aecd9ddee215f899080ce728",
  4. 6: "4e06aa7b5770cf4cc779c5976a269e91"
  5. }

当异步加载n.async("1",function(的时候,coolie 会先查找异步目录,async:"async/"下的1.js,然后去asyncModulesMap里查找是否有对应的版本号,最终找到的文件就是async/4.6039b8b176c5b79d8689eadc6cfa0840.js

4github

构建异步模块(demo9) - 图5github.com

原文: https://coolie.ydr.me/guide/build-async-module