gulp 프로모션 - 사용자 정의 gulp 플러그인

7257 단어
gulp는 이미 많은 프로젝트의 표준이 되었고 gulp의 플러그인 생태도 매우 번영했다. 2015.1.5까지 npm에 10190종의 gulp 플러그인이 우리에게 사용되었다.우리는 완전히 바보같이 구축할 수 있다.
그러나 우리는 문서에 대응하는 매개 변수에 따라 플러그인을 호출하는 경우가 종종 발생한다. 그러나 결과가 예상보다 좋지 않다는 것을 발견했다. 이때 우리는 조금씩 잘못 배열해야 한다. 이것은gulp플러그인의 작업 원리에 대해 어느 정도 알아야 한다.본고는gulp플러그인을 실현하는 것을 예로 삼아gulp플러그인이 어떻게 작동하는지 설명한다.
요구 사항 설명
일반적으로 우리의 구축 자원은 js/css/html 및 기타 일부 자원 파일로 개발 또는 발표 단계에서 js/css는 합병, 압축, 이름 바꾸기 등 처리 절차를 거친다.
일부 장면에서 우리는 구축을 거친 후에 js/css의 이름이나 수량을 확정할 수 없다. 그러면 HTML 파일에 자원의 인용 주소를 쓸 수 없다. 그러면 최종적으로 생성된 자원 파일/주소를 HTML에 주입하기 위해Gulp의 플러그인을 어떻게 실현해야 하는가?
다음과 같은 방법으로 플러그 인을 사용해야 한다고 가정합니다.
<html>
<head>
    <!--InlineResource:\.css$-->
</head>
<body>
    <!--InlineResource:\.js$-->
</body>
</html>

우리는 HTML 주석을 통해 의존해야 할 자원을 설명합니다. Inline Resource는 일치하는 키워드입니다. ":"는 분할로,/*.css$/,/*.js$/의존할 파일의 정규 일치입니다.
gulpfile에서.js 이 설정이 필요합니다:
gulp.task('dist', function () {
    return gulp.src('index.html')
               .pipe(InjectResources(
                    gulp.src(['*.js', '*.css'])
                        .pipe(hash(/*  MD5     */))
               ))
               .pipe(gulp.dest('dist'))
})

여기서는 몇 가지 방법 및 단계를 간략하게 설명합니다.
  • gulp.src('index.html')는 파일 시스템의 현재 디렉터리에 있는 index를 읽습니다.html, 그리고 읽을 수 있는 Stream을 생성하여 후속 단계 소비에 사용
  • InjectResources(stream)는 HTML에 주입할 JS/CSS를 가져오는 매개 변수를 받아들이는 플러그인입니다. 이 매개 변수는Stream 실례이고, 이전에 흘러들어온 데이터를 수신하고 처리하는 데 사용되어야 합니다
  • hash(options)는 현재 흐르는 파일 이름에md5열을 추가하는 제3자 플러그인입니다. 예를 들어gulp-hash
  • gulp.Dest('dist')는 리소스를 주입한 HTML 파일을 현재 디렉토리에 생성하는 데 사용됨
  • 우리가 관심을 가져야 할 것은 두 번째이다. 어떻게 모든 자원 파일을 연결하고 주입을 완성합니까?
    우리는 이 논리를 4단계로 나눌 수 있다
  • 모든 js/css 자원 가져오기
  • 모든 HTML 파일 가져오기
  • HTML의 종속 선언 찾기
  • 의존 자원 일치
  • 의존하는 자원 라벨 생성 및 주입
  • 편집을 시작하기 전에 우리는 중요한 제3자 라이브러리인 맵-stream에 의존해야 한다.
    map-stream은 현재 흐름의 모든 파일 데이터를 가져오고 데이터 내용을 수정하는 데 사용됩니다.
    1단계(JS/CSS 에셋)
    module.exports = function (resourcesStream) {
        // step 1: TODO =>         js/css  
    }

    리소스 흐름은 InjectResources 메소드에 매개 변수로 전달되며, 여기서는 비동기적인 인스턴스 메소드를 통해 모든 파일 객체를 가져와 리소스 목록에 배치합니다.
    var resources = []
    function getResources(done) {
        if (resources) return done(resources)
        //             ,     ...
        resourcesStream.pipe(mapStream(function (data, cb) {
                resources.push(data)
                cb(null, data)
            }))
            .on('end', function () {
                done(resources)
            })
    }
  • mapStream의 처리 방법에서 얻은 데이터는gulp입니다.src에서 생성한vinyl 대상은 하나의 파일을 대표한다
  • 모든stream이 받아들인 후에end 이벤트
  • 를 던집니다.
    Note:mapStream 처리 방법 중의 cb 방법, 두 번째 파라미터는 현재 처리된 파일 대상을 교체하는 데 사용할 수 있습니다
    여기까지, 우리는 첫 번째 포장을 완성했다!
    module.exports = function (resourcesStream) {
        // step 1:
        function getResources () {
            ...
        }
    }

    2단계(HTML 파일)
    module.exports = function (resourcesStream) {
        // step 1: ✔︎
     
        // step 2: TODO =>            HTML  
        return mapStream(function (data, cb) {
     
        })
    }

    InjectResources 플러그인 방법은 Writable Stream 실례를 되돌려줍니다. InjectResources로 흐르는 HTML 파일을 수신하고 처리하는 데 사용되며, mapStream의 반환 값은 writable stream입니다.
    이때 맵스트림 처리 방법으로 얻은 데이터는 HTML 파일의 대상이고 그 다음에 내용 처리를 한다.
    3단계(종속 위치 지정)
    module.exports = function (resourcesStream) {
        // step 1: ✔︎
     
        // step 2: ✔
        return mapStream(function (data, cb) {
            var html = data.contents.toString()
            // step 3: TODO =>   HTML        
     
        })
    }

    우리가 받은 데이터는vinyl 대상입니다. 콘텐츠 속성은 파일의 내용입니다. 형식은 버퍼일 수도 있고 스트링일 수도 있습니다. toStraing () 을 통해 문자열의 내용을 얻을 수 있습니다.
    모든 의존 성명에는 Inline Resource 키워드가 있습니다. 간단한 방법은 정규를 통해 HTML의 자원 의존을 포지셔닝하고 바꿀 수 있습니다.
    html.replace(/<!--InlineResource:(.*?)-->/g, function (expr, fileRegexpStr){
        // fileRegexp               
    })

    이로써 우리는 자원 의존의 포지셔닝을 완성했고 다음 단계는 의존하는 자원을 가져와 대체하는 것이다.
    4단계(종속 일치)
    1단계에서 정의한 getResources 방법을 사용하여 필요한 리소스 파일을 가져옵니다.
    module.exports = function (resourcesStream) {
        // step 1: ✔︎
     
        // step 2: ✔
        return mapStream(function (data, cb) {
            // step 3: ✔
     
            getResources(function (list) {
                html.replace(depRegexp, function (expr, fileRegexpStr) {
                    var fileRegexp = new RegExp(fileRegexpStr)
                    // step 4: TODO =>        
                })
            })
        })
    }

    getResources는 비동기적인 방법이기 때문에, 대체 처리 논리 패키지를 getResources의 리셋 방법에 넣어야 합니다
    종속 선언의 정규 표현식에 따라 리소스 목록이 하나씩 일치합니다.
    function matchingDependences(list, regexp) {
        var deps = []
        list.forEach(function (file) {
            var fpath = file.path
            if (fileRegexp.test(fpath)) {
                deps.push(fpath)
            }
        })
        return deps
    }

    마지막으로 리소스를 HTML 태그로 변환하여 HTML에 주입하는 방법밖에 없습니다.
    5단계(리소스 변환/종속 주입)
    module.exports = function (resourcesStream) {
        // step 1: ✔︎
     
        // step 2: ✔
        return mapStream(function (data, cb) {
            // step 3: ✔
     
            // step 4: ✔
            // ...
                html.replace(depRegexp, function (expr, fileRegexpStr) {
                    var deps = matchingDependences(list, fileRegexpStr)
                    // step 5:        HTML  
                })
        })
    }

    다음 정의는transform 방법으로 경로 목록을 HTML로 변환하는 자원 탭 목록입니다. path 모듈은 파일 경로를 가져오는 정보를 분석하는 데 사용됩니다. 이 모듈은node 내장 모듈입니다.
    var path = require('path')
     
    function transform(deps) {
        return deps.map(function (dep) {
            var ext = path.extname(dep)
            switch (ext) {
                case 'js':
                        '<script>' + dep + '</script>'
                break
                case 'css':
                    return '<link rel="stylesheet" href="' + dep + '">'
                break
            }
            return ''
        }).join('')
    }

    마지막으로 HTML의 의존 성명 (주입) 을 문자열로 탭 목록을 연결합니다.
    html = html.replace(depRegexp, function (expr, fileRegexpStr) {
        var deps = matchingDependences(list, fileRegexpStr)
        // step 5:        HTML  
        return transform(deps)
    })
    // html    
    data.contents = new Buffer(html)
    //            HTML  
    cb(null, data)

    이로써 기본적인 주입 기능을 갖춘 플러그인을 완전하게 실현하였다~~~~~
    One More Thing
    위에서 실현한 예시 절차를 통해gulp 플러그인의 작업 원리를 분명히 알 수 있다.그러나 사용하기 쉽고 사용자 정의가 가능한 플러그인을 만들려면 다음과 같은 보완을 계속해야 한다.
  • 자원 경로와 HTML 경로를 비교하고 출력 상대 경로를 기본 탭 자원 경로로 한다
  • sort 옵션 방법을 제공하여 자원의 주입 순서를 수정합니다
  • transform 옵션 방법을 제공하여 맞춤형 탭의 자원 경로에 사용
  • 의존 성명에서 inline 성명을 지원하여 자원 내용을 HTML에 연결합니다. 예를 들어
  • <!--InjectResources:*\.js$??inline-->
  • 같은 자원 흐름에 여러 번 자원 주입을 사용하는 구분에 사용되는 명명 공간을 지원한다. 예를 들어
  • gulp.src('index.html')
          .pipe(
              InjectResources(gulp.src('asserts/*.js'), { name: 'asserts'})
          )
          .pipe(
              InjectResources(gulp.src('components/*.js'), { name: 'components'})
          )
          ...
  • . . .
  • 좋은 웹페이지 즐겨찾기