美文网首页
前端小白成长之16--自动化构建Gulp

前端小白成长之16--自动化构建Gulp

作者: Clover园 | 来源:发表于2020-06-16 01:14 被阅读0次

    ctrl+e ctrl+1
    https://www.cnblogs.com/xqbiii/p/8406978.html

    yarn init --yes
    yarn add gulp --dev
    

    一.基本使用

    exports.foo = (done) => {
        console.log('任务foo')
        done() // 标识任务执行完成
    }//yarn gulp foo
    
    // 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()
    })
    

    二.执行并行任务,串行任务

    const { series, parallel } = require('gulp')

    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)
    

    三.异步任务的几种方法

    const fs = require('fs')
    // 一回调
    exports.callback = done => {
        console.log('callback task')
        done()
    }
    exports.callback_error = done => {
        console.log('回调报错处理')
        done(new Error('task failed'))
    }
    //二 通过promise,这里也是支持promise的,resolve不需要返回值,就算返回也会被忽略,直接resolve()
    exports.promise = done => {
        console.log('promise')
        return Promise.resolve()
    }
    
    exports.promise_error = () => {
        console.log('promise_error')
        return Promise.reject(new Error('promise failed'))
    }
    
    // 三async await
    const timeOut = (time) => {
        return new Promise(resolve => {
            setTimeout(resolve(), time);
        })
    }
    exports.async = async () => {
        await timeOut(1000)
        console.log('1秒后打印')
    }
    
    // stream
    exports.stream = () => {
        const read = fs.createReadStream('yarn.lock')
        const write = fs.createWriteStream('a.txt')
        read.pipe(write)
        return read
    }
    

    四.glup构建过程

    image.png
    image.png

    eg:这里用node自带的读取流写入流

    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) // 写入
    }
    

    eg:gulp的读取流,写入流
    const { src, dest } = require('gulp')

    const { src, dest } = require('gulp')
    const cleanCSS = require('gulp-clean-css')//转换流插件压缩css
    const rename = require('gulp-rename')//重命名后缀
    
    exports.default = () => {
      return src('src/*.css')
        .pipe(cleanCSS())
        .pipe(rename({ extname: '.min.css' }))
        .pipe(dest('dist'))
    }
    
    //定义变量,引入gulp及各个插件
    
    const gulp = require("gulp"),
        sass = require("gulp-sass"),
        connect = require("gulp-connect"),
        uglify = require("gulp-uglify"),
        babel = require("gulp-babel"),
        htmlmin = require("gulp-htmlmin");
    
    // 编译SCSS文件
    gulp.task("sass", function() {
        gulp.src("./src/scss/*.scss")
            .pipe(sass({outputStyle:"compressed"}))
            .pipe(gulp.dest("./src/css"))
            .pipe(connect.reload());
    });
    // html文件修改刷新
    gulp.task("html", function() {
        gulp.src("./src/**/*.html")
            .pipe(connect.reload());
    });
    // js文件修改刷新
    gulp.task("js", function() {
        gulp.src("./src/js/*.js")
            .pipe(connect.reload());
    });
    // 启动服务器
    gulp.task("connect", function() {
        connect.server({
            root : "src",
            livereload : true
        });
    });
    // 监视任务
    gulp.task("watch", function(){
        gulp.watch("./src/**/*.html", ["html"]);
        gulp.watch("./src/js/*.js", ["js"]);
        gulp.watch("./src/scss/*.scss", ["sass"]);
    });
    // 开发环境下的gulp任务
    gulp.task("dev", ["sass", "html", "js", "connect", "watch"]);
    
    /***************************************************************/
    // 生产环境下的 gulp 任务,将项目生成到 dist 目录下
    // dist 目录下的资源是直接用于生产环境(发布项目)的资源
    // 编译SCSS文件:生产环境
    gulp.task("prod_sass", function() {
        gulp.src("./src/scss/*.scss")
            .pipe(sass({outputStyle:"compressed"}))
            .pipe(gulp.dest("./dist/css"))
            .pipe(connect.reload());
    });
    // html文件压缩
    gulp.task("prod_html", function() {
        gulp.src("./src/**/*.html")
            .pipe(htmlmin({collapseWhitespace: true}))
            .pipe(gulp.dest("./dist"))
            .pipe(connect.reload());
    });
    // JS转换及压缩
    gulp.task("prod_js", function() {
        gulp.src("./src/js/*.js")
            .pipe(babel({
                presets: ['env']
            }))
            .pipe(uglify())
            .pipe(gulp.dest("./dist/js"))
            .pipe(connect.reload());
    });
    // 复制源文件夹下资源到目标文件夹
    gulp.task("copy-images", function() {
        gulp.src("./src/images/**/*.*")
            .pipe(gulp.dest("./dist/images"));
    });
    gulp.task("copy-lib", function() {
        gulp.src("./src/lib/**/*.*")
            .pipe(gulp.dest("./dist/lib"));
    });
    gulp.task("prod_copy", ["copy-images", "copy-lib"]);
    // 监视任务
    gulp.task("prod_watch", function(){
        gulp.watch("./src/**/*.html", ["prod_html"]);
        gulp.watch("./src/js/*.js", ["prod_js"]);
        gulp.watch("./src/scss/*.scss", ["prod_sass"]);
    });
    // 启动服务器
    gulp.task("prod_connect", function() {
        connect.server({
            root : "dist",
            livereload : true
        });
    });
    // 生产环境gulp任务
    gulp.task("production", ["prod_sass", "prod_html", "prod_js", "prod_copy", "prod_connect", "prod_watch"]);
    

    1.基础

    //入门 没有用插件yarn add gulp-load-plugins --dev,来自动加载插件,插件入门学习
    const { src, dest, parallel,series } = require('gulp')
    
    const del = require('del')//清除文件。返回的是promise
    
    const sass = require('gulp-sass')
    const babel = require('gulp-babel')
    const swig = require('gulp-swig')
    const imagemin = require('gulp-imagemin')
    
    const data = {
     ...
    }
    
    const clear = () => {
      return del(['dist'])
    }
    
    const style = () => {
      return src('src/assets/styles/*.scss', { base: 'src' })
        .pipe(sass({outputStyle:"expanded"}))
      .pipe(dest('dist'))
    }
    
    const script = () => {
      return src('src/assets/scripts/*.js', { base: 'src' })
        .pipe(babel({presets:['@babel/preset-env']}))
      .pipe(dest('dist'))
    }
    
    const page = () => {
      return src('src/*.html')
      .pipe(swig({data}))
      .pipe(dest('dist'))
    }
    
    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 extra = () => {
      return src('public/**', { base: 'public' })
      .pipe(dest('dist'))
    }
    
    
    const complete =  parallel(script,page,style,image,font)//编译src目录下的组合
    const build =  series(clear,parallel(extra,complete))//编译整个public和src,这里用series,先去清除dist文件,再生成新的
    
    module.exports = {
      complete,
      build
    }
    
    /**
     * 开发阶段,不去构建图片,字体,公共public,所以下个文件用serev时,baseDir指定为一个数组
     */
    const { src, dest, parallel, series, watch } = require('gulp')
    
    const del = require('del')//清除文件。返回的是promise
    const browserSync = require('browser-sync')//引入服务器,监听变化
    const bs = browserSync.create()//创建一个服务器
    
    const loadPlugins = require('gulp-load-plugins')
    const plugins = loadPlugins()
    
    const data = {
      ...
    }
    
    const clear = () => {
        return del(['dist'])//删除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')
            .pipe(plugins.swig({ data, defaults: { cache: false } }))// 防止模板缓存导致页面不能及时更新
            .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 complete = parallel(script, page, style, image, font)//编译src目录下的组合
    const build = series(clear, parallel(extra, complete))//编译整个public和src,这里用series,先去清除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),
            bs.init({
                notify: false,//右上角是否连上browser-sync提示是否关掉
                port: 8080,//默认是3000,
                open: false,//是否默认打开
                files: 'dist/**',//监听dist文件下变化实时更新
                server: {
                    baseDir: 'dist',
                    routes: {
                        '/node_modules': 'node_modules'//basic.html文件里面node_modules的样式路由到node_modules文件下找
                    }
                }
            })
    }
    
    module.exports = {
        complete,
        build,
        serve
    }
    
    /**
     * 1.开发阶段,不去构建图片,字体,公共public,所以用serev时,baseDir指定为一个数组   baseDir: ['dist','src','public'],这样开发阶段不用构建图片,字体,公共public
     *  2.files: 'dist/**',//监听dist文件下变化实时更新 不用这种方法,就在上面定义各个方法时,reload一下,比如page里面加上.pipe(bs.reload({ stream: true })),这里stream: true指,以流的方式推入浏览器
     * 3.
     */
    const { src, dest, parallel, series, watch } = require('gulp')
    
    const del = require('del')//清除文件。返回的是promise
    const browserSync = require('browser-sync')//引入服务器,监听变化
    const bs = browserSync.create()//创建一个服务器
    
    const loadPlugins = require('gulp-load-plugins')
    const plugins = loadPlugins()
    
    const data = {
    ...
    }
    
    const clear = () => {
      return del(['dist'])//删除dist文件
    }
    
    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')
        .pipe(plugins.swig({ data, defaults: { cache: false } }))// 防止模板缓存导致页面不能及时更新
        .pipe(dest('dist'))
        .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 complete = parallel(script, page, style)//编译src目录下的组合
    
    const build = series(clear, parallel(extra, complete, font, image))//编译整个public和src,这里用series,先去清除dist文件,再生成新的,上线之前执行build任务,开发阶段不需要构建图片字体等,没有必要,本来构建的图片字体就是原样压缩的
    
    const serve = () => {//初始化服务器配置
      watch('src/assets/styles/*.scss', style)//监视第一个参数路径的里面是否变化,变化就执行第二个参数任务
      watch('src/assets/scripts/*.js', script)
      watch('src/*.html', page)
      watch([
        'src/assets/images/**',
        'src/assets/fonts/**',
        'public/**'], bs.reload)
      bs.init({
        notify: false,//右上角是否连上browser-sync提示是否关掉
        port: 8080,//默认是3000,
        open: false,//是否默认打开
        // files: 'dist/**',//监听dist文件下变化实时更新 不用这种方法,就在上面定义各个方法时,reload一下,比如page里面加上.pipe(bs.reload({ stream: true })),这里stream: true指,以流的方式推入浏览器
        server: {
          baseDir: ['dist','src','public'],
          routes: {
            '/node_modules': 'node_modules'//basic.html文件里面node_modules的样式路由到node_modules文件下找
          }
        }
      })
    }
    
    const develop = series(build,serve)//开发阶段执行这个就够了
    module.exports = {
      complete,
      clear,
      build,
      develop
    }
    

    封装了常用的gulpfile.js,在lib下面,在用的时候直接在项目里面link,再引进gulpfile.js,通过config.js可以重新传值,但是为了不用总是写gulpfile.js文件,封装一下利用cli,添加cli时要在packjson文件中,添加bin:'bin/加上自己的命令文件,最好保持一致',发布时候记得再file里面添加上bin文件


    image.png
    • bin/zce-page.js
    #!/usr/bin/env node
    
    // process.argv传参用push
    process.argv.push('--cwd')
    process.argv.push(process.cwd())
    process.argv.push('--gulpfile')
    process.argv.push(require.resolve('..'))//..就会到packjson中找到main对应的入口文件
    
    require('gulp/bin/gulp')//   就是找到node_nodules下的gulp/bin/gulp然后走cli   =>require('gulp-cli')();
    
    • lib/index.js
    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 cwd = process.cwd()
    let config = {
      // default 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 clean = () => {
      return del([config.build.dist, config.build.temp])
    }
    
    const style = () => {
      return src(config.build.paths.styles, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.sass({ outputStyle: 'expanded' }))
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true }))
    }
    
    const script = () => {
      return src(config.build.paths.scripts, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.babel({ presets: [require('@babel/preset-env')] }))
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true }))
    }
    
    const page = () => {
      return src(config.build.paths.pages, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.swig({ data: config.data, defaults: { cache: false } }))
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true }))
    }
    
    const image = () => {
      return src(config.build.paths.images, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.imagemin())
        .pipe(dest(config.build.dist))
    }
    
    const font = () => {
      return src(config.build.paths.fonts, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.imagemin())
        .pipe(dest(config.build.dist))
    }
    
    const extra = () => {
      return src('**', { base: config.build.public, cwd: config.build.public })
        .pipe(dest(config.build.dist))
    }
    
    const serve = () => {
      watch(config.build.paths.styles, { cwd: config.build.src }, style)
      watch(config.build.paths.scripts, { cwd: config.build.src }, script)
      watch(config.build.paths.pages, { cwd: config.build.src }, page)
      // watch('src/assets/images/**', image)
      // watch('src/assets/fonts/**', font)
      // watch('public/**', extra)
      watch([
        config.build.paths.images,
        config.build.paths.fonts
      ], { cwd: config.build.src }, bs.reload)
    
      watch('**', { cwd: config.build.public }, bs.reload)
    
      bs.init({
        notify: false,
        port: 2080,
        // open: false,
        // files: 'dist/**',
        server: {
          baseDir: [config.build.temp, config.build.dist, config.build.public],
          routes: {
            '/node_modules': 'node_modules'
          }
        }
      })
    }
    
    const useref = () => {
      return src(config.build.paths.pages, { base: config.build.temp, cwd: config.build.temp })
        .pipe(plugins.useref({ searchPath: [config.build.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(config.build.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
    }
    
    
    • 引用项目里面传参zcepage.config.js
    module.exports = {
      build: {
        src: 'src',
        dist: 'release',
        temp: '.tmp',
        public: 'public',
        paths: {
          styles: 'assets/styles/*.scss',
          scripts: 'assets/scripts/*.js',
          pages: '*.html',
          images: 'assets/images/**',
          fonts: 'assets/fonts/**'
        }
      },
      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()
      }
    }
    
    

    相关文章

      网友评论

          本文标题:前端小白成长之16--自动化构建Gulp

          本文链接:https://www.haomeiwen.com/subject/hhghtktx.html