接下来考虑一些gulpfile的复用问题,因为如果涉及到开发多个同类型的项目,那么我们这个自动化构建工作流应该是一样的。就面临着复用gulpfile的问题。
提取一个可复用的自动化构建工作流
Gulp是一个自动化构建工作流的一个平台;gulpfile帮我们提供构建任务。
- Gulpfile + Gulp = 构建工作流
- Gulpfile + Gulp CLI = zce-pages
具体做法就是创建一个模块,然后把这个模块发布到npm仓库上面,最后在项目中使用这个模块就可以了。
提取gulpfile
-
新建一个项目A,项目A的作用是把之前gulp案例项目中创建的自动化构建工作流提取过来
-
在项目A,执行
npm init
,初始化package.json -
将之前gulp案例项目安装的 gulp相关的开发依赖安装到项目A下(在项目A中作为生产依赖dependencies)
-
设置入口文件,并将之前写的gulpfile.js文件放到入口文件中,这样项目A导出的就是一个gulpfile
-
执行
yarn link
或npm link
(将项目A link到全局) -
执行
yarn link 项目A名称
或npm link 项目A名称
(这样就可以在开发项目中 中去使用项目A这个模块了) -
修改原来的项目下gulpfile.js文件
module.exports = require('项目A')
注意:我们在本地模拟npm模块时需要在开发的项目中安装gulp和gulp-cli,因为gulp命令执行时它会去node_modules的bin目录下去找gulp命令。但是当后面将项目A发布到npm上的时候就不需要安装gulp和gulp-cli了,因为那时候会自动将它们安装到开发的项目中。
解决模块中的问题
在gulpfile.js中可以看到html任务中使用的根目录下的package.json文件,当我们把gulpfile抽离到模块中后就读取不到这个package.json了。而且同时读取的这些本就应该是属于项目的,而不属于这个公共模块。
通过约定大于配置的方式,在项目根目录下创建一个配置文件,然后在模块中尝试读取项目根目录下的配置文件。
项目配置文件pages.config.js
module.exports = {
title: 'gulp构建'
}
let config = {
title: ''
}
try {
loadConfig = require(`${cwd}/pages.config.js`)
config = Object.assign({}, config, loadConfig)
} catch (e) {
}
抽象路径配置
在模块中像src、assets、dist等路径都是写死的,也可以说这是我们约定好的,约定固然好,但提供灵活的配置同样也很重要。所以接下来要把这些路径都抽象出来,形成配置,完了就可以在我们开发项目中的配置文件中去配置。从而形成覆盖。
包装Gulp Cli
开发项目中的gulpfile.js文件现在存在的价值就是把 模块中提供的gulp任务进行导出。
现在希望在项目的根目录下没有gulpfile文件也能够正常工作。
-
删除项目中的gulpfile文件,gulp-cli提供了一个参数可以指定gulpfile文件所在的路径
//gulp-cli提供了参数可以指定gulpfile文件的路径 :--gulpfile 后面添加 //--cwd 指定当前项目所在的工作目录 yarn gulp develop --gulpfile ./node_modules/wjp-page/lib/index.js --cwd .
-
在模块中也提供一个cli,这个cli自动的传入这些参数,然后在内部调gulp-cli提供的可执行程序,这样使用时就不用使用gulp,将gulp模块完全包装到模块当中
-
首先在模块中添加cli程序,添加cli的入口文件,并且在package.json中添加 bin 字段设置为入口文件路径,这样这个入口文件才会作为cli的入口
-
然后把对gulp-cli的调用、以及传递的一些参数放在当前入口文件中
#!/usr/bin/env Node // 在gulp-cli中也是通过process.argv来拿到所有参数的 process.argv.push('--cwd') process.argv.push(process.cwd()) process.argv.push('--gulpfile') process.argv.push( require.resolve('../lib/index.js') ); console.log( process.argv ); require('gulp/bin/gulp')
cli(wjp-page模块的入口文件)就相当于node_modules/.bin目录下的执行命令(**.cmd),执行:
.\node_modules\.bin\gulp
相当于-----
wjp-page
在命令行直接输入 文件路径就可以执行脚本,
发布并使用模块
发布到npm的仓库当中,并在我们的项目中使用这个模块提供的cli以及它提供的自动化构建工作流。
- npm去publicsh的时候会默认去把项目根目录下的文件,和package.json中的files配置的对应目录发布到npm仓库当中。
FIS
安装fis3到项目目录下
npm install fis3 --save-dev
在项目目录下新建一个fis的配置文件fis-conf.js
资源定位
FIS3 配置文件(默认fis-conf.js)所在的目录为项目根目录 执行 **fis3 release -d ‘路径’**将资源发布到该路径
fis.match(selector, props)
- selector: FIS3 把匹配文件路径的路径作为selector,匹配到的文件会分配给它设置的 props
- props :编译规则属性,包括文件属性和插件属性
例如:
fis3 release -d output
编译与压缩
可以通过配置文件的方式 去配置 如何处理文件的编译
fis-conf的书写方式是类似于css的声明方式,通过match方法的第一个参数去指定一个选择器(global通配符),用选择器去命中那些转换过程中的文件
scss文件的转换:
-
安装 fis-parser-node-sass(依赖node-sass)
yarn add fis-parser-node-sass --save-dev
-
在match选项中添加parser,通过fis.plugin载入插件
fis.match('**/*.scss', { //renameExt扩展名的修改 rExt:'.css', //通过node-sass 指定使用插件 parser : fis.plugin('node-sass'), //fis内置,压缩css optimizer:fis.plugin('clean-css') } )
-
执行
fis3 release -d output
执行编译后会发现assets/css目录下生成了.css文件,而且在最终使用这些文件的地方,也会自动只使用编译后的资源(index.html引用scss文件变成了引用css文件)
这也是资源定位能力的核心体现。
JS文件(ES6)的转换:
-
安装babel
yarn add fis-parser-babel-6.x --save-dev
-
在match选项中添加parser,通过fis.plugin载入插件
fis.match('**/*.js', { //通过node-sass 指定使用插件 parser : fis.plugin('babel-6.x'), //fis内置,压缩js optimizer:fis.plugin('uglify-js') } )
-
执行
fis3 release -d output
自调用函数时传入window和document
- 性能问题,这样在函数当中使用它们时相当于使用局部变量,不用去通过作用域链一层层向上寻找,减少性能开销
- 使用这种方式,使用的比例越多,压缩后的结果会将它们替换成一些简单的字符,字符数会减少很多