| const path = require('path') | = | const path = require('path') |
| // ------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------- | |
| // Config | // Config | |
| const env = require('gulp-environment') | const env = require('gulp-environment') | |
| process.env.NODE_ENV = env.current.name | process.env.NODE_ENV = env.current.name | |
| const conf = (() => { | const conf = (() => { | |
| const _conf = require('./build-config') | const _conf = require('./build-config') | |
| return require('deepmerge').all([{}, _conf.base || {}, _conf[process.env.NODE_ENV] || {}]) | return require('deepmerge').all([{}, _conf.base || {}, _conf[process.env.NODE_ENV] || {}]) | |
| })() | })() | |
| conf.buildPath = path.resolve(__dirname, conf.buildPath).replace(/\\/g, '/') | conf.buildPath = path.resolve(__dirname, conf.buildPath).replace(/\\/g, '/') | |
| // ------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------- | |
| // Modules | // Modules | |
| const { src, dest, parallel, series, watch } = require('gulp') | const { src, dest, parallel, series, watch } = require('gulp') | |
| const webpack = require('webpack') | const webpack = require('webpack') | |
| const sass = require('gulp-sass') | const sass = require('gulp-sass') | |
| const autoprefixer = require('gulp-autoprefixer') | const autoprefixer = require('gulp-autoprefixer') | |
| const rename = require('gulp-rename') | const rename = require('gulp-rename') | |
| const replace = require('gulp-replace') | const replace = require('gulp-replace') | |
| const gulpIf = require('gulp-if') | const gulpIf = require('gulp-if') | |
| const sourcemaps = require('gulp-sourcemaps') | const sourcemaps = require('gulp-sourcemaps') | |
| const del = require('del') | const del = require('del') | |
| const colors = require('ansi-colors') | const colors = require('ansi-colors') | |
| const log = require('fancy-log') | const log = require('fancy-log') | |
| colors.enabled = require('color-support').hasBasic | colors.enabled = require('color-support').hasBasic | |
| // ------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------- | |
| // Utilities | // Utilities | |
| function normalize(p) { | function normalize(p) { | |
| return p.replace(/\\/g, '/') | return p.replace(/\\/g, '/') | |
| } | } | |
| function root(p) { | function root(p) { | |
| return p.startsWith('!') ? | return p.startsWith('!') ? | |
| normalize(`!${path.join(__dirname, p.slice(1))}`) : | normalize(`!${path.join(__dirname, p.slice(1))}`) : | |
| normalize(path.join(__dirname, p)) | normalize(path.join(__dirname, p)) | |
| } | } | |
| function getSrc(...src) { | function getSrc(...src) { | |
| return src.map(p => root(p)).concat(conf.exclude.map(d => `!${root(d)}/**/*`)) | return src.map(p => root(p)).concat(conf.exclude.map(d => `!${root(d)}/**/*`)) | |
| } | } | |
| // ------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------- | |
| // Clean build directory | // Clean build directory | |
| const cleanTask = function () { | const cleanTask = function () { | |
| return del([conf.buildPath], { | return del([conf.buildPath], { | |
| force: true | force: true | |
| }) | }) | |
| } | } | |
| // ------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------- | |
| // Build css | // Build css | |
| const buildCssTask = function () { | const buildCssTask = function () { | |
| return src(getSrc('**/*.scss', '!**/_*.scss'), { base: root('.') }) | return src(getSrc('**/*.scss', '!**/_*.scss'), { base: root('.') }) | |
| .pipe(gulpIf(conf.sourcemaps, sourcemaps.init())) | .pipe(gulpIf(conf.sourcemaps, sourcemaps.init())) | |
| .pipe(sass({ | .pipe(sass({ | |
| outputStyle: conf.minify ? 'compressed' : 'nested' | outputStyle: conf.minify ? 'compressed' : 'nested' | |
| }).on('error', sass.logError)) | }).on('error', sass.logError)) | |
| .pipe(gulpIf(conf.sourcemaps, sourcemaps.write())) | .pipe(gulpIf(conf.sourcemaps, sourcemaps.write())) | |
| .pipe(gulpIf(conf.sourcemaps, sourcemaps.init({ | .pipe(gulpIf(conf.sourcemaps, sourcemaps.init({ | |
| loadMaps: true | loadMaps: true | |
| }))) | }))) | |
| .pipe(autoprefixer({ | .pipe(autoprefixer({ | |
| browsers: [ | <> | overrideBrowserslist: [ |
| '>= 1%', | = | '>= 1%', |
| 'last 2 versions', | 'last 2 versions', | |
| 'not dead', | 'not dead', | |
| 'Chrome >= 45', | 'Chrome >= 45', | |
| 'Firefox >= 38', | 'Firefox >= 38', | |
| 'Edge >= 12', | 'Edge >= 12', | |
| 'Explorer >= 10', | 'Explorer >= 10', | |
| 'iOS >= 9', | 'iOS >= 9', | |
| 'Safari >= 9', | 'Safari >= 9', | |
| 'Android >= 4.4', | 'Android >= 4.4', | |
| 'Opera >= 30' | 'Opera >= 30' | |
| ] | ] | |
| })) | })) | |
| .pipe(gulpIf(conf.sourcemaps, sourcemaps.write())) | .pipe(gulpIf(conf.sourcemaps, sourcemaps.write())) | |
| .pipe(dest(conf.buildPath)) | .pipe(dest(conf.buildPath)) | |
| } | } | |
| // ------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------- | |
| // Build js | // Build js | |
| const buildJsTask = function (cb) { | const buildJsTask = function (cb) { | |
| setTimeout(function () { | setTimeout(function () { | |
| webpack(require('./webpack.config'), (err, stats) => { | webpack(require('./webpack.config'), (err, stats) => { | |
| if (err) { | if (err) { | |
| log(colors.gray('Webpack error:'), colors.red(err.stack || err)) | log(colors.gray('Webpack error:'), colors.red(err.stack || err)) | |
| if (err.details) log(colors.gray('Webpack error details:'), err.details) | if (err.details) log(colors.gray('Webpack error details:'), err.details) | |
| return cb() | return cb() | |
| } | } | |
| const info = stats.toJson() | const info = stats.toJson() | |
| if (stats.hasErrors()) { | if (stats.hasErrors()) { | |
| info.errors.forEach(e => log(colors.gray('Webpack compilation error:'), colors.red(e))) | info.errors.forEach(e => log(colors.gray('Webpack compilation error:'), colors.red(e))) | |
| } | } | |
| if (stats.hasWarnings()) { | if (stats.hasWarnings()) { | |
| info.warnings.forEach(w => log(colors.gray('Webpack compilation warning:'), colors.yellow(w))) | info.warnings.forEach(w => log(colors.gray('Webpack compilation warning:'), colors.yellow(w))) | |
| } | } | |
| // Print log | // Print log | |
| log(stats.toString({ | log(stats.toString({ | |
| colors: colors.enabled, | colors: colors.enabled, | |
| hash: false, | hash: false, | |
| timings: false, | timings: false, | |
| chunks: false, | chunks: false, | |
| chunkModules: false, | chunkModules: false, | |
| modules: false, | modules: false, | |
| children: true, | children: true, | |
| version: true, | version: true, | |
| cached: false, | cached: false, | |
| cachedAssets: false, | cachedAssets: false, | |
| reasons: false, | reasons: false, | |
| source: false, | source: false, | |
| errorDetails: false | errorDetails: false | |
| })) | })) | |
| cb() | cb() | |
| }) | }) | |
| }, 1) | }, 1) | |
| } | } | |
| // ------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------- | |
| // Build fonts | // Build fonts | |
| const FONT_TASKS = [{ | const FONT_TASKS = [{ | |
| name: 'fontawesome', | name: 'fontawesome', | |
| path: 'node_modules/@fortawesome/fontawesome-free/webfonts/*' | path: 'node_modules/@fortawesome/fontawesome-free/webfonts/*' | |
| }, | }, | |
| { | { | |
| name: 'linearicons', | name: 'linearicons', | |
| path: 'node_modules/linearicons/dist/web-font/fonts/*' | path: 'node_modules/linearicons/dist/web-font/fonts/*' | |
| }, | }, | |
| { | { | |
| name: 'pe-icon-7-stroke', | name: 'pe-icon-7-stroke', | |
| path: 'node_modules/pixeden-stroke-7-icon/pe-icon-7-stroke/fonts/*' | path: 'node_modules/pixeden-stroke-7-icon/pe-icon-7-stroke/fonts/*' | |
| }, | }, | |
| { | { | |
| name: 'open-iconic', | name: 'open-iconic', | |
| path: 'node_modules/open-iconic/font/fonts/*' | path: 'node_modules/open-iconic/font/fonts/*' | |
| }, | }, | |
| { | { | |
| name: 'ionicons', | name: 'ionicons', | |
| path: 'node_modules/ionicons/dist/fonts/*' | path: 'node_modules/ionicons/dist/fonts/*' | |
| } | } | |
| ].reduce(function (tasks, font) { | ].reduce(function (tasks, font) { | |
| const functionName = `buildFonts${font.name.replace(/^./, m => m.toUpperCase())}Task` | const functionName = `buildFonts${font.name.replace(/^./, m => m.toUpperCase())}Task` | |
| const taskFunction = function () { | const taskFunction = function () { | |
| return src(root(font.path)) | return src(root(font.path)) | |
| .pipe(dest(normalize(path.join(conf.buildPath, 'fonts', font.name)))) | .pipe(dest(normalize(path.join(conf.buildPath, 'fonts', font.name)))) | |
| } | } | |
| Object.defineProperty(taskFunction, 'name', { | Object.defineProperty(taskFunction, 'name', { | |
| value: functionName | value: functionName | |
| }); | }); | |
| return tasks.concat([taskFunction]) | return tasks.concat([taskFunction]) | |
| }, []) | }, []) | |
| // Copy linearicons' style.css | // Copy linearicons' style.css | |
| FONT_TASKS.push(function buildFontsLinearicons () { | FONT_TASKS.push(function buildFontsLinearicons () { | |
| return src(root('node_modules/linearicons/dist/web-font/style.css')) | return src(root('node_modules/linearicons/dist/web-font/style.css')) | |
| .pipe(replace(/'fonts\//g, '\'linearicons/')) | .pipe(replace(/'fonts\//g, '\'linearicons/')) | |
| .pipe(rename({ | .pipe(rename({ | |
| basename: 'linearicons' | basename: 'linearicons' | |
| })) | })) | |
| .pipe(dest(normalize(path.join(conf.buildPath, 'fonts')))) | .pipe(dest(normalize(path.join(conf.buildPath, 'fonts')))) | |
| }) | }) | |
| const buildFontsTask = parallel(FONT_TASKS) | const buildFontsTask = parallel(FONT_TASKS) | |
| // ------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------- | |
| // Copy | // Copy | |
| const buildCopyTask = function () { | const buildCopyTask = function () { | |
| return src(getSrc('**/*.png', '**/*.gif', '**/*.jpg', '**/*.jpeg', '**/*.svg', '**/*.swf', '**/*.eot', '**/*.ttf', '**/*.woff', '**/*.woff2'), { | return src(getSrc('**/*.png', '**/*.gif', '**/*.jpg', '**/*.jpeg', '**/*.svg', '**/*.swf', '**/*.eot', '**/*.ttf', '**/*.woff', '**/*.woff2'), { | |
| base: root('.') | base: root('.') | |
| }) | }) | |
| .pipe(dest(conf.buildPath)) | .pipe(dest(conf.buildPath)) | |
| } | } | |
| // ------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------- | |
| // Watch | // Watch | |
| const watchTask = function () { | const watchTask = function () { | |
| watch(getSrc('**/*.scss', '!fonts/**/*.scss'), buildCssTask) | watch(getSrc('**/*.scss', '!fonts/**/*.scss'), buildCssTask) | |
| watch(getSrc('fonts/**/*.scss'), parallel(buildCssTask, buildFontsTask)) | watch(getSrc('fonts/**/*.scss'), parallel(buildCssTask, buildFontsTask)) | |
| watch(getSrc('**/*.@(js|es6)', '!*.js'), buildJsTask) | watch(getSrc('**/*.@(js|es6)', '!*.js'), buildJsTask) | |
| watch(getSrc('**/*.png', '**/*.gif', '**/*.jpg', '**/*.jpeg', '**/*.svg', '**/*.swf'), buildCopyTask) | watch(getSrc('**/*.png', '**/*.gif', '**/*.jpg', '**/*.jpeg', '**/*.svg', '**/*.swf'), buildCopyTask) | |
| } | } | |
| // ------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------- | |
| // Build | // Build | |
| const buildTasks = [ | const buildTasks = [ | |
| buildCssTask, | buildCssTask, | |
| buildJsTask, | buildJsTask, | |
| buildFontsTask, | buildFontsTask, | |
| buildCopyTask | buildCopyTask | |
| ] | ] | |
| const buildTask = conf.cleanBuild ? | const buildTask = conf.cleanBuild ? | |
| series(cleanTask, parallel(buildTasks)) : | series(cleanTask, parallel(buildTasks)) : | |
| parallel(buildTasks) | parallel(buildTasks) | |
| // ------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------- | |
| // Exports | // Exports | |
| module.exports = { | module.exports = { | |
| default: buildTask, | default: buildTask, | |
| build: buildTask, | build: buildTask, | |
| 'build:js': buildJsTask, | 'build:js': buildJsTask, | |
| 'build:css': buildCssTask, | 'build:css': buildCssTask, | |
| 'build:fonts': buildFontsTask, | 'build:fonts': buildFontsTask, | |
| 'build:copy': buildCopyTask, | 'build:copy': buildCopyTask, | |
| watch: watchTask | watch: watchTask | |
| } | } |