自动化构建
自动化构建
源代码 -> 生成代码
输入 scss scss/main.scss css/style.css
即可构建出 css
缺点:每次都需要重复输入这个复杂的命令
npm script 就是用来解决这个问题
json{ "scripts": { "build": "sass scss/main.scss css/style.css --watch", }, }
接下来安装 browser-sync
用于启动测试服务器
yarn add browser-sync --dev
运行测试服务器 npm run serve
--files
监听文件变化
{
"scripts": {
"serve": "browser-sync . --files \"css/*.css\"
},
}
不过这里可能有个问题,如果在运行测试服务器之前,没有生成 css,浏览器就没办法展示样式
- 这里就可以用到 npm script 的钩子机制
preserve
在启动任务之前,让 build 先去工作
{
"scripts": {
"preserve": "yarn build"
},
}
如果给 build 增加 --watch
参数,scss 会阻塞命令行等待文件变化,就会导致 browser-sync
没办法直接去工作
这里就需要用
npm-run-all
同时执行多个命令bashyarn add npm-run-all --dev
{
"scripts": {
"start": "run-p build serve"
},
}
常用工具
- 严格来说 Webpack 是模块打包工具
- Grunt、Gulp、FIS 是自动化构建工具
- Grunt 老牌构建工具,插件生态完善,但是它的工作过程是基于临时文件实现的,所以构建速度较慢(Scss 编译后就会将结果写入到临时文件,下一个插件读取这个临时文件进行操作,环节越多读取文件次数越多)
- Gulp 基于内存实现的,对文件的处理都是在内存中实现,速度快一些,默认同时支持多个任务,目前比较流行
- FIS 百度团队研发,把项目中最典型需求都集成到内部,大而全
Grunt
基本使用
yarn init –yes
yarn add grunt
新建 gruntfile.js
- Grunt 的入口文件,用于定义一些需要 Grunt 自动执行的任务
- 需要导出一个函数,该函数接收一个 grunt 对象,内部提供一些创建任务可以用到的 API
module.exports = grunt => {
grunt.registerTask('foo', '任务描述', () => {
console.log('foo')
})
grunt.registerTask('bar', () => {
console.log('bar')
})
// 第二个参数可以指定此任务的映射任务
// 这样执行 default 就相当于执行对应的任务
// 这里映射的任务会按顺序依次执行,不会同步执行
grunt.registerTask('default', ['foo', 'bar'])
// 由于函数体中需要使用 this,所以这里不能使用箭头函数
grunt.registerTask('async-task', function () {
const done = this.async()
setTimeout(() => {
console.log('async task working~')
done()
}, 1000)
})
}
标记任务失败
任务函数执行过程中如果返回 false,则意味着此任务执行失败
如果一个任务列表中的某个任务执行失败,则后续任务默认不会运行
除非 grunt 运行时指定
--force
参数强制执行异步函数中标记当前任务执行失败的方式是为回调函数指定一个 false 的实参
module.exports = grunt => {
grunt.registerTask('bad', () => {
console.log('bad working~')
return false
})
grunt.registerTask('foo', () => {
console.log('foo working~')
})
grunt.registerTask('bar', () => {
console.log('bar working~')
})
grunt.registerTask('default', ['foo', 'bad', 'bar'])
grunt.registerTask('bad-async', function () {
const done = this.async()
setTimeout(() => {
console.log('async task working~')
done(false)
}, 1000)
})
}
配置选项方法
用 init
配置,用 grunt.config
获取属性值
module.exports = grunt => {
grunt.initConfig({
foo: {
bar: 123,
},
})
grunt.registerTask('foo', () => {
console.log(grunt.config('foo.bar'))
})
}
多目标任务
用 init
配置,通过 this
拿到执行的名称和数据
module.exports = grunt => {
// 多目标模式,可以让任务根据配置形成多个子任务
grunt.initConfig({
build: {
options: {
msg: 'task options',
},
foo: {
options: {
msg: 'foo target options',
},
},
bar: '456',
},
})
grunt.registerMultiTask('build', function () {
console.log(this.options())
console.log(`target:${this.target},data:${this.data}`)
})
}
Grunt 插件
安装 grunt-contrib-clean
yarn add grunt-contrib-clean --dev
将 temp 目录下所有文件都清除
module.exports = grunt => {
grunt.initConfig({
clean: {
temp: 'temp/**',
},
})
grunt.loadNpmTasks('grunt-contrib-clean')
}
安装 grunt-sass
、sass
yarn add grunt-sass sass --dev
安装 grunt-babal
、babel
yarn add grunt-babel @babel/core @babel/preset-env --dev
随着 gruntfile.js
越来越复杂,loadNpmTasks
操作也会越来越多,可以使用 load-grunt-tasks
yarn add load-grunt-tasks --dev
当文件修改完,需要自动去编译,这时需要另外一个插件 grunt-contrib-watch
yarn add grunt-contrib-watch --dev
Grunt 使用插件
const sass = require('sass')
const loadGruntTasks = require('load-grunt-tasks')
module.exports = grunt => {
grunt.initConfig({
sass: {
options: {
sourceMap: true,
implementation: sass,
},
main: {
files: {
'dist/css/main.css': 'src/scss/main.scss',
},
},
},
babel: {
options: {
sourceMap: true,
presets: ['@babel/preset-env'],
},
main: {
files: {
'dist/js/app.js': 'src/js/app.js',
},
},
},
watch: {
js: {
files: ['src/js/*.js'],
tasks: ['babel'],
},
css: {
files: ['src/scss/*.scss'],
tasks: ['sass'],
},
},
})
loadGruntTasks(grunt) // 自动加载所有 grunt 插件中的任务
grunt.registerTask('default', ['sass', 'babel', 'watch'])
}
Gulp
基本使用
Gulp 核心特点:高效易用
- 安装 Gulp 同时会自动安装一个叫 gulpcli 模块
yarn init --yes
yarn add gulp --dev
创建 gulpfile.js
入口,导出一个 foo 函数
exports.foo = () => {
console.log('foo task working~')
}
执行 yarn gulp foo
,发现有报错
- gulp 取消了同步代码模式,约定每一个任务都是异步的,当任务执行完需要通过回调函数标记任务执行完毕
[11:04:54] The following tasks did not complete: foo
[11:04:54] Did you forget to signal async completion?
error Command failed with exit code 1.
gulp 4.0 以后的保留了 gulp.task
API
- gulp 4.0 以后推荐使用导出函数成员方式
exports.foo = done => {
console.log('foo task working~')
done() // 标识任务执行完成
}
// default 是默认任务
exports.default = done => {
console.log('default task working~')
done()
}
// v4.0 之前需要通过 gulp.task() 方法注册任务
const gulp = require('gulp')
gulp.task('bar', done => {
console.log('bar task working~')
done()
})
组合任务
通过 series
、parallel
组合多个任务
- 编译 CSS、JS 任务互不干扰可以并行处理
const { series, parallel } = require('gulp')
const task1 = done => {
setTimeout(() => {
console.log('task1 working~')
done()
}, 1000)
}
const task2 = done => {
setTimeout(() => {
console.log('task2 working~')
done()
}, 1000)
}
const task3 = done => {
setTimeout(() => {
console.log('task3 working~')
done()
}, 1000)
}
// 让多个任务按照顺序依次执行
exports.foo = series(task1, task2, task3)
// 让多个任务同时执行
exports.bar = parallel(task1, task2, task3)
异步任务
- 回调函数
- Promsie、async 和 await(Node 8 以上的版本)
- Stram 方式
const fs = require('fs')
exports.callback = done => {
console.log('callback task')
done()
}
exports.callback_error = done => {
console.log('callback task')
done(new Error('task failed'))
}
exports.promise = () => {
console.log('promise task')
return Promise.resolve()
}
exports.promise_error = () => {
console.log('promise task')
return Promise.reject(new Error('task failed'))
}
const timeout = time => {
return new Promise(resolve => {
setTimeout(resolve, time)
})
}
exports.async = async () => {
await timeout(1000)
console.log('async task')
}
exports.stream = () => {
const readStream = fs.createReadStream('package.json')
const writeStream = fs.createWriteStream('temp.txt')
readStream.pipe(writeStream) // pipe导入写入流中
// gulp 只是注册了 end 事件去结束
/* readStream.on('end', () => {
done()
}) */
return readStream
}
核心工作原理
- The streaming build system
stream 的 Transform 类型可以创建文件转换流对象,里面需要指定 transform 属性(转化流核心转换过程)
const fs = require('fs')
const { Transform } = require('stream')
exports.default = () => {
// 文件读取流
const readStream = fs.createReadStream('normalize.css')
// 文件写入流
const writeStream = fs.createWriteStream('normalize.min.css')
// 文件转换流
const transformStream = new Transform({
// 核心转换过程
transform: (chunk, encoding, callback) => {
const input = chunk.toString()
const output = input.replace(/\s+/g, '').replace(/\/\*.+?\*\//g, '')
callback(null, output)
},
})
return readStream
.pipe(transformStream) // 转换
.pipe(writeStream) // 写入
}
文件操作 API
yarn add gulp-clean-css --dev
yarn add gulp-rename --dev
通过 src 去 pipe 到插件转换流,再去 pipe 到写入流的过程就是使用 gulp 常规过程
const { src, dest } = require('gulp')
const cleanCSS = require('gulp-clean-css')
const rename = require('gulp-rename')
exports.default = () => {
return src('src/*.css')
.pipe(cleanCSS())
.pipe(rename({ extname: '.min.css' }))
.pipe(dest('dist'))
}
Gulp 案例
样式编译
下载代码
git clone https://github.com/zec/zec-gulp-demo.git
安装 gulp
、gulp-sass
- 安装
gulp-sass
会安装 node-sass(是 C++ 模块),内部会有对 C++ 程序集的依赖,二进制包需要国外站点去下载,有时会下载不下来,可以配置淘宝镜像源下载
yarn add gulp --dev
yarn add gulp-sass --dev
const { src, dest } = require('gulp')
const sass = require('gulp-sass')
const style = () => {
return src(`src/assets/styles/*.scss`, { base: 'src' })
.pipe(sass({ outputStyle: 'expanded' }))
.pipe(dest('dist'))
}
module.exports = {
style,
}
脚本编译
安装 gulp-babel
、@babel/core
、@babel/preset-env
yarn add gulp-babel --dev
yarn add @babel/core @babel/preset-env --dev
const { src, dest } = require('gulp')
const babel = require('gulp-babel')
const script = () => {
return src(`src/assets/scripts/*.js`, { base: 'src' })
.pipe(babel({ presets: ['@babel/preset-env'] }))
.pipe(dest('dist'))
}
module.exports = {
script,
}
页面模板编译
安装 gulp-swig
yarn add gulp-swig --dev
const { src, dest, parallel } = require('gulp')
const swig = require('gulp-swig')
const data = {
menus: [
{
name: 'Home',
icon: 'aperture',
link: 'index.html',
},
{
name: 'Features',
link: 'features.html',
},
{
name: 'About',
link: 'about.html',
},
{
name: 'Contact',
link: '#',
children: [
{
name: 'Twitter',
link: 'https://twitter.com/w_zce',
},
{
name: 'About',
link: 'https://weibo.com/zceme',
},
{
name: 'divider',
},
{
name: 'About',
link: 'https://github.com/zce',
},
],
},
],
pkg: require('./package.json'),
date: new Date(),
}
const page = () => {
return src(`src/**/*.html`, { base: 'src' }).pipe(swig({ data })).pipe(dest('dist'))
}
const compile = parallel(style, script, page)
module.exports = {
compile
}
图片和字体文件的转换
安装 gulp-imagemin
- 内部依赖的模块也是通过 C++ 模块,需要下载二进制程序集(大部分 GitHub 下载),但是这个没办法配置镜像
yarn add gulp-imagemin --dev
const { src, dest, parallel } = require('gulp')
const imagemin = require('gulp-imagemin')
const image = () => {
return src(`src/assets/images/**`, { base: 'src' }).pipe(imagemin()).pipe(dest('dist'))
}
const font = () => {
return src(`src/assets/fonts/**`, { base: 'src' }).pipe(imagemin()).pipe(dest('dist'))
}
const compile = parallel(style, script, page, image, font)
module.exports = {
compile
}
其它文件及文件清除
安装 del
yarn add del --dev
const { src, dest, parallel, series } = require('gulp')
const del = require('del')
const clean = () => {
return del(['dist'])
}
const compile = parallel(style, script, page, image, font)
const build = series(clean, parallel(compile, extra))
module.exports = {
build,
}
自动加载插件
安装 gulp-load-plugins
yarn add gulp-load-plugins --dev
const { src, dest, parallel, series } = require('gulp')
const del = require('del')
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()
const data = {...}
const clean = () => {
return del(['dist'])
}
const style = () => {
return src(`src/assets/styles/*.scss`, { base: 'src' })
.pipe(plugins.sass({ outputStyle: 'expanded' }))
.pipe(dest('dist'))
}
const script = () => {
return src(`src/assets/scripts/*.js`, { base: 'src' })
.pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
.pipe(dest('dist'))
}
const page = () => {
return src(`src/**/*.html`, { base: 'src' }).pipe(plugins.swig({ data })).pipe(dest('dist'))
}
const image = () => {
return src(`src/assets/images/**`, { base: 'src' }).pipe(plugins.imagemin()).pipe(dest('dist'))
}
const font = () => {
return src(`src/assets/fonts/**`, { base: 'src' }).pipe(plugins.imagemin()).pipe(dest('dist'))
}
const extra = () => {
return src(`public/**`, { base: 'public' }).pipe(dest('dist'))
}
const compile = parallel(style, script, page, image, font)
const build = series(clean, parallel(compile, extra))
module.exports = {
build,
}
热更新开发服务器
安装 browser-sync
yarn add browser-sync --dev
编译过程中并没有处理
node_modules
模块下面的拷贝可以给
browser-sync
增加一个单独的路由(routes
),这个路由优先级比baseDir
高
const browserSync = require('browser-sync')
const bs = browserSync.create()
const serve = () => {
bs.init({
notify: false,
port: 2080,
// open: false,
files: 'dist/**',
server: {
baseDir: 'dist',
routes: {
'/node_modules': 'node_modules',
},
},
})
}
module.exports = {
serve,
}
监听变化及构建优化
style
、script
、page
文件改变可以.pipe(bs.reload({ stream: true }))
这样
files: 'dist/**'
就不需要了
const { src, dest, parallel, series, watch } = require('gulp')
const style = () => {
return src(`src/assets/styles/*.scss`, { base: 'src' })
.pipe(plugins.sass({ outputStyle: 'expanded' }))
.pipe(dest('dist'))
.pipe(bs.reload({ stream: true }))
}
const script = () => {
return src(`src/assets/scripts/*.js`, { base: 'src' })
.pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
.pipe(dest('dist'))
.pipe(bs.reload({ stream: true }))
}
const page = () => {
return src(`src/**/*.html`, { base: 'src' })
.pipe(plugins.swig({ data }))
.pipe(dest('dist'))
.pipe(bs.reload({ stream: true }))
}
const serve = () => {
watch('src/assets/styles/*.scss', style)
watch('src/assets/scripts/*.js', script)
watch('src/*.html', page)
// watch('src/assets/images/**', image)
// watch('src/assets/fonts/**', font)
// watch('public/**', extra)
watch(['src/assets/images/**', 'src/assets/fonts/**', 'public/**'], bs.reload)
bs.init({
notify: false,
port: 2080,
// open: false,
// files: 'dist/**',
server: {
baseDir: ['dist', 'src', 'public'],
routes: {
'/node_modules': 'node_modules',
},
},
})
}
const compile = parallel(style, script, page)
const build = series(clean, parallel(compile, image, font, extra))
const develop = series(compile, serve)
useref 文件引用处理
有些文件依赖的是 node_modules
下的文件,这里并没有将其拷贝到 dist 目录,如果上线肯定找不到,本地能找到是因为做了路由映射
yarn add gulp-useref --dev
构建注释
<!-- build:css assets/styles/vendor.css -->
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.css">
<!-- endbuild -->
<!-- build:css assets/styles/main.css -->
<link rel="stylesheet" href="assets/styles/main.css">
<!-- endbuild -->
const useref = () => {
return src('dist/*.html', { base: 'dist' })
.pipe(plugins.useref({ searchPath: ['dist', '.'] }))
.pipe(dest('dist'))
}
分别压缩 HTML、CSS、JS
- 另外还需要判断对不同文件的操作,这个时候就需要一个额外的插件去判断
yarn add gulp-htmlmin gulp-uglify gulp-clean-css --dev
yarn add gulp-if --dev
操作时会发现 main.css
没有内容,这时因为文件读写冲突,一边读一边写
- 可以把最终转换的结果放在其他目录中
const useref = () => {
return src('dist/*.html', { base: 'dist' })
.pipe(plugins.useref({ searchPath: ['dist', '.'] }))
.pipe(plugins.if(/\.js$/, plugins.uglify()))
.pipe(plugins.if(/\.css$/, plugins.cleanCss()))
.pipe(
plugins.if(
/\.html$/,
plugins.htmlmin({
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true,
})
)
)
.pipe(dest('release'))
}
重新规划构建过程
useref 打破了我们的目录结构
- 打包上线是 dist 目录,而 useref 把目录改成了 release
增加临时目录 temp
script
、style
、page
放到 temp 目录image
、font
、extra
不需要改,这三个只需要 build 时候去做,只有被 useref 影响才需要serve
里的 baseDir 需要改为 tempuseref
src 从 temp 里取,把结果放到dist
目录里
const { src, dest, parallel, series, watch } = require('gulp')
const del = require('del')
const browserSync = require('browser-sync')
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()
const bs = browserSync.create()
const clean = () => {
return del(['dist', 'temp'])
}
const style = () => {
return src('src/assets/styles/*.scss', { base: 'src' })
.pipe(plugins.sass({ outputStyle: 'expanded' }))
.pipe(dest('temp'))
.pipe(bs.reload({ stream: true }))
}
const script = () => {
return src('src/assets/scripts/*.js', { base: 'src' })
.pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
.pipe(dest('temp'))
.pipe(bs.reload({ stream: true }))
}
const page = () => {
return src('src/*.html', { base: 'src' })
.pipe(plugins.swig({ data, defaults: { cache: false } })) // 防止模板缓存导致页面不能及时更新
.pipe(dest('temp'))
.pipe(bs.reload({ stream: true }))
}
const image = () => {
return src('src/assets/images/**', { base: 'src' })
.pipe(plugins.imagemin())
.pipe(dest('dist'))
}
const font = () => {
return src('src/assets/fonts/**', { base: 'src' })
.pipe(plugins.imagemin())
.pipe(dest('dist'))
}
const extra = () => {
return src('public/**', { base: 'public' })
.pipe(dest('dist'))
}
const serve = () => {
watch('src/assets/styles/*.scss', style)
watch('src/assets/scripts/*.js', script)
watch('src/*.html', page)
// watch('src/assets/images/**', image)
// watch('src/assets/fonts/**', font)
// watch('public/**', extra)
watch([
'src/assets/images/**',
'src/assets/fonts/**',
'public/**'
], bs.reload)
bs.init({
notify: false,
port: 2080,
// open: false,
// files: 'dist/**',
server: {
baseDir: ['temp', 'src', 'public'],
routes: {
'/node_modules': 'node_modules'
}
}
})
}
const useref = () => {
return src('temp/*.html', { base: 'temp' })
.pipe(plugins.useref({ searchPath: ['temp', '.'] }))
// html js css
.pipe(plugins.if(/\.js$/, plugins.uglify()))
.pipe(plugins.if(/\.css$/, plugins.cleanCss()))
.pipe(plugins.if(/\.html$/, plugins.htmlmin({
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true
})))
.pipe(dest('dist'))
}
const compile = parallel(style, script, page)
const build = series(
clean,
parallel(
series(compile, useref),
image,
font,
extra
)
)
const develop = series(compile, serve)
module.exports = {
clean,
build,
develop
}
构建完这套系统,如果你不想写文档说明,导出几个常用即可,clean
、build
、develop
- 并在
package.json
中增加 script 命令
"scripts": {
"clean": "gulp clean",
"build": "gulp build",
"develop": "gulp develop"
},
封装工作流
提取多个项目共同的自动化构建过程(Don't repeat yourself)
提取 gulpfile
zce-gulp-demo
这里叫 A,zce-pages
这里叫 B
- 在命令行输入
code . -a
在同一窗口打开这个项目
把 A 项目工作流提取到 B 项目中,操作步骤如下:
- 把 A 的
gulpfile.js
内容复制到 B 的lib/index.js
- 把 A 的
package.json
中的devDependencies
复制到 B 中dependencies
- 把 A 的
package.json
中的devDependencies
全部删除,并把node_modules
全部删除 - 把 B link 到全局,切换到 A 输入命令
yarn link zce-pages
,B 项目会通过软链接形式链过来 - 在 B 中新建
gulpfile.js
新增module.exports = require('zce-pages')
内容 - 执行
yarn build
执行 yarn build
我这边报错了,是因为 gulp-sass
没有下载下来
Error in plugin "gulp-sass"
Message:
gulp-sass no longer has a default Sass compiler; please set one yourself.
Both the "sass" and "node-sass" packages are permitted.
解决:安装 sass
yarn add sass
修改 lib/index.js
const sass = require('gulp-sass')(require('sass'))
const style = () => {
return src('src/assets/styles/*.scss', { base: 'src' })
.pipe(sass({ outputStyle: 'expanded' }))
.pipe(dest('temp'))
.pipe(bs.reload({ stream: true }))
}
抽象路径配置
对于代码里写死的路径,如 sass 的路径,这样不是很灵活,我们可以抽象一下形成配置
cwd
返回命令行工作目录,然后拿到工作文件pages.config.js
require
不存在的目录会报错,所以这里用try...catch...
包裹一下
const cwd = process.cwd()
let config = {
build: {
src: 'src',
dist: 'dist',
temp: 'temp',
public: 'public',
paths: {
styles: 'assets/styles/*.scss',
scripts: 'assets/scripts/*.js',
pages: '*.html',
images: 'assets/images/**',
fonts: 'assets/fonts/**'
}
}
}
try {
const loadConfig = require(`${cwd}/pages.config.js`)
config = Object.assign({}, config, loadConfig)
} catch (e) {}
const style = () => {
return src(config.build.paths.styles, { base: config.build.src, cwd: config.build.src })
.pipe(sass({ outputStyle: 'expanded' }))
.pipe(dest(config.build.temp))
.pipe(bs.reload({ stream: true }))
}
包装 Gulp Cli
gulpfile.js
里只是写了个 module.exports = require('zce-pages')
,其实有点冗余,我们希望没有 gulpfile.js
也能正常工作
- 这里需要制定一下工作目录为当前
yarn gulp build --gulpfile ./node_modules/zce-pages/lib/index.js --cwd .
不过这么多参数就很复杂了,可以集成 cli
创建
bin/zce-pages.js
作为 cli 执行入口在
package.json
中增加bin
字段json"bin": "bin/zce-pages.js",
修改 zce-pages.js
process.argv
是一个数组require
是载入这个模块,require.resolve
是找到这个模块所在的路径
#!/usr/bin/env node
process.argv.push('--cwd')
process.argv.push(process.cwd())
process.argv.push('--gulpfile')
process.argv.push(require.resolve('..'))
require('gulp/bin/gulp')
代码提交完,就可以使用 publish 提交 git
yarn publish --registry https://registry.yarnpkg.com
同步时可能会有问题,因为你发布的是 npm 源,但是你是从淘宝源下载,可能会存在同步问题,可以进入淘宝镜像搜一下你 publish 的包,然后更新
总结
新建项目如果想要使用工作流,直接运行
package.json
中的命令即可创建的 cli 是
node_modules/bin/zce-pages.cmd
,这个文件中是通过 node 去执行zce-pages/bin/zce-pages.js
在
node_modules
找到zce-pages/bin/zce-pages.js
,里面就是告诉 gulp 工作时的工作目录和 gulpfile 的工作目录之后执行
gulp/bin/gulp
就可以执行 gulpifle 了,完成整个工作流过程
FIS
高度集成,只需要简单配置
yarn global add fis3
relase 解决的资源定位
fis3 realse -d output
新建 fis-conf.js
编译与压缩
安装
yarn add fis-parser-node-sass
、yarn add fis-parser-babel-6.x
fis.match('*.{js,scss,png}', {
release: '/assets/$0',
})
fis.match('**/*.scss', {
rExt: '.css',
parser: fis.plugin('node-sass'),
optimizer: fis.plugin('clean-css'),
})
fis.match('**/*.js', {
parser: fis.plugin('babel-6.x'),
optimizer: fis.plugin('uglify-js'),
})
查看转换过程中转换的配置
fis3 inspect