@@ -22,10 +22,10 @@ import gulpHtmlmin from 'gulp-htmlmin';
22
22
import gulpUglify from 'gulp-uglify' ;
23
23
import gulpIf from 'gulp-if' ;
24
24
import gulpUseref from 'gulp-useref' ;
25
- import gulpRev from 'gulp-rev' ;
26
- import gulpRevReplace from 'gulp-rev-replace' ;
27
- import uglifySaveLicense from 'uglify-save-license' ;
25
+ import GulpRevAll from 'gulp-rev-all' ;
26
+ import mergeStream from 'merge-stream' ;
28
27
import path from 'path' ;
28
+ import uglifySaveLicense from 'uglify-save-license' ;
29
29
30
30
import conf from './conf' ;
31
31
import { multiDest } from './multidest' ;
@@ -41,19 +41,67 @@ gulp.task('build', ['backend:prod', 'build-frontend']);
41
41
gulp . task ( 'build:cross' , [ 'backend:prod:cross' , 'build-frontend:cross' ] ) ;
42
42
43
43
/**
44
- * Builds production version of the frontend application for the current architecture.
44
+ * Builds production version of the frontend application for the default architecture.
45
+ */
46
+ gulp . task (
47
+ 'build-frontend' , [ 'localize' , 'locales-for-backend' ] , function ( ) { return doRevision ( ) ; } ) ;
48
+
49
+ /**
50
+ * Builds production version of the frontend application for all supported architectures.
51
+ */
52
+ gulp . task ( 'build-frontend:cross' , [ 'localize:cross' , 'locales-for-backend:cross' ] , function ( ) {
53
+ return doRevision ( ) ;
54
+ } ) ;
55
+
56
+ /**
57
+ * Localizes all pre-created frontend copies for the default arch, so that they are ready to serve.
58
+ */
59
+ gulp . task ( 'localize' , [ 'frontend-copies' ] , function ( ) {
60
+ return localize ( [ path . join ( conf . paths . distPre , conf . arch . default , 'public' ) ] ) ;
61
+ } ) ;
62
+
63
+ /**
64
+ * Localizes all pre-created frontend copies in all cross-arch directories, so that they are ready
65
+ * to serve.
66
+ */
67
+ gulp . task ( 'localize:cross' , [ 'frontend-copies:cross' ] , function ( ) {
68
+ return localize ( conf . arch . list . map ( ( arch ) => path . join ( conf . paths . distPre , arch , 'public' ) ) ) ;
69
+ } ) ;
70
+
71
+ /**
72
+ * Copies the locales configuration to the default arch directory.
73
+ * This configuration file is then used by the backend to localize dashboard.
74
+ */
75
+ gulp . task ( 'locales-for-backend' , [ 'clean-dist' ] , function ( ) {
76
+ return localesForBackend ( [ conf . paths . dist ] ) ;
77
+ } ) ;
78
+
79
+ /**
80
+ * Copies the locales configuration to each arch directory.
81
+ * This configuration file is then used by the backend to localize dashboard.
82
+ */
83
+ gulp . task ( 'locales-for-backend:cross' , [ 'clean-dist' ] , function ( ) {
84
+ return localesForBackend ( conf . paths . distCross ) ;
85
+ } ) ;
86
+
87
+ /**
88
+ * Builds production version of the frontend application for the default architecture
89
+ * (one copy per locale) and plcaes it under .tmp/dist , preparing it for localization and revision.
45
90
*/
46
- gulp . task ( 'build- frontend' , [ 'fonts' , 'icons' , 'assets' , 'index:prod' , 'clean-dist' ] , function ( ) {
47
- return buildFrontend ( conf . paths . distPublic ) ;
91
+ gulp . task ( 'frontend-copies ' , [ 'fonts' , 'icons' , 'assets' , 'index:prod' , 'clean-dist' ] , function ( ) {
92
+ return createFrontendCopies ( [ path . join ( conf . paths . distPre , conf . arch . default , 'public' ) ] ) ;
48
93
} ) ;
49
94
50
95
/**
51
- * Builds production version of the frontend application for all architecures.
96
+ * Builds production versions of the frontend application for all architecures
97
+ * (one copy per locale) and places them under .tmp, preparing them for localization and revision.
52
98
*/
53
99
gulp . task (
54
- 'build-frontend:cross' ,
55
- [ 'fonts:cross' , 'icons:cross' , 'assets:cross' , 'index:prod' , 'clean-dist' ] ,
56
- function ( ) { return buildFrontend ( conf . paths . distPublicCross ) ; } ) ;
100
+ 'frontend-copies:cross' ,
101
+ [ 'fonts:cross' , 'icons:cross' , 'assets:cross' , 'index:prod' , 'clean-dist' ] , function ( ) {
102
+ return createFrontendCopies (
103
+ conf . arch . list . map ( ( arch ) => path . join ( conf . paths . distPre , arch , 'public' ) ) ) ;
104
+ } ) ;
57
105
58
106
/**
59
107
* Copies assets to the dist directory for current architecture.
@@ -69,24 +117,22 @@ gulp.task(
69
117
/**
70
118
* Copies icons to the dist directory for current architecture.
71
119
*/
72
- gulp . task ( 'icons' , [ 'clean-dist' ] , function ( ) { return icons ( conf . paths . iconsDistPublic ) ; } ) ;
120
+ gulp . task ( 'icons' , [ 'clean-dist' ] , function ( ) { return icons ( [ conf . paths . distPublic ] ) ; } ) ;
73
121
74
122
/**
75
123
* Copies icons to the dist directory for all architectures.
76
124
*/
77
- gulp . task (
78
- 'icons:cross' , [ 'clean-dist' ] , function ( ) { return icons ( conf . paths . iconsDistPublicCross ) ; } ) ;
125
+ gulp . task ( 'icons:cross' , [ 'clean-dist' ] , function ( ) { return icons ( conf . paths . distPublicCross ) ; } ) ;
79
126
80
127
/**
81
128
* Copies fonts to the dist directory for current architecture.
82
129
*/
83
- gulp . task ( 'fonts' , [ 'clean-dist' ] , function ( ) { return fonts ( conf . paths . fontsDistPublic ) ; } ) ;
130
+ gulp . task ( 'fonts' , [ 'clean-dist' ] , function ( ) { return fonts ( [ conf . paths . distPublic ] ) ; } ) ;
84
131
85
132
/**
86
133
* Copies fonts to the dist directory for all architectures.
87
134
*/
88
- gulp . task (
89
- 'fonts:cross' , [ 'clean-dist' ] , function ( ) { return fonts ( conf . paths . fontsDistPublicCross ) ; } ) ;
135
+ gulp . task ( 'fonts:cross' , [ 'clean-dist' ] , function ( ) { return fonts ( conf . paths . distPublicCross ) ; } ) ;
90
136
91
137
/**
92
138
* Cleans all build artifacts.
@@ -98,20 +144,27 @@ gulp.task('clean', ['clean-dist'], function() {
98
144
/**
99
145
* Cleans all build artifacts in the dist/ folder.
100
146
*/
101
- gulp . task ( 'clean-dist' , function ( ) { return del ( [ conf . paths . distRoot ] ) ; } ) ;
147
+ gulp . task ( 'clean-dist' , function ( ) { return del ( [ conf . paths . distRoot , conf . paths . distPre ] ) ; } ) ;
102
148
103
149
/**
104
- * Builds production version of the frontend application.
150
+ * Builds production version of the frontend application and copies it to all
151
+ * the specified outputDirs, creating one copy per (outputDir x locale) tuple.
105
152
*
106
153
* Following steps are done here:
107
154
* 1. Vendor CSS and JS files are concatenated and minified.
108
155
* 2. index.html is minified.
109
- * 3. CSS and JS assets are suffixed with version hash .
110
- * 4. Everything is saved in the dist directory.
111
- * @param {string| !Array<string> } outputDirs
156
+ * 3. Everything is saved in the .tmp/dist directory, ready to be localized and revisioned .
157
+ *
158
+ * @param {!Array<string> } outputDirs
112
159
* @return {stream }
113
160
*/
114
- function buildFrontend ( outputDirs ) {
161
+ function createFrontendCopies ( outputDirs ) {
162
+ // create an output for each locale
163
+ let localizedOutputDirs = outputDirs . reduce ( ( localizedDirs , outputDir ) => {
164
+ return localizedDirs . concat (
165
+ conf . translations . map ( ( translation ) => { return path . join ( outputDir , translation . key ) ; } ) ) ;
166
+ } , [ ] ) ;
167
+
115
168
let searchPath = [
116
169
// To resolve local paths.
117
170
path . relative ( conf . paths . base , conf . paths . prodTmp ) ,
@@ -123,44 +176,109 @@ function buildFrontend(outputDirs) {
123
176
. pipe ( gulpUseref ( { searchPath : searchPath } ) )
124
177
. pipe ( gulpIf ( '**/vendor.css' , gulpMinifyCss ( ) ) )
125
178
. pipe ( gulpIf ( '**/vendor.js' , gulpUglify ( { preserveComments : uglifySaveLicense } ) ) )
126
- . pipe ( gulpIf ( [ '**/*.js' , '**/*.css' ] , gulpRev ( ) ) )
127
- . pipe ( gulpUseref ( { searchPath : searchPath } ) )
128
- . pipe ( gulpRevReplace ( ) )
129
179
. pipe ( gulpIf ( '*.html' , gulpHtmlmin ( {
130
180
removeComments : true ,
131
181
collapseWhitespace : true ,
132
182
conservativeCollapse : true ,
133
183
} ) ) )
134
- . pipe ( multiDest ( outputDirs ) ) ;
184
+ . pipe ( multiDest ( localizedOutputDirs ) ) ;
135
185
}
136
186
137
187
/**
138
- * @param {string|!Array<string> } outputDirs
188
+ * Creates revisions of all .js anc .css files at once (for production).
189
+ * Replaces the occurances of those files in index.html with their new names.
190
+ * index.html does not get renamed in the process.
191
+ * The processed files are then moved to the dist directory.
192
+ * @return {stream }
193
+ */
194
+ function doRevision ( ) {
195
+ // Do not update references other than in index.html. Do not rev index.html itself.
196
+ let revAll =
197
+ new GulpRevAll ( { dontRenameFile : [ 'index.html' ] , dontSearchFile : [ / ^ (? ! .* i n d e x \. h t m l $ ) .* $ / ] } ) ;
198
+ return gulp . src ( [ path . join ( conf . paths . distPre , '**' ) , '!**/assets/**/*' ] )
199
+ . pipe ( revAll . revision ( ) )
200
+ . pipe ( gulp . dest ( conf . paths . distRoot ) ) ;
201
+ }
202
+
203
+ /**
204
+ * Copies the localized app.js files for each supported language in outputDir/<locale>/static
205
+ * for each of the specified output dirs.
206
+ * @param {!Array<string> } outputDirs - list of all arch directories
207
+ * @return {stream }
208
+ */
209
+ function localize ( outputDirs ) {
210
+ let streams = conf . translations . map ( ( translation ) => {
211
+ let localizedOutputDirs =
212
+ outputDirs . map ( ( outputDir ) => { return path . join ( outputDir , translation . key , 'static' ) ; } ) ;
213
+ return gulp . src ( path . join ( conf . paths . i18nProd , translation . key , '*.js' ) )
214
+ . pipe ( multiDest ( localizedOutputDirs ) ) ;
215
+ } ) ;
216
+
217
+ return mergeStream . apply ( null , streams ) ;
218
+ }
219
+
220
+ /**
221
+ * Copies the locales configuration file at the base of each arch directory, next to
222
+ * all of the localized subdirs. This file is meant to be used by the backend binary
223
+ * to compare against and determine the right locale to serve at runtime.
224
+ * @param {!Array<string> } outputDirs - list of all arch directories
225
+ * @return {stream }
226
+ */
227
+ function localesForBackend ( outputDirs ) {
228
+ return gulp . src ( path . join ( conf . paths . base , 'i18n' , '*.json' ) ) . pipe ( multiDest ( outputDirs ) ) ;
229
+ }
230
+
231
+ /**
232
+ * Copies the assets files to all dist directories per arch and locale.
233
+ * @param {!Array<string> } outputDirs
139
234
* @return {stream }
140
235
*/
141
236
function assets ( outputDirs ) {
237
+ let localizedOutputDirs = createLocalizedOutputs ( outputDirs ) ;
142
238
return gulp . src ( path . join ( conf . paths . assets , '/**/*' ) , { base : conf . paths . app } )
143
- . pipe ( multiDest ( outputDirs ) ) ;
239
+ . pipe ( multiDest ( localizedOutputDirs ) ) ;
144
240
}
145
241
146
242
/**
147
- * @param {string|!Array<string> } outputDirs
243
+ * Copies the icons files to all dist directories per arch and locale.
244
+ * @param {!Array<string> } outputDirs
148
245
* @return {stream }
149
246
*/
150
247
function icons ( outputDirs ) {
248
+ let localizedOutputDirs = createLocalizedOutputs ( outputDirs , 'static' ) ;
151
249
return gulp
152
250
. src (
153
251
path . join ( conf . paths . materialIcons , '/**/*.+(woff2|woff|eot|ttf)' ) ,
154
252
{ base : conf . paths . materialIcons } )
155
- . pipe ( multiDest ( outputDirs ) ) ;
253
+ . pipe ( multiDest ( localizedOutputDirs ) ) ;
156
254
}
157
255
158
256
/**
159
- * @param {string|!Array<string> } outputDirs
257
+ * Copies the font files to all dist directories per arch and locale.
258
+ * @param {!Array<string> } outputDirs
160
259
* @return {stream }
161
260
*/
162
261
function fonts ( outputDirs ) {
262
+ let localizedOutputDirs = createLocalizedOutputs ( outputDirs , 'fonts' ) ;
163
263
return gulp
164
264
. src ( path . join ( conf . paths . robotoFonts , '/**/*.+(woff2)' ) , { base : conf . paths . robotoFonts } )
165
- . pipe ( multiDest ( outputDirs ) ) ;
265
+ . pipe ( multiDest ( localizedOutputDirs ) ) ;
266
+ }
267
+
268
+ /**
269
+ * Returns one subdirectory path for each supported locale inside all of the specified
270
+ * outputDirs. Optionally, a subdirectory structure can be passed to append after each locale path.
271
+ * @param {!Array<string> } outputDirs
272
+ * @param {undefined|string } opt_subdir - an optional sub directory inside each locale directory.
273
+ * @return {!Array<string> } localized output directories
274
+ */
275
+ function createLocalizedOutputs ( outputDirs , opt_subdir ) {
276
+ return outputDirs . reduce ( ( localizedDirs , outputDir ) => {
277
+ return localizedDirs . concat ( conf . translations . map ( ( translation ) => {
278
+ if ( opt_subdir ) {
279
+ return path . join ( outputDir , translation . key , opt_subdir ) ;
280
+ }
281
+ return path . join ( outputDir , translation . key ) ;
282
+ } ) ) ;
283
+ } , [ ] ) ;
166
284
}
0 commit comments