最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 使用 makefile 压缩 JavaScript 代码

    正文概述 掘金(上沅同学)   2021-05-02   605

    一、makefile 初探

    1. 什么是 make指令 和 makefile?

    make 指令就像它的名字一样 ,用于制作某个文件(make filename),或者根据 makefile target 自动化编译、打包、生成一个文件(可执行文件或压缩文件)。

    例如,我们想根据 a.txtb.txt 文件合成 output.txt 文件,可以书写如下 makefile 文件:

    output.txt: a.txt b.txt
    	@# 根据 a.txt b.txt 文件合成 output.txt 文件
    	@cat a.txt b.txt > output.txt
    
    # 制作 output.txt 文件
    make output.txt
    

    通常我们用 make 指令构建 c/c++ 项目,当然,我们也可以用 make 指令构建 go 语言项目、java项目及 node.js 项目。

    例如,我们用 make 指令编译 hello.cpp 文件

    #include <iostream>
    using namespace std;
    int main(){
       cout << "Hello World!";
       return 0;
    }
    

    makefile 文件:

    hellocpp:	hello.o
    	echo "开始编译"
    	g++ -o hello hello.o
    	rm -f hello.o
    	echo "编译结束"
    

    执行 make 指令

    # 使用 makefile 执行 hello.cpp
    make
    
    # 执行生成的 hello文件
    ./hello
    > Hello World!
    

    没玩过 makefile 的同学肯定以为 makefile 和 shell 脚本很像,没错,makefile 确实可以当做 shell 脚本使用(bushi),接下来我就简单介绍一下 makefile 的基本规则和常见写法。

    2、makefile 的结构

    makefile 文件是由一系列的规则(rules) 组成的,每条规则的写法如下:

    <target> : <prerequisites> 
    [tab]  <commands>
    

    其中,冒号前面的部分表示目标(target),表示执行的动作。目标可以是一个文件名(如上文中的 output.txt),也可以是多个文件名,中间用空格隔开。目标除了是文件名,也可以是操作名,这种在 makefile 中,叫伪目标(phony target),用 .PHONY 声明目标操作。

    我们在 makefile 中一般有一些约定俗成的目标,如:

    • make all:编译所有文件
    • make install:安装编译好的应用程序
    • make clean:清理应用程序,可执行文件,目标文件等。

    冒号后面的部分表示前置条件(prerequisites),之间用空格分隔。声明的目标指定了前置条件,如果没有该前置条件匹配的文件,那么就要先生成该前置条件所需要的文件,才能执行目标。

    命令(commands)表示如何构建目标文件,每个命令前必须以 tab 开头,可以和 prerequisites 写在一行,不过要用分号做分隔。

    前置条件和命令为非必填项,不过其中一个没写另一个就必须要写。

    makefile 里主要包含了五个东西:

    • 变量的定义
    • 显式规则:根据上文的 target-prerequisites-commands 的书写方式,就是显示规则
    • 隐晦规则:由于 makefile 具有自动推到的功能,所以隐晦规则可以让我们粗糙的书写makefile。用makefile 内置的变量和函数编写的规则就是隐晦规则。
    • 文件指示:可以用 include 指令嵌套引入 makefile
    • 注释

    变量的定义一般都是字符串,和C语言中的宏比较类似,所以我们有的时候也管makefile中的变量称作宏。

    和 vue 的差值模板以及 shell、php 的变量一样,我们一般用${VARIABLE}$(VARIABLE) 的方式去使用一个变量。

    在 makefile 中,变量有四种声明方式:

    VARIABLE = value # 惰性赋值,在执行时扩展,可以递归扩展
    
    VARIABLE := value # 立即赋值
    
    VARIABLE ?= value # 只有在该变量为空时才设置值
    
    VARIABLE += value # 将值追加到变量的尾端
    

    这四种赋值方式的具体区别可以查看 Stack Overflow,因为这四种赋值方式的区别不是本文讨论的重点,所以我就不过多赘述。

    除了用户声明的变量外,makefile 中还有内置变量和自动变量。

    内置变量分为两类,作为程序名称的变量(如CC),包含程序参数的变量(如CFLAGS)。关于makefile 所有的内置变量可以查看官方文档。

    自动变量的值与当前的规则有关。

    一般常用的有以下几个:

    • $@:当前目标
    • $?:比目标更新的前置条件
    • $<:第一个前置条件
    • $*:与通配符匹配的部分
    • $^:所有前置条件
    • $(@D)$(@F)$@ 的目录名和文件名
    • $(<D)$(<F)$< 的目录名和文件名

    @指代的是当前的目标文件,如下面这个例子中,@ 指代的是当前的目标文件,如下面这个例子中,@指代的是当前的目标文件,如下面这个例子中,@ 就表示 a.txt 和 b.txt 两个目标文件的文件名;

    # 下面两种写法等价
    # 写法一
    a.txt b.txt: 
        touch $@
    # 写法二
    a.txt:
        touch a.txt
    b.txt:
        touch b.txt
    

    <表示第一个前置条件,如下面这个例子中,< 表示第一个前置条件,如下面这个例子中,<表示第一个前置条件,如下面这个例子中,< 就表示 b.txt

    # 下面两种写法等价
    # 写法一
    a.txt: b.txt c.txt
        cp $< $@ 
    # 写法二
    a.txt: b.txt c.txt
        cp b.txt a.txt 
    

    除了内置变量和自动变量,makefile 还可以使用内置函数,使用方法和变量一样。官方文档总共列举了总共14种函数,常用的主要有以下几种:

    • shell,shell 函数可以执行shell 命令,个人觉得和 shell 里的管道作用很像。例如 dir:=$(shell pwd)
    • subst,用于文本替换,用法如下:$(subst from,to,text)
    • patsubst,patsubst 函数用于模式匹配的替换,主要用于替换通配符。用法为 $(patsubst pattern,replacement,text) 。例如 $(patsubst %.c,%.o,a.c.c b.c) 可以将 a.c.c 和 b.c 替换成 a.c.o 和 b.o。
    • wildcard,wildcard 函数可以用空格分格所有匹配此格式的文件列表。例如,$(wildcard *.c) 可以获取工作目录下的所有的*.c*文件列表。

    makefile 还有一些其他的语法需要值得注意:

    回声:@

    正常情况下,make 在执行的过程中会打印每条 command,包括注释,这种现象在 makefile 中叫做回声。如果不想打印回声的话,可以用 @ 操作符来关闭回声。如:

    @# 关闭注释
    test:
    	@echo "编译中。。。"
    	@npm run dev
    

    通配符(wildcard)

    make 的通配符和 shell 一样,主要有*?

    模式匹配

    make 的模式匹配主要的操作符是%,允许对文件名进行类似正则的匹配

    注释

    makefile 的注释和 shell 脚本l 一样,都是 #

    循环和判断指令

    makefile的循环判断指令和 shell 脚本一样,主要有以下几种:

    • ifeq (if eqaul)指令。它包含两个参数,用逗号分隔并用圆括号包围。变量替换在两个参数上执行,然后进行比较。如果两个参数匹配,则遵循 ifeq 后面的命令行;否则会被忽略。
    • ifneq (if not eqaul)指令。它包含两个参数,用逗号分隔并用圆括号包围。变量替换在两个参数上执行,然后进行比较。如果两个参数不匹配,则遵循ifneq后面的makefile行;否则会被忽略。
    • ifdef (if defined)指令。它包含单个参数。如果给定的参数为真,则条件成立。
    • ifndef (if not defined)指令。它包含单个参数。如果给定的参数为假,则条件成立。
    • else 指令。
    • endif 指令结束的语句,每个 if 条件必须以 endif 结尾。
    • for-in-do-done,循环

    include 指令

    include 指令可以引入其他的 makefile 文件。语法如下

    include <filename>
    # 文件名可以包含 shell 格式的文件名匹配。额外的空格是允许的,并且在行的开始处被忽略,但不允许使用制表符 tab(\t)
    
    -include <filename>
    # 无论include过程中出现什么错误,都不要报错继续执行。上面那条指令若是找不到include的目标文件,会报错
    

    override 指令

    如果想要重新赋值一个变量,则要使用 override 指令。如

    override VARIABLE = value
    

    二、使用 make 构建 JavaScript 代码

    前面已经简单介绍了下 make 的用法及 makefile 的一些规则,接下来我们讲一讲如何用 make 压缩 JavaScript 代码。

    废话不多说,直接上代码:

    src_files := $(shell find src -name '*.js')
    dist_files := $(patsubst src/%.js, dist/%.min.js, $(src_files))
    
    node_modules: package.json package-lock.json
    	@npm i uglifyjs 
    
    $(dist_files): $(src_files)
    	@rm -rf dist
    	@mkdir dist
    	@npx uglifyjs $^ -cmo $@
    
    all: node_modules $(dist_files) 
    
    .PHONY: all
    

    为了方便测试,我们用零宽空格测试文件是否压缩成功。

    在根目录下新建 src 目录,并新建 app.js 文件,文件内容为如下代码:

    ​​​​​​​​​​​​​​​​​​a​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
    

    虽然在编辑器中,只显示一个字符a,但是该字符串的长度却是 221,文件大小是 601 字节。这是由零宽字符导致的。

    那么什么是零宽字符(zero-width space)呢?

    用多个字节表示的字符称之为宽字符,我们常见的 Unicode 编码就是宽字符的一种实现,但是宽字符并不一定是 Unicode。

    零宽字符,顾名思义,就是宽度为0的字符。零宽字符在浏览器等环境是不可见的,但却是真是存在的,获取字符长度时也占有长度。常用于防止爬虫,数据隐写,也可以用于 DOS 攻击。

    以下为浏览器中常见的特殊字符:

    零宽空格(zero-width space, ZWSP)用于可能需要换行处。
        Unicode: U+200B  HTML: &#8203;
    零宽不连字 (zero-width non-joiner,ZWNJ)放在电子文本的两个字符之间,抑制本来会发生的连字,而是以这两个字符原本的字形来绘制。
        Unicode: U+200C  HTML: &#8204;
    零宽连字(zero-width joiner,ZWJ)是一个控制字符,放在某些需要复杂排版语言(如阿拉伯语、印地语)的两个字符之间,使得这两个本不会发生连字的字符产生了连字效果。
        Unicode: U+200D  HTML: &#8205;
    左至右符号(Left-to-right mark,LRM)是一种控制字符,用于计算机的双向文稿排版中。
        Unicode: U+200E  HTML: &lrm; &#x200E; 或&#8206;
    右至左符号(Right-to-left mark,RLM)是一种控制字符,用于计算机的双向文稿排版中。
        Unicode: U+200F  HTML: &rlm; &#x200F; 或&#8207;
    字节顺序标记(byte-order mark,BOM)常被用来当做标示文件是以UTF-8、UTF-16或UTF-32编码的标记。
        Unicode: U+FEFF
    

    知道了零宽字符的含义后,我们来测试 JavaScript 的压缩功能。

    在终端输入 make all 指令,打开生成的 dist 目录,查看 app.min.js 文件,发现大小被压缩到 2个字节了。

    上面只是简单列举了用 makefile 构建前端项目的例子,在实际开发中,我们可以使用 make -j 开启多线程来提升我们的构建速度,但是在现代的前端构建程序上,如 webpack、rollup,我们也可以使用多进程提升我们的打包速度(如 thread-loader)。所以这里建议大家,在实际的开发场景中,最好用同构的代码来构建我们的项目。

    代码晚些时间会长传至 Github。


    起源地下载网 » 使用 makefile 压缩 JavaScript 代码

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元