gulp-svg-sprite3
해결 코드
let svgSpriteEachFunc = [];
glob.sync("./src/img/sprites-svg/*").map(function (dir, index) {
svgSpriteEachFunc[index] = function () {
const directoryName = dir.replace(`${path.dirname(dir)}/`, "");
let options = {
mode: {
css: {
dest: './',
bust: false,
sprite: `./src/img/${directoryName}-svg.svg`,
render: {
scss: {
template: path.join('./src/scss/vendor', 'sprite-svg-mixins.handlebars'),
dest: `./src/scss/vendor/_${directoryName}-svg-mixins.scss`,
}
}
}
},
shape: {
spacing: {
padding: 4
},
},
variables: {
spriteName: `${directoryName}`,
baseName : path.posix.relative('./src/css', path.posix.join(`./src/img`, `${directoryName}-svg`)),
svgToPng : ''
}
}
return src(`./src/img/sprites-svg/${directoryName}/*.svg`)
.pipe(svgSprite(options))
.pipe(dest('./'))
}
});
function markup_watch() {
series(
clean_dist, update_normalize,
parallel(copy_json, process_html, make_indexfile, ...svgSpriteEachFunc, sprites),
optimize_others, sass, server, () => {
})();
}
exports.default = markup_watch;
상황
async function spriteSvg() {
const folders = getFolders(`${gulpConfig.src}/img/sprites-svg`);
let options = {
spritesmith: (options) => {
const { folder, gulpConfig } = options;
return {
shape: {
spacing: {
padding: 4
},
id: {
generator: function (name) {
return path.basename(name.split(`${gulpConfig.src}/scss/vendor`).join(this.separator), '.svg');
}
}
},
mode: {
css: {
dest: './',
bust: false,
sprite: folder + '-svg.svg',
render: {
scss: {
template: path.join(`${gulpConfig.src}/scss/vendor`, 'sprite-svg-mixins.handlebars'),
dest: path.posix.relative(`${gulpConfig.src}/img`, path.posix.join(`${gulpConfig.src}/scss`, 'vendor', '_'+folder+'-svg-mixins.scss'))
}
}
}
},
variables: {
spriteName: folder,
baseName: path.posix.relative(`${gulpConfig.src}/css`, path.posix.join(`${gulpConfig.src}/img`, folder + '-svg')),
svgToPng: ''
}
}
},
};
return folders.map((folder) => {
return new Promise((resolve) => {
src(path.join(`${gulpConfig.src}/img/sprites-svg`, folder, '*.svg'))
.pipe($.sort())
.pipe($.svgSprite(options.spritesmith({folder, gulpConfig})))
.pipe(dest(`${gulpConfig.src}/img`))
.on('end',resolve);
});
});
}
라인걸프에는 위와 같은 spriteSvg
함수가 있습니다.
svg 이미지 파일들을 하나의 sprite image 파일로 합쳐주는 함수입니다.
위 코드를 자세히 보시면 sprites-svg
폴더 하위에 여러개의 폴더가 있다는 가정 하에 작성된 것을 알 수 있습니다.
그렇기 때문에 .map
메서드를 활용해 반복문을 돌려 각 폴더별로 sprite 이미지를 내보내고 있습니다.
gulp4의 특징
제가 알기론 gulp4는 gulp3과 다르게 함수가 끝나는 시점을 정확히 알려줘야된다고 알고 있습니다.
즉, gulp3 때보다 이거에 관련해 더 엄격해진 것으로 알고 있습니다.
아마도 series
(순차적)으로 실행되어야하는 함수들을 잘 구별해 함수를 실행하기 위함인 것 같습니다.
gulp의 특징
function funcName() {
return gulp.src()
.pipe()
}
gulp를 보시면 위와 같은 식들을 볼 수 있습니다.
이번에 조사하면서 알게된 사실인데 gulp의 위와 같은 구문을 반복문 처리했을 때 return을 제대로 인식하지 못한다는 겁니다.
제가 아직 Promise
나 비동기 에 대해 완벽히 이해하고 있지 못해 이점은 정확하게 설명드릴 수는 없습니다.. ㅠ
하지만 확실한 것은 아래와 같은 코드는 함수가 ‘실제로 끝나는 시점’보다 더 앞서 해당 함수가 끝났다고 인식해버린다는 것입니다.
function funcNameB() {
return gulp.src()
.pipe()
}
function funcName() {
return for() {
gulp.src()
.pipe()
}
}
exports.default = gulp.series(funcName, funcNameB)
즉, 위와 같은 코드는 반복문이 한번만 돌아도 return
처리가 되기에 실제로 funcName
이 완료하지도 않았음에도 불구하고 완료했다고 인식하여 다음 함수인 funcNameB
를 실행한다는 것입니다.
불편한 해결방법..?
즉, 이와 같이 반복문을 돌릴때의 문제를 해결하려면 모두 개별함수로 처리해야된다는 결론이 나옵니다.
function funcName() {
return for(let i = 0; i < 3; i++) {
gulp.src()
.pipe()
}
}
즉 위와 같은 반복문 함수가 있다면,
function funcName1() {
return gulp.src()
.pipe()
}
function funcName2() {
return gulp.src()
.pipe()
}
function funcName3() {
return gulp.src()
.pipe()
}
위와 같이 각각 모두 개별로 작성해줘야된다는 것입니다.
하지만 위와 같이 작성하려면 불편합니다.
더군다나 spriteSvg
함수는 sprite-svg 폴더의 하위 폴더에 있는 폴더를 구별하여 함수가 실행되어야하는데, 위와 같이 일일히 손으로 작성하게되면 폴더가 늘어나거나 삭제될 때마다 수동으로 gulpfile.js를 수정해야됩니다.
편한 해결방법!
반복문을 일일히 수동으로 작성안해도 쉽게 처리할 수 있는 방법이 있습니다.
spriteSvg
함수로 예를 보여드리겠습니다.
let svgSpriteEachFunc = [];
glob.sync("./src/img/sprites-svg/*").map(function (dir, index) {
svgSpriteEachFunc[index] = function () {
const directoryName = dir.replace(`${path.dirname(dir)}/`, "");
let options = {
mode: {
css: {
dest: './',
bust: false,
sprite: `./src/img/${directoryName}-svg.svg`,
render: {
scss: {
template: path.join('./src/scss/vendor', 'sprite-svg-mixins.handlebars'),
dest: `./src/scss/vendor/_${directoryName}-svg-mixins.scss`,
}
}
}
},
shape: {
spacing: {
padding: 4
},
},
variables: {
spriteName: `${directoryName}`,
baseName : path.posix.relative('./src/css', path.posix.join(`./src/img`, `${directoryName}-svg`)),
svgToPng : ''
}
}
return src(`./src/img/sprites-svg/${directoryName}/*.svg`)
.pipe(svgSprite(options))
.pipe(dest('./'))
}
});
function markup_watch() {
series(
clean_dist, update_normalize,
parallel(copy_json, process_html, make_indexfile, ...svgSpriteEachFunc, sprites),
optimize_others, sass, server, () => {
})();
}
exports.default = markup_watch;
위와 같이 개별로 작성해야될 함수를 미리 반복문을 통해 만들어놓는 것입니다.
반복문을 통해 return
으로 함수를 리턴해 배열에 담아놓은 다음에 ...
스프레드 연산자로 gulp 에서 실행하면됩니다.
위와 같이 작성해 걸프를 실행하면 spriteSvg
함수가 각각의 폴더별로 따로따로 생성되어 따로따로 실행됩니다.
그렇기 때문에 실제 함수가 끝나는 시점과 return
되는 시점이 정확하게 일치하게 됩니다.
이렇게 하면 watch
하거나 어떤 경우에서도 오류가 없어질 것입니다.