前言
在日常开发中,我们开发多个同类型项目时,自动化构建流大致都是相同的。而我们需要在每个项目都去重复配置构建任务,所以针对此问题,我们去提取一个可复用的自动化工作流
☆ 主要考虑:gulpfile 复用的问题,对于gulpfile的配置可以去看gulp的基本使用方式,此文中提到的gulpfile配置都可以在上面找到
思路
通过我们创建一个模块,去包装一下gulp 以及gulpfile, 把自动化构建工作流包装到这个模块里面去。之后提供此模块去构建项目
准备工作
- 创建一个模块,然后把这个模块发布到npm仓库上,最后在项目中使用
- github上面创建一个仓库
yp-gulp - 在本地创建一个新的目录文件,并
yarn init --yes初始化这个项目 - 创建一个lib/index.js 作为这个模块的入口文件
提取gulpfile
- 把gulpfile中的内容全部copy到 lib/index.js中
- 在dependencies中加上gulpfile需要的依赖, 执行
yarn去安装这些依赖 - 开发阶段通过
yarn link的方式把我们开发的模块link到全局 - 之后我们根据这个模块运行时候的问题进行修改
- 在需要构建的项目中,通过
yarn link "yp-gulp"去使用这个模块 - 因为
yp-gulp模块导出的就是一个gulpfile,所以先在项目的 gulpfile.js中引入并导出这个模块module.exports = require('yp-gulp')(后面会对这个操作进行处理,暂时先这样写) - 在项目中执行
yarn build会发生报错gulp: command not found, 这个地方我们先把gulp安装进来,等后续进行处理yarn add gulp gulp-cli --dev
解决模块中出现的问题
主要去解决在工作模块中不应该被提取的东西,全部抽象出来
抽象data
- 在项目中运行
yarn build的时候,出现报错Cannot find module './package.json' - 在项目根目录初始化一个配置文件
pages.config.js,然后在yp-gulp/lib/index.js 中读取这个配置文件,用于去替换之前写死的data
// 项目中 pages.config.js 的配置
module.exports ={
data: {
menus: [
{
name: "Home",
icon: "aperture",
link: "index.html"
},
{
name: "Features",
link: "features.html"
},
{
name: "About",
link: "about.html"
}
],
pkg: require('./package.json'),
date: new Date()
}
}
// yp-gulp/lib/index.js 中的data读取改成读取当前命令目录下的配置文件
const cwd = process.cwd() // 会返回当前命令行工作的目录
let config = {
// default config
}
try {
const loadConfig = require(`${cwd}/pages.config.js`)
config = Object.assign({},config,loadConfig)
}catch(e){}
- 然后运行
yarn build就会显示新的报错PluginError: Cannot find module '@babel/preset-env'
更改babel-preset的引入方式
这个模块是我们在创建script任务配置babel的时候指定的preset,babel转换会通过preset去找对应的preset模块,然后转换ES模块,其查找规则是到项目根目录下的node_modules/@babel-preset模块,但是此时项目中并没有这个模块,解决问题的方式也很简单,就是吧preset中的配置去做一个修改,通过require的方式载入
require的方式是先到当前目录下面依次查找,也就是先从lib查找,最后找到上一级的node_modules 中找到
const script = ()=>{
return src('src/assets/scripts/*.js', { base: 'src' })
.pipe(plugins.babel({presets: [require('@babel/preset-env')]})) // 去修改这个地方,通过require的方式载入
.pipe(dest('temp'))
.pipe(bs.reload({stream: true}))
}
- 再去运行
yarn build发现build 正常执行了,并且项目下成功生成了dist文件
抽象路径配置
为我们lib/index.js文件中固定的路径改写成可配置的路径
- 实现方法就是在我们
lib/index.js的配置中填写一个默认的config,把模块中写死的路径改成可配置,用户可以通过配置来实现模块路径的改写
// lib/index.js 下面的文档路径配置
let config = {
// default config
build:{
src:'src',
dist: 'dist',
temp: '.temp',
public: 'public',
paths:{
pages: '*.html',
script: 'assets/scripts/*.js',
style: 'assets/styles/*.scss',
image: 'assets/images/**',
font: 'assets/fonts/**'
}
}
}
- 改变下模块中每个文件的路径配置,拿script任务为例(需要需改的配置地方比较多,可以在github上找到所有的配置)
const script = ()=>{
return src(config.build.paths.script, { cwd: config.build.src , base: config.build.src })
.pipe(plugins.babel({presets: [require('@babel/preset-env')]}))
.pipe(dest(config.build.temp))
.pipe(bs.reload({stream: true})) // 内部以流的方式推到浏览器,
}
包装Gulp Cli
需求:目前我们通过在gulpfile导出yp-gulp模块来实现构建,我们希望没有和这个导出步骤,模块也能正常工作
- 我们在项目中删除gulpfile然后运行
yarn gulp build --gulpfile ./node_modules/yp-gulp/lib/index.js --cwd .也是可以正常工作的- --gulpfile:去指定gulpfile所在的目录
- --cwd:指定当前的工作目录(不指定的话当前的工作目录会在
~/lagou/gulpConf/node_modules/yp-gulp/lib)
- 项目运行参数过于繁琐,所以我们尝试在模块中封装一个cli,来把gulp-cli的操作封装起来
- 在yp-gulp 模块去创建 bin/yp-gulp.js 作为我们cli的入口文件
- 在package.json 中加入bin 字段
bin: bin/yp-gulp.js
yp-gulp.js 的配置
#!/usr/bin/env node
// 命令行中传递的参数可以通过process.argv 来拿到,这是一个数组
// 所以在代码运行前,我们可以现在cli中push 对应的参数
process.argv.push('--cwd')
process.argv.push(process.cwd()); // 当前命令行所在目录
process.argv.push('--gulpfile')
process.argv.push(require.resolve('..'))
require('gulp/bin/gulp') // 自动去载入gulp-cli
- ✨ 这里需要注意的一点是 在Mac中需要将cli的可读权限设置为
chmod 755 bin/yp-gulp.js - 重新link这个模块,运行
yp-gulp build就可以对文件进行build操作
发布模块
这边需要注意一个小点,我们通过npm publish 的时候默认会把项目根目录下的文件,和在package.json中files 配置的目录发布到仓库中,所以需要在files中加上bin和lib
// package.json
files:[
"lib","bin"
]
保存过后,我们进入命令行执行 yarn publish --registry https://registry.yarnpkg.com 就成功发布这个模块啦