FED

©FrontEndDev.org
2015 - 2024
web@2.22.0 api@2.20.0

跟我学 coolie 之 3 模块化构建 hello world

什么是前端构建

前端构建,指的是将开发环境中的代码编译、修改、重写成生产环境下可更快、更好运行的代码。比如压缩 JS、CSS 文件,或者合并 JS、CSS 文件,这些操作都是一个构建过程。

为什么要前端构建

可以不要前端构建吗?答案当然是可以,即生产环境和开发环境是同一份代码。

  • 开发环境:通常是本地环境。
  • 生产环境:通常是线上环境或预发布环境、测试环境。

如果开发和生产同一份代码,那么会出现以下问题:

  • 代码没有经过压缩:浏览器下载的资源会比压缩后的大很多,比如 jquery.js(http://code.jquery.com/jquery-2.1.4.js) 未压缩时大约有 87KB,而压缩版本 jquery.min.js(http://code.jquery.com/jquery-2.1.4.min.js) 只有34KB,文件的容量只有源文件的1/3。压缩后的代码对浏览器来说,都是可读的,不必担心其运行效率。
  • 代码没有经过合并:比如网页上放置了10个script标签,那么浏览器就要去加载这10个文件后才能运行完毕,而浏览器的并发请求数量是有上限的。例如一次请求只有 5 个,那么就需要连续请求2次。另外,HTTP 请求是无状态的,每次请求都需要重新发起,更加延长了加载时间。
  • 没有做版本处理:如果没有做版本管理的话,那么在网站更新的时候,客户机拿到的代码很可能因为缓存的原因,拿到的是旧代码,导致不可预计的问题。
  • 等等更多。

构建哪些东西

coolie 很好的每一位前端开发者完成了上述的工作,并且它是低侵入性的,即不需要修改任何源代码(开发环境下代码的不会被修改),也不需要监听构建(百度的 fis 竟然要实时监听构建,无可理喻),几乎 0 配置(比起 spm 那个坑货来说,coolie 构建实在是太强大了)。

coolie 主要构建了哪些东西?

有兴趣的朋友,可以点击上述链接详看。

如何进行前端构建

生成配置文件

在上一节说到的根目录执行

coolie json
# 生成构建配置文件 coolie.json

如同生成模块加载器配置文件一样,也会通过对话的方式生成:

➜  coolie json

   ╔═════════════════════════════════════════╗
   ║   coolie@0.21.6                         ║
   ║   The front-end development builder.    ║
   ╚═════════════════════════════════════════╝
   
                tips => 以下操作留空回车表示同意默认配置。

           file path => /path/to/coolie.json
             warning => 如果上述目录不正确,请按`ctrl+C`退出后重新指定。
                 1/7 => 请输入 JS 入口模块的路径。
                        支持通配符,多个路径使用空格分开,默认为“./static/js/app/**/*.js”。
./index.js
                 2/7 => 请输入 coolie.js 配置文件所在的路径,默认为“./static/js/coolie-config.js”。
./coolie-config.js
                 3/7 => 请输入合并压缩后的非模块化 JS 文件的保存目录。默认为“./static/js/”。
                        不建议与 JS 入口模块的目录一样
./
                 4/7 => 请输入合并压缩后的 CSS 文件的保存目录。默认为“./static/css/”。
./
                 5/7 => 请输入 HTML 文件所在的路径。
                        支持通配符,多个路径使用空格分开。默认为“./views/**/*.html”。
./index.html
                 6/7 => 请输入构建之后的静态资源(如:图片、字体)的目录,默认为“./static/res/”。
./
                 7/7 => 请输入构建的目标目录,默认为“../dest/”。

             confirm => 文件内容为:
         coolie.json => {
                          "js": {
                            "src": [
                              "./index.js"
                            ],
                            "coolie-config.js": "./coolie-config.js",
                            "dest": "./",
                            "chunk": []
                          },
                          "css": {
                            "dest": "./",
                            "minify": {
                              "compatibility": "ie7"
                            }
                          },
                          "html": {
                            "src": [
                              "./index.html"
                            ],
                            "minify": true
                          },
                          "resource": {
                            "dest": "./res/",
                            "minify": true
                          },
                          "copy": [],
                          "dest": {
                            "dirname": "../dest/",
                            "host": ""
                          }
                        }
             confirm => 确认文件内容正确并生成文件?([y]/n)
y
                  √  => /path/to/coolie.json

生成的配置文件(以下为了说明各个参数的意思,加了注释,实际 JSON 文件是不允许有注释的):

{
// JS 文件构建配置
  "js": {
  	// JS 文件构建路径,可以使用 glob 通配符
    "src": [
      "./index.js"
    ],
	// 模块加载器配置文件路径
    "coolie-config.js": "./coolie-config.js",
	// 非模块化脚本存放位置
	"dest": "./",
	// chunk 模块列表
	"chunk": []
  },
  // CSS 文件构建配置
  "css": {
  	// CSS 文件的生成目录
    "dest": "./"
  },
  // HTML 文件构建配置
  "html": {
  	// HTML 文件的构建目录,可以使用 glob 通配符
    "src": [
      "./index.html"
    ],
	// 是否压缩 HTML 文件
    "minify": true
  },
  // 静态资源文件构建配置
  "resource": {
  	// 静态资源的生成目录
    "dest": "./",
	// 是否压缩静态资源文件
    "minify": true
  },
  // 构建结果目录
  "dest": "../dest/",
  // 需要复制到构建目录的文件或目录的列表,可以使用 glob 通配符
  "copy": []
}

上文提到的 glob 通配符:

  • *Matches 0 or more characters in a single path portion
  • ? Matches 1 character
  • [...] Matches a range of characters, similar to a RegExp range. If the first character of the range is ! or ^ then it matches any character not in the range.
  • !(pattern|pattern|pattern) Matches anything that does not match any of the patterns provided.
  • ?(pattern|pattern|pattern) Matches zero or one occurrence of the patterns provided.
  • +(pattern|pattern|pattern) Matches one or more occurrences of the patterns provided.
  • *(a|b|c) Matches zero or more occurrences of the patterns provided
  • @(pattern|pat*|pat?erN) Matches exactly one of the patterns provided
  • ** If a "globstar" is alone in a path portion, then it matches zero or more directories and subdirectories searching for matches. It does not crawl symlinked directories.

更多:https://github.com/isaacs/node-glob

执行构建

配置文件生成之后,就可以执行构建了:

coolie build

此时,命令行会输出构建细节:

➜  test  coolie build

   ╔═════════════════════════════════════════╗
   ║   coolie@0.21.6                         ║
   ║   The front-end development builder.    ║
   ╚═════════════════════════════════════════╝


                 1/5 => copy files

                 2/5 => build main
                  √  => /path/to/src/index.js
                  ×  => unchunk modules

                 3/5 => overwrite config
                  √  => base: "./"
                  √  => version: "{
                          "index.js": "0c0e55a404cb28a132fd79b5d1dec5b1"
                        }"
                  √  => callbacks: 0
                  √  => /path/to/dest/coolie-config.30b4c2b3e6b2e4ec52950f0f91f9f085.js

                 4/5 => build html css
                  √  => /path/to/dest/coolie.min.js
                  √  => /path/to/src/index.html

                 5/5 => generator relationship map
                  √  => /path/to/dest/relationship-map.json

       build success => copy 1 file(s),
                        build 1 main file(s),
                        build 0 js file(s),
                        build 1 html file(s),
                        build 0 css file(s),
                        build 0 resource file(s),
                        past 138 ms

如上构建细节,会描述正在构建的资源和其他构建信息。此时的文件目录是这样的:

- src 开发目录
|-- index.js
|-- coolie.min.js
|-- coolie-config.js
|-- index.html
`-- coolie.json
- dest 生产目录
|-- coolie-config.30b4c2b3e6b2e4ec52950f0f91f9f085.js
|-- coolie.min.js
|-- index.0c0e55a404cb28a132fd79b5d1dec5b1.js
|-- index.html
`-- relationship-map.json #资源关系引用地图

我们打开index.html,和预期一样,弹出了警告框:

构建结果

我们来分别看下各个文件

index.html

为了演示,已加了一些空白。

<!doctype html>
<meta charset="utf8">
<script src="/coolie.min.js" 
data-config="./coolie-config.30b4c2b3e6b2e4ec52950f0f91f9f085.js" 
data-main="index.js"></script>
<!--coolie@0.21.6-->

可以明显看到是:

  • 文件经过了压缩,其他没有做修改。
  • 配置文件也被修改了。
  • 文件末尾添加了签名。

index.版本号.js

/*coolie@0.21.6*/
define("0",[],function(e,l,n){alert("Hello world!")});

可以明显看到:

  • 文件经过了压缩。
  • 文件内容也发生了变化。

coolie-config.版本号.js

/*coolie@0.21.6*/
coolie.config({base:"./",debug:!1,cache:!0,
version:{"index.js":"0c0e55a404cb28a132fd79b5d1dec5b1"}}).use();

可以明显看到:

  • 文件经过了压缩。
  • 配置文件增加了debugcacheversion3 个参数:
    • debug:是否在控制台输出调试信息,生产环境是不需要的。
    • cache:是否保留模块缓存,生产环境是需要的。
    • version:指定入口文件的版本信息,而index.js的版本就是0c0e55a404cb28a132fd79b5d1dec5b1,所以模块加载器加载的就是 index.0c0e55a404cb28a132fd79b5d1dec5b1.js文件。

relationship-map.json

{
	// 被构建的 HTML 页面
    "index.html": {
		// 该页面引用的 CSS 文件
        "css": [],
        // 非模块化 JS 文件
        "js": {},
		// 该页面的入口 JS 模块
        "main": "index.js",
		// 该页面依赖的 JS 模块
        "deps": []
    }
}

此文件描述的时构建读取到的一些依赖信息,详细说明如上。

结语

从上,很明显的看到,开发环境和生产环境中代码的不同,并且做了版本管理。以小见大,在大的工程构建上面,达到的效果会更加可观。