Grunt 侧重对整个过程的控制管理,是任务类型的的打包工具,代码检查、预编译、合并压缩;生成雪碧图、sourceMap、版本管理;运行单元测试、监控等。
Grunt 执行异步任务
- 执行异步任务的回调函数不能使用箭头函数
- 异步任务完成需要调用任务内置函数告知已经完成
Grunt 标记任务失败
- 同步任务通过 return false来标记任务失败
- 异步任务通过内置函数 done 传递 false 参数 ***done(false)**来标记任务失败
- 如果多任务执行,只要标记任务失败,后续任务将不在执行。添加
--force
选项,会强制执行后续任务
Grunt 设置配置
- 使用
initConfig
方法去配置参数 - 使用
grunt.config
方法来获取参数
Grunt 插件使用
- Grunt 插件命名规则
grunt-contrib-任务名
或grunt-任务名
- Grunt 常用插件 样式预编译、JS编译、文件监听
- 使用插件前,需要使用**
loadNpmTasks
**方法加载插件,然后才可以使用。load-grunt-tasks
插件可自动加载所有插件
npx
npx是一个npm包执行器,有如下特点:
临时安装可执行依赖包,不用全局安装,故不用担心长期的污染
可以执行依赖包中的命令,安装完成自动运行
自动加载
node_modules
中依赖包,而无需指定$PATH
,还可以指定node.js版本,命令的版本。1
2
3
4
5
6
7// 指定uglify-js 版本,npx 运行时,会到node_modules/.bin路径 和 环境变量$PATH里检查命令是否存。
// 如果找不到,会临时安装,然后执行
npx uglify-js@3.1.0 ./test/test_npx.js -o ./test/haha.js
// 指定node版本的
npx -p node@8 npm run build
Gulp
Gulp在4.0版本之后,无需引入gulp,然后在注册任务才可以调用,现在可直接通过exports导出任务。且取消了同步任务,约定每次任务执行完成后,都要调用回调函数的方法参数才可以。
Gulp 异步任务的多种形式
- 回调函数,
标记任务失败,在方法done中传入错误对象。其后面的任务也不会在执行
- 回调函数,
- promise
Promise.resolve() 任务成功; Promise.reject() 任务失败
- promise
- async、await
- 使用gulp读取文件操作时,返回文件流,gulp会自动在流上注册一个end事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 返回文件流
const fs = require('fs');
exports.stream = () => {
const readstream = fs.createReadStream("package.json");
const writestream = fs.createWriteStream("temp.txt");
readstream.pipe(writestream);
return readstream;
}
exports.stream2 = (done) => {
const readstream = fs.createReadStream("package.json");
const writestream = fs.createWriteStream("temp2.txt");
readstream.pipe(writestream);
readstream.on("end", () => {
done()
})
}
gulp 文件操作
Gulp使用 src
方法匹配到源文件,然后通过node.js的pipe
将文件流 输送到 gulp插件(编译,压缩),最后通过dest
方法,将编译好的文件输出到指定编译目录中。
webpack用于JavaScript应用程序的静态模块打包工具。他会在内部从一个或多个入口点构建一个依赖图(dependency graph),然后将项目中所需要的每一个模块组合成一个或多个bundles,它们均为静态资源。
对webpack而言,一起文件都是一个个模块,根据个模块之间的依赖关系,对模块进行组合和打包,最终输出浏览器能使用的静态资源。
context 基础目录
- webpack的基础目录,必须是绝对路径,用于从配置中解析 入口点(entry)和 加载器(loader),默认为当前目录。
1 | const path = require("path"); |
基础目录 为 /home/project/webpack-config/config/src
, 运行 npx webpack --config ./config/webpack.config-1.js
,会报错,找不到./src/index.js
.
context
,entry
做如下修改,在执行 npx webpack 命令,编译正常。由此可知,context 是作为 entry 和 loader 的 根目录
1 | const path = require("path"); |
entry 入口文件
entry支持字符串、字符串数组、对象、函数类型
string 类型
1
entry: "./src/index.js"
字符串数组 类型
两个文件会合并打包为一个chunk文件1
entry: ["./src/index.js", "./src/calc/js"]
对象类型
entry 对象有2个入口,入口 a 和 b, 通过 dependOn 配置 b 依赖于 a, 构建是会等 a构建完成后再启动b的构建。
entry 配置有多个入口文件,所以输出output
的配置也要满足,使用[name]
占位符来确保每个文件具有唯一代名称。
1 | const path = require("path"); |
output 输出
output属性最低要求,设置为一个对象,配置输出文件的文件名,默认输出目录dist
1 | output: { |
如果配置2个或多个入口文件,则应该使用 占位符来保证每个文件具有唯一的名称
生成 hash 文件名, 例如 b.ec5d198e69.js
1 | const path = require("path"); |
常用的hash 占位符有:
- hash, hash跟整个项目构建相关,每次构建生成的文件hash值都一样,只要项目中文件内容发生变化,hash值也会变化
- contenthash, 由文件内容产生的hash值,内容不同产生的值也不一样
- chunkhash, 每一次构建后生成的hash值都不一样,即使文件内容没有改变,不利于浏览器的缓存
生成 umd 模式的文件
1 | const path = require("path"); |
执行 npx webpack --config ./config/webpack.config-6.js
, 生成 main.7f77f8.js
js文件,新建index.html并引入打包后的js文件,控制台打印lqUtils
,可看到输出结果。表面 打包的js文件是 umd格式,支持浏览器。 js文件如下:
1 | /* |
tips
npm view webpack devDependencies
,npm view webpack dependencies
查看webpack的依赖
脚手架工具
inquirer, 询问交互
ejs, 模板解析
在 package.json中,bin字段指向可执行文件,其值是字符串,或者 对象。
对象形式,myjs-cli 即为脚手架的名字
字符串,脚手架的名字 就是 name的值
执行脚手架,就会执行在package.json 中配置项 bin 指向的可执行文件
“bin”: {
“myjs-cli”: “bin/index.js”
},
process.cwd(),node 运行时的路径
webpack 原理
webpack 原理
自定义 loader, plugin
简易的 webpack
webpack 核心配置
entry, 可执行模块 或者 库的入口
chunk, 多个文件组成的一个代码块。可以将可执行模块和它所依赖的模块组合成一个chunk
loader, 文件转换器。 es6 转换 为 es5, scass 转换为 css
plugin, 扩展webpack功能的插件。 在 webpack 构建的生命周期节点上加入扩展hook,添加功能
webpack 构建过程?
初始化参数, 解析webpack 配置参数,合并shell传入和webpack.config.js 文件配置的参数,形成最后的配置结果
开始编译
通过上一步得到 的参数 初始化 compiler 对象
注册所有配置的插件, 插件 监听webpack构建生命周期的事件节点,做出相应的处理
执行对象的run方法开始执行编译
确认入口, 从配置的 entry 入口,开始解析文件,构建AST语法树,找出依赖,递归下去
编译模块, 递归中 根据文件类型和loader配置,调用所有配置的loader对文件进行转换,在找出该模块依赖的模块,在递归本步骤,直到所有入口依赖的文件都经过处理
完成模块编译并输出,递归完成后,等到每个文件结果,包含每个模块以及它们之间的依赖关系,根据 entry 配置生成代码块 chunk
输出完成, 输出所有的chunk 到文件系统
自定义 plugins
plugins 的钩子函数分为 compiler钩子,和 compilation钩子,每个钩子还有很多各自的钩子周期函数,在不同钩子周期函数中,webpack 进行不同的操作。
如何创建 webpack plugin?
构建函数
扩展 apply 方法
指定webpack 自身的事件钩子
处理 webpack 内部实例的特定数据
功能完成后,调用 webpack 提供的回调函数