Left file: appwork-v1_4_0/src/gulpfile.js  
Right file: appwork-v1_5_0/src/gulpfile.js  
1 const path = require('path') = 1 const path = require('path')
2     2  
3 // -------------------------------------------------------------------------------   3 // -------------------------------------------------------------------------------
4 // Config   4 // Config
5     5  
6 const env = require('gulp-environment')   6 const env = require('gulp-environment')
7     7  
8 process.env.NODE_ENV = env.current.name   8 process.env.NODE_ENV = env.current.name
9     9  
10 const conf = (() => {   10 const conf = (() => {
11   const _conf = require('./build-config')   11   const _conf = require('./build-config')
12   return require('deepmerge').all([{}, _conf.base || {}, _conf[process.env.NODE_ENV] || {}])   12   return require('deepmerge').all([{}, _conf.base || {}, _conf[process.env.NODE_ENV] || {}])
13 })()   13 })()
14     14  
15 conf.buildPath = path.resolve(__dirname, conf.buildPath).replace(/\\/g, '/')   15 conf.buildPath = path.resolve(__dirname, conf.buildPath).replace(/\\/g, '/')
16     16  
17 // -------------------------------------------------------------------------------   17 // -------------------------------------------------------------------------------
18 // Modules   18 // Modules
19     19  
20 const { src, dest, parallel, series, watch } = require('gulp')   20 const { src, dest, parallel, series, watch } = require('gulp')
21 const webpack = require('webpack')   21 const webpack = require('webpack')
22 const sass = require('gulp-sass')   22 const sass = require('gulp-sass')
23 const autoprefixer = require('gulp-autoprefixer')   23 const autoprefixer = require('gulp-autoprefixer')
24 const rename = require('gulp-rename')   24 const rename = require('gulp-rename')
25 const replace = require('gulp-replace')   25 const replace = require('gulp-replace')
26 const gulpIf = require('gulp-if')   26 const gulpIf = require('gulp-if')
27 const sourcemaps = require('gulp-sourcemaps')   27 const sourcemaps = require('gulp-sourcemaps')
28 const del = require('del')   28 const del = require('del')
29 const colors = require('ansi-colors')   29 const colors = require('ansi-colors')
30 const log = require('fancy-log')   30 const log = require('fancy-log')
31     31  
    -+ 32 sass.compiler = require('node-sass')
32 colors.enabled = require('color-support').hasBasic = 33 colors.enabled = require('color-support').hasBasic
33     34  
34 // -------------------------------------------------------------------------------   35 // -------------------------------------------------------------------------------
35 // Utilities   36 // Utilities
36     37  
37 function normalize(p) {   38 function normalize(p) {
38   return p.replace(/\\/g, '/')   39   return p.replace(/\\/g, '/')
39 }   40 }
40     41  
41 function root(p) {   42 function root(p) {
42   return p.startsWith('!') ?   43   return p.startsWith('!') ?
43     normalize(`!${path.join(__dirname, p.slice(1))}`) :   44     normalize(`!${path.join(__dirname, p.slice(1))}`) :
44     normalize(path.join(__dirname, p))   45     normalize(path.join(__dirname, p))
45 }   46 }
46     47  
47 function getSrc(...src) {   48 function getSrc(...src) {
48   return src.map(p => root(p)).concat(conf.exclude.map(d => `!${root(d)}/**/*`))   49   return src.map(p => root(p)).concat(conf.exclude.map(d => `!${root(d)}/**/*`))
49 }   50 }
50     51  
51 // -------------------------------------------------------------------------------   52 // -------------------------------------------------------------------------------
52 // Clean build directory   53 // Clean build directory
53     54  
54 const cleanTask = function () {   55 const cleanTask = function () {
55   return del([conf.buildPath], {   56   return del([conf.buildPath], {
56     force: true   57     force: true
57   })   58   })
58 }   59 }
59     60  
60 // -------------------------------------------------------------------------------   61 // -------------------------------------------------------------------------------
61 // Build css   62 // Build css
62     63  
63 const buildCssTask = function () {   64 const buildCssTask = function () {
64   return src(getSrc('**/*.scss', '!**/_*.scss'), { base: root('.') })   65   return src(getSrc('**/*.scss', '!**/_*.scss'), { base: root('.') })
65     66  
66     .pipe(gulpIf(conf.sourcemaps, sourcemaps.init()))   67     .pipe(gulpIf(conf.sourcemaps, sourcemaps.init()))
67     .pipe(sass({   68     .pipe(sass({
68       outputStyle: conf.minify ? 'compressed' : 'nested'   69       outputStyle: conf.minify ? 'compressed' : 'nested'
69     }).on('error', sass.logError))   70     }).on('error', sass.logError))
70     .pipe(gulpIf(conf.sourcemaps, sourcemaps.write()))   71     .pipe(gulpIf(conf.sourcemaps, sourcemaps.write()))
71     72  
72     .pipe(gulpIf(conf.sourcemaps, sourcemaps.init({   73     .pipe(gulpIf(conf.sourcemaps, sourcemaps.init({
73       loadMaps: true   74       loadMaps: true
74     })))   75     })))
75     .pipe(autoprefixer({   76     .pipe(autoprefixer({
76       overrideBrowserslist: [   77       overrideBrowserslist: [
77         '>= 1%',   78         '>= 1%',
78         'last 2 versions',   79         'last 2 versions',
79         'not dead',   80         'not dead',
80         'Chrome >= 45',   81         'Chrome >= 45',
81         'Firefox >= 38',   82         'Firefox >= 38',
82         'Edge >= 12',   83         'Edge >= 12',
83         'Explorer >= 10',   84         'Explorer >= 10',
84         'iOS >= 9',   85         'iOS >= 9',
85         'Safari >= 9',   86         'Safari >= 9',
86         'Android >= 4.4',   87         'Android >= 4.4',
87         'Opera >= 30'   88         'Opera >= 30'
88       ]   89       ]
89     }))   90     }))
90     .pipe(gulpIf(conf.sourcemaps, sourcemaps.write()))   91     .pipe(gulpIf(conf.sourcemaps, sourcemaps.write()))
91     92  
92     .pipe(dest(conf.buildPath))   93     .pipe(dest(conf.buildPath))
93 }   94 }
94     95  
95 // -------------------------------------------------------------------------------   96 // -------------------------------------------------------------------------------
96 // Build js   97 // Build js
97     98  
98 const buildJsTask = function (cb) {   99 const buildJsTask = function (cb) {
99   setTimeout(function () {   100   setTimeout(function () {
100     webpack(require('./webpack.config'), (err, stats) => {   101     webpack(require('./webpack.config'), (err, stats) => {
101       if (err) {   102       if (err) {
102         log(colors.gray('Webpack error:'), colors.red(err.stack || err))   103         log(colors.gray('Webpack error:'), colors.red(err.stack || err))
103         if (err.details) log(colors.gray('Webpack error details:'), err.details)   104         if (err.details) log(colors.gray('Webpack error details:'), err.details)
104         return cb()   105         return cb()
105       }   106       }
106     107  
107       const info = stats.toJson()   108       const info = stats.toJson()
108     109  
109       if (stats.hasErrors()) {   110       if (stats.hasErrors()) {
110         info.errors.forEach(e => log(colors.gray('Webpack compilation error:'), colors.red(e)))   111         info.errors.forEach(e => log(colors.gray('Webpack compilation error:'), colors.red(e)))
111       }   112       }
112     113  
113       if (stats.hasWarnings()) {   114       if (stats.hasWarnings()) {
114         info.warnings.forEach(w => log(colors.gray('Webpack compilation warning:'), colors.yellow(w)))   115         info.warnings.forEach(w => log(colors.gray('Webpack compilation warning:'), colors.yellow(w)))
115       }   116       }
116     117  
117       // Print log   118       // Print log
118       log(stats.toString({   119       log(stats.toString({
119         colors: colors.enabled,   120         colors: colors.enabled,
120         hash: false,   121         hash: false,
121         timings: false,   122         timings: false,
122         chunks: false,   123         chunks: false,
123         chunkModules: false,   124         chunkModules: false,
124         modules: false,   125         modules: false,
125         children: true,   126         children: true,
126         version: true,   127         version: true,
127         cached: false,   128         cached: false,
128         cachedAssets: false,   129         cachedAssets: false,
129         reasons: false,   130         reasons: false,
130         source: false,   131         source: false,
131         errorDetails: false   132         errorDetails: false
132       }))   133       }))
133     134  
134       cb()   135       cb()
135     })   136     })
136   }, 1)   137   }, 1)
137 }   138 }
138     139  
139 // -------------------------------------------------------------------------------   140 // -------------------------------------------------------------------------------
140 // Build fonts   141 // Build fonts
141     142  
142 const FONT_TASKS = [{   143 const FONT_TASKS = [{
143     name: 'fontawesome',   144     name: 'fontawesome',
144     path: 'node_modules/@fortawesome/fontawesome-free/webfonts/*'   145     path: 'node_modules/@fortawesome/fontawesome-free/webfonts/*'
145   },   146   },
146   {   147   {
147     name: 'linearicons',   148     name: 'linearicons',
148     path: 'node_modules/linearicons/dist/web-font/fonts/*'   149     path: 'node_modules/linearicons/dist/web-font/fonts/*'
149   },   150   },
150   {   151   {
151     name: 'pe-icon-7-stroke',   152     name: 'pe-icon-7-stroke',
152     path: 'node_modules/pixeden-stroke-7-icon/pe-icon-7-stroke/fonts/*'   153     path: 'node_modules/pixeden-stroke-7-icon/pe-icon-7-stroke/fonts/*'
153   },   154   },
154   {   155   {
155     name: 'open-iconic',   156     name: 'open-iconic',
156     path: 'node_modules/open-iconic/font/fonts/*'   157     path: 'node_modules/open-iconic/font/fonts/*'
157   },   158   },
158   {   159   {
159     name: 'ionicons',   160     name: 'ionicons',
160     path: 'node_modules/ionicons/dist/fonts/*'   161     path: 'node_modules/ionicons/dist/fonts/*'
161   }   162   }
162 ].reduce(function (tasks, font) {   163 ].reduce(function (tasks, font) {
163   const functionName = `buildFonts${font.name.replace(/^./, m => m.toUpperCase())}Task`   164   const functionName = `buildFonts${font.name.replace(/^./, m => m.toUpperCase())}Task`
164   const taskFunction = function () {   165   const taskFunction = function () {
165     return src(root(font.path))   166     return src(root(font.path))
166       .pipe(dest(normalize(path.join(conf.buildPath, 'fonts', font.name))))   167       .pipe(dest(normalize(path.join(conf.buildPath, 'fonts', font.name))))
167   }   168   }
168     169  
169   Object.defineProperty(taskFunction, 'name', {   170   Object.defineProperty(taskFunction, 'name', {
170     value: functionName   171     value: functionName
171   });   172   });
172     173  
173   return tasks.concat([taskFunction])   174   return tasks.concat([taskFunction])
174 }, [])   175 }, [])
175     176  
176 // Copy linearicons' style.css   177 // Copy linearicons' style.css
177 FONT_TASKS.push(function buildFontsLinearicons () {   178 FONT_TASKS.push(function buildFontsLinearicons () {
178   return src(root('node_modules/linearicons/dist/web-font/style.css'))   179   return src(root('node_modules/linearicons/dist/web-font/style.css'))
179     .pipe(replace(/'fonts\//g, '\'linearicons/'))   180     .pipe(replace(/'fonts\//g, '\'linearicons/'))
180     .pipe(rename({   181     .pipe(rename({
181       basename: 'linearicons'   182       basename: 'linearicons'
182     }))   183     }))
183     .pipe(dest(normalize(path.join(conf.buildPath, 'fonts'))))   184     .pipe(dest(normalize(path.join(conf.buildPath, 'fonts'))))
184 })   185 })
185     186  
186 const buildFontsTask = parallel(FONT_TASKS)   187 const buildFontsTask = parallel(FONT_TASKS)
187     188  
188 // -------------------------------------------------------------------------------   189 // -------------------------------------------------------------------------------
189 // Copy   190 // Copy
190     191  
191 const buildCopyTask = function () {   192 const buildCopyTask = function () {
192   return src(getSrc('**/*.png', '**/*.gif', '**/*.jpg', '**/*.jpeg', '**/*.svg', '**/*.swf', '**/*.eot', '**/*.ttf', '**/*.woff', '**/*.woff2'), {   193   return src(getSrc('**/*.png', '**/*.gif', '**/*.jpg', '**/*.jpeg', '**/*.svg', '**/*.swf', '**/*.eot', '**/*.ttf', '**/*.woff', '**/*.woff2'), {
193     base: root('.')   194     base: root('.')
194   })   195   })
195   .pipe(dest(conf.buildPath))   196   .pipe(dest(conf.buildPath))
196 }   197 }
197     198  
198 // -------------------------------------------------------------------------------   199 // -------------------------------------------------------------------------------
199 // Watch   200 // Watch
200     201  
201 const watchTask = function () {   202 const watchTask = function () {
202   watch(getSrc('**/*.scss', '!fonts/**/*.scss'), buildCssTask)   203   watch(getSrc('**/*.scss', '!fonts/**/*.scss'), buildCssTask)
203   watch(getSrc('fonts/**/*.scss'), parallel(buildCssTask, buildFontsTask))   204   watch(getSrc('fonts/**/*.scss'), parallel(buildCssTask, buildFontsTask))
204   watch(getSrc('**/*.@(js|es6)', '!*.js'), buildJsTask)   205   watch(getSrc('**/*.@(js|es6)', '!*.js'), buildJsTask)
205   watch(getSrc('**/*.png', '**/*.gif', '**/*.jpg', '**/*.jpeg', '**/*.svg', '**/*.swf'), buildCopyTask)   206   watch(getSrc('**/*.png', '**/*.gif', '**/*.jpg', '**/*.jpeg', '**/*.svg', '**/*.swf'), buildCopyTask)
206 }   207 }
207     208  
208 // -------------------------------------------------------------------------------   209 // -------------------------------------------------------------------------------
209 // Build   210 // Build
210     211  
211 const buildTasks = [   212 const buildTasks = [
212   buildCssTask,   213   buildCssTask,
213   buildJsTask,   214   buildJsTask,
214   buildFontsTask,   215   buildFontsTask,
215   buildCopyTask   216   buildCopyTask
216 ]   217 ]
217     218  
218 const buildTask = conf.cleanBuild ?   219 const buildTask = conf.cleanBuild ?
219   series(cleanTask, parallel(buildTasks)) :   220   series(cleanTask, parallel(buildTasks)) :
220   parallel(buildTasks)   221   parallel(buildTasks)
221     222  
222 // -------------------------------------------------------------------------------   223 // -------------------------------------------------------------------------------
223 // Exports   224 // Exports
224     225  
225 module.exports = {   226 module.exports = {
226   default: buildTask,   227   default: buildTask,
227   build: buildTask,   228   build: buildTask,
228   'build:js': buildJsTask,   229   'build:js': buildJsTask,
229   'build:css': buildCssTask,   230   'build:css': buildCssTask,
230   'build:fonts': buildFontsTask,   231   'build:fonts': buildFontsTask,
231   'build:copy': buildCopyTask,   232   'build:copy': buildCopyTask,
232   watch: watchTask   233   watch: watchTask
233 }   234 }