• gulp 搭建个人工作流:文件注入、热启动、跨域


    个人比价推崇前后端分离的开发方式,大家伙各司其职,只需通过 API 进行交流,不仅避免了沟通上的成本,更提升了开发效率。而在前端开发工作中,许多需求和问题是相似的,所以我们的开发模式往往是雷同的,是否能够总结出一套通用的模式呢?

    (备份一个webpack的中文网站:https://angular.cn/docs/ts/latest/guide/webpack.html)

    日常前端开发的处境

    1、 开发流程相似

    ​ 前端开发工作包含哪些?html、css、js,对应的工程目录也相似,每次重新创建都要耗费一些时间。

    2、 需求更改频繁

    ​ 开发们都推崇两个字“复用”,那么是什么阻碍了代码的复用?答:产品经理的需求变更。虽然有些搞笑的成分,但毋庸置疑,前端开发中需求频繁更改是非常常见的,我们可不想因为一条样式修改而找遍所有文件。

    3、 如何跨域

    ​ 如何跨域是每个前端必须面对的,最优的解决方案是服务器的反向代理来实现,而多数前端都没有这方面的经验。幸好,在开发环境中,我们可以利用 node 或者 gulp 来解决跨域问题。

    ​ 之前我的一篇博客介绍了利用node.js进行跨域访问:http://www.cnblogs.com/fayin/p/6628150.html

    ​ 今天,我将介绍用gulp搭建工作流,并带来第二种前端跨域的方式。

    点击:这里查看完整代码

    gulp 搭建工作流

    首先介绍下安装依赖,明确有哪些task:

    • gulp-load-plugins:用来加载插件,避免我们再头部声明一堆插件,做到想用就用
    • less:用于编译 .less文件
    • autoprefixer:自动添加css前缀
    • babel:es6 编译成 es5
    • uglify:JS压缩
    • minify:CSS压缩
    • rename:重命名
    • sourcemaps:资源映射
    • concat:合并文件
    • del:删除文件、文件夹
    • inject:文件注入
    • notify:提示信息
    • browser-sync:热启动
    • http-proxy-middleware:配合browser-sync进行跨域
    • changed:只有发生了改变的文件才能进入流中
    • sequence:让task按顺序完成
    • rev:添加MD5
    • watch:监听文件变化

    gulpfile.js

    /**
     * gulp mask list
     *
     * gulp-load-plugins
     *
     * babel, less, uglify, browser-sync, del, autoprefixer, concat, minifyCss, rename
     * sourcemaps, inject, notify
     *
     */
    
    const APIURL = 'http://192.168.1.30:6760';
    const ISPROXY = false;
    
    const DEV_PRO = false;
    
    
    const
        fs   = require('fs'),
        path = require('path'),
        gulp = require('gulp'),
        gulpLoadPlugins = require('gulp-load-plugins'),
        del = require('del'),
        browserSync = require('browser-sync').create(),
        reload = browserSync.reload,
        plugins = gulpLoadPlugins(),
        sequence = require('gulp-sequence'),
        gulpCopy = require('gulp-file-copy'),
        proxy = require('http-proxy-middleware'),
        fileinclude = require('gulp-file-include'),
        pngquant = require('imagemin-pngquant'),
        mozjpeg = require('imagemin-mozjpeg'),
        merge = require('merge-stream');
    
    const DIST = 'dist',
        SRC = 'dist';
    
    const getFolders = (dir)=> {
        return fs.readdirSync(dir)
            .filter((file)=> {
                return fs.statSync(path.join(dir, file)).isDirectory();
            })
    };
    const getError = function(err) {
        console.log(err.toString());
        this.emit('end');
    };
    
    
    gulp.task('clean', function () {
       return del(['dist/**/*'])
    });
    
    gulp.task('clean-css', function () {
        return del(['dist/css/**/*.*'])
    });
    
    gulp.task('clean-js', function () {
        return del(['dist/js/*.*'])
    });
    
    gulp.task('include', function () {
       return gulp.src('src/*.html')
           .pipe(plugins.changed(DIST))
           .pipe(fileinclude({
               prefix: '@@',
               basepath: '@file'
           }))
           .pipe(plugins.debug({title: '文件引入:'}))
           .pipe(gulp.dest('dist'))
    });
    
    
    gulp.task('css', ()=> {
        let commonStyle = gulp.src('src/less/*.less',{base: 'src/less'})
            .pipe(plugins.changed(DIST, {extension: '.css'}))
            //.pipe(plugins.watch('src/less/*.less'))
            .pipe(plugins.sourcemaps.init())
            .pipe(plugins.less())
            .on('error', getError)
            .pipe(plugins.autoprefixer({
                browsers: ['last 4 version','Android >= 4.0'],
                cascade: true,
                remove: true
            }))
            .pipe(plugins.concat('common.css'))
            .pipe(plugins.minifyCss())
            .pipe(plugins.rename({suffix: '.min'}))
            //.pipe(plugins.rev())    // 添加md5
            .pipe(plugins.sourcemaps.write('.'))
            .pipe(plugins.debug({title: '编译css:'}))
            .pipe(gulp.dest('dist/css'))
            .pipe(browserSync.stream({match: '**/*.css'}));
        // .pipe(gulp.rev.manifest())
        // .pipe(gulp.dest('dist/rev'))
        let lessPath = 'src/less';
        let folders = getFolders(lessPath);
    
        let folderStyle = folders.map((folder)=> {
            let newPath = path.join(lessPath, folder, '/*.less');
            return gulp.src(newPath)
                .pipe(plugins.changed(DIST, {extension: '.css'}))
                //.pipe(plugins.watch(newPath))
                .pipe(plugins.sourcemaps.init())
                .pipe(plugins.less())
                .pipe(plugins.autoprefixer({
                    browsers: ['last 4 version','Android >= 4.0'],
                    cascade: true,
                    remove: true
                }))
                .pipe(plugins.concat(folder+'.css'))
                .pipe(plugins.minifyCss())
                .pipe(plugins.rename({suffix: '.min'}))
                //.pipe(plugins.rev())    // 添加md5
                .pipe(plugins.sourcemaps.write('.'))
                .pipe(plugins.debug({title: '编译foldercss:'}))
                .pipe(gulp.dest('dist/css/'+folder))
                .pipe(browserSync.stream({match: '**/*.css'}));
        });
        return merge(commonStyle, folderStyle);
    });
    
    gulp.task('es6ToEs5', function () {
        return gulp.src('src/js/**/*.js')
            .pipe(plugins.changed(DIST, {extension: '.js'}))
            .pipe(plugins.sourcemaps.init())
            .pipe(plugins.babel({
                presets: ['es2015']
            }))
            .on('error', getError)
            //.pipe(plugins.concat('main.js'))
            .pipe(plugins.uglify())
            .pipe(plugins.rename({suffix: '.min'}))
            //.pipe(plugins.rev())
            .pipe(plugins.sourcemaps.write('.'))
            .pipe(plugins.debug({title: '编译js:'}))
            .pipe(gulp.dest('dist/js'))
            .pipe(browserSync.stream({match: '**/*.js'}));
    });
    
    gulp.task('rev',['css'],function() {
        return gulp.src(['dist/rev/rev-manifest.json','dist/*.html'])  //获取rev-manifest.json和要替换的html文件
            .pipe(plugins.revCollector({
                replaceReved: true		//根据rev-manifest.json的规则替换html里的路径,由于替换是根据rev-manifest.json规则来的,所以一定要先生成这个文件再进行替换
            }))
            .pipe(gulp.dest('dist'))
            .pipe(browserSync.stream({match: '**/*.css'}));
            //.pipe(plugins.notify('md5 success!!!!'))
    });
    
    
    gulp.task('copy', function () {
        let start = 'src/lib/*.*',
            start2 = 'src/images/**/*.*';
        let copyLib = gulp.src(start)
            .pipe(plugins.changed(DIST))
            .pipe(gulpCopy('dist/lib', {
                start: 'src/lib'
            }));
    
        let copyImages = gulp.src(start2)
            .pipe(plugins.changed(DIST))
            .pipe(plugins.imagemin(
                [pngquant(), mozjpeg()],
                {verbose: true}
            ))
            .pipe(gulp.dest('dist/images'));
        return merge(copyLib, copyImages)
    });
    
    gulp.task('injectFile', function () {
       let target = ['src/*.html','!src/_head.html'],
           target2 = ['dist/lib/*.js', 'dist/js/*.js', 'dist/css/*.css'],
           sources = gulp.src(target2, {'read': false});
       return gulp.src(target)
           .pipe(plugins.changed(DIST))
           .pipe(fileinclude({
               prefix: '@@',
               basepath: '@file'
           }))
           .pipe(plugins.inject(sources, {relative: true}))
           .pipe(plugins.debug({title: '注入:'}))
           .pipe(gulp.dest('dist'))
           .pipe(browserSync.stream({match: '**/*.html'}));
           //.pipe(plugins.notify('inject success'))
    });
    
    gulp.task('watch-css', function (callback) {
        sequence('rev', 'injectFile', callback)
    });
    
    gulp.task('watch-js', function (callback) {
        sequence('es6ToEs5', 'injectFile', callback)
    });
    
    gulp.task('del-maps', function () {
        return del(['dist/**/*.map']);
    });
    
    gulp.task('html-watch', ['injectFile'], function (done) {
        browserSync.reload();
        done();
    });
    
    gulp.task('server', function() {
        const aipProxy = proxy('/api', {
            target: APIURL,
            changeOrigin: true,
            ws: true
        });
    
        if (!ISPROXY) {
            browserSync.init({
                // files:'**',
                server: {
                    baseDir: './'
                }
            });
        }else {
            browserSync.init({
                server: {
                    baseDir: './',
                    middleware: [aipProxy]
                }
            });
        }
    
        gulp.watch(['src/*.html'], ['injectFile']);
        gulp.watch(['src/images/**/*.*'], ['copy']);
        gulp.watch(['src/less/**/*'], ['watch-css']);
        gulp.watch(['src/js/**/*.js', 'src/lib/*.*'], ['watch-js']);
        gulp.watch(['dist/*.html']).on('change', browserSync.reload);
        gulp.watch(['src/**/**'])
            .on('change', function (event) {
                if(event.type == 'deleted') {
                    let _path = event.path,
                        cssPath = _path.replace(/src\less/, 'dist\css');
                    console.log(cssPath);
                    if(path.extname(_path) === '.less') {
                        del(path.dirname(cssPath)+'/*.*');
                        sequence('rev', 'injectFile');
                    }else {
                        del(_path.replace(/src/, 'dist'))
                    }
    
                }
            })
            .on('error', function (err) {
                console.log(err)
            });
        //browserSync.watch('./src/**/*.*').on('change',reload);
        //browserSync.watch('./dist/**/*').on('change',reload);
    });
    
    gulp.task('dev', sequence('clean', ['rev', 'es6ToEs5','copy'], 'injectFile', 'server'));
    
    
    gulp.task('build-pro', sequence('clean',['rev', 'es6ToEs5', 'copy'],'injectFile', 'del-maps'));
    
    

    目录

  • 相关阅读:
    编写一个函数func(),将此函数的输入参数(int型)逆序输出显示,如54321 –> 12345,要求使用递归,并且函数体代码不超过8行
    java中两种单例模式
    springMVC配置freemarker 二(问题讨论篇)
    springMVC配置freemarker
    java中@value的环境配置
    java环境log4j日志环境的配置。
    websocket协议
    http报文和浏览器缓存机制
    详解网络连接
    编码总结
  • 原文地址:https://www.cnblogs.com/fayin/p/6635943.html
Copyright © 2020-2023  润新知